int fork_pipes (int n, struct command *cmd) { int i; pid_t pid; int in, fd [2]; /* The first process should get its input from the original file descriptor 0. */ in = 0; /* Note the loop bound, we spawn here all, but the last stage of the pipeline. */ for (i = 0; i < n - 1; ++i) { pipe (fd); /* f [1] is the write end of the pipe, we carry `in` from the prev iteration. */ spawn_proc (in, fd [1], cmd + i); /* No need for the write end of the pipe, the child will write here. */ close (fd [1]); /* Keep the read end of the pipe, the next child will read from there. */ in = fd [0]; } /* Last stage of the pipeline - set stdin be the read end of the previous pipe and output to the original file descriptor 1. */ if (in != 0) dup2 (in, 0); /* Execute the last stage with the current process. */ return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv); }
int handle_start_proc(struct request * r) { fprintf(stderr, "starting proc\n"); struct child_process * c = make_child_proc((struct svc_packet *)r->data); if (0 == c) { fprintf(stderr, "failed to created child process structure\n"); return -1; } else { if (c->start_calendar_interval) { struct timeval now; gettimeofday(&now, 0); c->last_restart = *(next_start(&now, c->start_calendar_interval)); queue_proc(c); } else { fprintf(stderr, "starting proc %s\n", c->label); gettimeofday(&c->last_restart, 0); spawn_proc(c); } return 0; } }
/* Helper function that forks pipes */ static void fork_pipes(int n, struct command *cmd) { int i; int in = 0; int fd[2]; for (i = 0; i < n - 1; ++i) { pipe(fd); spawn_proc(in, fd[1], cmd + i); close(fd[1]); in = fd[0]; } if (dup2(in, 0) < 0) { err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]); } fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd[i].argv[0]); execvp(cmd[i].argv[0], cmd[i].argv); err_syserr("failed to execute %s: ", cmd[i].argv[0]); }
int main(int argc, char * argv[]) { int fd; struct sigaction sig; struct passwd * pwd = 0; if (argc == 2) { if (argv[1]) { errno = 0; pwd = getpwnam(argv[1]); if (0 == pwd) { fprintf(stderr, "getpwnam failed: %s\n", strerror(errno)); while(1) { pause(); } } } } if (pwd) { sprintf(process_manager_run_dir, "/run/process-manager.%s", pwd->pw_name); sprintf(process_manager_socket_path, "/run/process-manager.%s/procman", pwd->pw_name); } else { sprintf(process_manager_run_dir, "/run/process-manager"); sprintf(process_manager_socket_path, "/run/process-manager/procman"); we_are_root = 1; } (void)fprintf(stderr, "process-manager: process-manager starting...\n"); memset(&sig, 0, sizeof(sig)); sigfillset(&sig.sa_mask); sig.sa_flags = SA_SIGINFO; sig.sa_sigaction = handle_sigterm; sigaction(SIGTERM, &sig, 0); memset(&sig, 0, sizeof(sig)); sigfillset(&sig.sa_mask); sig.sa_flags = SA_SIGINFO; sig.sa_sigaction = handle_sigchild; sigaction(SIGCHLD, &sig, 0); memset(&sig, 0, sizeof(sig)); sigfillset(&sig.sa_mask); sig.sa_flags = SA_SIGINFO; sig.sa_sigaction = handle_sigalarm; sigaction(SIGALRM, &sig, 0); fd = open("/dev/console", O_RDWR | O_NOCTTY); if (fd >= 0) { dup2(fd,0); dup2(fd,1); dup2(fd,2); if (fd > 2) close(fd); (void)fprintf(stderr, "process-manager: console reopened...\n"); } else { (void)fprintf(stderr, "failed to open console"); } if (we_are_root) { struct stat stat_buf; memset(&stat_buf, 0, sizeof(stat_buf)); if (-1 == stat("/run/process-manager", &stat_buf)) { fprintf(stderr, "expected stat error: %s\n", strerror(errno)); if (-1 == mount("none", "/run", "tmpfs", 0, 0)) { fprintf(stderr, "failed to mount tmpfs on /run: %s\n", strerror(errno)); while(1) pause(); } fprintf(stderr, "we are root\n"); if (-1 == mkdir("/run/process-manager", 0770)) { fprintf(stderr, "failed to make dir /run/process-manager: %s\n", strerror(errno)); while(1) pause(); } struct group * g = getgrnam("process-manager"); if (g) { if (-1 == chown("/run/process-manager", -1, g->gr_gid)) fprintf(stderr, "chown gid %d failed: %s\n", g->gr_gid, strerror(errno)); if (-1 == chmod("/run/process-manager", S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP |S_IXGRP)) fprintf(stderr, "chmod failed: %s\n", strerror(errno)); } else { fprintf(stderr, "getgrnam process-manager failed: %s\n", strerror(errno)); } } } else { mkdir(process_manager_run_dir, 0700); if (-1 == chown(process_manager_run_dir, pwd->pw_uid, pwd->pw_gid)) fprintf(stderr, "chown failed: %s\n", strerror(errno)); } running = malloc(sizeof(*running)); memset(running, 0, sizeof(*running)); running->next = running; waiting = malloc(sizeof(*waiting)); memset(waiting, 0, sizeof(*waiting)); waiting->next = waiting; waiting->pid = 0x7fffffff; waiting->last_restart.tv_sec = 0x7fffffffffffffff; inactive = malloc(sizeof(*inactive)); memset(inactive,0 ,sizeof(*inactive)); inactive->next = inactive; struct sockaddr_un ctl_un; pid_t ctl_pid; socklen_t ctl_len; int ctl_p_endp = launch_control_proc(pwd, process_manager_socket_path, &ctl_un, &ctl_len, &ctl_pid); if (ctl_p_endp < 0) //socket already exists and another instance is running { fprintf(stderr, "socket in use, ctl_p_endp: %d\n", ctl_p_endp); return 1; } if (we_are_root) spawn_proc(&arbitrator); while(0 == run_state) { int status; pid_t child_pid = -1; struct child_process * proc; unsigned char restart_proc = 0; if (waiting->next == waiting) { alarm(0); } else { struct timeval now; gettimeofday(&now, 0); alarm(waiting->next->last_restart.tv_sec - now.tv_sec); } timeout = 0; fprintf(stderr, "waiting for exiting childern...\n"); unsigned char data[1024]; unsigned int len = sizeof(data); if (-1 == recvfrom(ctl_p_endp, data, len, 0, &ctl_un, &ctl_len)) { if (errno == EINTR) { fprintf(stderr, "process-manager: signal received: %d, run_state == %d\n", signum, run_state); if (timeout) { timeout = 0; struct timeval now; gettimeofday(&now, 0); fprintf(stderr, "we got timeout. next timeout %ld, it is now %ld\n", waiting->next->last_restart.tv_sec, now.tv_sec); while(waiting->next->last_restart.tv_sec <= now.tv_sec) { struct child_process * c = dequeue_proc(); fprintf(stderr, "restarting queued proc %s\n", c->label); spawn_proc(c); } } if (got_sigchild) { got_sigchild = 0; while((child_pid = waitpid(-1, &status, WNOHANG))) { if (child_pid < 0) { fprintf(stderr, "failed to get child status: %s\n", strerror(errno)); if (EINTR != errno) break; } else { proc = get_process(child_pid); child_pid = -1; if (proc) { kill(-proc->pid, SIGTERM); restart_proc = 0; if (proc->start_calendar_interval) { struct timeval now; gettimeofday(&now, 0); proc->last_restart = *(next_start(&now, proc->start_calendar_interval)); queue_proc(proc); } else if (proc->keepalive_opts) { int i = 0; while(proc->keepalive_opts[i]) { fprintf(stderr, "keepalive opts %d:%d\n", proc->keepalive_opts[i], proc->keepalive_opts[i + 1]); if (SUCCESSFUL_EXIT == proc->keepalive_opts[i]) { if (0 < proc->keepalive_opts[i + 1]) { if (WIFEXITED(status)) { restart_proc |= 1; } } else { if (WIFSIGNALED(status)) { restart_proc |= 1; } } } i += 2; } } if (restart_proc) { fprintf(stderr, "restarting %s, exec file %s\n", proc->label, proc->exec_file_path); struct timeval now; gettimeofday(&now, 0); fprintf(stderr, "%s last restart %ld it is now %ld\n", proc->label, proc->last_restart.tv_sec, now.tv_sec); if ((proc->last_restart.tv_sec + 10) < now.tv_sec) { gettimeofday(&proc->last_restart, 0); spawn_proc(proc); fprintf(stderr, "spawn %s pid %d\n", proc->exec_file_path, proc->pid); } else { if (proc->throttle_count < 40) { fprintf(stderr, "throttling %s\n", proc->label); gettimeofday(&proc->last_restart, 0); proc->last_restart.tv_sec += 10; proc->throttle_count++; fprintf(stderr, "%s throttle_count %d restart at %ld\n", proc->label, proc->throttle_count, proc->last_restart.tv_sec); queue_proc(proc); } else { fprintf(stderr, "%s exceeded throttle limit\n", proc->label); destroy_proc_struct(proc); } } } else { if (WIFEXITED(status)) fprintf(stderr, "process %s:%d %s exited with %d\n", proc->label, proc->pid, proc->exec_file_path, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) fprintf(stderr, "process %s:%d signaled with %d\n", proc->label, proc->pid, WTERMSIG(status)); destroy_proc_struct(proc); } } } } } } else { fprintf(stderr, "recvfrom failed: %s\n", strerror(errno)); sleep(3); } } else { handle_data(data, len); } } unsigned char any_child_exists = 1; int status = 0; fprintf(stderr, "sending SIGTERM to all children...\n"); struct child_process * v = running->next; while(running != v) { if (-1 == kill(-v->pid, SIGTERM)) { fprintf(stderr, "process-manager: kill process group %d failed: %s\n", -v->pid, strerror(errno)); if (-1 == kill(v->pid, SIGTERM)) { fprintf(stderr, "process-manager: kill %d failed: %s\n", v->pid, strerror(errno)); } } v = v->next; } kill(ctl_pid, SIGTERM); alarm(5); while (any_child_exists) { pid_t child = wait(&status); if (0 > child) { if (ECHILD == errno) { any_child_exists = 0; fprintf(stderr, "process-manager: no more children left...\n"); } else if (EINTR == errno) { if (timeout) { timeout = 0; any_child_exists = 0; } } } } alarm(0); sleep(1); close(ctl_p_endp); unlink(process_manager_socket_path); return 0; }
int executePipe( int no_of_pipes, char *com, int redirectFlag,char *homedir) { pc *pcmd=malloc(100 * sizeof(pc)); int fd[2]; int isFirstPipe=1; int count = 0; char *commandline=malloc(1024*sizeof(char)); strcpy(commandline,com); char *command=malloc(1024*sizeof(char)); char **argv=malloc ( 100 * sizeof(char)); //Number of tokens there can be char *token=malloc(1024*sizeof(char)); int i=0,j=0; command = strtok ( com,"|"); //first command while( command!=NULL) { pcmd[i].argv=command; pcmd[i].redirectFlag=isRedirect(command); command = strtok (NULL, "|"); i++; } //Tokenise command for execution //parseCommand(pcmd[0].argv,argv); int in=0; for(i=0;i<no_of_pipes;i++) { pipe(fd); spawn_proc(in,fd[1],pcmd[i],pcmd[i].redirectFlag,homedir); close(fd[1]); in=fd[0]; } if(in!=0) dup2(in,0); //last command infile=0; outfile=0; int random=isRedirect(pcmd[i].argv); int no_of_tokens=parseCommand(pcmd[i].argv,argv,pcmd[i].redirectFlag); int std_out=dup(1); if(outfile!=0) { int fd1; if(outfile==1) { fd1=open(output,O_CREAT|O_RDWR|O_TRUNC,00666); lseek(fd1, 0, SEEK_SET); } else if(outfile==2) { fd1=open(output,O_APPEND|O_CREAT|O_RDWR,00666); } if(fd1==-1) { fprintf(stderr, "Can't open file for output 1!\n"); memset(output, 0, 10); outfile=0; return; } dup2(fd1,STDOUT_FILENO); close(fd1); memset(output, 0, 10); outfile=0; //redirectFlag=0; } if(infile==3) { int fd2; fd2=open(inputfile,O_RDWR,00666); if(fd2==-1) { fprintf(stderr, "Can't open file for input! 3\n"); memset(inputfile, 0, 10); infile=0; return; } dup2(fd2,STDIN_FILENO); close(fd2); memset(inputfile, 0, 10); infile=0; //redirectFlag=0; } if(isBuiltInCommand(argv[0])==1) { job_no++; addJob(0,argv[0],0,job_no); executeBuiltInCommand(argv[0],argv,no_of_tokens,homedir); _exit(1); dup2(std_out,1); return(0); } else return(execvp(argv[0],argv)); }