source: trunk/minix/commands/httpd/cgiexec.c@ 21

Last change on this file since 21 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 5.9 KB
Line 
1/* cgiexec.c by Michael Temari 02/17/96
2 *
3 * This file is part of httpd.
4 *
5 * 02/17/1996 Michael Temari <Michael@TemWare.Com>
6 * 07/07/1996 Initial Release Michael Temari <Michael@TemWare.Com>
7 * 12/29/2002 Michael Temari <Michael@TemWare.Com>
8 * 02/08/2005 Michael Temari <Michael@TemWare.Com>
9 *
10 */
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <sys/wait.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <fcntl.h>
17#include <errno.h>
18#include <unistd.h>
19#include <string.h>
20#include <time.h>
21
22#include "http.h"
23#include "config.h"
24#include "net.h"
25
26_PROTOTYPE(char **cgienv, (struct http_request *rq, struct http_reply *rp));
27_PROTOTYPE(static int addenv, (char *name, char *value, char **buf, int *len));
28
29int cgiexec(rq, rp)
30struct http_request *rq;
31struct http_reply *rp;
32{
33struct stat st;
34char *prog;
35int cmdpid;
36int status;
37char *argv[5];
38int ifds[2];
39int ofds[2];
40static char cmd[2048];
41char **cmdenv;
42int dirflag = 0;
43
44 if(stat(rp->realurl, &st)) {
45 if(errno == EACCES)
46 rp->status = HTTP_STATUS_FORBIDDEN;
47 else
48 rp->status = HTTP_STATUS_NOT_FOUND;
49 strcpy(rp->statusmsg, strerror(errno));
50 return(-1);
51 }
52
53 if((st.st_mode & S_IFMT) == S_IFDIR)
54 if(direxec != NULL) {
55 prog = direxec; dirflag = 1;
56 } else
57 return(0);
58 else
59 prog = rp->realurl;
60
61 /* check if prog is allowed to be exec'd */
62 if(!dirflag && !(rp->urlaccess & URLA_EXEC))
63 return(0);
64
65 /* if cannot exec mode then return */
66 if( (st.st_mode & S_IXUSR) == 0 &&
67 (st.st_mode & S_IXGRP) == 0 &&
68 (st.st_mode & S_IXOTH) == 0 )
69 return(0);
70
71 if((cmdenv = cgienv(rq, rp)) == NULL) {
72 rp->status = HTTP_STATUS_SERVER_ERROR;
73 strcpy(rp->statusmsg, "Could not setup cgi environment");
74 return(-1);
75 }
76
77 argv[0] = prog;
78 argv[1] = rp->realurl;
79 argv[2] = rq->url;
80 argv[3] = (char *)NULL;
81
82 if(pipe(ifds) < 0) {
83 rp->status = HTTP_STATUS_NOT_FOUND;
84 strcpy(rp->statusmsg, strerror(errno));
85 return(-1);
86 }
87
88 if(pipe(ofds) < 0) {
89 rp->status = HTTP_STATUS_NOT_FOUND;
90 strcpy(rp->statusmsg, strerror(errno));
91 close(ifds[0]); close(ifds[1]);
92 return(-1);
93 }
94
95 if((cmdpid = fork()) < 0) {
96 close(ifds[0]); close(ofds[0]);
97 close(ifds[1]); close(ofds[1]);
98 rp->status = HTTP_STATUS_NOT_FOUND;
99 strcpy(rp->statusmsg, strerror(errno));
100 return(-1);
101 }
102
103 /* We don't know how much data is going to be passed back */
104 rp->size = 0;
105
106 if(cmdpid == 0) { /* Child */
107#if 0
108 if((cmdpid = fork()) < 0) {
109 close(ifds[0]); close(ofds[0]);
110 close(ifds[1]); close(ofds[1]);
111 exit(-1);
112 }
113 if(cmdpid != 0) {
114 close(ifds[0]); close(ofds[0]);
115 close(ifds[1]); close(ofds[1]);
116 exit(0);
117 }
118#endif
119 setsid();
120 close(ifds[0]); close(ofds[1]);
121 dup2(ofds[0], 0);
122 dup2(ifds[1], 1);
123 dup2(ifds[1], 2);
124 close(ifds[1]); close(ofds[0]);
125 execve(argv[0], argv, cmdenv);
126 exit(0);
127 }
128
129#if 0
130 /* Get rid of Zombie child */
131 (void) wait(&status);
132#endif
133
134 close(ifds[1]); close(ofds[0]);
135
136 rp->fd = ifds[0];
137 rp->ofd = ofds[1];
138 rp->pid = cmdpid;
139
140 if(rp->urlaccess & URLA_HEADERS)
141 rp->headers = -1;
142
143 return(-1);
144}
145
146char **cgienv(rq, rp)
147struct http_request *rq;
148struct http_reply *rp;
149{
150static char buffer[4096];
151char *p, *p2;
152char **e;
153int len;
154char temp[20];
155
156 p = buffer;
157 len = sizeof(buffer);
158
159 if(addenv("PATH", "/usr/local/bin:/bin:/usr/bin", &p, &len)) return(NULL);
160 if(getenv("TZ") != (char *)NULL)
161 if(addenv("TZ", getenv("TZ"), &p, &len)) return(NULL);
162
163 /* HACK - some of these are hardcoded and should not be MAT 3/17/96 */
164
165 /* HTTP_ */
166
167 if(addenv("SERVER_SOFTWARE", "Temari httpd/1.0", &p, &len)) return(NULL);
168 if(addenv("SERVER_NAME", myhostname, &p, &len)) return(NULL);
169 if(addenv("GATEWAY_INTERFACE", "CGI/1.1", &p, &len)) return(NULL);
170 if(addenv("SERVER_PROTOCOL", "HTTP/1.0", &p, &len)) return(NULL);
171 if(rq->port)
172 sprintf(temp, "%u", rq->port);
173 else
174 strcpy(temp, "80");
175 if(addenv("SERVER_PORT", temp, &p, &len)) return(NULL);
176 switch(rq->method) {
177 case HTTP_METHOD_GET:
178 if(addenv("REQUEST_METHOD", "GET", &p, &len)) return(NULL);
179 break;
180 case HTTP_METHOD_POST:
181 if(addenv("REQUEST_METHOD", "POST", &p, &len)) return(NULL);
182 break;
183 case HTTP_METHOD_HEAD:
184 if(addenv("REQUEST_METHOD", "HEAD", &p, &len)) return(NULL);
185 break;
186 case HTTP_METHOD_PUT:
187 if(addenv("REQUEST_METHOD", "PUT", &p, &len)) return(NULL);
188 break;
189 default:
190 if(addenv("REQUEST_METHOD", "UNKNOWN", &p, &len)) return(NULL);
191 }
192 if(addenv("PATH_INFO", "?", &p, &len)) return(NULL);
193 if(addenv("PATH_TRANSLATED", "?", &p, &len)) return(NULL);
194 if(addenv("SCRIPT_NAME", rq->url, &p, &len)) return(NULL);
195 if(addenv("QUERY_STRING", rq->query, &p, &len)) return(NULL);
196 if(addenv("REMOTE_HOST", rmthostname, &p, &len)) return(NULL);
197 if(addenv("REMOTE_ADDR", rmthostaddr, &p, &len)) return(NULL);
198 if(rq->authuser != (char *)NULL)
199 if(addenv("AUTH_USER", rq->authuser, &p, &len)) return(NULL);
200 /* AUTH_TYPE */
201 /* REMOTE_USER */
202 /* REMOTE_IDENT */
203 if(rq->method == HTTP_METHOD_POST) {
204 if(addenv("CONTENT_TYPE", "application/x-www-form-urlencoded", &p, &len)) return(NULL);
205 sprintf(temp, "%lu", rq->size);
206 if(addenv("CONTENT_LENGTH", temp, &p, &len)) return(NULL);
207 }
208 /* COOKIE */
209 if(rq->cookie[0] != '\0')
210 if(addenv("COOKIE", rq->cookie, &p, &len)) return(NULL);
211 /* HOST */
212 if(addenv("HOST", rq->host, &p, &len)) return(NULL);
213
214 if(len < 1) return(NULL);
215 *p++ = '\0';
216
217 p2 = buffer;
218 e = (char **)p;
219 while(*p2) {
220 if(len < sizeof(e)) return(NULL);
221 len -= sizeof(e);
222 *e++ = p2;
223 while(*p2) p2++;
224 p2++;
225 }
226 if(len < sizeof(e)) return(NULL);
227 *e++ = NULL;
228
229 return((char **)p);
230}
231
232static int addenv(name, value, buf, len)
233char *name;
234char *value;
235char **buf;
236int *len;
237{
238char *p;
239int size;
240
241 p = *buf;
242
243 size = strlen(name)+1+strlen(value)+1;
244
245 if(size > *len)
246 return(-1);
247
248 sprintf(p, "%s=%s", name, value);
249
250 p += size;
251 *buf = p;
252 *len -= size;
253
254 return(0);
255}
Note: See TracBrowser for help on using the repository browser.