static void run(void) { pid_t pids[NPROCS*4], wp; int i, status; for (i=0; i<NPROCS; i++) { pids[i*4] = dofork(mkdir_proc); pids[i*4+1] = dofork(mkdir_proc); pids[i*4+2] = dofork(rename_proc); pids[i*4+3] = dofork(rmdir_proc); } for (i=0; i<NPROCS*4; i++) { if (pids[i]>=0) { wp = waitpid(pids[i], &status, 0); if (wp<0) { say("waitpid %d: %s\n", (int) pids[i], strerror(errno)); } else if (WIFSIGNALED(status)) { say("pid %d: signal %d\n", (int) pids[i], WTERMSIG(status)); } else if (WIFEXITED(status) && WEXITSTATUS(status)!=0) { say("pid %d: exit %d\n", (int) pids[i], WEXITSTATUS(status)); } } } }
int main() { int pid0, pid1, pid2; pid0 = dofork(); putchar('0'); check(); putchar('a'); pid1 = dofork(); putchar('1'); check(); putchar('b'); pid2 = dofork(); putchar('2'); check(); //putchar('c'); dowait(pid2); dowait(pid1); dowait(pid0); putchar('\n'); return 0; }
/* * Actually run the test. */ static void test() { int pid0, pid1, ret; pid0 = dofork(); warnx("Child 0 created."); pid1 = dofork(); warnx("Child 1 created."); ret = kill(pid1, 17); if (ret == -1) { warn("kill failed."); } else { warnx("Child 1 stopped."); } ret = kill(pid0, 17); if (ret == -1) { warn("kill failed."); } else { warnx("Child 0 stopped."); } ret = kill(pid1, 19); if (ret == -1) { warn("kill failed."); } else { warnx("Child 0 continued."); } ret = kill(pid1, 17); if (ret == -1) { warnx("Correct error when child 1 stopped twice"); } else { warnx("Child 1 stopped twice?"); } ret = kill(pid1, 9); if (ret == -1) { warn("kill failed."); } else { warnx("Child 1 killed."); } ret = kill(pid0, 9); if (ret == -1) { warn("kill failed."); } else { warnx("Child 0 killed."); } }
/** * @brief dispatch * 并发数分配到若干进程 * * 将期待的并发量p->num * 也就是参数 c 的值分组 * 每组调用一次dofork函数得到一个进程 * 默认一个进程里面会产生BM_GROUP_THREADS个线程 * p->num在对BM_GROUP_THREADS求余 * 剩下的不足BM_GROUP_THREADS都会分配到一个进程中 * * @param p * cbenchmark全局信息 */ void dispatch(struct bench * bp) { long int i; for (i = 0; i < bp->num/BM_GROUP_THREADS; i++) { dofork(bp,BM_GROUP_THREADS,i); } if(bp->num%BM_GROUP_THREADS > 0) dofork(bp,bp->num%BM_GROUP_THREADS,i); }
static void doforkall(const char *phasename, void (*func)(void)) { int i, bad = 0; pid_t pids[numprocs]; for (i=0; i<numprocs; i++) { pids[i] = dofork(); if (pids[i] < 0) { bad = 1; } else if (pids[i] == 0) { /* child */ me = i; func(); exit(0); } } for (i=0; i<numprocs; i++) { if (pids[i] > 0 && dowait(i, pids[i])) { bad = 1; } } if (bad) { complainx("%s failed.", phasename); exit(1); } }
static void expect_segfault(segfault_fn func) { int status; int result; pid_t pid = dofork(); if (pid == 0) { func(); // This exits } else { result = waitpid(pid, &status, 0); tprintf("status is %d \n", status); if (result == -1) { err(1, "waitpid"); } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != 11) { errx(1, "child: Signal %d", WTERMSIG(status)); } } else { errx(1, "child exited, expected segfault"); } } }
/* * Fork and then allocate in both the parent and the child, in case * fork messes up the heap. Note: this is not intended to test the * parent and child running concurrently -- that should probably be * its own test program. */ static void test12(void) { pid_t pid; void *p; tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ say("Child allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } say("Child done.\n"); exit(0); } /* parent */ say("Parent allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent"); } say("Parent done.\n"); dowait(pid); tprintf("Passed sbrk test 12.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
/* * Allocate and then fork, in case fork doesn't preserve the heap. */ static void test13(void) { pid_t pid; void *p; printf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt before forking"); } printf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } exit(0); } if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent"); } dowait(pid); printf("Passed sbrk test 13.\n"); }
/* * Actually run the test for signals that should cause termination. */ static void testsig_die(int signum, const char *signame) { int pid0, ret, status; pid0 = dofork(); warnx("Child %d created.",pid0); ret = kill(pid0, signum); if (ret == -1) { warn("kill failed."); } else { warnx("Child %d sent %s.",pid0, signame); } ret = waitpid(pid0, &status, 0); if (ret != pid0) { warn("waitpid failed (signal %s, status %d)",signame,WEXITSTATUS(status)); } else { warnx("waitpid succeeded (signal %s, status %d, rawstatus %d).",signame,WEXITSTATUS(status),status); if (WIFSIGNALED(status)) { warnx("\t status %d indicates exit due to signal."); } else { warnx("\t status %d does NOT indicate exit due to signal."); } } }
int main() { pid_p = getpid(); //printf("value of pid_p after getpid is %d \n", pid_p); putchar('w'); pid_c = dofork(); //printf("value of pid_c after getpid is %d \n", pid_c); if (getpid() == pid_p) { check(); dowait(pid_c); } else { putchar('e'); _exit(0); } putchar('k'); if (getpid() == pid_p) putchar('p'); else printf("wrong %d\n", getpid()); putchar('\n'); return 0; }
void dofile() { (void)printf("(This file must be converted; you knew that already.)\n"); (void)printf("\n"); pos_ptr = 1; state = 0; rep_char = -1; rep_count = 0; outchar(':'); doheader(); dofork(data_fork, data_size); dofork(rsrc_fork, rsrc_size); finish(); (void)putchar(':'); (void)putchar('\n'); }
/* * Allocate, then fork, then free the allocated page in the child. */ static void test14(void) { pid_t pid; void *p; tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt before forking"); } tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } tprintf("Child freeing a page...\n"); dosbrk(-PAGE_SIZE); exit(0); } dowait(pid); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent after child ran"); } tprintf("Passed sbrk test 14.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
int main() { int pid; int result, status; warnx("Starting."); /* Wait for child - parent should have to wait */ warnx("Creating long-running child. Parent should have to wait."); pid = dofork(10, 10000); result = waitpid(pid, &status, 0); if (result != pid) { warn("unexpected result %d from waitpid, status %d.",result,status); } else { warnx("waitpid returned status %d (raw %d).", WEXITSTATUS(status), status); } /* Wait for child - child should exit before parent does wait */ warnx("Creating short-running child. Parent should not have to wait."); pid = dofork(20, 0); result = waitpid(pid, &status, 0); if (result != pid) { warn("unexpected result %d from waitpid, status %d.",result,status); } else { warnx("waitpid returned status %d (raw %d).", WEXITSTATUS(status), status); } /* Wait for child, WNOHANG */ warnx("Creating long-running child. Parent should not have to wait (WNOHANG)."); pid = dofork(30, 10000); status = 0xabababab; /* pattern should not be changed unless status is set */ result = waitpid(pid, &status, WNOHANG); if (result != 0 || status != (int)0xabababab) { warn("unexpected result from waitpid (result %d, status 0x%x).",result,status); } else { warnx("waitpid returned status %d (raw %d).", WEXITSTATUS(status), status); } warnx("Complete."); return 0; }
int background(void) { int pid = dofork(); if (pid == 0) { dlog("backgrounded"); foreground = 0; } return pid; }
int background(void) { int pid = dofork(); if (pid == 0) { dlog("backgrounded"); foreground = 0; } else dlog("forked process %d", pid); return pid; }
int background(void) { int pid = dofork(); if (pid == 0) { #ifdef DEBUG dlog("backgrounded"); #endif /* DEBUG */ foreground = 0; } return pid; }
/* * Actually run the test. */ static void test(int nowait) { int pid0, pid1, pid2, pid3; /* * Caution: This generates processes geometrically. * * It is unrolled to encourage gcc to registerize the pids, * to prevent wait/exit problems if fork corrupts memory. */ pid0 = dofork(); putchar('0'); check(); pid1 = dofork(); putchar('1'); check(); pid2 = dofork(); putchar('2'); check(); pid3 = dofork(); putchar('3'); check(); /* * These must be called in reverse order to avoid waiting * improperly. */ dowait(nowait, pid3); dowait(nowait, pid2); dowait(nowait, pid1); dowait(nowait, pid0); putchar('\n'); }
arg_t _fork(void) { // allocate new process struct p_tab *new_process; arg_t r; irqflags_t irq; if (flags) { /* Brief period of grace... */ // udata.u_error = EINVAL; // return -1; kputs("warning: rebuild libc\n"); } new_process = ptab_alloc(); if (!new_process) return -1; irq = di(); // we're going to run our child process next, so mark this process as being ready to run udata.u_ptab->p_status = P_READY; // kick off the new process (the bifurcation happens inside here, we returns in both // the child and parent contexts) r = dofork(new_process); #ifdef DEBUG kprintf("Dofork %x (n %x)returns %d\n", udata.u_ptab, new_process, r); kprintf("udata.u_page %d p_page %d\n", udata.u_page, udata.u_ptab->p_page); kprintf("parent %x\n", udata.u_ptab->p_pptr); #endif // if we fail this returns -1 if (r == -1) { udata.u_ptab->p_status = P_RUNNING; pagemap_free(new_process); new_process->p_status = P_EMPTY; udata.u_error = ENOMEM; nproc--; nready--; } irqrestore(irq); return r; }
static void dotest(void) { unsigned i, me; pid_t pids[BRANCHES]; int t; me = 0; for (i=0; i<BRANCHES; i++) { pids[i] = dofork(); if (pids[i] == 0) { me += 1U<<i; } grind(); t = trace(); if (t == right[i]) { tsay("Stage %u #%u done: %d\n", i, me, trace()); } else { tsay("Stage %u #%u FAILED: got %d, expected %d\n", i, me, t, right[i]); success(TEST161_FAIL, SECRET, "/testbin/bigfork"); failures++; } TEST161_TPROGRESS(0); } for (i=BRANCHES; i-- > 0; ) { dowait(pids[i]); } if (failures > 0) { tprintf("%u failures.\n", failures); success(TEST161_FAIL, SECRET, "/testbin/bigfork"); } else { tprintf("Done.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/bigfork"); } }
int main() { pid_p = getpid(); putchar('a'); pid_c = dofork(); if (getpid() == pid_p) { check(); putchar('t'); _exit(0); } else { putchar('t'); _exit(0); } putchar('e'); putchar('\n'); return 0; }
/* * Actually run the test for signals that should be ignored. */ static void testsig_ignore(int signum, const char *signame) { int pid0, ret, status=123456; int i, ok=0; pid0 = dofork(); warnx("Child %d created.",pid0); ret = kill(pid0, signum); if (ret == -1) { warn("kill failed."); } else { warnx("Child %d sent %s.",pid0,signame); } /* check repeatedly to make sure signaled child is still there */ for (i=0; i < 100; i++) { ret = waitpid(pid0, &status, WNOHANG); if (ret != 0) { warn("waitpid with WNOHANG failed (%s)",signame); } else { ok++; } } if (ok == 100) { warnx("Success: signal %s appears to be ignored.",signame); } /* try killing child just to clean up */ warnx("Sending SIGKILL to Child %d to clean up...",pid0); ret = kill(pid0, SIGKILL); if (ret == -1) { warn("kill failed."); } ret = waitpid(pid0, &status, 0); warnx("\tretrieved %d status from pid %d\n",status,pid0); }
void main() { int x = 1; // should not count as a guarded-by; not shared dofork(&x); x = 1; // race }
int main(int argc, char *argv[]) { struct group *gr; struct stat st; int ask, ch, cnt, fflag, hflag, pflag, sflag, quietlog, rootlogin, rval; uid_t uid, saved_uid; gid_t saved_gid, saved_gids[NGROUPS_MAX]; int nsaved_gids; #ifdef notdef char *domain; #endif char *p, *ttyn; const char *pwprompt; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; char localhost[MAXHOSTNAMELEN + 1]; int need_chpass, require_chpass; int login_retries = DEFAULT_RETRIES, login_backoff = DEFAULT_BACKOFF; time_t pw_warntime = _PASSWORD_WARNDAYS * SECSPERDAY; char *loginname = NULL; #ifdef KERBEROS5 int Fflag; krb5_error_code kerror; #endif #if defined(KERBEROS5) int got_tickets = 0; #endif #ifdef LOGIN_CAP char *shell = NULL; login_cap_t *lc = NULL; #endif tbuf[0] = '\0'; rval = 0; pwprompt = NULL; nested = NULL; need_chpass = require_chpass = 0; (void)signal(SIGALRM, timedout); (void)alarm(timeout); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)setpriority(PRIO_PROCESS, 0, 0); openlog("login", 0, LOG_AUTH); /* * -p is used by getty to tell login not to destroy the environment * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the remote host to * login so that it may be placed in utmp/utmpx and wtmp/wtmpx * -a in addition to -h, a server may supply -a to pass the actual * server address. * -s is used to force use of S/Key or equivalent. */ if (gethostname(localhost, sizeof(localhost)) < 0) { syslog(LOG_ERR, "couldn't get local hostname: %m"); strcpy(hostname, "amnesiac"); } #ifdef notdef domain = strchr(localhost, '.'); #endif localhost[sizeof(localhost) - 1] = '\0'; fflag = hflag = pflag = sflag = 0; have_ss = 0; #ifdef KERBEROS5 Fflag = 0; have_forward = 0; #endif uid = getuid(); while ((ch = getopt(argc, argv, "a:Ffh:ps")) != -1) switch (ch) { case 'a': if (uid) errx(EXIT_FAILURE, "-a option: %s", strerror(EPERM)); decode_ss(optarg); #ifdef notdef (void)sockaddr_snprintf(optarg, sizeof(struct sockaddr_storage), "%a", (void *)&ss); #endif break; case 'F': #ifdef KERBEROS5 Fflag = 1; #endif /* FALLTHROUGH */ case 'f': fflag = 1; break; case 'h': if (uid) errx(EXIT_FAILURE, "-h option: %s", strerror(EPERM)); hflag = 1; #ifdef notdef if (domain && (p = strchr(optarg, '.')) != NULL && strcasecmp(p, domain) == 0) *p = '\0'; #endif hostname = optarg; break; case 'p': pflag = 1; break; case 's': sflag = 1; break; default: case '?': usage(); break; } setproctitle(NULL); argc -= optind; argv += optind; if (*argv) { username = loginname = *argv; ask = 0; } else ask = 1; #ifdef F_CLOSEM (void)fcntl(3, F_CLOSEM, 0); #else for (cnt = getdtablesize(); cnt > 2; cnt--) (void)close(cnt); #endif ttyn = ttyname(STDIN_FILENO); if (ttyn == NULL || *ttyn == '\0') { (void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY); ttyn = tname; } if ((tty = strstr(ttyn, "/pts/")) != NULL) ++tty; else if ((tty = strrchr(ttyn, '/')) != NULL) ++tty; else tty = ttyn; if (issetugid()) { nested = strdup(user_from_uid(getuid(), 0)); if (nested == NULL) { syslog(LOG_ERR, "strdup: %m"); sleepexit(EXIT_FAILURE); } } #ifdef LOGIN_CAP /* Get "login-retries" and "login-backoff" from default class */ if ((lc = login_getclass(NULL)) != NULL) { login_retries = (int)login_getcapnum(lc, "login-retries", DEFAULT_RETRIES, DEFAULT_RETRIES); login_backoff = (int)login_getcapnum(lc, "login-backoff", DEFAULT_BACKOFF, DEFAULT_BACKOFF); login_close(lc); lc = NULL; } #endif #ifdef KERBEROS5 kerror = krb5_init_context(&kcontext); if (kerror) { /* * If Kerberos is not configured, that is, we are * not using Kerberos, do not log the error message. * However, if Kerberos is configured, and the * context init fails for some other reason, we need * to issue a no tickets warning to the user when the * login succeeds. */ if (kerror != ENXIO) { /* XXX NetBSD-local Heimdal hack */ syslog(LOG_NOTICE, "%s when initializing Kerberos context", error_message(kerror)); krb5_configured = 1; } login_krb5_get_tickets = 0; } #endif /* KERBEROS5 */ for (cnt = 0;; ask = 1) { #if defined(KERBEROS5) if (login_krb5_get_tickets) k5destroy(); #endif if (ask) { fflag = 0; loginname = getloginname(); } rootlogin = 0; #ifdef KERBEROS5 if ((instance = strchr(loginname, '/')) != NULL) *instance++ = '\0'; else instance = __UNCONST(""); #endif username = trimloginname(loginname); /* * Note if trying multiple user names; log failures for * previous user name, but don't bother logging one failure * for nonexistent name (mistyped username). */ if (failures && strcmp(tbuf, username)) { if (failures > (pwd ? 0 : 1)) badlogin(tbuf); failures = 0; } (void)strlcpy(tbuf, username, sizeof(tbuf)); pwd = getpwnam(username); #ifdef LOGIN_CAP /* * Establish the class now, before we might goto * within the next block. pwd can be NULL since it * falls back to the "default" class if it is. */ lc = login_getclass(pwd ? pwd->pw_class : NULL); #endif /* * if we have a valid account name, and it doesn't have a * password, or the -f option was specified and the caller * is root or the caller isn't changing their uid, don't * authenticate. */ if (pwd) { if (pwd->pw_uid == 0) rootlogin = 1; if (fflag && (uid == 0 || uid == pwd->pw_uid)) { /* already authenticated */ #ifdef KERBEROS5 if (login_krb5_get_tickets && Fflag) k5_read_creds(username); #endif break; } else if (pwd->pw_passwd[0] == '\0') { /* pretend password okay */ rval = 0; goto ttycheck; } } fflag = 0; (void)setpriority(PRIO_PROCESS, 0, -4); #ifdef SKEY if (skey_haskey(username) == 0) { static char skprompt[80]; const char *skinfo = skey_keyinfo(username); (void)snprintf(skprompt, sizeof(skprompt), "Password [ %s ]:", skinfo ? skinfo : "error getting challenge"); pwprompt = skprompt; } else #endif pwprompt = "Password:"******"Login incorrect or refused on this " "terminal.\n"); if (hostname) syslog(LOG_NOTICE, "LOGIN %s REFUSED FROM %s ON TTY %s", pwd->pw_name, hostname, tty); else syslog(LOG_NOTICE, "LOGIN %s REFUSED ON TTY %s", pwd->pw_name, tty); continue; } if (pwd && !rval) break; (void)printf("Login incorrect or refused on this " "terminal.\n"); failures++; cnt++; /* * We allow login_retries tries, but after login_backoff * we start backing off. These default to 10 and 3 * respectively. */ if (cnt > login_backoff) { if (cnt >= login_retries) { badlogin(username); sleepexit(EXIT_FAILURE); } sleep((u_int)((cnt - login_backoff) * 5)); } } /* committed to login -- turn off timeout */ (void)alarm((u_int)0); endpwent(); /* if user not super-user, check for disabled logins */ #ifdef LOGIN_CAP if (!login_getcapbool(lc, "ignorenologin", rootlogin)) checknologin(login_getcapstr(lc, "nologin", NULL, NULL)); #else if (!rootlogin) checknologin(NULL); #endif #ifdef LOGIN_CAP quietlog = login_getcapbool(lc, "hushlogin", 0); #else quietlog = 0; #endif /* Temporarily give up special privileges so we can change */ /* into NFS-mounted homes that are exported for non-root */ /* access and have mode 7x0 */ saved_uid = geteuid(); saved_gid = getegid(); nsaved_gids = getgroups(NGROUPS_MAX, saved_gids); (void)setegid(pwd->pw_gid); initgroups(username, pwd->pw_gid); (void)seteuid(pwd->pw_uid); if (chdir(pwd->pw_dir) < 0) { #ifdef LOGIN_CAP if (login_getcapbool(lc, "requirehome", 0)) { (void)printf("Home directory %s required\n", pwd->pw_dir); sleepexit(EXIT_FAILURE); } #endif (void)printf("No home directory %s!\n", pwd->pw_dir); if (chdir("/") == -1) exit(EXIT_FAILURE); pwd->pw_dir = __UNCONST("/"); (void)printf("Logging in with home = \"/\".\n"); } if (!quietlog) quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; /* regain special privileges */ (void)seteuid(saved_uid); setgroups(nsaved_gids, saved_gids); (void)setegid(saved_gid); #ifdef LOGIN_CAP pw_warntime = login_getcaptime(lc, "password-warn", _PASSWORD_WARNDAYS * SECSPERDAY, _PASSWORD_WARNDAYS * SECSPERDAY); #endif (void)gettimeofday(&now, NULL); if (pwd->pw_expire) { if (now.tv_sec >= pwd->pw_expire) { (void)printf("Sorry -- your account has expired.\n"); sleepexit(EXIT_FAILURE); } else if (pwd->pw_expire - now.tv_sec < pw_warntime && !quietlog) (void)printf("Warning: your account expires on %s", ctime(&pwd->pw_expire)); } if (pwd->pw_change) { if (pwd->pw_change == _PASSWORD_CHGNOW) need_chpass = 1; else if (now.tv_sec >= pwd->pw_change) { (void)printf("Sorry -- your password has expired.\n"); sleepexit(EXIT_FAILURE); } else if (pwd->pw_change - now.tv_sec < pw_warntime && !quietlog) (void)printf("Warning: your password expires on %s", ctime(&pwd->pw_change)); } /* Nothing else left to fail -- really log in. */ update_db(quietlog, rootlogin, fflag); (void)chown(ttyn, pwd->pw_uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); if (ttyaction(ttyn, "login", pwd->pw_name)) (void)printf("Warning: ttyaction failed.\n"); #if defined(KERBEROS5) /* Fork so that we can call kdestroy */ if (! login_krb5_retain_ccache && has_ccache) dofork(); #endif /* Destroy environment unless user has requested its preservation. */ if (!pflag) environ = envinit; #ifdef LOGIN_CAP if (nested == NULL && setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETLOGIN) != 0) { syslog(LOG_ERR, "setusercontext failed"); exit(EXIT_FAILURE); } if (setusercontext(lc, pwd, pwd->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETLOGIN))) != 0) { syslog(LOG_ERR, "setusercontext failed"); exit(EXIT_FAILURE); } #else (void)setgid(pwd->pw_gid); initgroups(username, pwd->pw_gid); if (nested == NULL && setlogin(pwd->pw_name) < 0) syslog(LOG_ERR, "setlogin() failure: %m"); /* Discard permissions last so can't get killed and drop core. */ if (rootlogin) (void)setuid(0); else (void)setuid(pwd->pw_uid); #endif if (*pwd->pw_shell == '\0') pwd->pw_shell = __UNCONST(_PATH_BSHELL); #ifdef LOGIN_CAP if ((shell = login_getcapstr(lc, "shell", NULL, NULL)) != NULL) { if ((shell = strdup(shell)) == NULL) { syslog(LOG_ERR, "Cannot alloc mem"); sleepexit(EXIT_FAILURE); } pwd->pw_shell = shell; } #endif (void)setenv("HOME", pwd->pw_dir, 1); (void)setenv("SHELL", pwd->pw_shell, 1); if (term[0] == '\0') { const char *tt = stypeof(tty); #ifdef LOGIN_CAP if (tt == NULL) tt = login_getcapstr(lc, "term", NULL, NULL); #endif /* unknown term -> "su" */ (void)strlcpy(term, tt != NULL ? tt : "su", sizeof(term)); } (void)setenv("TERM", term, 0); (void)setenv("LOGNAME", pwd->pw_name, 1); (void)setenv("USER", pwd->pw_name, 1); #ifdef LOGIN_CAP setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH); #else (void)setenv("PATH", _PATH_DEFPATH, 0); #endif #ifdef KERBEROS5 if (krb5tkfile_env) (void)setenv("KRB5CCNAME", krb5tkfile_env, 1); #endif /* If fflag is on, assume caller/authenticator has logged root login. */ if (rootlogin && fflag == 0) { if (hostname) syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", username, tty, hostname); else syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); } #if defined(KERBEROS5) if (KERBEROS_CONFIGURED && !quietlog && notickets == 1) (void)printf("Warning: no Kerberos tickets issued.\n"); #endif if (!quietlog) { const char *fname; #ifdef LOGIN_CAP fname = login_getcapstr(lc, "copyright", NULL, NULL); if (fname != NULL && access(fname, F_OK) == 0) motd(fname); else #endif (void)printf("%s", copyrightstr); #ifdef LOGIN_CAP fname = login_getcapstr(lc, "welcome", NULL, NULL); if (fname == NULL || access(fname, F_OK) != 0) #endif fname = _PATH_MOTDFILE; motd(fname); (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) (void)printf("You have %smail.\n", (st.st_mtime > st.st_atime) ? "new " : ""); } #ifdef LOGIN_CAP login_close(lc); #endif (void)signal(SIGALRM, SIG_DFL); (void)signal(SIGQUIT, SIG_DFL); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTSTP, SIG_IGN); tbuf[0] = '-'; (void)strlcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell, sizeof(tbuf) - 1); /* Wait to change password until we're unprivileged */ if (need_chpass) { if (!require_chpass) (void)printf( "Warning: your password has expired. Please change it as soon as possible.\n"); else { int status; (void)printf( "Your password has expired. Please choose a new one.\n"); switch (fork()) { case -1: warn("fork"); sleepexit(EXIT_FAILURE); case 0: execl(_PATH_BINPASSWD, "passwd", NULL); _exit(EXIT_FAILURE); default: if (wait(&status) == -1 || WEXITSTATUS(status)) sleepexit(EXIT_FAILURE); } } } #ifdef KERBEROS5 if (login_krb5_get_tickets) k5_write_creds(); #endif execlp(pwd->pw_shell, tbuf, NULL); err(EXIT_FAILURE, "%s", pwd->pw_shell); }
extern bool walk(Node *n, bool parent) { top: sigchk(); if (n == NULL) { if (!parent) exit(0); set(TRUE); return TRUE; } switch (n->type) { case nArgs: case nBackq: case nConcat: case nCount: case nFlat: case nLappend: case nRedir: case nVar: case nVarsub: case nWord: exec(glob(glom(n)), parent); /* simple command */ break; case nBody: walk(n->u[0].p, TRUE); WALK(n->u[1].p, parent); /* WALK doesn't fall through */ case nNowait: { int pid; if ((pid = rc_fork()) == 0) { #if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP) setsigdefaults(FALSE); rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ rc_signal(SIGTTIN, SIG_IGN); rc_signal(SIGTSTP, SIG_IGN); setpgid(0, getpid()); #else setsigdefaults(TRUE); /* ignore SIGINT, SIGQUIT, SIGTERM */ #endif mvfd(rc_open("/dev/null", rFrom), 0); walk(n->u[0].p, FALSE); exit(getstatus()); } if (interactive) fprint(2, "%d\n", pid); varassign("apid", word(nprint("%d", pid), NULL), FALSE); redirq = NULL; /* kill pre-redir queue */ break; } case nAndalso: { bool oldcond = cond; cond = TRUE; if (walk(n->u[0].p, TRUE)) { cond = oldcond; WALK(n->u[1].p, parent); } else cond = oldcond; break; } case nOrelse: { bool oldcond = cond; cond = TRUE; if (!walk(n->u[0].p, TRUE)) { cond = oldcond; WALK(n->u[1].p, parent); } else cond = oldcond; break; } case nBang: set(!walk(n->u[0].p, TRUE)); break; case nIf: { bool oldcond = cond; Node *true_cmd = n->u[1].p, *false_cmd = NULL; if (true_cmd != NULL && true_cmd->type == nElse) { false_cmd = true_cmd->u[1].p; true_cmd = true_cmd->u[0].p; } cond = TRUE; if (!walk(n->u[0].p, TRUE)) true_cmd = false_cmd; /* run the else clause */ cond = oldcond; WALK(true_cmd, parent); } case nWhile: { Jbwrap j; Edata jbreak; Estack e1, e2; bool testtrue, oldcond = cond; cond = TRUE; if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */ cond = oldcond; break; } if (sigsetjmp(j.j, 1)) break; jbreak.jb = &j; except(eBreak, jbreak, &e1); do { Edata block; block.b = newblock(); cond = oldcond; except(eArena, block, &e2); walk(n->u[1].p, TRUE); testtrue = walk(n->u[0].p, TRUE); unexcept(); /* eArena */ cond = TRUE; } while (testtrue); cond = oldcond; unexcept(); /* eBreak */ break; } case nForin: { List *l, *var = glom(n->u[0].p); Jbwrap j; Estack e1, e2; Edata jbreak; if (sigsetjmp(j.j, 1)) break; jbreak.jb = &j; except(eBreak, jbreak, &e1); for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { Edata block; assign(var, word(l->w, NULL), FALSE); block.b = newblock(); except(eArena, block, &e2); walk(n->u[2].p, TRUE); unexcept(); /* eArena */ } unexcept(); /* eBreak */ break; } case nSubshell: if (dofork(TRUE)) { setsigdefaults(FALSE); walk(n->u[0].p, FALSE); rc_exit(getstatus()); } break; case nAssign: if (n->u[0].p == NULL) rc_error("null variable name"); assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE); set(TRUE); break; case nPipe: dopipe(n); break; case nNewfn: { List *l = glom(n->u[0].p); if (l == NULL) rc_error("null function name"); while (l != NULL) { if (dashex) prettyprint_fn(2, l->w, n->u[1].p); fnassign(l->w, n->u[1].p); l = l->n; } set(TRUE); break; } case nRmfn: { List *l = glom(n->u[0].p); while (l != NULL) { if (dashex) fprint(2, "fn %S\n", l->w); fnrm(l->w); l = l->n; } set(TRUE); break; } case nDup: redirq = NULL; break; /* Null command */ case nMatch: { List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); if (dashex) fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " "); set(lmatch(a, b)); break; } case nSwitch: { List *v = glom(n->u[0].p); while (1) { do { n = n->u[1].p; if (n == NULL) return istrue(); } while (n->u[0].p == NULL || n->u[0].p->type != nCase); if (lmatch(v, glom(n->u[0].p->u[0].p))) { for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) walk(n->u[0].p, TRUE); break; } } break; } case nPre: { List *v; if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ break; setsigdefaults(FALSE); qredir(n->u[0].p); if (!haspreredir(n->u[1].p)) doredirs(); /* no more preredirs, empty queue */ walk(n->u[1].p, FALSE); rc_exit(getstatus()); /* NOTREACHED */ } else if (n->u[0].p->type == nAssign) { if (isallpre(n->u[1].p)) { walk(n->u[0].p, TRUE); WALK(n->u[1].p, parent); } else { Estack e; Edata var; v = glom(n->u[0].p->u[0].p); assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE); var.name = v->w; except(eVarstack, var, &e); walk(n->u[1].p, parent); varrm(v->w, TRUE); unexcept(); /* eVarstack */ } } else panic("unexpected node in preredir section of walk"); break; } case nBrace: if (n->u[1].p == NULL) { WALK(n->u[0].p, parent); } else if (dofork(parent)) { setsigdefaults(FALSE); walk(n->u[1].p, TRUE); /* Do redirections */ redirq = NULL; /* Reset redirection queue */ walk(n->u[0].p, FALSE); /* Do commands */ rc_exit(getstatus()); /* NOTREACHED */ } break; case nEpilog: qredir(n->u[0].p); if (n->u[1].p != NULL) { WALK(n->u[1].p, parent); /* Do more redirections. */ } else { doredirs(); /* Okay, we hit the bottom. */ } break; case nNmpipe: rc_error("named pipes cannot be executed as commands"); /* NOTREACHED */ default: panic("unknown node in walk"); /* NOTREACHED */ } return istrue(); }
static pid_t Make_lpd_call( const char *name, WorkerProc *proc, int passfd_count, int *passfd, struct line_list *args, int intern_logger, int intern_status, int intern_mail, int intern_lpd_request, int param_fd ) { int pid, fd, i, n, newfd; struct line_list env; Init_line_list(&env); pid = dofork(1); if( pid ){ return(pid); } Name = "LPD_CALL"; if(DEBUGL2){ LOGDEBUG("Make_lpd_call: name '%s', lpd path '%s'", name, Lpd_path_DYN ); LOGDEBUG("Make_lpd_call: passfd count %d", passfd_count ); for( i = 0; i < passfd_count; ++i ){ LOGDEBUG(" [%d] %d", i, passfd[i]); } Dump_line_list("Make_lpd_call - args", args ); } for( i = 0; i < passfd_count; ++i ){ fd = passfd[i]; if( fd < i ){ /* we have fd 3 -> 4, but 3 gets wiped out */ do{ newfd = dup(fd); Max_open(newfd); if( newfd < 0 ){ Errorcode = JABORT; logerr_die(LOG_INFO, "Make_lpd_call: dup failed"); } DEBUG4("Make_lpd_call: fd [%d] = %d, dup2 -> %d", i, fd, newfd ); passfd[i] = newfd; } while( newfd < i ); } } if(DEBUGL2){ LOGDEBUG("Make_lpd_call: after fixing fd count %d", passfd_count); for( i = 0 ; i < passfd_count; ++i ){ fd = passfd[i]; LOGDEBUG(" [%d]=%d",i,fd); } } for( i = 0; i < passfd_count; ++i ){ fd = passfd[i]; DEBUG2("Make_lpd_call: fd %d -> %d",fd, i ); if( dup2( fd, i ) == -1 ){ Errorcode = JABORT; logerr_die(LOG_INFO, "Make_lpd_call: dup2(%d,%d) failed", fd, i ); } } /* close other ones to simulate close_on_exec() */ n = Max_fd+10; for( i = passfd_count ; i < n; ++i ){ close(i); } Do_work( name, args, proc, intern_logger, intern_status, intern_mail, intern_lpd_request, param_fd ); /* not reached: */ return(0); }
/* * Allocate and free in both the parent and the child, and do more * than one page. */ static void test15(void) { unsigned num = 12; pid_t pid; unsigned i; void *p; tprintf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); for (i=0; i<num; i++) { markpage(p, i); } for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking"); } } tprintf("Freeing one page...\n"); (void)dosbrk(-PAGE_SIZE); num--; for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking (2)"); } } tprintf("Allocating two pages...\n"); (void)dosbrk(PAGE_SIZE * 2); markpage(p, num++); markpage(p, num++); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking (3)"); } } tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child"); } } say("Child: freeing three pages\n"); dosbrk(-PAGE_SIZE * 3); num -= 3; for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child (2)"); } } say("Child: allocating two pages\n"); dosbrk(PAGE_SIZE * 2); markpage(p, num++); markpage(p, num++); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child (3)"); } } say("Child: freeing all\n"); dosbrk(-PAGE_SIZE * num); exit(0); } say("Parent: allocating four pages\n"); dosbrk(PAGE_SIZE * 4); for (i=0; i<4; i++) { markpage(p, num++); } for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in parent"); } } say("Parent: waiting\n"); dowait(pid); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt after waiting"); } } (void)dosbrk(-PAGE_SIZE * num); tprintf("Passed sbrk test 15.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }