1: /************************************************************************* 2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is * 3: * provided to you without charge for use only on a licensed Unix * 4: * system. You may copy JOVE provided that this notice is included with * 5: * the copy. You may not sell copies of this program or versions * 6: * modified for use on microcomputer systems, unless the copies are * 7: * included with a Unix system distribution and the source is provided. * 8: *************************************************************************/ 9: 10: #include "jove.h" 11: 12: #ifdef IPROCS 13: 14: int proc_child(); 15: 16: #ifdef PIPEPROCS 17: # include "iproc-pipes.c" 18: #else 19: # include "iproc-ptys.c" 20: #endif 21: 22: KillProcs() 23: { 24: register Process *p; 25: int killem = -1; /* -1 means undetermined */ 26: char *yorn; 27: 28: for (p = procs; p != 0; p = p->p_next) 29: if (!isdead(p)) { 30: if (killem == -1) { 31: yorn = ask("y", "Should I kill your i-processes? "); 32: killem = (Upper(*yorn) == 'Y'); 33: } 34: if (killem) 35: proc_kill(p, SIGKILL); 36: } 37: } 38: 39: static Process * 40: proc_exists(name) 41: char *name; 42: { 43: register Process *p; 44: 45: for (p = procs; p != 0; p = p->p_next) 46: if (strcmp(proc_buf(p), name) == 0) { 47: (void) pstate(p); 48: if (p->p_eof) { 49: DealWDeath(); 50: return 0; 51: } 52: break; 53: } 54: 55: return p; 56: } 57: 58: assign_p() 59: { 60: register Process *p; 61: 62: for (p = procs; p != 0; p = p->p_next) 63: if (p->p_buffer == curbuf) { 64: cur_proc = p; 65: break; 66: } 67: } 68: 69: pbuftiedp(b) 70: Buffer *b; 71: { 72: register Process *p; 73: 74: for (p = procs; p != 0; p = p->p_next) 75: if (p->p_buffer == b && !p->p_eof) 76: complain("[There is a process tied to %s]", proc_buf(p)); 77: } 78: 79: /* Process receive: receives the characters in buf, and appends them to 80: the buffer associated with p. */ 81: 82: static 83: proc_rec(p, buf) 84: register Process *p; 85: char *buf; 86: { 87: Buffer *saveb = curbuf; 88: Window *w; 89: Mark *savepoint; 90: int sameplace = 0, 91: do_disp = 0; 92: 93: if (curwind->w_bufp == p->p_buffer) 94: w = curwind; 95: else 96: w = windbp(p->p_buffer); /* Is this window visible? */ 97: if (w != 0) 98: do_disp = (in_window(w, p->p_mark->m_line) != -1); 99: SetBuf(p->p_buffer); 100: savepoint = MakeMark(curline, curchar, FLOATER); 101: ToMark(p->p_mark); /* Where output last stopped. */ 102: if (savepoint->m_line == curline && savepoint->m_char == curchar) 103: sameplace++; 104: 105: ins_str(buf, YES); 106: if (do_disp) { 107: w->w_line = curline; 108: w->w_char = curchar; 109: redisplay(); 110: } 111: MarkSet(p->p_mark, curline, curchar); 112: if (!sameplace) 113: ToMark(savepoint); /* Back to where we were. */ 114: DelMark(savepoint); 115: SetBuf(saveb); 116: } 117: 118: proc_kill(p, sig) 119: Process *p; 120: { 121: if (p == 0 || p->p_state == DEAD) 122: return; 123: if (killpg(p->p_pid, sig) == -1) 124: s_mess("Cannot kill %s!", proc_buf(p)); 125: } 126: 127: /* Deal with a process' death. proc_rec turns on the FREEUP bit when it 128: it gets the "EOF" from portsrv. FREEUP'd processes get unlinked from 129: the list, and the proc stucture and proc_buf(p) get free'd up, here. */ 130: 131: static 132: DealWDeath() 133: { 134: register Process *p, 135: *next, 136: *prev = 0; 137: 138: for (p = procs; p != 0; p = next) { 139: next = p->p_next; 140: if (!p->p_eof) { 141: prev = p; 142: continue; 143: } 144: if (cur_proc == p) 145: cur_proc = next ? next : prev; 146: proc_close(p); 147: free((char *) p->p_name); 148: free((char *) p); 149: if (prev) 150: prev->p_next = next; 151: else 152: procs = next; 153: } 154: } 155: 156: ProcList() 157: { 158: register Process *p; 159: char *fmt = "%-15s %-15s %-8s %s", 160: pidstr[10]; 161: 162: if (procs == 0) { 163: message("[No subprocesses]"); 164: return; 165: } 166: TOstart("Process list", TRUE); 167: 168: Typeout(fmt, "Buffer", "Status", "Pid ", "Command"); 169: Typeout(fmt, "------", "------", "--- ", "-------"); 170: for (p = procs; p != 0; p = p->p_next) { 171: sprintf(pidstr, "%d", p->p_pid); 172: Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name); 173: } 174: DealWDeath(); 175: TOstop(); 176: } 177: 178: ProcNewline() 179: { 180: if (isdead(cur_proc)) 181: return; 182: if (lastp(curline)) { 183: Eol(); 184: LineInsert(); 185: do_rtp(cur_proc->p_mark); 186: MarkSet(cur_proc->p_mark, curline, curchar); 187: } else { 188: Bol(); 189: while (LookingAt(proc_prompt, linebuf, curchar)) 190: SetDot(dosearch(proc_prompt, 1, 1)); 191: strcpy(genbuf, linebuf + curchar); 192: ToLast(); 193: ins_str(genbuf, NO); 194: } 195: } 196: 197: IShell() 198: { 199: char shell[30]; 200: int number = 1; 201: 202: do 203: sprintf(shell, "shell-%d", number++); 204: while (proc_exists(shell)); 205: 206: proc_strt(shell, "i-shell", Shell, basename(Shell), "-i", 0); 207: SetWind(windlook(shell)); 208: } 209: 210: Iprocess() 211: { 212: extern char ShcomBuf[100], 213: *MakeName(); 214: char *command; 215: 216: command = ask(ShcomBuf, ProcFmt); 217: null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1); 218: proc_strt(MakeName(command), command, Shell, basename(Shell), ShFlags, command, 0); 219: } 220: 221: proc_child() 222: { 223: union wait w; 224: int pid; 225: 226: for (;;) { 227: #ifndef VMUNIX 228: pid = wait2(&w.w_status, (WNOHANG | WUNTRACED)); 229: #else 230: pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0); 231: #endif 232: if (pid <= 0) 233: break; 234: kill_off(pid, w); 235: } 236: } 237: 238: kill_off(pid, w) 239: int pid; 240: union wait w; 241: { 242: Process *child; 243: 244: if ((child = proc_pid(pid)) == 0) 245: return; 246: 247: if (WIFSTOPPED(w)) 248: child->p_state = STOPPED; 249: else { 250: child->p_state = DEAD; 251: if (WIFEXITED(w)) 252: child->p_howdied = EXITED; 253: else if (WIFSIGNALED(w)) { 254: child->p_reason = w.w_termsig; 255: child->p_howdied = KILLED; 256: } 257: proc_close(child); 258: } 259: s_mess("%s [%s] %s", pstate(child), proc_buf(child), proc_cmd(child)); 260: } 261: 262: /* Push/pod process bindings. I openly acknowledge that this is a 263: kludge, but I can't be bothered making it right. */ 264: 265: struct proc_bind { 266: int pb_key; 267: data_obj **pb_map; 268: data_obj *pb_push; 269: data_obj *pb_cmd; 270: struct proc_bind *pb_next; 271: }; 272: 273: struct proc_bind *PBinds = 0; 274: 275: PopPBs() 276: { 277: register struct proc_bind *p; 278: 279: for (p = PBinds; p != 0; p = p->pb_next) 280: p->pb_map[p->pb_key] = p->pb_push; 281: } 282: 283: PushPBs() 284: { 285: register struct proc_bind *p; 286: 287: for (p = PBinds; p != 0; p = p->pb_next) { 288: p->pb_push = p->pb_map[p->pb_key]; 289: p->pb_map[p->pb_key] = p->pb_cmd; 290: } 291: } 292: /* VARARGS0 */ 293: 294: ProcBind() 295: { 296: data_obj *d; 297: 298: if ((d = findcom(ProcFmt, NOTHING)) == 0) 299: return; 300: s_mess(": %f %s ", d->Name); 301: ProcB2(mainmap, EOF, d); 302: } 303: 304: ProcB2(map, lastkey, cmd) 305: data_obj **map, 306: *cmd; 307: { 308: register struct proc_bind *p; 309: data_obj **nextmap; 310: int c; 311: 312: c = addgetc(); 313: if (c == EOF) { 314: if (lastkey == EOF) 315: complain("[Empty key sequence]"); 316: complain("[Unexpected end-of-line]"); 317: } else { 318: if (nextmap = IsPrefix(map[c])) 319: ProcB2(nextmap, c, cmd); 320: else { 321: if (curbuf->b_type == B_IPROCESS) 322: PopPBs(); 323: 324: for (p = PBinds; p != 0; p = p->pb_next) 325: if (p->pb_key == c && p->pb_map == map) 326: break; 327: if (p == 0) { 328: p = (struct proc_bind *) emalloc(sizeof *p); 329: p->pb_next = PBinds; 330: PBinds = p; 331: } 332: p->pb_map = map; 333: p->pb_key = c; 334: p->pb_cmd = cmd; 335: 336: if (curbuf->b_type == B_IPROCESS) 337: PushPBs(); 338: } 339: } 340: } 341: 342: #endif IPROCS