This commit was manufactured by cvs2svn to create branch 'fedora'.
[linux-2.6.git] / net / tux / cgi.c
1 /*
2  * TUX - Integrated Application Protocols Layer and Object Cache
3  *
4  * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
5  *
6  * cgi.c: user-space CGI (and other) code execution.
7  */
8
9 #define __KERNEL_SYSCALLS__
10 #define __KERNEL_SYSCALLS_NO_ERRNO__
11
12 #include <net/tux.h>
13
14 /****************************************************************
15  *      This program is free software; you can redistribute it and/or modify
16  *      it under the terms of the GNU General Public License as published by
17  *      the Free Software Foundation; either version 2, or (at your option)
18  *      any later version.
19  *
20  *      This program is distributed in the hope that it will be useful,
21  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *      GNU General Public License for more details.
24  *
25  *      You should have received a copy of the GNU General Public License
26  *      along with this program; if not, write to the Free Software
27  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28  *
29  ****************************************************************/
30
31 static int exec_usermode(char *program_path, char *argv[], char *envp[])
32 {
33         int i, err;
34
35         err = tux_chroot(tux_cgiroot);
36         if (err) {
37                 printk(KERN_ERR "TUX: CGI chroot returned %d, /proc/sys/net/tux/cgiroot is probably set up incorrectly! Aborting CGI execution.\n", err);
38                 return err;
39         }
40
41         /* Allow execve args to be in kernel space. */
42         set_fs(KERNEL_DS);
43
44         flush_signals(current);
45         spin_lock_irq(&current->sighand->siglock);
46         flush_signal_handlers(current, 1);
47         spin_unlock_irq(&current->sighand->siglock);
48
49         for (i = 3; i < current->files->max_fds; i++ )
50                 if (current->files->fd[i])
51                         tux_close(i);
52
53         err = execve(program_path, argv, envp);
54         if (err < 0)
55                 return err;
56         return 0;
57 }
58
59 static inline long tux_dup(unsigned int fildes)
60 {
61         int ret = -EBADF;
62         struct file * file = fget(fildes);
63
64         if (file)
65                 ret = dupfd(file, 0);
66         return ret;
67 }
68
69 static int exec_helper (void * data)
70 {
71         exec_param_t *param = data;
72         char **tmp;
73         int ret;
74
75         sprintf(current->comm,"doexec - %d", current->pid);
76 #if CONFIG_SMP
77         if (!tux_cgi_inherit_cpu) {
78                 
79                 cpumask_t cgi_mask, map;
80                 
81                 mask_to_cpumask(tux_cgi_cpu_mask, &cgi_mask);
82                 cpus_and(map, cpu_online_map, cgi_mask);
83         
84                 if (!(cpus_empty(map)))
85                         set_cpus_allowed(current, cgi_mask);
86                 else
87                         set_cpus_allowed(current, cpu_online_map);
88         }
89 #endif
90
91         if (!param)
92                 TUX_BUG();
93         Dprintk("doing exec(%s).\n", param->command);
94
95         Dprintk("argv: ");
96         tmp = param->argv;
97         while (*tmp) {
98                 Dprintk("{%s} ", *tmp);
99                 tmp++;
100         }
101         Dprintk("\n");
102         Dprintk("envp: ");
103         tmp = param->envp;
104         while (*tmp) {
105                 Dprintk("{%s} ", *tmp);
106                 tmp++;
107         }
108         Dprintk("\n");
109         /*
110          * Set up stdin, stdout and stderr of the external
111          * CGI application.
112          */
113         if (param->pipe_fds) {
114                 tux_close(1);
115                 tux_close(2);
116                 tux_close(4);
117                 if (tux_dup(3) != 1)
118                         TUX_BUG();
119                 if (tux_dup(5) != 2)
120                         TUX_BUG();
121                 tux_close(3);
122                 tux_close(5);
123                 // do not close on exec.
124 #if 0
125                 sys_fcntl(0, F_SETFD, 0);
126                 sys_fcntl(1, F_SETFD, 0);
127                 sys_fcntl(2, F_SETFD, 0);
128 #else
129                 spin_lock(&current->files->file_lock);
130                 FD_CLR(0, current->files->close_on_exec);
131                 FD_CLR(1, current->files->close_on_exec);
132                 FD_CLR(2, current->files->close_on_exec);
133                 spin_unlock(&current->files->file_lock);
134 #endif
135         }
136         ret = exec_usermode(param->command, param->argv, param->envp);
137         if (ret < 0)
138                 Dprintk("bug: exec() returned %d.\n", ret);
139         else
140                 Dprintk("exec()-ed successfully!\n");
141         return 0;
142 }
143
144 pid_t tux_exec_process (char *command, char **argv,
145                         char **envp, int pipe_fds,
146                                 exec_param_t *param, int wait)
147 {
148         exec_param_t param_local;
149         pid_t pid;
150         struct k_sigaction *ka;
151
152         ka = current->sighand->action + SIGCHLD-1;
153         ka->sa.sa_handler = SIG_IGN;
154
155         if (!param && wait)
156                 param = &param_local;
157
158         param->command = command;
159         param->argv = argv;
160         param->envp = envp;
161         param->pipe_fds = pipe_fds;
162
163 repeat_fork:
164         pid = kernel_thread(exec_helper, (void*) param, CLONE_SIGHAND|SIGCHLD);
165         Dprintk("kernel thread created PID %d.\n", pid);
166         if (pid < 0) {
167                 printk(KERN_ERR "TUX: could not create new CGI kernel thread due to %d... retrying.\n", pid);
168                 current->state = TASK_UNINTERRUPTIBLE;
169                 schedule_timeout(HZ);
170                 goto repeat_fork;
171         }
172         return pid;
173 }