📄 ecufork.c
字号:
/*+------------------------------------------------------------------------- ecufork.c -- ecu spawning ground wht@n4hgf.Mt-Park.GA.US Defined functions: exec_cmd(cmdstr) expand_wildcard_list(wild,expcmd) find_executable(progname) is_executable(progname) shell(shellcmd) smart_fork()--------------------------------------------------------------------------*//*+:EDITS:*//*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 *//*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA *//*:04-29-1992-13:29-wht@n4hgf-ignore SIGQUIT when in executing a child *//*:09-25-1991-18:02-wht@n4hgf2-find_executable flunks directories now *//*:09-06-1991-04:20-wht@n4hgf2-expand_wildcard_list minor bug *//*:08-29-1991-01:56-wht@n4hgf2-use max esd size instead of 5120 *//*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 *//*:07-17-1991-07:04-wht@n4hgf-avoid SCO UNIX nap bug *//*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller *//*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */#include "ecu.h"#include "esd.h"#include "ecufork.h"extern int last_child_wait_status;extern int last_child_wait_pid;#ifdef M_I286#define MAX_EXEC_ARG 512#else#if defined(M_UNIX) || defined(ISC)#define MAX_EXEC_ARG 1024#else#define MAX_EXEC_ARG 2048#endif /* M_UNIX || ISC */#endif /* M_I286 *//*+------------------------------------------------------------------------- smart_fork()--------------------------------------------------------------------------*/intsmart_fork(){ register int count = 5; register int pid; while(count--) { if((pid = fork()) >= 0) return(pid); if(count) Nap(40L); } return(-1);} /* end of smart_fork *//*+----------------------------------------------------------------------- shell(shellcmd) param 'shellcmd' is a shell command prefixed with either a '!', '$', '>' character. '!' causes the command to run as a normal subshell of a process. '$' causes the communications line to be stdin and stdout for the spawned shell '>' causes spawned shell to receive exactly sames files as ecu------------------------------------------------------------------------*/voidshell(shellcmd)char *shellcmd;{ register shellpid; register itmp; register char *cptr;#if defined(FORK_DEBUG) char s40[40];#endif int wait_status; int restart_rcvr = need_rcvr_restart(); char *getenv(); kill_rcvr_process(SIGUSR1); /* stop receiver process gracefully */ signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGUSR1,SIG_IGN); signal(SIGUSR2,SIG_IGN); signal(SIGCLD,SIG_DFL); if((shellpid = smart_fork()) < 0) { ff(se,"Cannot fork\r\n"); if(restart_rcvr) start_rcvr_process(1); xmtr_signals(); return; } ttymode(0); /* set canonical tty mode */ if(shellpid == 0) /* we are the spawned (going to call shell) */ { if(*shellcmd != '>') /* '>' prefix means leave fd's alone! */ { /* Hook-up our "standard output" to either the tty or * the line as appropriate for '!' or '$' */ close(TTYOUT); fcntl(((*shellcmd == '$') ? shm->Liofd : TTYERR),F_DUPFD,TTYOUT); if(*shellcmd == '$') { close(TTYIN); fcntl(shm->Liofd,F_DUPFD,TTYIN); } close(shm->Liofd); } child_signals(); /* signals for child */ if(*shellcmd == '!') { cptr = getenv("SHELL"); if(cptr == (char *)0) cptr = "/bin/csh"; } else cptr = "/bin/sh"; shellcmd++; child_signals(); if(ulindex(cptr,"csh") > -1) { if(*shellcmd == '\0') execl(cptr,"csh",(char *)0); else execl(cptr,"csh","-c",shellcmd,(char *)0); } else { if(*shellcmd == '\0') execl(cptr,"sh",(char *)0); else execl(cptr,"sh","-c",shellcmd,(char *)0); } ff(se,"cannot execute %s\r\n",cptr); /* should not get here */ _exit(255); /* end of spawned process */ } /* end of if child process */#if defined(FORK_DEBUG) sprintf(s40,"DEBUG fork shell pid %d",shellpid); ecu_log_event(getpid(),s40); /* shell */#endif while(((itmp = wait(&wait_status)) != shellpid) && (itmp != -1)) ; last_child_wait_status = wait_status; last_child_wait_pid = shellpid; xmtr_signals(); /* restore standard xmtr signals */ ttymode(1); /* control tty back to raw mode *//* any comm program will probably doodle with the line characteristics. *//* we want to make sure they are restored to normal */ lreset_ksr(); /* restore comm line params */ if(restart_rcvr) start_rcvr_process(1);} /* end of shell *//*+------------------------------------------------------------------------- is_executable(progname)--------------------------------------------------------------------------*/is_executable(progname)char *progname;{ struct stat ss; if(stat(progname,&ss) < 0) /* if cannot stat, flunk */ return(0); if((ss.st_mode & 0111) == 0) /* if no --x--x--x, flunk */ return(0); if((ss.st_mode & S_IFMT) != S_IFREG)/* if no --x--x--x, flunk */ return(0); return(1); /* whew, this OUGHT to work */} /* end of is_executable *//*+------------------------------------------------------------------------- find_executable(progname)PATH=':/usr/wht/bin:/bin:/usr/bin:/usr/wht/bin:/etc/tuckerware' len=56--------------------------------------------------------------------------*/char *find_executable(progname)char *progname;{ register itmp; static char *path_buf = (char *)0;#define PATHNAME_QUAN 32 static char *path_name[PATHNAME_QUAN + 1]; static char rtn_path[256]; static int path_count = 0; char *cptr; char *getenv(); if(path_buf == (char *)0) { if((cptr = getenv("PATH")) == (char *)0) return(cptr); if(!(path_buf = malloc(strlen(cptr) + 1))) return((char *)0); strcpy(path_buf,cptr); path_name[PATHNAME_QUAN + 1] = (char *)0; cptr = path_buf; for(path_count = 0; path_count < PATHNAME_QUAN; path_count++) { if(*cptr == 0) break; path_name[path_count] = cptr; while((*cptr != ':') && (*cptr != 0)) cptr++; if(*cptr == ':') *cptr++ = 0; } } /* end of get and process path env variable *//* look for executable */ for(itmp = 0; itmp < path_count; itmp++) { if(*path_name[itmp] == 0) /* if null path (./) */ strcpy(rtn_path,"./"); else sprintf(rtn_path,"%s/",path_name[itmp]); strcat(rtn_path,progname); if(is_executable(rtn_path)) return(rtn_path); } return((char *)0);} /* end of find_executable *//*+------------------------------------------------------------------------- exec_cmd(cmdstr) - execute an arbitrary program with argumentskills rcvr process if alive and restarts it when done if was alive--------------------------------------------------------------------------*/exec_cmd(cmdstr)char *cmdstr;{ char *cmdpath; char *cmdargv[MAX_EXEC_ARG]; int itmp; int execpid; int restart_rcvr = need_rcvr_restart(); int old_ttymode = get_ttymode(); int wait_status = 0; char *strrchr();#if defined(FORK_DEBUG) char s80[80]; strcpy(s80,"DEBUG exec "); strncat(s80,cmdstr,sizeof(s80)-12); s80[sizeof(s80)-12] = 0; ecu_log_event(getpid(),s80);#endif build_arg_array(cmdstr,cmdargv,MAX_EXEC_ARG,&itmp); if(itmp == MAX_EXEC_ARG) { ff(se,"Too many arguments to command\r\n"); return(-1); } else if(!itmp) { ff(se,"null command\r\n"); return(-1); } if(*cmdargv[0] == '/') { cmdpath = cmdargv[0]; cmdargv[0] = strrchr(cmdargv[0],'/') + 1; } else { if((cmdpath = find_executable(cmdargv[0])) == (char *)0) { ff(se,"Cannot find %s\r\n",cmdargv[0]); return(-1); } } kill_rcvr_process(SIGUSR1); /* stop receiver process gracefully *//* this code executed by the father (forking) process *//* wait on death of child (morbid in life, but ok here) */ signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGUSR1,SIG_IGN); signal(SIGUSR2,SIG_IGN); signal(SIGCLD,SIG_DFL); if((execpid = smart_fork()) < 0) { ff(se,"Cannot fork\r\n"); if(restart_rcvr) start_rcvr_process(1); xmtr_signals(); return(-1); } if(execpid == 0) /* we are the spawned (going to call exec) */ { ttymode(0); /* set canonical tty mode */ child_signals(); execv(cmdpath,cmdargv); perror(cmdpath); _exit(255); /* end of spawned process */ } /* end of if child process */ wait_status = 0; while(((itmp = wait(&wait_status)) != execpid) && (itmp != -1)) ; last_child_wait_status = wait_status; last_child_wait_pid = execpid;/* resume our normally scheduled program */ lreset_ksr(); /* restore comm line params */ ttymode(old_ttymode); /* control tty back to original */ if(restart_rcvr) start_rcvr_process(1); xmtr_signals(); return(last_child_wait_status);} /* end of exec_cmd *//*+------------------------------------------------------------------------- expand_wildcard_list(wild,&expcmd)called with 'foo <wildcardlist>' for command expansion prior to exec() or '<wildcardlist>' to expand a list of files.If called with 'foo'-style wild, anything you want to protect from csh globbing or other interpretation must be properly protected (quoted) --AND quoting will be removed one level by the csh.if return 0, wild has been expanded, expcmd must be free()'d when doneif return -1, error, expcmd has error message (static message: DO NOT FREE)--------------------------------------------------------------------------*/expand_wildcard_list(wild,expcmd)char *wild;char **expcmd;{ register char *cptr;#define P_READ 0#define P_WRITE 1 PID_T pipe_pid; int stdout_pipe[2]; int stderr_pipe[2]; int count; int expcmd_size = 0; int itmp; int wait_status; int restart_rcvr = need_rcvr_restart(); FILE *fp_pipe = (FILE *)0; char *echo_cmd; static char s132[132]; char *strchr(); static char *pipe_err_msg = "system error: no pipe"; static char *mem_err_msg = "system error: no memory"; if(strchr(wild,'<') || strchr(wild,'>') || strchr(wild,'&')) { *expcmd = "illegal characters: '<', '>' or '&'"; return(-1); } if(pipe(stdout_pipe) < 0) { *expcmd = pipe_err_msg; return(-1); } if(pipe(stderr_pipe) < 0) { close(stdout_pipe[P_READ]); close(stdout_pipe[P_WRITE]); *expcmd = pipe_err_msg; return(-1); } if(!(echo_cmd = malloc(strlen(wild) + 10))) { close(stdout_pipe[P_READ]); close(stdout_pipe[P_WRITE]); close(stderr_pipe[P_READ]); close(stderr_pipe[P_WRITE]); *expcmd = mem_err_msg; return(-1); } strcpy(echo_cmd,"echo "); strcat(echo_cmd,wild); kill_rcvr_process(SIGUSR1); /* stop receiver process gracefully */ signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGUSR1,SIG_IGN); signal(SIGUSR2,SIG_IGN); signal(SIGCLD,SIG_DFL); if((pipe_pid = smart_fork()) == 0) { int null = open("/dev/null",O_WRONLY,0); close(stdout_pipe[P_READ]); close(TTYOUT); dup(stdout_pipe[P_WRITE]); close(stdout_pipe[P_WRITE]); close(TTYERR); dup(stderr_pipe[P_WRITE]); close(stderr_pipe[P_WRITE]); close(null); child_signals();#ifdef linux /* Most Linux systems don't have a csh */ execl("/bin/sh","sh","-c",echo_cmd,(char *)0);#else execl("/bin/csh","csh","-e","-f","-c",echo_cmd,(char *)0);#endif _exit(255); }#if defined(FORK_DEBUG) sprintf(s132,"DEBUG expand pid %d",pipe_pid); ecu_log_event(getpid(),s132); /* expand_wildcard_list */#endif free(echo_cmd); close(stdout_pipe[P_WRITE]); close(stderr_pipe[P_WRITE]); if(pipe_pid == -1) { close(stdout_pipe[P_READ]); close(stderr_pipe[P_READ]); *expcmd = "could not fork"; if(restart_rcvr) start_rcvr_process(0); xmtr_signals(); return(-1); } if(!(*expcmd = malloc(expcmd_size = ESD_MAXSIZE))) { close(stdout_pipe[P_READ]); close(stderr_pipe[P_READ]); kill(pipe_pid,SIGKILL); *expcmd = mem_err_msg; if(restart_rcvr) start_rcvr_process(0); xmtr_signals(); return(-1); } if(!(fp_pipe = fdopen(stdout_pipe[P_READ],"r")) || ((count = fread(*expcmd,1,expcmd_size,fp_pipe)) < 0)) { free(*expcmd); kill(pipe_pid,SIGKILL); close(stdout_pipe[P_READ]); close(stderr_pipe[P_READ]); *expcmd = "error reading wild list expansion"; if(restart_rcvr) start_rcvr_process(0); xmtr_signals(); return(-1); } /* * make sure stdout is closed */ if(fp_pipe) fclose(fp_pipe); close(stdout_pipe[P_READ]); /* * place trailing null * kill trailing new line */ if(count) { cptr = (*expcmd) + count; *cptr-- = 0; if(*cptr == '\n') { *cptr = 0; count--; } } /* * if no expansion, read stderr to find out why */ if(!count) { free(*expcmd); count = read(stderr_pipe[P_READ],s132,sizeof(s132) - 1); if(count < 0) strcpy(s132,errno_text(errno)); else s132[count] = 0; if(s132[count - 1] == '\n') s132[count - 1] = 0; close(stderr_pipe[P_READ]); if(strncmp(s132,"echo: ",6)) *expcmd = s132; else *expcmd = s132 + 6; if(restart_rcvr) start_rcvr_process(0); return(-1); } /* * clean up zombie */ wait_status = 0; while(((itmp = wait(&wait_status)) != pipe_pid) && (itmp != -1)) ; xmtr_signals(); /* * if bad termination status, read stderr */ if(wait_status) { free(*expcmd); count = read(stderr_pipe[P_READ],s132,sizeof(s132) - 1); if(count < 0) strcpy(s132,errno_text(errno)); else s132[count] = 0; if(s132[count - 1] == '\n') s132[count - 1] = 0; close(stderr_pipe[P_READ]); if(strncmp(s132,"echo: ",6)) *expcmd = s132; else *expcmd = s132 + 6; if(restart_rcvr) start_rcvr_process(0); return(-1); } close(stderr_pipe[P_READ]); /* * whew: we have (I think) a file list expansion */ if(restart_rcvr) start_rcvr_process(0); return(0);} /* end of expand_wildcard_list *//* vi: set tabstop=4 shiftwidth=4: *//* end of ecufork.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -