/* kill (built-in) a job */ int j_kill(const char *cp, int sig) { Job *j; int rv = 0; int ecode; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } if (j->pgrp == 0) { if (kill_job(j, sig) < 0) { bi_errorf("%s: %s", cp, strerror(errno)); rv = 1; } } else { if (killpg(j->pgrp, sig) < 0) { bi_errorf("%s: %s", cp, strerror(errno)); rv = 1; } } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return rv; }
int j_writei(struct inode *ip, char *src, uint off, uint n) { uint tot, m, i, j; struct buf *tbp; if(ip->type == T_DEV){ if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write) return -1; return devsw[ip->major].write(ip, src, n); } if(off + n < off) return -1; if(off + n > MAXFILE*BSIZE) n = MAXFILE*BSIZE - off; /* REAL CODE STARTS HERE */ // j_init(); b_index = 0; // new xfer, start keeping track of open bufs /* allocate all space needed */ for(i=0, j=off; i<n; i+=m, j+=m){ j_bmap(ip, j/BSIZE); m = min(n - i, BSIZE - j%BSIZE); } for(tot=0; tot<n; tot+=m, off+=m, src+=m){ bp[b_index] = bread(ip->dev, j_lookup(ip, off/BSIZE)); m = min(n - tot, BSIZE - off%BSIZE); memmove(bp[b_index]->data + off%BSIZE, src, m); b_index++; } if(n > 0 && off > ip->size){ ip->size = off; j_iupdate(ip); } journal_start(); panic("octomom"); for(i = 0; i < b_index; i++){ bwrite(bp[i]); brelse(bp[i]); } journal_end(); return n; }
/* wait for child, interruptable. */ int waitfor(const char *cp, int *sigp) { int rv; Job *j; int ecode; int flags = JW_INTERRUPT|JW_ASYNCNOTIFY; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); *sigp = 0; if (cp == (char *) 0) { /* wait for an unspecified job - always returns 0, so * don't have to worry about exited/signaled jobs */ for (j = job_list; j; j = j->next) /* at&t ksh will wait for stopped jobs - we don't */ if (j->ppid == procpid && j->state == PRUNNING) break; if (!j) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return -1; } } else if ((j = j_lookup(cp, &ecode))) { /* don't report normal job completion */ flags &= ~JW_ASYNCNOTIFY; if (j->ppid != procpid) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return -1; } } else { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); if (ecode != JL_NOSUCH) bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return -1; } /* at&t ksh will wait for stopped jobs - we don't */ rv = j_waitj(j, flags, "jw:waitfor"); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); if (rv < 0) /* we were interrupted */ *sigp = 128 + -rv; return rv; }
/* list jobs for jobs built-in */ int j_jobs(const char *cp, int slp, int nflag) /* 0: short, 1: long, 2: pgrp */ { Job *j, *tmp; int how; int zflag = 0; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); if (nflag < 0) { /* kludge: print zombies */ nflag = 0; zflag = 1; } if (cp) { int ecode; if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } } else j = job_list; how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP); for (; j; j = j->next) { if ((!(j->flags & JF_ZOMBIE) || zflag) && (!nflag || (j->flags & JF_CHANGED))) { j_print(j, how, shl_stdout); if (j->state == PEXITED || j->state == PSIGNALLED) j->flags |= JF_REMOVE; } if (cp) break; } /* Remove jobs after printing so there won't be multiple + or - jobs */ for (j = job_list; j; j = tmp) { tmp = j->next; if (j->flags & JF_REMOVE) remove_job(j, "jobs"); } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return 0; }
/* kill (built-in) a job */ int j_kill(const char *cp, int sig) { Job *j; int rv = 0; int ecode; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */ if (kill_job(j, sig) < 0) { bi_errorf("%s: %s", cp, strerror(errno)); rv = 1; } } else { #ifdef JOBS if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP)) (void) killpg(j->pgrp, SIGCONT); #endif /* JOBS */ if (killpg(j->pgrp, sig) < 0) { bi_errorf("%s: %s", cp, strerror(errno)); rv = 1; } } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return rv; }
/* fg and bg built-ins: called only if Flag(FMONITOR) set */ int j_resume(const char *cp, int bg) { Job *j; Proc *p; int ecode; int running; int rv = 0; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } if (j->pgrp == 0) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("job not job-controlled"); return 1; } if (bg) shprintf("[%d] ", j->job); running = 0; for (p = j->proc_list; p != (Proc *) 0; p = p->next) { if (p->state == PSTOPPED) { p->state = PRUNNING; p->status = 0; running = 1; } shprintf("%s%s", p->command, p->next ? "| " : null); } shprintf("%s", newline); shf_flush(shl_stdout); if (running) j->state = PRUNNING; put_job(j, PJ_PAST_STOPPED); if (bg) j_set_async(j); else { # ifdef JOBS /* attach tty to job */ if (j->state == PRUNNING) { if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) tcsetattr(tty_fd, TCSADRAIN, &j->ttystate); /* See comment in j_waitj regarding saved_ttypgrp. */ if (ttypgrp_ok && tcsetpgrp(tty_fd, (j->flags & JF_SAVEDTTYPGRP) ? j->saved_ttypgrp : j->pgrp) < 0) { if (j->flags & JF_SAVEDTTY) tcsetattr(tty_fd, TCSADRAIN, &tty_state); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("1st tcsetpgrp(%d, %d) failed: %s", tty_fd, (int) ((j->flags & JF_SAVEDTTYPGRP) ? j->saved_ttypgrp : j->pgrp), strerror(errno)); return 1; } } # endif /* JOBS */ j->flags |= JF_FG; j->flags &= ~JF_KNOWN; if (j == async_job) async_job = (Job *) 0; } if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) { int err = errno; if (!bg) { j->flags &= ~JF_FG; # ifdef JOBS if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) tcsetattr(tty_fd, TCSADRAIN, &tty_state); if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) { warningf(true, "fg: 2nd tcsetpgrp(%d, %d) failed: %s", tty_fd, (int) our_pgrp, strerror(errno)); } # endif /* JOBS */ } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("cannot continue job %s: %s", cp, strerror(err)); return 1; } if (!bg) { # ifdef JOBS if (ttypgrp_ok) { j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP); } # endif /* JOBS */ rv = j_waitj(j, JW_NONE, "jw:resume"); } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return rv; }