1 /* cgiexec.c by Michael Temari 02/17/96
3 * This file is part of httpd.
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>
11 #include <sys/types.h>
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
));
30 struct http_request
*rq
;
31 struct http_reply
*rp
;
40 static char cmd
[2048];
44 if(stat(rp
->realurl
, &st
)) {
46 rp
->status
= HTTP_STATUS_FORBIDDEN
;
48 rp
->status
= HTTP_STATUS_NOT_FOUND
;
49 strcpy(rp
->statusmsg
, strerror(errno
));
53 if((st
.st_mode
& S_IFMT
) == S_IFDIR
)
55 prog
= direxec
; dirflag
= 1;
61 /* check if prog is allowed to be exec'd */
62 if(!dirflag
&& !(rp
->urlaccess
& URLA_EXEC
))
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 )
71 if((cmdenv
= cgienv(rq
, rp
)) == NULL
) {
72 rp
->status
= HTTP_STATUS_SERVER_ERROR
;
73 strcpy(rp
->statusmsg
, "Could not setup cgi environment");
78 argv
[1] = rp
->realurl
;
80 argv
[3] = (char *)NULL
;
83 rp
->status
= HTTP_STATUS_NOT_FOUND
;
84 strcpy(rp
->statusmsg
, strerror(errno
));
89 rp
->status
= HTTP_STATUS_NOT_FOUND
;
90 strcpy(rp
->statusmsg
, strerror(errno
));
91 close(ifds
[0]); close(ifds
[1]);
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
));
103 /* We don't know how much data is going to be passed back */
106 if(cmdpid
== 0) { /* Child */
108 if((cmdpid
= fork()) < 0) {
109 close(ifds
[0]); close(ofds
[0]);
110 close(ifds
[1]); close(ofds
[1]);
114 close(ifds
[0]); close(ofds
[0]);
115 close(ifds
[1]); close(ofds
[1]);
120 close(ifds
[0]); close(ofds
[1]);
124 close(ifds
[1]); close(ofds
[0]);
125 execve(argv
[0], argv
, cmdenv
);
130 /* Get rid of Zombie child */
131 (void) wait(&status
);
134 close(ifds
[1]); close(ofds
[0]);
140 if(rp
->urlaccess
& URLA_HEADERS
)
146 char **cgienv(rq
, rp
)
147 struct http_request
*rq
;
148 struct http_reply
*rp
;
150 static char buffer
[4096];
157 len
= sizeof(buffer
);
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
);
163 /* HACK - some of these are hardcoded and should not be MAT 3/17/96 */
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
);
172 sprintf(temp
, "%u", rq
->port
);
175 if(addenv("SERVER_PORT", temp
, &p
, &len
)) return(NULL
);
177 case HTTP_METHOD_GET
:
178 if(addenv("REQUEST_METHOD", "GET", &p
, &len
)) return(NULL
);
180 case HTTP_METHOD_POST
:
181 if(addenv("REQUEST_METHOD", "POST", &p
, &len
)) return(NULL
);
183 case HTTP_METHOD_HEAD
:
184 if(addenv("REQUEST_METHOD", "HEAD", &p
, &len
)) return(NULL
);
186 case HTTP_METHOD_PUT
:
187 if(addenv("REQUEST_METHOD", "PUT", &p
, &len
)) return(NULL
);
190 if(addenv("REQUEST_METHOD", "UNKNOWN", &p
, &len
)) return(NULL
);
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
);
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
);
209 if(rq
->cookie
[0] != '\0')
210 if(addenv("COOKIE", rq
->cookie
, &p
, &len
)) return(NULL
);
212 if(addenv("HOST", rq
->host
, &p
, &len
)) return(NULL
);
214 if(len
< 1) return(NULL
);
220 if(len
< sizeof(e
)) return(NULL
);
226 if(len
< sizeof(e
)) return(NULL
);
232 static int addenv(name
, value
, buf
, len
)
243 size
= strlen(name
)+1+strlen(value
)+1;
248 sprintf(p
, "%s=%s", name
, value
);