This is iproc.c in view mode; [Download] [Up]
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * * is provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ***************************************************************************/ #include "jove.h" #include "termcap.h" #include "re.h" #include "ctype.h" #include "disp.h" #if defined(IPROCS) # include "fp.h" # include "iproc.h" #endif #ifdef STDARGS # include <stdarg.h> #else # include <varargs.h> #endif #ifdef IPROCS private void proc_rec proto ((Process *, char *)), proc_close proto ((Process *)), proc_kill proto((Process *, int)), SendData proto ((int)); private SIGRESULT proc_child proto((int)); #ifdef PIPEPROCS # include "iproc-pipes.c" #else # include "iproc-ptys.c" #endif char proc_prompt[128] = "% "; char * pstate(p) Process *p; { switch (proc_state(p)) { case NEW: return "New"; case STOPPED: return "Stopped"; case RUNNING: return "Running"; case DEAD: if (p->p_howdied == EXITED) { if (p->p_reason == 0) return "Done"; return sprint("Exit %d", p->p_reason); } return sprint("Killed %d", p->p_reason); default: return "Unknown state"; } } void KillProcs() { register Process *p; register int killem = -1; /* -1 means undetermined */ register char *yorn; for (p = procs; p != 0; p = p->p_next) if (!isdead(p)) { if (killem == -1) { yorn = ask("y", "Should I kill your i-processes? "); killem = (CharUpcase(*yorn) == 'Y'); } if (killem) proc_kill(p, SIGKILL); } } void pbuftiedp(b) register Buffer *b; { register Process *p = b->b_process; if (!isdead(p)) complain("Process %s, attached to %b, is %s.", proc_cmd(p), b, pstate(p)); } char dbx_parse_fmt[128] = "line \\([0-9]*\\) in \\{file,\\} *\"\\([^\"]*\\)\""; void DBXpoutput() { if (curbuf->b_process == 0) complain("[Must be in a process buffer to enable dbx mode]"); curbuf->b_process->p_dbx_mode = !curbuf->b_process->p_dbx_mode; UpdModLine = YES; } private void watch_input(m) Mark *m; { Bufpos save; char fname[FILESIZE], lineno[FILESIZE]; int lnum; Window *savew = curwind; Buffer *buf; DOTsave(&save); ToMark(m); if (dosearch(dbx_parse_fmt, FORWARD, YES) != NULL) { get_FL_info(fname, lineno); buf = do_find((Window *) 0, fname, YES); pop_wind(buf->b_name, NO, -1); lnum = atoi(lineno); SetLine(next_line(buf->b_first, lnum - 1)); SetWind(savew); } SetDot(&save); } /* Process receive: receives the characters in buf, and appends them to the buffer associated with p. */ private void proc_rec(p, buf) register Process *p; char *buf; { Buffer *saveb = curbuf; register Window *w; register Mark *savepoint; int sameplace = NO, do_disp = NO; if (curwind->w_bufp == p->p_buffer) w = curwind; else w = windbp(p->p_buffer); /* Is this window visible? */ if (w != 0) do_disp = (in_window(w, p->p_mark->m_line) != -1); SetBuf(p->p_buffer); savepoint = MakeMark(curline, curchar, M_FLOATER); ToMark(p->p_mark); /* where output last stopped */ if (savepoint->m_line == curline && savepoint->m_char == curchar) sameplace = YES; ins_str(buf, YES, WrapProcessLines ? CO : -1); if (do_disp == YES && p->p_dbx_mode == YES) watch_input(p->p_mark); MarkSet(p->p_mark, curline, curchar); if (!sameplace) ToMark(savepoint); /* back to where we were */ DelMark(savepoint); /* redisplay now, instead of right after the ins_str, so that we don't get a bouncing effect if point is not the same as the process output position */ if (do_disp) { w->w_line = curline; w->w_char = curchar; redisplay(); } SetBuf(saveb); } private void proc_kill(p, sig) register Process *p; int sig; { if (isdead(p)) return; if (killpg(p->p_pid, sig) == -1) s_mess("Cannot kill %s!", proc_buf(p)); } /* Free process CHILD. Do all the necessary cleaning up (closing fd's, etc.). */ private void free_proc(child) Process *child; { register Process *p, *prev = 0; if (!isdead(child)) return; for (p = procs; p != child; prev = p, p = p->p_next) ; if (prev == 0) procs = child->p_next; else prev->p_next = child->p_next; proc_close(child); /* if not already closed */ /* It's possible that the buffer has been given another process between the time CHILD dies and CHILD's death is noticed (via list-processes). So we only set it the buffer's process to 0 if CHILD is still the controlling process. */ if (child->p_buffer->b_process == child) { child->p_buffer->b_process = 0; } { Buffer *old = curbuf; SetBuf(child->p_buffer); DelMark(child->p_mark); SetBuf(old); } free((char *) child->p_name); free((char *) child); } void ProcList() { register Process *p, *next; char *fmt = "%-15s %-15s %-8s %s", pidstr[16]; if (procs == 0) { message("[No subprocesses]"); return; } TOstart("Process list", TRUE); Typeout(fmt, "Buffer", "Status", "Pid ", "Command"); Typeout(fmt, "------", "------", "--- ", "-------"); for (p = procs; p != 0; p = next) { next = p->p_next; swritef(pidstr, "%d", p->p_pid); Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name); if (isdead(p)) { free_proc(p); UpdModLine = YES; } } TOstop(); } private void do_rtp(mp) register Mark *mp; { register Process *p = curbuf->b_process; Line *line1 = curline, *line2 = mp->m_line; int char1 = curchar, char2 = mp->m_char; char *gp; size_t nbytes; if (isdead(p) || p->p_buffer != curbuf) return; (void) fixorder(&line1, &char1, &line2, &char2); while (line1 != line2->l_next) { gp = ltobuf(line1, genbuf) + char1; if (line1 == line2) gp[char2] = '\0'; else strcat(gp, "\n"); if ((nbytes = strlen(gp)) != 0) proc_write(p, gp, nbytes); line1 = line1->l_next; char1 = 0; } } void ProcNewline() { #ifdef ABBREV MaybeAbbrevExpand(); #endif SendData(YES); } void ProcSendData() { #ifdef ABBREV MaybeAbbrevExpand(); #endif SendData(NO); } private void SendData(newlinep) int newlinep; { register Process *p = curbuf->b_process; register char *lp, *gp; /* JF fix for better prompt handling */ if (isdead(p)) return; /* If the process mark was involved in a big deletion, because the user hit ^W or something, then let's do some magic with the process mark. Problem is that if the user yanks back the text he deleted, the mark stays at the beginning of the region, and so the next time SendData() is called the entire region will be sent. That's not good. So, to deal with that we reset the mark to the last line, after skipping over the prompt, etc. */ if (p->p_mark->m_flags & M_BIG_DELETE) { Bufpos bp; p->p_mark->m_flags &= ~M_BIG_DELETE; DOTsave(&bp); ToLast(); Bol(); /* While we're looking at a prompt, and while we're moving forward. This is for people who accidently set their process-prompt to ">*" which will always match! */ while ((LookingAt(proc_prompt, linebuf, curchar)) && (REeom > curchar)) curchar = REeom; MarkSet(p->p_mark, curline, curchar); SetDot(&bp); } if (lastp(curline)) { Eol(); if (newlinep) LineInsert(1); do_rtp(p->p_mark); MarkSet(p->p_mark, curline, curchar); } else { /* Either we're looking at a prompt, or we're not, in which case we want to strip off the beginning of the line anything that looks like what the prompt at the end of the file is. In other words, if "(dbx) stop in ProcessNewline" is the line we're on, and the last line in the buffer is "(dbx) ", then we strip off the leading "(dbx) " from this line, because we know it's part of the prompt. But this only happens if "(dbx) " isn't one of the process prompts ... follow what I'm saying? */ Bol(); if (LookingAt(proc_prompt, linebuf, curchar)) { do curchar = REeom; while ((LookingAt(proc_prompt, linebuf, curchar)) && (REeom > curchar)); strcpy(genbuf, linebuf + curchar); Eof(); ins_str(genbuf, NO, -1); } else { strcpy(genbuf, linebuf + curchar); Eof(); gp = genbuf; lp = linebuf; while (*lp == *gp && *lp != '\0') { lp += 1; gp += 1; } ins_str(gp, NO, -1); } } } void ShellProc() { char *shbuf = "*shell*"; register Buffer *b; b = buf_exists(shbuf); if (b == 0 || isdead(b->b_process)) proc_strt(shbuf, NO, Shell, "-i", (char *) 0); pop_wind(shbuf, NO, -1); } void Iprocess() { register char *command; char scratch[64], *bnm; int cnt = 1; Buffer *bp; command = ask(ShcomBuf, ProcFmt); null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1); bnm = MakeName(command); strcpy(scratch, bnm); while ((bp = buf_exists(scratch)) != NIL && !isdead(bp->b_process)) swritef(scratch, "%s.%d", bnm, cnt++); proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0); } private SIGRESULT proc_child(junk) int junk; /* needed for signal handler; not used */ { union wait w; register int pid; for (;;) { #ifndef WAIT3 pid = wait2(&w.w_status, (WNOHANG | WUNTRACED)); #else pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0); #endif if (pid <= 0) break; kill_off(pid, w); } SIGRETURN; } void kill_off(pid, w) register int pid; union wait w; { register Process *child; if ((child = proc_pid(pid)) == 0) return; UpdModLine = YES; /* we're changing state ... */ if (WIFSTOPPED(w)) child->p_state = STOPPED; else { child->p_state = DEAD; if (WIFEXITED(w)) child->p_howdied = EXITED; else if (WIFSIGNALED(w)) { child->p_reason = w_termsignum(w); child->p_howdied = KILLED; } { Buffer *save = curbuf; char mesg[128]; /* insert status message now */ swritef(mesg, "[Process %s: %s]\n", proc_cmd(child), pstate(child)); SetBuf(child->p_buffer); ins_str(mesg, NO, -1); SetBuf(save); redisplay(); } } } #endif /* IPROCS */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.