- remove redundant merge conflict
[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         for (i = 3; i < current->files->max_fds; i++ )
45                 if (current->files->fd[i])
46                         tux_close(i);
47
48         err = __exec_usermodehelper(program_path, argv, envp);
49         if (err < 0)
50                 return err;
51         return 0;
52 }
53
54 static inline long tux_dup(unsigned int fildes)
55 {
56         int ret = -EBADF;
57         struct file * file = fget(fildes);
58
59         if (file)
60                 ret = dupfd(file, 0);
61         return ret;
62 }
63
64 static int exec_helper (void * data)
65 {
66         exec_param_t *param = data;
67         char **tmp;
68         int ret;
69
70         sprintf(current->comm,"doexec - %d", current->pid);
71 #if CONFIG_SMP
72         if (!tux_cgi_inherit_cpu) {
73                 cpumask_t map;
74                 
75                 cpus_and(map, cpu_online_map, tux_cgi_cpu_mask);
76         
77                 if (!(cpus_empty(map)))
78                         set_cpus_allowed(current, map);
79                 else
80                         set_cpus_allowed(current, cpu_online_map);
81         }
82 #endif
83
84         if (!param)
85                 TUX_BUG();
86         Dprintk("doing exec(%s).\n", param->command);
87
88         Dprintk("argv: ");
89         tmp = param->argv;
90         while (*tmp) {
91                 Dprintk("{%s} ", *tmp);
92                 tmp++;
93         }
94         Dprintk("\n");
95         Dprintk("envp: ");
96         tmp = param->envp;
97         while (*tmp) {
98                 Dprintk("{%s} ", *tmp);
99                 tmp++;
100         }
101         Dprintk("\n");
102         /*
103          * Set up stdin, stdout and stderr of the external
104          * CGI application.
105          */
106         if (param->pipe_fds) {
107                 tux_close(1);
108                 tux_close(2);
109                 tux_close(4);
110                 if (tux_dup(3) != 1)
111                         TUX_BUG();
112                 if (tux_dup(5) != 2)
113                         TUX_BUG();
114                 tux_close(3);
115                 tux_close(5);
116                 // do not close on exec.
117                 spin_lock(&current->files->file_lock);
118                 FD_CLR(0, current->files->close_on_exec);
119                 FD_CLR(1, current->files->close_on_exec);
120                 FD_CLR(2, current->files->close_on_exec);
121                 spin_unlock(&current->files->file_lock);
122         }
123         ret = exec_usermode(param->command, param->argv, param->envp);
124         if (ret < 0)
125                 Dprintk("bug: exec() returned %d.\n", ret);
126         else
127                 Dprintk("exec()-ed successfully!\n");
128         return 0;
129 }
130
131 pid_t tux_exec_process (char *command, char **argv,
132                         char **envp, int pipe_fds,
133                                 exec_param_t *param, int wait)
134 {
135         exec_param_t param_local;
136         pid_t pid;
137         struct k_sigaction *ka;
138
139         ka = current->sighand->action + SIGCHLD-1;
140         ka->sa.sa_handler = SIG_IGN;
141
142         if (!param && wait)
143                 param = &param_local;
144
145         param->command = command;
146         param->argv = argv;
147         param->envp = envp;
148         param->pipe_fds = pipe_fds;
149
150 repeat_fork:
151         pid = kernel_thread(exec_helper, (void*) param, CLONE_SIGHAND|SIGCHLD);
152         Dprintk("kernel thread created PID %d.\n", pid);
153         if (pid < 0) {
154                 printk(KERN_ERR "TUX: could not create new CGI kernel thread due to %d... retrying.\n", pid);
155                 current->state = TASK_UNINTERRUPTIBLE;
156                 schedule_timeout(HZ);
157                 goto repeat_fork;
158         }
159         return pid;
160 }