int init_cgi(request * req)
{
int child_pid;
int pipes[2];
int use_pipes = 0;
char *aargv[CGI_ARGC_MAX + 1] = {NULL}; // wyl modify for vfork mem leak
char query[1024] = {0};
int i = 0;
SQUASH_KA(req);
if (req->is_cgi) {
snprintf(query,sizeof(query),"%s",req->query_string);
if(check_is_msfs_cgi(req,query,sizeof(query)) == -1)
return 0;
if (complete_env(req,query) == 0) {
return 0;
}
}
#ifdef FASCIST_LOGGING
{
int i;
for (i = 0; i < req->cgi_env_index; ++i)
fprintf(stderr, "%s - environment variable for cgi: \"%s\"\n",
__FILE__, req->cgi_env[i]);
}
#endif
if (req->is_cgi == CGI || 1) {
use_pipes = 1;
if (pipe(pipes) == -1) {
log_error_time();
perror("pipe");
return 0;
}
fcntl(pipes[0], F_SETFD, 1);
fcntl(pipes[1], F_SETFD, 1);
/* set the read end of the socket to non-blocking */
if (set_nonblock_fd(pipes[0]) == -1) {
log_error_time();
perror("cgi-fcntl");
close(pipes[0]);
close(pipes[1]);
return 0;
}
}
child_pid = vfork();
switch(child_pid) {
case -1:
/* fork unsuccessful */
log_error_time();
perror("fork");
if (use_pipes) {
close(pipes[0]);
close(pipes[1]);
}
send_r_error(req);
/* FIXME: There is aproblem here. send_r_error would work
for NPH and CGI, but not for GUNZIP. Fix that. */
/* i'd like to send_r_error, but.... */
return 0;
break;
case 0:
/* child */
//msprintf("===cgi path:%s===is cgi:%d===", req->pathname, req->is_cgi);
if (req->is_cgi == CGI || req->is_cgi == NPH) {
//msprintf("000000000");
char *foo = strdup(req->pathname);
char *c;
if (!foo) {
WARN("unable to strdup pathname for req->pathname");
_exit(1);
}
c = strrchr(foo, '/');
if (c) {
++c;
*c = '\0';
} else {
/* we have a serious problem */
log_error_time();
perror("chdir");
if (use_pipes)
close(pipes[1]);
free(foo);
_exit(1);
}
if (chdir(foo) != 0) {
log_error_time();
perror("chdir");
if (use_pipes)
close(pipes[1]);
free(foo);
_exit(1);
}
free(foo);
}
if (use_pipes) {
logger_write("/tmp/logs", "test.log", "11111");
close(pipes[0]);
logger_write("/tmp/logs", "test.log", "22222222");
/* tie cgi's STDOUT to it's write end of pipe */
if (dup2(pipes[1], STDOUT_FILENO) == -1) {
logger_write("/tmp/logs", "test.log", "33333333333");
log_error_time();
perror("dup2 - pipes");
close(pipes[1]);
_exit(1);
}
logger_write("/tmp/logs", "test.log", "44444444444");
close(pipes[1]);
if (set_block_fd(STDOUT_FILENO) == -1) {
logger_write("/tmp/logs", "test.log", "55555555555555");
log_error_time();
perror("cgi-fcntl");
_exit(1);
}
logger_write("/tmp/logs", "test.log", "66666666666666");
} else {
//msprintf("2222222");
/* tie stdout to socket */
if (dup2(req->fd, STDOUT_FILENO) == -1) {
log_error_time();
perror("dup2 - fd");
_exit(1);
}
/* Switch socket flags back to blocking */
if (set_block_fd(req->fd) == -1) {
log_error_time();
perror("cgi-fcntl");
_exit(1);
}
}
/* tie post_data_fd to POST stdin */
if (req->method == M_POST) { /* tie stdin to file */
logger_write("/tmp/logs", "test.log", "aaaaaaaaaaaa");
lseek(req->post_data_fd, SEEK_SET, 0);
dup2(req->post_data_fd, STDIN_FILENO);
close(req->post_data_fd);
}
/* Close access log, so CGI program can't scribble
* where it shouldn't
*/
logger_write("/tmp/logs", "test.log", "============");
close_access_log();
logger_write("/tmp/logs", "test.log", "name:%s", req->pathname);
/*
* tie STDERR to cgi_log_fd
* cgi_log_fd will automatically close, close-on-exec rocks!
* if we don't tied STDERR (current log_error) to cgi_log_fd,
* then we ought to close it.
*/
logger_write("/tmp/logs", "test.log", "===cgi path:%s==66666", req->pathname);
if (!cgi_log_fd)
dup2(devnullfd, STDERR_FILENO);
else
dup2(cgi_log_fd, STDERR_FILENO);
logger_write("/tmp/logs", "test.log", "===cgi path:%s==7777", req->pathname);
if (req->is_cgi) {
create_argv(req, aargv,query);
msprintf("exec");
logger_write("/tmp/logs", "test.log", "exec");
char cwd[256];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
logger_write("/tmp/logs", "test.log", "getcwd: %s", cwd);
} else {
logger_write("/tmp/logs", "test.log", "getcwd failed: %s", strerror(errno));
}
if (access(req->pathname, F_OK) != 0) {
logger_write("/tmp/logs", "test.log", "CGI file not found: %s, errno=%d:%s", req->pathname, errno, strerror(errno));
}
if (access(req->pathname, X_OK) != 0) {
logger_write("/tmp/logs", "test.log", "CGI file not executable: %s, errno=%d:%s", req->pathname, errno, strerror(errno));
}
struct stat st;
if (stat(req->pathname, &st) != 0) {
logger_write("/tmp/logs", "test.log", "stat failed: %s, errno=%d:%s", req->pathname, errno, strerror(errno));
} else {
if (!S_ISREG(st.st_mode)) {
logger_write("/tmp/logs", "test.log", "CGI file is not regular file: %s", req->pathname);
}
}
for (int i = 0; aargv[i] != NULL; ++i)
logger_write("/tmp/logs", "test.log", "aargv[%d]=%s", i, aargv[i]);
for (int i = 0; req->cgi_env[i] != NULL; ++i)
logger_write("/tmp/logs", "test.log", "env[%d]=%s", i, req->cgi_env[i]);
logger_write("/tmp/logs", "test.log", "execve path=%s", req->pathname);
for (int i = 0; aargv[i] != NULL; ++i)
logger_write("/tmp/logs", "test.log", "aargv[%d]=%s", i, aargv[i]);
execve(req->pathname, aargv, req->cgi_env);
logger_write("/tmp/logs", "test.log", "execve failed: errno=%d, %s", errno, strerror(errno));
msprintf("exec failed");
} else {
if (req->pathname[strlen(req->pathname) - 1] == '/')
{
logger_write("/tmp/logs", "test.log", "===cgi path:%s==7777", req->pathname);
execl(dirmaker, dirmaker, req->pathname, req->request_uri,
NULL);
}
#ifdef GUNZIP
else
{
logger_write("/tmp/logs", "test.log", "===cgi path:%s==8888", req->pathname);
execl(GUNZIP, GUNZIP, "--stdout", "--decompress",
req->pathname, NULL);
}
#endif
}
/* execve failed */
WARN(req->pathname);
_exit(1);
break;
default:
/* parent */
/* if here, fork was successful */
for(i = 1; i < CGI_ARGC_MAX + 1 && aargv[i] != NULL; i++)
{
printf("===parent==free==%s===========\n", aargv[i]);
free(aargv[i]);
aargv[i] = NULL;
}
if (verbose_cgi_logs) {
log_error_time();
fprintf(stderr, "Forked child \"%s\" pid %d\n",
req->pathname, child_pid);
}
if (req->method == M_POST) {
close(req->post_data_fd); /* child closed it too */
req->post_data_fd = 0;
}
/* NPH, GUNZIP, etc... all go straight to the fd */
if (!use_pipes)
return 0;
close(pipes[1]);
req->data_fd = pipes[0];
//msprintf("===PIPE_READ==");
req->status = PIPE_READ;
if (req->is_cgi == CGI) {
req->cgi_status = CGI_PARSE; /* got to parse cgi header */
/* for cgi_header... I get half the buffer! */
req->header_line = req->header_end =
(req->buffer + BUFFER_SIZE / 2);
} else {
req->cgi_status = CGI_BUFFER;
/* I get all the buffer! */
req->header_line = req->header_end = req->buffer;
}
/* reset req->filepos for logging (it's used in pipe.c) */
/* still don't know why req->filesize might be reset though */
req->filepos = 0;
//msprintf("===PIPE_READ==9999");
break;
}
return 1;
}
我的代码与打印[1970-01-03 15:39:32] 11111
[1970-01-03 15:39:32] 22222222
[1970-01-03 15:39:32] 44444444444
[1970-01-03 15:39:32] 66666666666666
[1970-01-03 15:39:32] aaaaaaaaaaaa
[1970-01-03 15:39:32] ============
[1970-01-03 15:39:32] name:/opt/app/www/dataloader.cgi
[1970-01-03 15:39:32] ===cgi path:/opt/app/www/dataloader.cgi==66666
[1970-01-03 15:39:32] ===cgi path:/opt/app/www/dataloader.cgi==7777
[1970-01-03 15:39:32] exec
[1970-01-03 15:39:32] getcwd: /opt/app/www
[1970-01-03 15:39:32] aargv[0]=/opt/app/www/dataloader.cgi
[1970-01-03 15:39:32] env[0]=PATH=/bin:/usr/bin:/usr/local/bin:/opt/app/bin
[1970-01-03 15:39:32] env[1]=SERVER_SOFTWARE=WebServer
[1970-01-03 15:39:32] env[2]=SERVER_NAME=IPNC
[1970-01-03 15:39:32] env[3]=GATEWAY_INTERFACE=CGI/1.1
[1970-01-03 15:39:32] env[4]=SERVER_PORT=80
[1970-01-03 15:39:32] env[5]=SERVER_ADMIN=
[1970-01-03 15:39:32] env[6]=HTTP_HOST=192.168.1.1
[1970-01-03 15:39:32] env[7]=HTTP_CACHE_CONTROL=max-age=0
[1970-01-03 15:39:32] env[8]=HTTP_SEC_CH_UA="Not;A=Brand";v="99", "Microsoft Edge";v="139", "Chromium";v="139"
[1970-01-03 15:39:32] env[9]=HTTP_SEC_CH_UA_MOBILE=?0
[1970-01-03 15:39:32] env[10]=HTTP_SEC_CH_UA_PLATFORM="Windows"
[1970-01-03 15:39:32] env[11]=HTTP_ORIGIN=https://192.168.1.1
[1970-01-03 15:39:32] env[12]=HTTP_UPGRADE_INSECURE_REQUESTS=1
[1970-01-03 15:39:32] env[13]=HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0
[1970-01-03 15:39:32] env[14]=HTTP_SEC_FETCH_SITE=same-origin
[1970-01-03 15:39:32] env[15]=HTTP_SEC_FETCH_MODE=navigate
[1970-01-03 15:39:32] env[16]=HTTP_SEC_FETCH_USER=?1
[1970-01-03 15:39:32] env[17]=HTTP_SEC_FETCH_DEST=iframe
[1970-01-03 15:39:32] env[18]=HTTP_REFERER=https://192.168.1.1/firmupdate.html
[1970-01-03 15:39:32] env[19]=HTTP_ACCEPT_ENCODING=gzip, deflate, br, zstd
[1970-01-03 15:39:32] env[20]=HTTP_ACCEPT_LANGUAGE=zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
[1970-01-03 15:39:32] env[21]=REQUEST_METHOD=POST
[1970-01-03 15:39:32] env[22]=SERVER_ADDR=::ffff:192.168.1.1
[1970-01-03 15:39:32] env[23]=SERVER_PROTOCOL=HTTP/1.1
[1970-01-03 15:39:32] env[24]=REQUEST_URI=/dataloader.cgi
[1970-01-03 15:39:32] env[25]=LD_LIBRARY_PATH=/opt/app/libs/
[1970-01-03 15:39:32] env[26]=SCRIPT_NAME=/dataloader.cgi
[1970-01-03 15:39:32] env[27]=QUERY_STRING=dw=cfg
[1970-01-03 15:39:32] env[28]=SD_STATE=0
[1970-01-03 15:39:32] env[29]=REMOTE_ADDR=::ffff:192.168.1.100
[1970-01-03 15:39:32] env[30]=REMOTE_PORT=62429
[1970-01-03 15:39:32] env[31]=CONTENT_TYPE=multipart/form-data; boundary=----WebKitFormBoundary88Dw8lAhA2jBaAPc
[1970-01-03 15:39:32] env[32]=CONTENT_LENGTH=44
[1970-01-03 15:39:32] execve path=/opt/app/www/dataloader.cgi
[1970-01-03 15:39:32] aargv[0]=/opt/app/www/dataloader.cgi
最新发布