void requestServeDynamic(int fd, char *filename, char *cgiargs, request* req) { char buf[MAXLINE], *emptylist[] = {NULL}; /* The server does only a little bit of the header. */ /* The CGI script has to finish writing out the header. */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); sprintf(buf, "%s Server: Tiny Web Server\r\n", buf); /* CS537: Your statistics go here -- fill in the 0's with something * useful! */ sprintf(buf, "%s Stat-req-arrival: %f\r\n", buf, toMS(req->req_arrival)); sprintf(buf, "%s Stat-req-dispatch: %f\r\n", buf, toMS(req->req_dispatch)); sprintf(buf, "%s Stat-thread-id: %d\r\n", buf, req->t_stats.thread_id); sprintf(buf, "%s Stat-thread-count: %d\r\n", buf, req->t_stats.thread_count); sprintf(buf, "%s Stat-thread-static: %d\r\n", buf, req->t_stats.thread_static); sprintf(buf, "%s Stat-thread-dynamic: %d\r\n", buf, req->t_stats.thread_dynamic); Rio_writen(fd, buf, strlen(buf)); if(Fork() == 0) { /* Child process */ Setenv("QUERY_STRING", cgiargs, 1); /* When the CGI process writes to stdout, it will instead go to * the socket */ Dup2(fd, STDOUT_FILENO); Execve(filename, emptylist, environ); } Wait(NULL); }
int main(int argc, char **argv) { int pid; sigset_t mask; Signal(SIGCHLD, handler); initjobs(); /* Initialize the job list */ while (1) { Sigemptyset(&mask); Sigaddset(&mask, SIGCHLD); Sigprocmask(SIG_BLOCK, &mask, NULL); /* Block SIGCHLD */ /* Child process */ if ((pid = Fork()) == 0) { Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Unblock SIGCHLD */ Execve("/bin/ls", argv, NULL); } /* Parent process */ addjob(pid); /* Add the child to the job list */ Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Unblock SIGCHLD */ } exit(0); }
/* $begin get_dynamic */ void get_dynamic(int fd, char *filename, char *cgiargs) { char buf[MAXLINE], *emptylist[] = { NULL },httpsbuf[MAXLINE]; int p[2]; /* Return first part of HTTP response */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); sprintf(buf, "%sServer: Tiny Web Server\r\n",buf); if(ishttps) SSL_write(ssl,buf,strlen(buf)); else Rio_writen(fd, buf, strlen(buf)); if(ishttps) { if(pipe(p)==-1) syslog(LOG_ERR,"cannot create pipe"); if (Fork() == 0) { /* child */ close(p[0]); setenv("QUERY_STRING", cgiargs, 1); Dup2(p[1], STDOUT_FILENO); /* Redirect stdout to p[1] */ Execve(filename, emptylist, environ); /* Run CGI program */ } close(p[1]); Read(p[0],httpsbuf,MAXLINE); /* parent read from p[0] */ SSL_write(ssl,httpsbuf,strlen(httpsbuf)); Wait(NULL); /* Parent waits for and reaps child */ } else { if (Fork() == 0) { /* child */ /* Real server would set all CGI vars here */ setenv("QUERY_STRING", cgiargs, 1); Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ Execve(filename, emptylist, environ); /* Run CGI program */ } Wait(NULL); /* Parent waits for and reaps child */ } }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { // Get memory for our parsed input char temp[MAXLINE]; char** argv = (char**)temp; // Return if only newline if (strcmp(cmdline, "\n") == 0) { return; } // Parse the input int background = parseline(cmdline, argv); // Check if built in command if (builtin_cmd(argv) == 0) { // Not a built in command char* programName = argv[0]; // Block sigchild signal sigset_t mask; Sigemptyset(&mask); Sigaddset(&mask, SIGCHLD); Sigprocmask(SIG_BLOCK, &mask, NULL); // Create a child process pid_t pid = Fork(); // Unblock sichild signal Sigprocmask(SIG_UNBLOCK, &mask, NULL); if (pid == 0) { // Child // Assign it a new process group id setpgid(0,0); // Run the external program Execve(programName, argv, environ); } else { // Parent if (background == 0) { // Add it to the list addjob(jobs, pid, FG, cmdline); // Make the shell wait for the process in the fg waitfg(pid); } else { // Add it to the list addjob(jobs, pid, BG, cmdline); // Get the job id int jid = pid2jid(pid); // Print info on background job printf("[%d] (%d) %s", jid, pid, cmdline); } } } return; }
/*错误处理函数*/ void error_handler(char * msg, char * msg2) { char * emptylist[] = { NULL }; setenv("QUERY_STRING", msg, 1); if (NULL == msg2) { setenv("QUERY_STRING2", "../index.htm", 1); } else { setenv("QUERY_STRING2", msg2, 1); } Execve("cgi-bin/error", emptylist, environ); }
void evalcmd(char *argv[], int bg) { int status; pid_t pid; if ((pid = Fork()) == 0) // run cmd as child Execve(argv[0], argv, environ); if (!bg) Waitpid(pid, &status, 0); else { Waitpid(pid, &status, WNOHANG); printf("%d %s\n", pid, argv[0]); } return; }
void misc() { char *bufp; int size=0; /* $begin execve */ Execve("a.out", NULL, NULL); /* $end execve */ /* $begin mmap */ bufp = Mmap(-1, size, PROT_READ, MAP_PRIVATE|MAP_ANON, 0, 0); /* $end mmap */ }
/* * serve_dynamic- run a CGI program on behalf of the client */ void serve_dynamic(int fd, char *filename, char *cgiargs) { char buf[MAXLINE], *emptylist[] = {NULL}; sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); if (Fork() == 0) { setenv("QUERY_STRING", cgiargs, 1); Dup2(fd, STDOUT_FILENO); Execve(filename, emptylist, environ); } Wait(NULL); }
/* * serve_dynamic - serve dynamic content */ void serve_dynamic(int connfd, char* filename, char* cgiargs) { char body[MAXBUF], *emptylist[] = {NULL}; /* send response headers to client */ sprintf(body, "HTTP/1.0 200 OK\r\n"); sprintf(body, "%sServer: Tiny Web Server\r\n", body); Rio_writen(connfd, body, strlen(body)); if (Fork() == 0) { /* fork a new child */ setenv("QUERY_STRING", cgiargs, 1); Dup2(connfd, STDOUT_FILENO); /* redirect stdout to connfd */ Execve(filename, emptylist, environ); } Wait(NULL); /* parent wait */ }
void serve_dynamic(int fd, char* filename, char* cgiargs) { char buf[MAXLINE], *emptylist[] = {NULL}; //return first part of HTTP response sprintf(buf, "HTTP/1.0 200 0k\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); if (Fork() == 0) { //child //real server would set all cgi vars here setenv("QUERY_STRING", cgiargs, 1); Dup2(fd, STDOUT_FILENO); // redirect stdout to client Execve(filename, emptylist, environ); //Run cgi program } Wait(NULL); //parent waits for and reaps child }
/* $begin serve_dynamic */ void serve_dynamic(int fd, char *filename, char *cgiargs) { char buf[MAXLINE], *emptylist[] = { NULL }; /* Return first part of HTTP response */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); if (Fork() == 0) { /* child */ //line:netp:servedynamic:fork /* Real server would set all CGI vars here */ setenv("QUERY_STRING", cgiargs, 1); //line:netp:servedynamic:setenv Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ //line:netp:servedynamic:dup2 Execve(filename, emptylist, environ); /* Run CGI program */ //line:netp:servedynamic:execve } Wait(NULL); /* Parent waits for and reaps child */ //line:netp:servedynamic:wait }
void serve_dynamic(int fd, char *filename, char *cgiargs) { char buf[MAXLINE], *emptylist[] = { NULL }; /* Return first part of HTTP response */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); if (Fork() == 0) { /* Child */ /* Real server would set all CGI vars here */ setenv("QUERY_STRING", cgiargs, 1); Dup2(fd, STDOUT_FILENO); /* 重定向标准输出 */ Execve(filename, emptylist, environ); /* Run CGI program */ } Wait(NULL); /* 等待子进程终止 */ }
/* $begin post_dynamic */ void post_dynamic(int fd, char *filename, int contentLength,rio_t *rp) { char buf[MAXLINE],length[32], *emptylist[] = { NULL },data[MAXLINE]; int p[2]; sprintf(length,"%d",contentLength); if(pipe(p)==-1) syslog(LOG_ERR,"cannot create pipe"); /* The post data is sended by client,we need to redirct the data to cgi stdin. * so, child read contentLength bytes data from fp,and write to p[1]; * parent should redirct p[0] to stdin. As a result, the cgi script can * read the post data from the stdin. */ if(!ishttps) /* https already read all data ,include post data by SSL_read() */ { if (Fork() == 0) { /* child */ close(p[0]); Rio_readnb(rp,data,contentLength); Rio_writen(p[1],data,contentLength); exit(0) ; } } else { } /* Send response headers to client */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); Dup2(p[0],STDIN_FILENO); /* Redirct p[0] to stdin */ close(p[0]); close(p[1]); setenv("CONTENT-LENGTH",length , 1); Dup2(fd,STDOUT_FILENO); /* Redirct stdout to client */ Execve(filename, emptylist, environ); }
/* $begin serve_dynamic */ void serve_dynamic(int fd, char *filename, char *cgiargs, rio_t *rp) { char buf[MAXLINE], *emptylist[] = { NULL }; /* Return first part of HTTP response */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); if (Fork() == 0) { /* child */ /* Real server would set all CGI vars here */ read_request(rp, cgiargs); setenv("QUERY_STRING", cgiargs, 1); fprintf(stderr, "%s: %s\r\n", "QUERY_STRING", cgiargs); Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ Execve(filename, emptylist, environ); /* Run CGI program */ } Wait(NULL); /* Parent waits for and reaps child */ }
void requestServeDynamic(int fd, char *filename, char *cgiargs) { char buf[MAXLINE], *emptylist[] = {NULL}; // The server does only a little bit of the header. // The CGI script has to finish writing out the header. sprintf(buf, "HTTP/1.0 200 OK\r\n"); sprintf(buf, "%sServer: CS537 Web Server\r\n", buf); Rio_writen(fd, buf, strlen(buf)); if (Fork() == 0) { /* Child process */ Setenv("QUERY_STRING", cgiargs, 1); /* When the CGI process writes to stdout, it will instead go to the socket */ Dup2(fd, STDOUT_FILENO); Execve(filename, emptylist, environ); } Wait(NULL); }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ int job_state; /* initial value of job BG or FG based on bg */ int status; int check; struct cmdline_tokens tok; pid_t pid = -255; // Initialzing to int jid = -255; // dummy values sigset_t mask; sigset_t mask2; int flag = 0; //Used while processing "fg" built in command int infile_fd ; //file descriptor to be used for infile if specified in job int outfile_fd ; //file descriptor to be used for outfile if specified in job //Get shell pid tsh_pid = getpid(); //Intialize mask for blocked signal //Block SIGCHLD SIGINT SIGTSTP signals Sigemptyset(&mask); Sigemptyset(&mask2); Sigaddset(&mask,SIGCHLD); Sigaddset(&mask,SIGINT); Sigaddset(&mask2,SIGINT); Sigaddset(&mask,SIGTSTP); Sigaddset(&mask2,SIGTSTP); Sigprocmask(SIG_BLOCK,&mask,NULL); /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) return; /* parsing error */ if (tok.argv[0] == NULL) return; /* ignore empty lines */ /* If tok is a BUILTIN shell command */ if (tok.builtins != BUILTIN_NONE) { switch(tok.builtins) { //Built in command quit : //Send SIGKILL to all processes in shell case BUILTIN_QUIT : tsh_pid = getpid(); kill(-tsh_pid,SIGKILL); break; //List out all jobs when "jobs" called //Also open output file if redirection specified and //redirect jobs output to the new file's descriptor case BUILTIN_JOBS : if (tok.outfile != NULL) { outfile_fd = open(tok.outfile , O_WRONLY); listjobs(job_list,outfile_fd); break; } else listjobs(job_list,STDOUT_FILENO); break; // Parse job id or pid given with bg command // Change state from ST to BG in job_list // Send SIGCONT signal to job case BUILTIN_FG : if(*(char *)(tok.argv[1]) == '%' ) { jid = atoi( (((char *)(tok.argv[1])) + 1) ); pid = jid2pid(jid); } else { pid = atoi(tok.argv[1]); jid = pid2jid(pid); } change_job_state(job_list,pid,FG); flag = 1; //flag set because we want to jump into else clause below // to process resumed job as a foreground job Kill(-pid,SIGCONT); break; //Parse job id or pid given with bg command // Change state from ST to BG in job_list // Send SIGCONT signal to job case BUILTIN_BG : if(*(char *)(tok.argv[1]) == '%' ) { jid = atoi( (((char *)(tok.argv[1])) + 1) ); pid = jid2pid(jid); } else { pid = atoi(tok.argv[1]); jid = pid2jid(pid); } printjob(pid,STDOUT_FILENO); change_job_state(job_list,pid,BG); Kill(-pid,SIGCONT); break; case BUILTIN_NONE : break; default : break; } } //If tok is a external program to be run by shell else if ((tok.builtins == BUILTIN_NONE) || (flag == 1)) { if (flag == 1) bg = 0; if(!bg) job_state = FG; else job_state = BG; //Child process if ((pid = Fork()) == 0) { setpgid(0,0); //Start process in new group Signal(SIGINT, SIG_DFL); /* ctrl-c from child handled by parent's sigchld */ addjob(job_list,getpid(),job_state,cmdline); // If input/output redirection specified open given file and point STDIN/STDOUT descriptor // to new file's file descriptor if (tok.infile != NULL) { infile_fd = open(tok.infile , O_RDONLY); dup2(infile_fd,STDIN_FILENO); } if (tok.outfile != NULL) { outfile_fd = open(tok.outfile , O_WRONLY); dup2(outfile_fd,STDOUT_FILENO); } //Unblock masks inherited from parent process //and execute program using exec Sigprocmask(SIG_UNBLOCK,&mask,NULL); Execve(tok.argv[0],tok.argv,environ); } //Parent process //Add child to job list and unblock signal,also set fg_pid if job is foreground job addjob(job_list,pid,job_state,cmdline); if(!bg) fg_pid = pid; Sigprocmask(SIG_UNBLOCK,&mask2,NULL); //Until foreground process terminates SIGCHLD functionality is done here , SIGINT and SIGTSTP are handled by handlers if(!bg) { check = waitpid(pid,&status,WUNTRACED); if ((check<0) && (errno!=ECHILD)) unix_error("waitfg : wait pid error\n"); if ((check == pid) && WIFSTOPPED(status)){ print_sigtstp_job(job_list,pid,SIGTSTP,STDOUT_FILENO); //Print message that job was stopped by SIGSTP signal //Change stopped job state in list to ST (stopped) change_job_state(job_list,pid,ST); return; } if ((check == pid) && (WIFSIGNALED(status))) print_sigint_job(job_list,pid,WTERMSIG(status),STDOUT_FILENO); //Print message that job/pid was terminated by a signal deletejob(job_list,pid); Sigprocmask(SIG_UNBLOCK,&mask,NULL); } else { Sigprocmask(SIG_UNBLOCK,&mask,NULL); printjob(pid,STDOUT_FILENO); } } return; }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ struct cmdline_tokens tok; /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) return; /* parsing error */ if (tok.argv[0] == NULL) return; /* ignore empty lines */ /* Built-in Command */ if (tok.builtins!=BUILTIN_NONE){ builtin_command(&tok); return; } /* Common tasks for both foreground and background */ pid_t pid; sigset_t mask; Sigemptyset(&mask); Sigaddset(&mask, SIGCHLD); Sigaddset(&mask, SIGINT); Sigaddset(&mask, SIGTSTP); /* Block signal receving in parent */ Sigprocmask(SIG_BLOCK, &mask, NULL); if ((pid=Fork())==0){ /* Unblock signal receiving in child */ Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Changes the child's process group from the shell's */ Setpgid(0,0); /* Change the input and output file descriptors */ IOredirection(&tok); Execve(tok.argv[0], tok.argv, environ); /* Command not found */ printf("Executable file not found\n"); exit(0); } /* Foreground job*/ if (!bg){ if (!addjob(job_list, pid, FG, cmdline)) return; Sigprocmask(SIG_UNBLOCK, &mask, NULL); wait_for_fg(pid); return; } /* Background job */ if (bg){ if (!addjob(job_list, pid, BG, cmdline)) return; Sigprocmask(SIG_UNBLOCK, &mask, NULL); printf("[%d] (%d) %s\n", pid2jid(pid), pid, cmdline); } return; }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ struct cmdline_tokens tok; pid_t cpid ; //child's pid sigset_t mask; sigset_t prev; int parseId; //prepare for the jid or pid in the future int state; struct job_t* job; //use for the fg or bg int infg = 0; //default STDIN int outfg = 1; //default STDOUT /* Create block signal */ Sigemptyset(&mask); /* block int stp child signal with the block signal*/ Sigaddset(&mask, SIGINT); Sigaddset(&mask, SIGTSTP); Sigaddset(&mask, SIGCHLD); /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) /* parsing error */ return; if (tok.argv[0] == NULL) /* ignore empty lines */ return; /* When there is a redirect input or output , change the value infg and out fg to the file */ if (tok.infile != NULL) { infg = Open(tok.infile, O_RDONLY, 0); } if (tok.outfile!=NULL) { outfg = Open(tok.outfile, O_WRONLY,0); } /* There are 5 situations: 1. Not a builtin command 2. Quit 3. list jobs 4. builtin foreground jobs 5. builtin background jobs */ switch (tok.builtins) { case BUILTIN_NONE: //we need to fork and create a child process Sigprocmask(SIG_BLOCK, &mask, &prev); if ((cpid=Fork())==0) { //in the child process //we should unblock all signals Sigprocmask(SIG_UNBLOCK, &mask, NULL); cpid = getpid(); //set child process group to avoid race condition setpgid(cpid,cpid); Sigprocmask(SIG_SETMASK, &prev, NULL); //set the in and out direction if(infg != 0){ Dup2(infg, 0); Close(infg); } if (outfg != 1) { Dup2(outfg, 1); Close(outfg); } //process the outside command Execve(tok.argv[0], tok.argv, environ); }else{ //in the parent process //determin whether it is a bg or fg if (bg==1) { state = BG; } else{ state = FG; } //add the job to job list addjob(job_list, cpid, state, cmdline); //get the job from job list by pid job = getjobpid(job_list, cpid); //unblock all signal Sigprocmask(SIG_UNBLOCK, &mask, NULL); //use while to //set the shell wait until the job is stp or killed if(state == FG){ while (fgpid(job_list)!=0) { Sigsuspend(&prev); } } else{ //if bg, print the background job printf("[%d] (%d) %s\n",job->jid, job->pid,cmdline); } } break; case BUILTIN_QUIT: //use the exit function exit(0); break; case BUILTIN_JOBS: //use the listjobs function listjobs(job_list, outfg); break; case BUILTIN_BG: //get the jid if (tok.argv[1][0]=='%') { parseId = atoi(&tok.argv[1][1]); job = getjobjid(job_list, parseId); } //or get the pid else if ((tok.argv[1][0] >= '0')&&(tok.argv[1][0]<='9')) { parseId = atoi(&tok.argv[1][0]); job = getjobpid(job_list, (pid_t)parseId); } printf("[%d] (%d) %s\n",job->jid, job->pid,job->cmdline); //set the job state to BG job->state = BG; //send SIGCONT Kill(-(job->pid), SIGCONT); break; case BUILTIN_FG: //get jid if (tok.argv[1][0]=='%') { parseId = atoi(&tok.argv[1][1]); job = getjobjid(job_list, parseId); } //get pid else if ((tok.argv[1][0] >= '0')&&(tok.argv[1][0]<='9')) { parseId = atoi(&tok.argv[1][0]); job = getjobpid(job_list, (pid_t)parseId); } //set the job state to FG job->state = FG; //send SIGCONT Kill(-(job->pid), SIGCONT); break; default: break; } return; }
/* $begin post_dynamic */ static void post_dynamic(int fd, char *filename, int contentLength,rio_t *rp) { char buf[MAXLINE],length[32], *emptylist[] = { NULL },data[MAXLINE]; int p[2]; #ifdef HTTPS int httpsp[2]; #endif sprintf(length,"%d",contentLength); memset(data,0,MAXLINE); Pipe(p); /* The post data is sended by client,we need to redirct the data to cgi stdin. * so, child read contentLength bytes data from fp,and write to p[1]; * parent should redirct p[0] to stdin. As a result, the cgi script can * read the post data from the stdin. */ /* https already read all data ,include post data by SSL_read() */ if (Fork() == 0) { /* child */ Close(p[0]); #ifdef HTTPS if(ishttps) { Write(p[1],httpspostdata,contentLength); } else #endif { Rio_readnb(rp,data,contentLength); Rio_writen(p[1],data,contentLength); } exit(0) ; } /* Send response headers to client */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); sprintf(buf, "%sServer: Tiny Web Server\r\n",buf); #ifdef HTTPS if(ishttps) SSL_write(ssl,buf,strlen(buf)); else #endif Rio_writen(fd, buf, strlen(buf)); //Wait(NULL); Dup2(p[0],STDIN_FILENO); /* Redirct p[0] to stdin */ Close(p[0]); Close(p[1]); setenv("CONTENT-LENGTH",length , 1); #ifdef HTTPS if(ishttps) /* if ishttps,we couldnot redirct stdout to client,we must use SSL_write */ { Pipe(httpsp); if(Fork()==0) { Dup2(httpsp[1],STDOUT_FILENO); /* Redirct stdout to https[1] */ Execve(filename, emptylist, environ); } //Wait(NULL); Read(httpsp[0],data,MAXLINE); SSL_write(ssl,data,strlen(data)); } else #endif { Dup2(fd,STDOUT_FILENO); /* Redirct stdout to client */ Execve(filename, emptylist, environ); } }
/* * eval - Evaluate the command line that the user has * just typed in * * If the user has requested a built-in command (quit, jobs, * bg or fg) then execute it immediately. Otherwise, fork a * child process and run the job in the context of the child. * If the job is running in the foreground, wait for it to * terminate and then return. * * Note: each child process must have a unique process * group ID so that our background children don't receive * SIGINT (SIGSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { char *argv[MAXARGS], buf[MAXLINE]; int bg, status, state; volatile pid_t pid; int jid; sigset_t mask_all, mask_one, prev_one; Log("EVAL [0]\n", 9); strcpy(buf, cmdline); bg = parseline(buf, argv); if (argv[0] == NULL) { return; } Log("EVAL [1]\n", 9); if (builtin_cmd(argv)) { return; } Log("EVAL [2]\n", 9); Sigfillset(&mask_all); Sigemptyset(&mask_one); Sigaddset(&mask_one, SIGCHLD); Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); pid = Fork(); if (pid == CHILD) { Sigprocmask(SIG_SETMASK, &prev_one, NULL); Setpgid(0, 0); Log("EVAL [3]\n", 9); Execve(argv[0], argv, environ); } Sigprocmask(SIG_BLOCK, &mask_all, NULL); state = bg ? BG : FG; Log("EVAL [4]\n", 9); status = addjob(jobs, pid, state, cmdline); Log("EVAL [5]\n", 9); /* Stores jid while process has not been removed */ jid = getjobpid(jobs, pid)->jid; atomic_fggpid = bg ? 0 : pid; Log("EVAL [5a]\n", 10); Sigprocmask(SIG_SETMASK, &prev_one, NULL); Log("EVAL [5b]\n", 10); /* Handle errors when generating a new job */ if (!status) { return; } /* Parent waits for foreground job to terminate */ if (!bg) { Log("EVAL [6]\n", 9); waitfg(pid); } else { Log("EVAL [7]\n", 9); printf("[%d] (%d) %s", jid, pid, cmdline); } }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ struct cmdline_tokens tok; pid_t pid; sigset_t mask; /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) return; /* parsing error */ if (tok.argv[0] == NULL) return; /* ignore empty lines */ sigemptyset(&mask); sigaddset(&mask,SIGCHLD); sigaddset(&mask,SIGINT); sigaddset(&mask,SIGTSTP); sigprocmask(SIG_BLOCK,&mask,NULL); if(!builtin_handler(tok)) { if((pid=Fork())==0) { /*restore default handlers*/ Signal(SIGINT,SIG_DFL); Signal(SIGTSTP,SIG_DFL); sigprocmask(SIG_UNBLOCK,&mask,NULL); /*Put child process in its own group*/ Setpgid(0,0); IO_redirection(tok); Execve(tok.argv[0],tok.argv,environ); } else /*Shell Processing*/ { if(bg) { addjob(job_list,pid,BG,cmdline); printf("[%d] (%d) %s\n", pid2jid(pid), pid, cmdline); sigprocmask(SIG_UNBLOCK,&mask,NULL); } else { addjob(job_list,pid,FG,cmdline); sigprocmask(SIG_UNBLOCK,&mask,NULL); while(fgpid(job_list) != 0) { } } } } }
int main(int argc, char **argv) { Execve("/bin/ls", argv, environ); exit(0); }