/* * This is the CGI process wrapper. It will open and redirect stdin * and stdout to stdIn and stdOut. It converts argv to an argc, argv * pair to pass to the user entry. It initializes the task environment * with envp strings. Then it will call the user entry. */ static void vxWebsCgiEntry(void *entryAddr(int argc, char_t **argv), char_t **argp, char_t **envp, char_t *stdIn, char_t *stdOut) { char_t **p; int argc, taskId, fdin, fdout; /* * Open the stdIn and stdOut files and redirect stdin and stdout * to them. */ taskId = taskIdSelf(); if ((fdout = gopen(stdOut, O_RDWR | O_CREAT, 0666)) < 0 && (fdout = creat(stdOut, O_RDWR)) < 0) { exit(0); } ioTaskStdSet(taskId, 1, fdout); if ((fdin = gopen(stdIn, O_RDONLY | O_CREAT, 0666)) < 0 && (fdin = creat(stdIn, O_RDWR)) < 0) { printf("content-type: text/html\n\n" "Can not create CGI stdin to %s\n", stdIn); gclose(fdout); exit (0); } ioTaskStdSet(taskId, 0, fdin); /* * Count the number of entries in argv */ for (argc = 0, p = argp; p != NULL && *p != NULL; p++, argc++) { } /* * Create a private envirnonment and copy the envp strings to it. */ if (envPrivateCreate(taskId, -1) != OK) { printf("content-type: text/html\n\n" "Can not create CGI environment space\n"); gclose(fdin); gclose(fdout); exit (0); } for (p = envp; p != NULL && *p != NULL; p++) { putenv(*p); } /* * Call the user entry. */ (*entryAddr)(argc, argp); /* * The user code should return here for cleanup. */ envPrivateDestroy(taskId); gclose(fdin); gclose(fdout); exit(0); }
/* N.B.!! We do *not* execute in the context of the dying task here, but rather that of tExcTask - we do get a pointer to the task's TCB though - this pointer is in fact also the task's ID. */ static void save_reclaim(WIND_TCB *tcbp) { int i, var, oldfd; struct task_data *tdp; struct mall_data *mdp, *mdnextp; if ((var = taskVarGet((int)tcbp, (int *)&task_data)) != ERROR && var != 0) { tdp = (struct task_data *)var; if (tdp->version == (FUNCPTR)save_reclaim) { /* Only handle our own */ #ifdef DEBUG fdprintf(2, "Reclaiming for task id 0x%x:\nFiles: ", (int)tcbp); #endif /* Ugh! VxWorks doesn't even flush stdout/err - we need to get at those (which are task-private of course, i.e. we can't just do fflush(stdout) here) - we could be really pedantic and try to redefine stdout/err (which "are" function calls) too, snarfing the values when they are used - but besides the overhead this is problematic since they are actually #defines already... We'll peek in the TCB instead (no documentation of course). And of course, we must also meddle with the *file descriptor* indirections, or we'll just flush out on tExcTask's descriptors... */ for (i = 1; i <= 2; i++) { if (tcbp->taskStdFp[i] != NULL) { #ifdef DEBUG fdprintf(2, "fflush(%s) ", i == 1 ? "stdout" : "stderr"); #endif oldfd = ioTaskStdGet(0, i); ioTaskStdSet(0, i, tcbp->taskStd[i]); fflush(tcbp->taskStdFp[i]); ioTaskStdSet(0, i, oldfd); } } for (i = 3; i < tdp->max_files; i++) { if (FD_ISSET(i, &tdp->open_fds)) { #ifdef DEBUG fdprintf(2, "close(%d) ", i); #endif (void) close(i); } if (tdp->open_fps[i] != NULL) { #ifdef DEBUG fdprintf(2, "fclose(%0x%x) ", (int)tdp->open_fps[i]); #endif (void) fclose(tdp->open_fps[i]); } } i = 0; mdp = tdp->mall_data; while (mdp != NULL) { mdnextp = mdp->next; if(reclaim_free_function != NULL) (*reclaim_free_function)(mdp->self); else free(mdp->self); i++; mdp = mdnextp; } #ifdef DEBUG fdprintf(2, "\nFreeing memory: total %d mallocs\n", i); #endif if (tdp->delete_hook != NULL) { #ifdef DEBUG fdprintf(2, "Calling delete hook at 0x%08x\n", tdp->delete_hook); #endif (*tdp->delete_hook)(tdp->hook_data); #ifdef DEBUG fdprintf(2, "Called delete hook at 0x%08x\n", tdp->delete_hook); #endif } #ifdef DEBUG fdprintf(2, "Freeing own mem at 0x%08x\n", tdp); #endif (void) free((char *)tdp); #ifdef DEBUG fdprintf(2, "Freed own mem at 0x%08x, done (0x%08x)\n**********\n", tdp, taskIdSelf()); checkStack(0); #endif } } #ifdef DEBUG else fdprintf(2, "No task data found for id 0x%x, var = %d\n", (int)tcbp, var); #endif }
/* Executed by the child process */ static void cmdTaskEntry(char *program, MprCmdTaskFn entry, int cmdArg) { MprCmd *cmd; MprCmdFile *files; WIND_TCB *tcb; char *item; int inFd, outFd, errFd, id, next; cmd = (MprCmd*) cmdArg; /* Open standard I/O files (in/out are from the server's perspective) */ files = cmd->files; inFd = open(files[MPR_CMD_STDIN].name, O_RDONLY, 0666); outFd = open(files[MPR_CMD_STDOUT].name, O_WRONLY, 0666); errFd = open(files[MPR_CMD_STDERR].name, O_WRONLY, 0666); if (inFd < 0 || outFd < 0 || errFd < 0) { exit(255); } id = taskIdSelf(); ioTaskStdSet(id, 0, inFd); ioTaskStdSet(id, 1, outFd); ioTaskStdSet(id, 2, errFd); /* Now that we have opened the stdin and stdout, wakeup our parent. */ semGive(cmd->startCond); /* Create the environment */ if (envPrivateCreate(id, -1) < 0) { exit(254); } for (ITERATE_ITEMS(cmd->env, item, next)) { putenv(item); } #if !VXWORKS { char *dir; int rc; /* Set current directory if required WARNING: Setting working directory on VxWorks is global */ if (cmd->dir) { rc = chdir(cmd->dir); } else { dir = mprGetPathDir(cmd->program); rc = chdir(dir); } if (rc < 0) { mprLog("error mpr cmd", 0, "Cannot change directory to %s", cmd->dir); exit(255); } } #endif /* Call the user's entry point */ (entry)(cmd->argc, (char**) cmd->argv, (char**) cmd->env); tcb = taskTcb(id); cmd->status = tcb->exitCode; /* Cleanup */ envPrivateDestroy(id); close(inFd); close(outFd); close(errFd); semGive(cmd->exitCond); }
static int start_process(Channel * c, char ** envp, char * dir, char * exe, char ** args, int attach, int * pid, int * selfattach, ChildProcess ** prs) { int err = 0; char * ptr; SYM_TYPE type; if (symFindByName(sysSymTbl, exe, &ptr, &type) != OK) { err = errno; if (err == S_symLib_SYMBOL_NOT_FOUND) err = ERR_SYM_NOT_FOUND; assert(err != 0); } else { int i; int pipes[2][2]; /* TODO: arguments, environment */ *pid = taskCreate("tTcf", 100, 0, 0x4000, (FUNCPTR)ptr, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); for (i = 0; i < 2; i++) { char pnm[32]; char pnm_m[32]; char pnm_s[32]; snprintf(pnm, sizeof(pnm), "/pty/tcf-%0*lx-%d", sizeof(*pid) * 2, *pid, i); snprintf(pnm_m, sizeof(pnm_m), "%sM", pnm); snprintf(pnm_s, sizeof(pnm_m), "%sS", pnm); if (ptyDevCreate(pnm, PIPE_SIZE, PIPE_SIZE) == ERROR) { err = errno; break; } pipes[i][0] = open(pnm_m, O_RDWR, 0); pipes[i][1] = open(pnm_s, O_RDWR, 0); if (pipes[i][0] < 0 || pipes[i][1] < 0) { err = errno; break; } } if (err) { taskDelete(*pid); *pid = 0; } else { semTake(prs_list_lock, WAIT_FOREVER); ioTaskStdSet(*pid, 0, pipes[0][1]); ioTaskStdSet(*pid, 1, pipes[0][1]); ioTaskStdSet(*pid, 2, pipes[1][1]); *prs = loc_alloc_zero(sizeof(ChildProcess)); (*prs)->inp = pipes[0][0]; (*prs)->out = pipes[0][0]; (*prs)->err = pipes[1][0]; (*prs)->pid = *pid; (*prs)->bcg = c->bcg; list_add_first(&(*prs)->link, &prs_list); if (attach) { taskStop(*pid); taskActivate(*pid); assert(taskIsStopped(*pid)); } else { taskActivate(*pid); } semGive(prs_list_lock); } } if (!err) return 0; errno = err; return -1; }
/* * Executed by the child process */ static void cmdTaskEntry(char *program, MprCmdTaskFn entry, int cmdArg) { MprCmd *cmd; MprCmdFile *files; WIND_TCB *tcb; char **ep, *dir; int inFd, outFd, errFd, id, rc; cmd = (MprCmd*) cmdArg; /* * Open standard I/O files (in/out are from the server's perspective) */ files = cmd->files; inFd = open(files[MPR_CMD_STDIN].name, O_RDONLY, 0666); outFd = open(files[MPR_CMD_STDOUT].name, O_WRONLY, 0666); errFd = open(files[MPR_CMD_STDERR].name, O_WRONLY, 0666); if (inFd < 0 || outFd < 0 || errFd < 0) { exit(255); } id = taskIdSelf(); ioTaskStdSet(id, 0, inFd); ioTaskStdSet(id, 1, outFd); ioTaskStdSet(id, 2, errFd); /* * Now that we have opened the stdin and stdout, wakeup our parent. */ semGive(cmd->startCond); /* * Create the environment */ if (envPrivateCreate(id, -1) < 0) { exit(254); } for (ep = cmd->env; ep && *ep; ep++) { putenv(*ep); } /* * Set current directory if required */ if (cmd->dir) { rc = chdir(cmd->dir); } else { dir = mprGetPathDir(cmd, cmd->program); rc = chdir(dir); mprFree(dir); } if (rc < 0) { mprLog(cmd, 0, "cmd: Can't change directory to %s", cmd->dir); exit(255); } /* * Call the user's entry point */ (entry)(cmd->argc, cmd->argv, cmd->env); tcb = taskTcb(id); cmd->status = tcb->exitCode; /* * Cleanup */ envPrivateDestroy(id); close(inFd); close(outFd); close(errFd); semGive(cmd->exitCond); }