|
|
1.1 root 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: #ifdef BSD4_2
11: # include <sys/wait.h>
12: #else
13: # include <wait.h>
14: #endif
15: #include <signal.h>
16: #include <sgtty.h>
17:
18: typedef struct process Process;
19:
20: #define DEAD 1 /* Dead but haven't informed user yet */
21: #define STOPPED 2 /* Job stopped */
22: #define RUNNING 3 /* Just running */
23: #define NEW 4 /* This process is brand new */
24:
25: /* If process is dead, flags says how. */
26: #define EXITED 1
27: #define KILLED 2
28:
29: #define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
30:
31: #define proc_buf(p) (p->p_buffer->b_name)
32: #define proc_cmd(p) (p->p_name)
33: #define proc_state(p) (p->p_state)
34:
35: struct process {
36: Process *p_next;
37: int p_fd, /* File descriptor of ptyp? opened r/w */
38: p_pid; /* pid of child (the shell) */
39: Buffer *p_buffer; /* Add output to end of this buffer */
40: char *p_name; /* ... */
41: char p_state, /* State */
42: p_howdied, /* Killed? or Exited? */
43: p_reason, /* If signaled, p_reason is the signal; else
44: it is the the exit code */
45: p_eof; /* Received EOF, so can be free'd up */
46: Mark *p_mark; /* Where output left us. */
47: data_obj
48: *p_cmd; /* Command to call when process dies */
49: } *procs = 0,
50: *cur_proc = 0;
51:
52: char proc_prompt[80] = "% ";
53:
54: int global_fd = 1,
55: NumProcs = 0;
56:
57: #ifdef BRLUNIX
58: extern struct sg_brl sg1;
59: #else
60: extern struct sgttyb sg1;
61: #endif
62:
63: extern struct tchars tc1;
64:
65: #ifdef TIOCSLTC
66: extern struct ltchars ls1;
67: #endif
68:
69: static char *
70: pstate(p)
71: Process *p;
72: {
73: switch (proc_state(p)) {
74: case STOPPED:
75: return "Stopped";
76:
77: case RUNNING:
78: return "Running";
79:
80: case DEAD:
81: if (p->p_howdied == EXITED) {
82: if (p->p_reason == 0)
83: return "Done";
84: return sprint("exit(%d)", p->p_reason);
85: }
86: return sprint("Killed(%d)", p->p_reason);
87:
88: default:
89: return "Unknown state.";
90: }
91: }
92:
93: static Process *
94: proc_pid(pid)
95: {
96: register Process *p;
97:
98: for (p = procs; p != 0; p = p->p_next)
99: if (p->p_pid == pid)
100: break;
101:
102: return p;
103: }
104:
105: read_proc(fd)
106: register int fd;
107: {
108: register Process *p;
109: unsigned int n;
110: char ibuf[1024];
111:
112: for (p = procs; p != 0; p = p->p_next)
113: if (p->p_fd == fd)
114: break;
115:
116: if (p == 0) {
117: printf("\riproc: unknown fd %d", fd);
118: return;
119: }
120:
121: n = read(fd, ibuf, sizeof(ibuf) - 1);
122:
123: if (n == 0) {
124: proc_close(p);
125: NumProcs--;
126: return;
127: }
128:
129: ibuf[n] = '\0';
130: proc_rec(p, ibuf);
131: redisplay();
132: }
133:
134: ProcKill()
135: {
136: register Buffer *b;
137: register Process *p;
138: Process *buf_to_proc();
139: char *bname;
140:
141: bname = ask_buf(cur_proc ? cur_proc->p_buffer : (Buffer *) 0);
142:
143: if ((b = buf_exists(bname)) == 0)
144: complain("[No such buffer]");
145: if ((p = buf_to_proc(b)) == 0)
146: complain("%s not tied to a process.", bname);
147: proc_kill(p, SIGKILL);
148: }
149:
150: Process *
151: buf_to_proc(b)
152: register Buffer *b;
153: {
154: register Process *p;
155:
156: for (p = procs; p != 0; p = p->p_next)
157: if (p->p_buffer == b)
158: return p;
159: return 0;
160: }
161:
162: ProcCont()
163: {
164: if (cur_proc == 0)
165: complain("[No processes]");
166: if (cur_proc->p_state != DEAD) {
167: proc_kill(cur_proc, SIGCONT);
168: cur_proc->p_state = RUNNING;
169: }
170: }
171:
172: ProcEof()
173: {
174: send_p(tc1.t_eofc);
175: }
176:
177: ProcInt()
178: {
179: send_p(tc1.t_intrc);
180: }
181:
182: ProcQuit()
183: {
184: send_p(tc1.t_quitc);
185: }
186:
187: #ifdef TIOCSLTC
188:
189: ProcStop()
190: {
191: send_p(ls1.t_suspc);
192: }
193:
194: ProcDStop()
195: {
196: send_p(ls1.t_dsuspc);
197: }
198:
199: #endif
200:
201: send_p(c)
202: char c;
203: {
204: if (cur_proc == 0)
205: complain("[No processes]");
206: if (cur_proc->p_buffer == curbuf)
207: ToLast();
208: (void) write(cur_proc->p_fd, &c, 1);
209: }
210:
211: static
212: proc_close(p)
213: Process *p;
214: {
215: (void) close(p->p_fd);
216: global_fd &= ~(1 << p->p_fd);
217: p->p_eof++;
218: }
219:
220: do_rtp(mp)
221: register Mark *mp;
222: {
223: register Process *p = cur_proc;
224: Line *line1 = curline,
225: *line2 = mp->m_line;
226: int char1 = curchar,
227: char2 = mp->m_char;
228: char *gp;
229:
230: if (isdead(p) || p->p_buffer != curbuf)
231: return;
232:
233: (void) fixorder(&line1, &char1, &line2, &char2);
234: while (line1 != line2->l_next) {
235: gp = ltobuf(line1, genbuf) + char1;
236: if (line1 == line2)
237: gp[char2] = '\0';
238: else
239: strcat(gp, "\n");
240: (void) write(p->p_fd, gp, strlen(gp));
241: line1 = line1->l_next;
242: char1 = 0;
243: }
244: }
245:
246: /* VARARGS2 */
247:
248: static
249: proc_strt(bufname, procname, cmd)
250: char *bufname,
251: *procname,
252: *cmd;
253: {
254: Window *owind = curwind;
255: int pid;
256: Process *newp;
257: Buffer *bp;
258: char **cp;
259: int i,
260: f,
261: ttyfd;
262: long ldisc,
263: lmode;
264: register char *s,
265: *t;
266: extern int errno;
267: extern char **environ;
268: static char ttybuf[11],
269: ptybuf[11];
270: char cmdbuf[128];
271: #ifdef BRLUNIX
272: struct sg_brl sg;
273: #else
274: struct sgttyb sg;
275: #endif
276:
277: #ifdef TIOCGWINSZ
278: struct winsize win;
279: #else
280: # ifdef BTL_BLIT
281: # include <sys/jioctl.h>
282: struct jwinsize jwin;
283: # endif
284: #endif
285:
286: bp = buf_exists(bufname);
287: if (bp != 0 && IsModified(bp) && bp->b_type != B_IPROCESS && bp->b_type != B_PROCESS)
288: complain("Command would over-write buffer %s.", procname, bufname);
289: pop_wind(bufname, 1, B_IPROCESS);
290:
291: for (s = "pqrs"; *s; s++) {
292: for (t = "0123456789abcdef"; *t; t++) {
293: sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
294: if ((ttyfd = open(ptybuf, 2)) >= 0)
295: goto out;
296: }
297: }
298:
299: out: if (s == 0 && t == 0)
300: complain("[Out of ptys!]");
301:
302: strcpy(ttybuf, ptybuf);
303: ttybuf[5] = 't';
304:
305: #ifdef TIOCGETD
306: (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
307: #endif
308: #ifdef TIOCLGET
309: (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
310: #endif
311: #ifdef TIOCGWINSZ
312: (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
313: #else
314: # ifdef BTL_BLIT
315: (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
316: # endif BTL_BLIT
317: #endif
318:
319: switch (pid = fork()) {
320: case -1:
321: (void) close(ttyfd);
322: complain("[Fork failed!]");
323:
324: case 0:
325: cp = &cmd;
326:
327: for (i = 0; i < 32; i++)
328: (void) close(i);
329:
330: #ifdef TIOCNOTTY
331: if ((i = open("/dev/tty", 2)) >= 0) {
332: (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
333: (void) close(i);
334: }
335: #endif
336: i = open(ttybuf, 2);
337: for (f = 0; f <= 2; f++)
338: (void) dup2(i, f);
339:
340: #ifdef TIOCSETD
341: (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
342: #endif
343: #ifdef TIOCLSET
344: (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
345: #endif
346: #ifdef TIOCSETC
347: (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
348: #endif
349: #ifdef TIOCSLTC
350: (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
351: #endif
352:
353: #ifdef TIOCGWINSZ
354: # ifdef SIGWINCH
355: (void) signal(SIGWINCH, SIG_IGN);
356: # endif
357: win.ws_row = curwind->w_height;
358: (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
359: #else
360: # ifdef BTL_BLIT
361: jwin.bytesy = curwind->w_height;
362: (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
363: # endif
364: #endif
365:
366: sg = sg1;
367: sg.sg_flags &= ~(ECHO | CRMOD);
368: (void) stty(0, &sg);
369:
370: i = getpid();
371: (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
372: (void) setpgrp(0, i);
373: execve(cp[0], &cp[1], environ);
374: (void) write(1, "execve failed!\n", 15);
375: _exit(errno + 1);
376: }
377:
378: sighold(SIGCHLD);
379: #ifdef SIGWINCH
380: sighold(SIGWINCH);
381: #endif
382: cur_proc = newp = (Process *) emalloc(sizeof *newp);
383:
384: newp->p_fd = ttyfd;
385: newp->p_pid = pid;
386: newp->p_eof = 0;
387: newp->p_buffer = curbuf;
388:
389: cp = &cmd + 1;
390: cmdbuf[0] = '\0';
391: while (*cp != 0)
392: (void) sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", *cp++);
393:
394: newp->p_name = copystr(cmdbuf);
395: newp->p_state = RUNNING;
396: newp->p_reason = 0;
397: newp->p_mark = MakeMark(curline, curchar, FLOATER);
398:
399: newp->p_next = procs;
400: procs = newp;
401: NumProcs++;
402: global_fd |= 1 << newp->p_fd;
403: sigrelse(SIGCHLD);
404: SetWind(owind);
405: }
406:
407: pinit()
408: {
409: (void) signal(SIGCHLD, proc_child);
410: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.