static void dovalidate(void) { const char *name; int fd, i, mykeys, keys_done, keys_to_do; int key, smallest, largest; name = PATH_SORTED; fd = doopen(name, O_RDONLY, 0); mykeys = getmykeys(); seekmyplace(name, fd); smallest = RANDOM_MAX; largest = 0; keys_done = 0; while (keys_done < mykeys) { keys_to_do = mykeys - keys_done; if (keys_to_do > WORKNUM) { keys_to_do = WORKNUM; } doexactread(name, fd, workspace, keys_to_do * sizeof(int)); for (i=0; i<keys_to_do; i++) { key = workspace[i]; if (key < 0) { complain("%s: found negative key", name); exit(1); } if (key == 0) { complain("%s: found zero key", name); exit(1); } if (key >= RANDOM_MAX) { complain("%s: found too-large key", name); exit(1); } if (key < smallest) { smallest = key; } if (key > largest) { largest = key; } } keys_done += keys_to_do; } doclose(name, fd); name = validname(me); fd = doopen(name, O_WRONLY|O_CREAT|O_TRUNC, 0664); dowrite(name, fd, &smallest, sizeof(smallest)); dowrite(name, fd, &largest, sizeof(largest)); doclose(name, fd); }
static void bin(void) { int infd, outfds[numprocs]; const char *name; int i, mykeys, keys_done, keys_to_do; int key, pivot, binnum; infd = doopen(PATH_KEYS, O_RDONLY, 0); mykeys = getmykeys(); seekmyplace(PATH_KEYS, infd); for (i=0; i<numprocs; i++) { name = binname(me, i); outfds[i] = doopen(name, O_WRONLY|O_CREAT|O_TRUNC, 0664); } pivot = (RANDOM_MAX / numprocs); keys_done = 0; while (keys_done < mykeys) { keys_to_do = mykeys - keys_done; if (keys_to_do > WORKNUM) { keys_to_do = WORKNUM; } doexactread(PATH_KEYS, infd, workspace, keys_to_do * sizeof(int)); for (i=0; i<keys_to_do; i++) { key = workspace[i]; binnum = key / pivot; if (key <= 0) { complainx("proc %d: garbage key %d", me, key); key = 0; } assert(binnum >= 0); assert(binnum < numprocs); dowrite("bin", outfds[binnum], &key, sizeof(key)); } keys_done += keys_to_do; } doclose(PATH_KEYS, infd); for (i=0; i<numprocs; i++) { doclose(binname(me, i), outfds[i]); } }
static void sortbins(void) { const char *name; int i, fd; off_t binsize; for (i=0; i<numprocs; i++) { name = binname(me, i); binsize = getsize(name); if (binsize % sizeof(int) != 0) { complainx("%s: bin size %ld no good", name, (long) binsize); exit(1); } if (binsize > (off_t) sizeof(workspace)) { complainx("proc %d: %s: bin too large", me, name); exit(1); } fd = doopen(name, O_RDWR, 0); doexactread(name, fd, workspace, binsize); sortints(workspace, binsize/sizeof(int)); dolseek(name, fd, 0, SEEK_SET); dowrite(name, fd, workspace, binsize); doclose(name, fd); } }
static void assemble(void) { off_t mypos; int i, fd; const char *args[3]; mypos = 0; for (i=0; i<me; i++) { mypos += getsize(mergedname(i)); } fd = doopen(PATH_SORTED, O_WRONLY, 0); dolseek(PATH_SORTED, fd, mypos, SEEK_SET); if (dup2(fd, STDOUT_FILENO) < 0) { complain("dup2"); exit(1); } doclose(PATH_SORTED, fd); args[0] = "cat"; args[1] = mergedname(me); args[2] = NULL; execv("/bin/cat", (char **) args); complain("/bin/cat: exec"); exit(1); }
static void docreate(const char *path) { int fd; fd = doopen(path, O_WRONLY|O_CREAT|O_TRUNC, 0664); doclose(path, fd); }
static void close_on_exec(void) { int j; for (j = UFTSIZE - 1; j >= 0; --j) { if (udata.u_cloexec & (1 << j)) doclose(j); } udata.u_cloexec = 0; }
static void cat(void) { pid_t pid; int rfd, wfd, result, status; const char *args[2]; rfd = doopen(INFILE, O_RDONLY); wfd = doopen(OUTFILE, O_WRONLY|O_CREAT|O_TRUNC); pid = fork(); if (pid < 0) { err(1, "fork"); } if (pid == 0) { /* child */ dodup2(rfd, STDIN_FILENO, INFILE); dodup2(wfd, STDOUT_FILENO, OUTFILE); doclose(rfd, INFILE); doclose(wfd, OUTFILE); args[0] = "cat"; args[1] = NULL; execv(PATH_CAT, (char **)args); warn("%s: execv", PATH_CAT); _exit(1); } /* parent */ doclose(rfd, INFILE); doclose(wfd, OUTFILE); result = waitpid(pid, &status, 0); if (result == -1) { err(1, "waitpid"); } if (WIFSIGNALED(status)) { errx(1, "pid %d: Signal %d", (int)pid, WTERMSIG(status)); } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { errx(1, "pid %d: Exit %d", (int)pid, WEXITSTATUS(status)); } }
static void randomize(void) { int fd; fd = doopen(PATH_RANDOM, O_RDONLY, 0); doexactread(PATH_RANDOM, fd, &randomseed, sizeof(randomseed)); doclose(PATH_RANDOM, fd); }
static int doexec(char *str) { char *t, *tend; char **argv; char **p; int nargs; pid_t pid; while( *str==' ' || *str=='\t' ) ++str; if( *str == '\0' ) return(-1); /* no command */ nargs = 1; for(t = str ; *t ; ) { ++nargs; while(*t!=' ' && *t!='\t' && *t!='\0') ++t; if(*t) /* replace first white space with \0, skip rest */ for( *t++ = '\0' ; *t==' ' || *t=='\t' ; ++t) ; } /* now allocate args array, copy pointer to start of each string, then terminate array with a null */ p = argv = (char **) ckalloc(nargs*sizeof(char *)); tend = t; for(t = str ; t<tend ; ) { *p++ = t; while( *t ) ++t; do { ++t; } while(t<tend && (*t==' ' || *t=='\t') ); } *p = NULL; /*TEMP for(p=argv; *p; ++p)printf("arg=%s\n", *p);*/ if((pid = fork()) == 0) { enbint(SIG_DFL); doclose(); enbint(intrupt); execvp(str, argv); printf("\n"); fatal1("Cannot load %s",str); } free( (char *) argv); return pid; }
static int doshell(char *comstring, int nohalt) { pid_t pid; if((pid = fork()) == 0) { enbint(SIG_DFL); doclose(); execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, NULL); fatal("Couldn't load Shell"); } return pid; }
/* internal function definitions */ static void acpt(struct lstn * p) { static char fnc[] = "acpt"; int r_namelen = p->r_namelen; struct sockaddr *r_name; int fd; int l_namelen = p->l_namelen; struct sockaddr *l_name; r_name = (struct sockaddr *) balloc(r_namelen); if ((fd = accept(p->fd, r_name, &r_namelen)) < 0) { if ((errno == EWOULDBLOCK) || (errno == EINTR)) { /* nothing to report */ } else if ((errno == EMFILE) || (errno == ENFILE) || (errno == ENXIO) || (errno == EIO)) { Warn("%t %s(%s): warn: accept(%d): %m\n", fnc, p->name, p->fd); } else { Warn("%t %s(%s): error: accept(%d): %m\n", fnc, p->name, p->fd); lstnclose(p); } bfree((char *) r_name); return; } l_name = (struct sockaddr *) balloc(l_namelen); if (getsockname(fd, l_name, &l_namelen) < 0) { Warn("%t %s(%s): error: getsockname(%d): %m\n", fnc, p->name, fd); doclose(fd); bfree((char *) l_name); bfree((char *) r_name); return; } p->acpttod = todsec(); (p->acptcount)++; r_name = (struct sockaddr *) brealloc((char *) r_name, r_namelen); l_name = (struct sockaddr *) brealloc((char *) l_name, l_namelen); (*(p->acptfunc)) (p, fd, r_name, r_namelen, l_name, l_namelen); return; }
arg_t _dup2(void) { if (getinode(oldd) == NULLINODE) return (-1); if (newd < 0 || newd >= UFTSIZE) { udata.u_error = EBADF; return (-1); } if (udata.u_files[newd] != NO_FILE) doclose(newd); udata.u_files[newd] = udata.u_files[oldd]; ++of_tab[udata.u_files[oldd]].o_refs; return (0); }
static void mkfile(void) { int fd; ssize_t r; fd = doopen(INFILE, O_WRONLY|O_CREAT|O_TRUNC); r = write(fd, slogan, strlen(slogan)); if (r < 0) { err(1, "%s: write", INFILE); } if ((size_t)r != strlen(slogan)) { errx(1, "%s: write: Short count (got %zd, expected %zu)", INFILE, r, strlen(slogan)); } doclose(fd, INFILE); }
static unsigned long checksum_file(const char *path) { int fd; char buf[512]; size_t count, i; unsigned long sum = 0; fd = doopen(path, O_RDONLY, 0); while ((count = doread(path, fd, buf, sizeof(buf))) > 0) { for (i=0; i<count; i++) { sum += (unsigned char) buf[i]; } } doclose(path, fd); return sum; }
static void genkeys_sub(void) { int fd, i, mykeys, keys_done, keys_to_do, value; fd = doopen(PATH_KEYS, O_WRONLY, 0); mykeys = getmykeys(); seekmyplace(PATH_KEYS, fd); srandom(seeds[me]); keys_done = 0; while (keys_done < mykeys) { keys_to_do = mykeys - keys_done; if (keys_to_do > WORKNUM) { keys_to_do = WORKNUM; } for (i=0; i<keys_to_do; i++) { value = random(); // check bounds of value assert(value >= 0); assert(value <= RANDOM_MAX); // do not allow the value to be zero or RANDOM_MAX while (value == 0 || value == RANDOM_MAX) { value = random(); } workspace[i] = value; } dowrite(PATH_KEYS, fd, workspace, keys_to_do*sizeof(int)); keys_done += keys_to_do; } doclose(PATH_KEYS, fd); }
static void chkfile(void) { char buf[256]; ssize_t r; int fd; fd = doopen(OUTFILE, O_RDONLY); r = read(fd, buf, sizeof(buf)); if (r < 0) { err(1, "%s: read", OUTFILE); } if (r == 0) { errx(1, "%s: read: Unexpected EOF", OUTFILE); } if ((size_t)r != strlen(slogan)) { errx(1, "%s: read: Short count (got %zd, expected %zu)", OUTFILE, r, strlen(slogan)); } doclose(fd, OUTFILE); }
int dotalk(const struct nh_cmd_arg *arg) { struct monst *mtmp; int tx, ty; struct obj *otmp; schar dx; schar dy; schar dz; if (!getargdir(arg, NULL, &dx, &dy, &dz)) { /* decided not to chat */ return 0; } if (is_silent(youmonst.data)) { pline("As %s, you cannot speak.", an(youmonst.data->mname)); return 0; } if (Strangled) { pline("You can't speak. You're choking!"); return 0; } if (Engulfed) { pline("They won't hear you out there."); return 0; } if (Underwater) { pline("Your speech is unintelligible underwater."); return 0; } if (!Blind && (otmp = shop_object(u.ux, u.uy)) != NULL) { /* standing on something in a shop and chatting causes the shopkeeper to describe the price(s). This can inhibit other chatting inside a shop, but that shouldn't matter much. shop_object() returns an object iff inside a shop and the shopkeeper is present and willing (not angry) and able (not asleep) to speak and the position contains any objects other than just gold. */ price_quote(otmp); return 1; } if (u.usteed && dz > 0) { if (!u.usteed->mcanmove || u.usteed->msleeping) { pline("Your steed remains silent..."); return 0; } return domonnoise(u.usteed); } if (dz) { pline("They won't hear you %s there.", dz < 0 ? "up" : "down"); return 0; } if (dx == 0 && dy == 0) { if (u.umonnum == PM_ETTIN) { pline("You discover that your other head makes boring conversation."); return 0; } pline("Talking to yourself is a bad habit for a dungeoneer."); return 0; } tx = u.ux + dx; ty = u.uy + dy; if (!isok(tx, ty)) { pline("You call out into the abyss, but nobody hears you."); return 0; } mtmp = m_at(level, tx, ty); /* Do we try to close a door on the square? We do if a) the square is known by the player to be a doorway, b) there's no invisible-I marker there, c) there's no monster in a chattable state there. */ if (!mtmp || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT) { int membg = level->locations[tx][ty].mem_bg; if (membg == S_vodoor || membg == S_vcdoor || membg == S_ndoor || membg == S_hodoor || membg == S_hcdoor) { if (!level->locations[tx][ty].mem_invis) { struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); return doclose(&newarg); } } pline("You start talking, but nobody seems to hear you."); return 0; } /* sleeping monsters won't talk, except priests (who wake up) */ if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) { /* If it is unseen, the player can't tell the difference between not noticing him and just not existing, so skip the message. */ if (canspotmon(mtmp)) pline("%s seems not to notice you.", Monnam(mtmp)); else pline("You start talking, but nobody seems to hear you."); return 0; } /* if this monster is waiting for something, prod it into action */ mtmp->mstrategy &= ~STRAT_WAITMASK; if (mtmp->mtame && mtmp->meating) { if (!canspotmon(mtmp)) map_invisible(mtmp->mx, mtmp->my); pline("%s is eating noisily.", Monnam(mtmp)); return 0; } return domonnoise(mtmp); }
static int dochat(int idx, int idy, int idz) { struct monst *mtmp; int tx, ty; struct obj *otmp; schar dx = idx; schar dy = idy; schar dz = idz; if (is_silent(youmonst.data)) { pline("As %s, you cannot speak.", an(youmonst.data->mname)); return 0; } if (Strangled) { pline("You can't speak. You're choking!"); return 0; } if (u.uswallow) { pline("They won't hear you out there."); return 0; } if (Underwater) { pline("Your speech is unintelligible underwater."); return 0; } if (!Blind && (otmp = shop_object(u.ux, u.uy)) != NULL) { /* standing on something in a shop and chatting causes the shopkeeper to describe the price(s). This can inhibit other chatting inside a shop, but that shouldn't matter much. shop_object() returns an object iff inside a shop and the shopkeeper is present and willing (not angry) and able (not asleep) to speak and the position contains any objects other than just gold. */ price_quote(otmp); return 1; } if (dx == -2 || dy == -2 || dz == -2) { if (!getdir(NULL, &dx, &dy, &dz)) { /* decided not to chat */ return 0; } } if (u.usteed && dz > 0) { if (!u.usteed->mcanmove || u.usteed->msleeping) { pline("Your steed remains silent..."); return 0; } return domonnoise(u.usteed); } if (dz) { pline("They won't hear you %s there.", dz < 0 ? "up" : "down"); return 0; } if (dx == 0 && dy == 0) { /* * Let's not include this. It raises all sorts of questions: can you wear * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith, * etc... --KAA if (u.umonnum == PM_ETTIN) { pline("You discover that your other head makes boring conversation."); return 1; } */ pline("Talking to yourself is a bad habit for a dungeoneer."); return 0; } tx = u.ux + dx; ty = u.uy + dy; mtmp = m_at(level, tx, ty); if (!mtmp || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT) { return doclose(dx, dy, 0); } /* sleeping monsters won't talk, except priests (who wake up) */ if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) { /* If it is unseen, the player can't tell the difference between not noticing him and just not existing, so skip the message. */ if (canspotmon(mtmp)) pline("%s seems not to notice you.", Monnam(mtmp)); return 0; } /* if this monster is waiting for something, prod it into action */ mtmp->mstrategy &= ~STRAT_WAITMASK; if (mtmp->mtame && mtmp->meating) { if (!canspotmon(mtmp)) map_invisible(mtmp->mx, mtmp->my); pline("%s is eating noisily.", Monnam(mtmp)); return 0; } return domonnoise(mtmp); }
/* try to open a door */ int doopen(const struct nh_cmd_arg *arg) { coord cc; struct rm *door; struct monst *mtmp; schar dx, dy, dz; if (nohands(youmonst.data)) { pline(msgc_cancelled, "You can't open, close, or unlock anything " "-- you have no hands!"); return 0; } if (u.utrap && u.utraptype == TT_PIT) { pline(msgc_cancelled, "You can't reach over the edge of the pit."); return 0; } if (!getargdir(arg, NULL, &dx, &dy, &dz)) return 0; cc.x = youmonst.mx + dx; cc.y = youmonst.my + dy; if (!isok(cc.x, cc.y)) return 0; if ((cc.x == youmonst.mx) && (cc.y == youmonst.my)) return 0; if ((mtmp = m_at(level, cc.x, cc.y)) && mtmp->m_ap_type == M_AP_FURNITURE && (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp, cc.x - youmonst.mx, cc.y - youmonst.my); return 1; } door = &level->locations[cc.x][cc.y]; if (!IS_DOOR(door->typ)) { if (is_db_wall(cc.x, cc.y)) { pline(msgc_cancelled, "There is no obvious way to open the drawbridge."); return 0; } pline(msgc_mispaste, "You %s no door there.", Blind ? "feel" : "see"); return 0; } if (door->doormask == D_ISOPEN) { struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); return doclose(&newarg); } if (!(door->doormask & D_CLOSED)) { const char *mesg; switch (door->doormask) { case D_BROKEN: mesg = " is broken"; break; case D_NODOOR: mesg = "way has no door"; break; case D_ISOPEN: mesg = " is already open"; break; default: if (last_command_was("open") && door->mem_door_l) { /* With the "open" command given explicitly (rather than implicitly via doorbumping), unlock the door. */ struct obj *bestpick = get_current_unlock_tool(); struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); if (!bestpick) pline(msgc_cancelled, "You have nothing to unlock that with."); else if (!bestpick->lastused) /* not msgc_controlhelp, or many players would get no message */ pline(msgc_hint, "Use an unlocking tool manually so I know " "which one you want to use."); else return pick_lock(bestpick, &newarg); } door->mem_door_l = 1; map_background(cc.x, cc.y, TRUE); mesg = " is locked"; break; } pline(msgc_cancelled, "This door%s.", mesg); if (Blind) feel_location(cc.x, cc.y); return 0; } if (verysmall(youmonst.data)) { pline(msgc_cancelled, "You're too small to pull the door open."); return 0; } /* door is known to be CLOSED */ if (rnl(20) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) { pline(msgc_actionok, "The door opens."); if (door->doormask & D_TRAPPED) { b_trapped("door", FINGER); door->doormask = D_NODOOR; if (*in_rooms(level, cc.x, cc.y, SHOPBASE)) add_damage(cc.x, cc.y, 0L); } else door->doormask = D_ISOPEN; if (Blind) feel_location(cc.x, cc.y); /* the hero knows she opened it */ else newsym(cc.x, cc.y); unblock_point(cc.x, cc.y); /* vision: new see through there */ } else { exercise(A_STR, TRUE); door->mem_door_l = 1; map_background(cc.x, cc.y, TRUE); pline(msgc_failrandom, "The door resists!"); } return 1; }
arg_t _close(void) { return (doclose(uindex)); }
void doexit(uint16_t val) { int16_t j; ptptr p; irqflags_t irq; #ifdef DEBUG kprintf("process %d exiting %d\n", udata.u_ptab->p_pid, val); kprintf ("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif if (udata.u_ptab->p_pid == 1) panic(PANIC_KILLED_INIT); sync(); /* Not necessary, but a good idea. */ irq = di(); /* We are exiting, hold all signals (they will never be delivered). If we don't do this we might take a signal while exiting which would be ... unfortunate */ udata.u_ptab->p_held = 0xFFFFFFFFUL; udata.u_cursig = 0; /* Discard our memory before we blow away and reuse the memory */ pagemap_free(udata.u_ptab); for (j = 0; j < UFTSIZE; ++j) { if (udata.u_files[j] != NO_FILE) doclose(j); } udata.u_ptab->p_exitval = val; i_deref(udata.u_cwd); i_deref(udata.u_root); /* Stash away child's execution tick counts in process table, * overlaying some no longer necessary stuff. * * Pedantically POSIX says we should do this at the point of wait() */ udata.u_utime += udata.u_cutime; udata.u_stime += udata.u_cstime; memcpy(&(udata.u_ptab->p_priority), &udata.u_utime, 2 * sizeof(clock_t)); for (p = ptab; p < ptab_end; ++p) { if (p->p_status == P_EMPTY || p == udata.u_ptab) continue; /* Set any child's parents to init */ if (p->p_pptr == udata.u_ptab) { p->p_pptr = ptab; /* ptab is always init */ /* Suppose our child is a zombie and init has SIGCLD blocked */ if (ptab[0].p_ignored & (1UL << SIGCHLD)) { p->p_status = P_EMPTY; } else { ssig(&ptab[0], SIGCHLD); wakeup(&ptab[0]); } } /* Send SIGHUP to any pgrp members and remove them from our pgrp */ if (p->p_pgrp == udata.u_ptab->p_pid) { p->p_pgrp = 0; ssig(p, SIGHUP); ssig(p, SIGCONT); } } tty_exit(); irqrestore(irq); #ifdef DEBUG kprintf ("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif #ifdef CONFIG_ACCT acctexit(p); #endif udata.u_page = 0xFFFFU; udata.u_page2 = 0xFFFFU; signal_parent(udata.u_ptab->p_pptr); nready--; nproc--; switchin(getproc()); panic(PANIC_DOEXIT); }
void doexit(int16_t val, int16_t val2) { int16_t j; ptptr p; irqflags_t irq; #ifdef DEBUG kprintf("process %d exiting\n", udata.u_ptab->p_pid); kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif if (udata.u_ptab->p_pid == 1) panic("killed init"); _sync(); /* Not necessary, but a good idea. */ irq = di(); /* Discard our memory before we blow away and reuse the memory */ pagemap_free(udata.u_ptab); for (j = 0; j < UFTSIZE; ++j) { if (udata.u_files[j] != NO_FILE) doclose(j); } udata.u_ptab->p_exitval = (val << 8) | (val2 & 0xff); i_deref(udata.u_cwd); i_deref(udata.u_root); /* Stash away child's execution tick counts in process table, * overlaying some no longer necessary stuff. * * Pedantically POSIX says we should do this at the point of wait() */ udata.u_utime += udata.u_cutime; udata.u_stime += udata.u_cstime; memcpy(&(udata.u_ptab->p_priority), &udata.u_utime, 2 * sizeof(clock_t)); for (p = ptab; p < ptab_end; ++p) { if (p->p_status == P_EMPTY || p == udata.u_ptab) continue; /* Set any child's parents to our parent */ if (p->p_pptr == udata.u_ptab) p->p_pptr = udata.u_ptab->p_pptr; /* Send SIGHUP to any pgrp members and remove them from our pgrp */ if (p->p_pgrp == udata.u_ptab->p_pid) { p->p_pgrp = 0; ssig(p, SIGHUP); } } tty_exit(); irqrestore(irq); #ifdef DEBUG kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif #ifdef CONFIG_ACCT acctexit(p); #endif udata.u_page = 0xFFFFU; udata.u_page2 = 0xFFFFU; /* FIXME: send SIGCLD here */ /* FIXME: POSIX.1 says that SIG_IGN for SIGCLD means don't go zombie, just clean up as we go */ /* Wake up a waiting parent, if any. */ wakeup((char *) udata.u_ptab->p_pptr); udata.u_ptab->p_status = P_ZOMBIE; nready--; nproc--; switchin(getproc()); panic("doexit: won't exit"); }
void doexit(uint16_t val) { int16_t j; ptptr p; irqflags_t irq; #ifdef DEBUG kprintf("process %d exiting\n", udata.u_ptab->p_pid); kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif if (udata.u_ptab->p_pid == 1) panic(PANIC_KILLED_INIT); sync(); /* Not necessary, but a good idea. */ irq = di(); /* Discard our memory before we blow away and reuse the memory */ pagemap_free(udata.u_ptab); for (j = 0; j < UFTSIZE; ++j) { if (udata.u_files[j] != NO_FILE) doclose(j); } udata.u_ptab->p_exitval = val; i_deref(udata.u_cwd); i_deref(udata.u_root); /* Stash away child's execution tick counts in process table, * overlaying some no longer necessary stuff. * * Pedantically POSIX says we should do this at the point of wait() */ udata.u_utime += udata.u_cutime; udata.u_stime += udata.u_cstime; memcpy(&(udata.u_ptab->p_priority), &udata.u_utime, 2 * sizeof(clock_t)); for (p = ptab; p < ptab_end; ++p) { if (p->p_status == P_EMPTY || p == udata.u_ptab) continue; /* Set any child's parents to our parent */ /* FIXME: do we need to wakeup the parent if we do this ? */ if (p->p_pptr == udata.u_ptab) p->p_pptr = udata.u_ptab->p_pptr; /* Send SIGHUP to any pgrp members and remove them from our pgrp */ if (p->p_pgrp == udata.u_ptab->p_pid) { p->p_pgrp = 0; ssig(p, SIGHUP); ssig(p, SIGCONT); } } tty_exit(); irqrestore(irq); #ifdef DEBUG kprintf ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n", udata.u_page, udata.u_ptab, udata.u_ptab->p_page); #endif #ifdef CONFIG_ACCT acctexit(p); #endif udata.u_page = 0xFFFFU; udata.u_page2 = 0xFFFFU; signal_parent(udata.u_ptab->p_pptr); nready--; nproc--; switchin(getproc()); panic(PANIC_DOEXIT); }
static void mergebins(void) { int infds[numprocs], outfd; int values[numprocs], ready[numprocs]; const char *name, *outname; int i, result; int numready, place, val, worknum; outname = mergedname(me); outfd = doopen(outname, O_WRONLY|O_CREAT|O_TRUNC, 0664); for (i=0; i<numprocs; i++) { name = binname(i, me); infds[i] = doopen(name, O_RDONLY, 0); values[i] = 0; ready[i] = 0; } worknum = 0; while (1) { numready = 0; for (i=0; i<numprocs; i++) { if (infds[i] < 0) { continue; } if (!ready[i]) { result = doread("bin", infds[i], &val, sizeof(int)); if (result == 0) { doclose("bin", infds[i]); infds[i] = -1; continue; } if ((size_t) result != sizeof(int)) { complainx("%s: read: short count", binname(i, me)); exit(1); } values[i] = val; ready[i] = 1; } numready++; } if (numready == 0) { break; } /* find the smallest */ place = -1; for (i=0; i<numprocs; i++) { if (!ready[i]) { continue; } if (place < 0 || values[i] < val) { val = values[i]; place = i; } } assert(place >= 0); workspace[worknum++] = val; if (worknum >= WORKNUM) { assert(worknum == WORKNUM); dowrite(outname, outfd, workspace, worknum * sizeof(int)); worknum = 0; } ready[place] = 0; } dowrite(outname, outfd, workspace, worknum * sizeof(int)); doclose(outname, outfd); for (i=0; i<numprocs; i++) { assert(infds[i] < 0); } }