spawn.c
来自「俄罗斯高人Mamaich的Pocket gcc编译器(运行在PocketPC上)」· C语言 代码 · 共 415 行
C
415 行
#include <stdlib.h>#include <stddef.h>#include <stdio.h>#include <errno.h>#include <sys/wcebase.h>#include <sys/wceerror.h>#include <sys/wcetrace.h>#include <sys/wcefile.h>#include <sys/wcethread.h>#include <sys/wcememory.h>#include <sys/shared.h>#include <sys/spawn.h>#include <sys/io.h>#define BUFSIZE 256extern char **environ;static int Pgid = 1;extern int __pgid;static DWORD LastPID=-1;static DWORD LastExitCode=-1;extern int __IsForkChild;void _done_exec(pid_t pid);intgetpgid(int pid){ return(__pgid);}intnewpgid(){ return(Pgid++);}intsetpgid(int pid, int pgid){ if (pgid == 0) { __pgid = Pgid++; } else { __pgid = pgid; } return(__pgid);}char **_argvcopy(char **argv, int *argc){ int i; char **newargv; /* Initial set up */ if (argv == NULL) { *argc = 0; } else { for (i = 0; argv[i] != NULL; i++); *argc = i; } /* 2 + terminating NULL entry */ *argc += 3; /* Allocate and copy */ newargv = calloc(*argc, sizeof(char **)); if (argv != NULL) { for (i = 0; argv[i] != NULL; i++) { newargv[i] = argv[i]; } } return(newargv);}int_spawnv(char *command, char *argv[], int pgid, int infd, int outfd, int errfd){ int i, pid; int argc; char buf[BUFSIZE]; char **newargv; _SHMBLK shmblk; if (argv == NULL) { errno == EINVAL; return(-1); } shmblk = _shared_init(pgid); if (shmblk == NULL) { errno = ENOMEM; return(-1); } WCETRACE(WCE_IO, "spawnv: _shared_init returns %x", shmblk); _shared_setenvblk(shmblk, environ); getcwd(buf, BUFSIZE); WCETRACE(WCE_IO, "spawnv: cwd \"%s\"", buf); _shared_setcwd(shmblk, buf); _shared_setstdinfd(shmblk, (infd >= 0) ? _fdtab[infd].fd : infd); _shared_setstdoutfd(shmblk, (outfd >= 0) ? _fdtab[outfd].fd : outfd); _shared_setstderrfd(shmblk, (errfd >= 0) ? _fdtab[errfd].fd : errfd); /* argvcopy assures argv is big enough for 2 more arguments + NULL */ newargv = _argvcopy(argv, &argc); WCETRACE(WCE_IO, "spawnv: newargv %x argc %d", newargv, argc); newargv[argc - 3] = "-pgid"; sprintf(buf, "%u", _shared_getpgid(shmblk)); newargv[argc - 2] = buf; if(command[0]!='/') { char tmp[BUFSIZE]; getcwd(tmp,BUFSIZE); if(tmp[strlen(tmp)-1]!='/') strcat(tmp,"/"); strcat(tmp,command); pid = _spawn(tmp, newargv); } else pid = _spawn(command, newargv); free(newargv); WCETRACE(WCE_IO, "spawnv: _spawn returns %u\n", pid); return(pid);}int_spawnvp(char *command, char *argv[], int pgid, int infd, int outfd, int errfd){ int i, pid; int argc; char buf[BUFSIZE], pathbuf[BUFSIZE]; char **newargv; _SHMBLK shmblk; if (command == NULL || strlen(command) == 0 || argv == NULL) { errno == EINVAL; return(-1); } WCETRACE(WCE_IO, "spawnvp \"%s\" pgid %d infd %d outfd %d errfd %d", command, pgid, infd, outfd, errfd); /* Similar to spawnv, but incorporate PATH search */ if (_findexec(command, pathbuf, BUFSIZE) != 0) { WCETRACE(WCE_IO, "spawnvp: can't locate exec \"%s\"", command); errno = ENOENT; return(-1); } shmblk = _shared_init(pgid); if (shmblk == NULL) { errno = ENOMEM; return(-1); } WCETRACE(WCE_IO, "spawnv: _shared_init returns %x", shmblk); _shared_setenvblk(shmblk, environ); getcwd(buf, BUFSIZE); WCETRACE(WCE_IO, "spawnvp: cwd \"%s\"", buf); _shared_setcwd(shmblk, buf); _shared_setstdinfd(shmblk, (infd >= 0) ? _fdtab[infd].fd : infd); _shared_setstdoutfd(shmblk, (outfd >= 0) ? _fdtab[outfd].fd : outfd); _shared_setstderrfd(shmblk, (errfd >= 0) ? _fdtab[errfd].fd : errfd); _shared_dump(shmblk); /* argvcopy assures argv is big enough for 2 more arguments + NULL */ newargv = _argvcopy(argv, &argc); WCETRACE(WCE_IO, "spawnv: newargv %x argc %d", newargv, argc); newargv[argc - 3] = "-pgid"; sprintf(buf, "%u", _shared_getpgid(shmblk)); newargv[argc - 2] = buf; pid = _spawn(pathbuf, newargv); free(newargv); WCETRACE(WCE_IO, "spawnvp: _spawn returns %u\n", pid); return(pid);}int_newlib_pre_spawn(int pgid, int infd, int outfd, int errfd){ _SHMBLK shmblk; char buf[BUFSIZE]; int newpgid; shmblk = _shared_init(pgid); if (shmblk == NULL) { errno = ENOMEM; return(-1); } _shared_setenvblk(shmblk, environ); getcwd(buf, BUFSIZE); _shared_setcwd(shmblk, buf); _shared_setstdinfd(shmblk, (infd >= 0) ? _fdtab[infd].fd : infd); _shared_setstdoutfd(shmblk, (outfd >= 0) ? _fdtab[outfd].fd : outfd); _shared_setstderrfd(shmblk, (errfd >= 0) ? _fdtab[errfd].fd : errfd); newpgid = _shared_getpgid(shmblk); return newpgid;} int_spawn(char *command, char *argv[]){ STARTUPINFOW si; PROCESS_INFORMATION pi; wchar_t commandW[MAX_CMDLEN]; char cmdline[MAX_CMDLINE]; wchar_t cmdlineW[MAX_CMDLINE]; char *cp; int i, winerr; memset(cmdline, 0, MAX_CMDLINE); memset(cmdlineW, 0, MAX_CMDLINE * sizeof(wchar_t)); if (argv != NULL) { for (i = 0; argv[i] != NULL; i++) { strcat(cmdline, argv[i]); if (argv[i+1] != NULL) strcat(cmdline, " "); } } mbstowcs(commandW, command, strlen(command) + 1); WCETRACE(WCE_IO, "_spawn: \"%s\" cmdline \"%s\"", command, cmdline); mbstowcs(cmdlineW, cmdline, strlen(cmdline) + 1); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); if (CreateProcessW(commandW, cmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == FALSE) { errno = _winerr2errno(GetLastError()); WCETRACE(WCE_IO, "_spawn: CreateProcess FAILED (errno %d winerr %d)", errno, GetLastError()); return(-1); } LastPID=pi.dwProcessId; return(pi.dwProcessId);}int_await(int pid, int msec){ HANDLE hnd; int retval, winerr; hnd = OpenProcess(0, FALSE, (unsigned int)pid); if (hnd == NULL) { errno = _winerr2errno(GetLastError()); WCETRACE(WCE_IO, "_await: ERROR can't open target process (errno %d winerr %d", errno, winerr); return(-1); } if (msec == 0) msec = INFINITE; if ((retval = WaitForSingleObject(hnd, msec)) == WAIT_FAILED) { CloseHandle(hnd); errno = _winerr2errno(GetLastError()); WCETRACE(WCE_IO, "_await: ERROR WFSO failed (errno %d, winerr %d", errno, winerr); return(-1); } GetExitCodeProcess(hnd,&LastExitCode); CloseHandle(hnd); WCETRACE(WCE_IO, "_await: WFSO joined pid %u", pid); return(0);}void *_getchildhnd(int pid){ HANDLE hnd; int retval, winerr; hnd = OpenProcess(0, FALSE, (unsigned int)pid); if (hnd == NULL) { errno = _winerr2errno(GetLastError()); WCETRACE(WCE_IO, "_getchildhnd: ERROR can't open target process (errno %d winerr %d", errno, winerr); return(NULL); } return((void *)hnd);}int execv(const char *command, char * const argv[]){ WCETRACE(WCE_IO, "execv: "); int pid=_spawnv(command, argv+1, getpgid(0), -1,-1,-1); /* eat process name from argv, get it from command */ if(__IsForkChild) _done_exec(pid); if(pid!=-1) { _await(pid,0); _exit(0); } return -1;}intexecvp(const char *command, char * const argv[]){ WCETRACE(WCE_IO, "execvp: "); int pid=_spawnvp(command, argv+1, getpgid(0), -1,-1,-1); if(__IsForkChild) _done_exec(pid); if(pid!=-1) { _await(pid,0); _exit(0); } return -1;}int_exec(const char *command, char * const argv[]){ return execv(command, argv); }pid_t_wait(int *status){ _await(LastPID,0); *status=LastExitCode; WCETRACE(WCE_IO, "wait: pid=%d, exit code=%d",LastPID,LastExitCode); return LastPID;}pid_t_wait_r(void* dum,int *status){ return _wait(status);}#define _P_WAIT 1int spawnv(int mode, const char *command, char * const argv[]){ WCETRACE(WCE_IO, "spawnv: "); if(mode&_P_WAIT) { int pid=_spawnv(command, argv+1, getpgid(0), -1,-1,-1); if(__IsForkChild) _done_exec(pid); if(pid!=-1) { _await(pid,0); return LastExitCode; } else return -1; } else return _spawnv(command, argv+1, getpgid(0), -1,-1,-1);}intspawnvp(int mode, const char *command, char * const argv[]){ WCETRACE(WCE_IO, "spawnvp: "); if(mode&_P_WAIT) { int pid=_spawnvp(command, argv+1, getpgid(0), -1,-1,-1); if(__IsForkChild) _done_exec(pid); if(pid!=-1) { _await(pid,0); return LastExitCode; } else return -1; } else return _spawnvp(command, argv+1, getpgid(0), -1,-1,-1);}/* FIXME: passed environment is ignored. Current is used instead */int _execve_r(void *dum, const char *command, char * const argv[], char * const env[]){ WCETRACE(WCE_IO, "execve: "); int pid=_spawnv(command, argv+1, getpgid(0), -1,-1,-1); if(__IsForkChild) _done_exec(pid); if(pid!=-1) { _await(pid,0); _exit(0); } return -1;}size_t getpagesize(void){ return 65536;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?