GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/csh/proc.c Lines: 0 639 0.0 %
Date: 2017-11-13 Branches: 0 563 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: proc.c,v 1.31 2017/07/22 09:37:21 anton Exp $	*/
2
/*	$NetBSD: proc.c,v 1.9 1995/04/29 23:21:33 mycroft Exp $	*/
3
4
/*-
5
 * Copyright (c) 1980, 1991, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/wait.h>
35
#include <errno.h>
36
#include <unistd.h>
37
#include <limits.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <stdarg.h>
41
42
#include "csh.h"
43
#include "dir.h"
44
#include "proc.h"
45
#include "extern.h"
46
47
#define BIGINDEX	9	/* largest desirable job index */
48
49
static struct rusage zru;
50
51
static void	 pflushall(void);
52
static void	 pflush(struct process *);
53
static void	 pclrcurr(struct process *);
54
static void	 padd(struct command *);
55
static int	 pprint(struct process *, int);
56
static void	 ptprint(struct process *);
57
static void	 pads(Char *);
58
static void	 pkill(Char **v, int);
59
static struct	process
60
		*pgetcurr(struct process *);
61
static void	 okpcntl(void);
62
63
/*
64
 * pchild - called at interrupt level by the SIGCHLD signal
65
 *	indicating that at least one child has terminated or stopped
66
 *	thus at least one wait system call will definitely return a
67
 *	childs status.  Top level routines (like pwait) must be sure
68
 *	to mask interrupts when playing with the proclist data structures!
69
 */
70
/* ARGUSED */
71
void
72
pchild(int notused)
73
{
74
    struct process *pp;
75
    struct process *fp;
76
    int pid;
77
    extern int insource;
78
    int save_errno = errno;
79
    int w;
80
    int     jobflags;
81
    struct rusage ru;
82
83
loop:
84
    errno = 0;			/* reset, just in case */
85
    pid = wait3(&w,
86
       (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
87
88
    if (pid <= 0) {
89
	if (errno == EINTR) {
90
	    errno = 0;
91
	    goto loop;
92
	}
93
	pnoprocesses = pid == -1;
94
	errno = save_errno;
95
	return;
96
    }
97
    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
98
	if (pid == pp->p_pid)
99
	    goto found;
100
    goto loop;
101
found:
102
    if (pid == atoi(short2str(value(STRchild))))
103
	unsetv(STRchild);
104
    pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
105
    if (WIFSTOPPED(w)) {
106
	pp->p_flags |= PSTOPPED;
107
	pp->p_reason = WSTOPSIG(w);
108
    }
109
    else {
110
	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
111
	    (void) clock_gettime(CLOCK_MONOTONIC, &pp->p_etime);
112
113
	pp->p_rusage = ru;
114
	if (WIFSIGNALED(w)) {
115
	    if (WTERMSIG(w) == SIGINT)
116
		pp->p_flags |= PINTERRUPTED;
117
	    else
118
		pp->p_flags |= PSIGNALED;
119
	    if (WCOREDUMP(w))
120
		pp->p_flags |= PDUMPED;
121
	    pp->p_reason = WTERMSIG(w);
122
	}
123
	else {
124
	    pp->p_reason = WEXITSTATUS(w);
125
	    if (pp->p_reason != 0)
126
		pp->p_flags |= PAEXITED;
127
	    else
128
		pp->p_flags |= PNEXITED;
129
	}
130
    }
131
    jobflags = 0;
132
    fp = pp;
133
    do {
134
	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
135
	    !child && adrof(STRtime) &&
136
	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
137
	    >= atoi(short2str(value(STRtime))))
138
	    fp->p_flags |= PTIME;
139
	jobflags |= fp->p_flags;
140
    } while ((fp = fp->p_friends) != pp);
141
    pp->p_flags &= ~PFOREGND;
142
    if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
143
	pp->p_flags &= ~PPTIME;
144
	pp->p_flags |= PTIME;
145
    }
146
    if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
147
	fp = pp;
148
	do {
149
	    if (fp->p_flags & PSTOPPED)
150
		fp->p_flags |= PREPORTED;
151
	} while ((fp = fp->p_friends) != pp);
152
	while (fp->p_pid != fp->p_jobid)
153
	    fp = fp->p_friends;
154
	if (jobflags & PSTOPPED) {
155
	    if (pcurrent && pcurrent != fp)
156
		pprevious = pcurrent;
157
	    pcurrent = fp;
158
	}
159
	else
160
	    pclrcurr(fp);
161
	if (jobflags & PFOREGND) {
162
	    if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
163
		!eq(dcwd->di_name, fp->p_cwd->di_name)) {
164
		;		/* print in pjwait */
165
	    }
166
	    /* PWP: print a newline after ^C */
167
	    else if (jobflags & PINTERRUPTED) {
168
		(void) vis_fputc('\r' | QUOTE, cshout);
169
		(void) fputc('\n', cshout);
170
	    }
171
	}
172
	else {
173
	    if (jobflags & PNOTIFY || adrof(STRnotify)) {
174
		(void) vis_fputc('\r' | QUOTE, cshout);
175
		(void) fputc('\n', cshout);
176
		(void) pprint(pp, NUMBER | NAME | REASON);
177
		if ((jobflags & PSTOPPED) == 0)
178
		    pflush(pp);
179
	    }
180
	    else {
181
		fp->p_flags |= PNEEDNOTE;
182
		neednote++;
183
	    }
184
	}
185
    }
186
    goto loop;
187
}
188
189
void
190
pnote(void)
191
{
192
    struct process *pp;
193
    int     flags;
194
    sigset_t sigset, osigset;
195
196
    neednote = 0;
197
    sigemptyset(&sigset);
198
    sigaddset(&sigset, SIGCHLD);
199
    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
200
	if (pp->p_flags & PNEEDNOTE) {
201
	    sigprocmask(SIG_BLOCK, &sigset, &osigset);
202
	    pp->p_flags &= ~PNEEDNOTE;
203
	    flags = pprint(pp, NUMBER | NAME | REASON);
204
	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
205
		pflush(pp);
206
	    sigprocmask(SIG_SETMASK, &osigset, NULL);
207
	}
208
    }
209
}
210
211
/*
212
 * pwait - wait for current job to terminate, maintaining integrity
213
 *	of current and previous job indicators.
214
 */
215
void
216
pwait(void)
217
{
218
    struct process *fp, *pp;
219
    sigset_t sigset, osigset;
220
221
    /*
222
     * Here's where dead procs get flushed.
223
     */
224
    sigemptyset(&sigset);
225
    sigaddset(&sigset, SIGCHLD);
226
    sigprocmask(SIG_BLOCK, &sigset, &osigset);
227
    for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
228
	if (pp->p_pid == 0) {
229
	    fp->p_next = pp->p_next;
230
	    free(pp->p_command);
231
	    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
232
		if (pp->p_cwd->di_next == 0)
233
		    dfree(pp->p_cwd);
234
	    free(pp);
235
	    pp = fp;
236
	}
237
    sigprocmask(SIG_SETMASK, &osigset, NULL);
238
    pjwait(pcurrjob);
239
}
240
241
242
/*
243
 * pjwait - wait for a job to finish or become stopped
244
 *	It is assumed to be in the foreground state (PFOREGND)
245
 */
246
void
247
pjwait(struct process *pp)
248
{
249
    struct process *fp;
250
    int     jobflags, reason;
251
    sigset_t sigset, osigset;
252
253
    while (pp->p_pid != pp->p_jobid)
254
	pp = pp->p_friends;
255
    fp = pp;
256
257
    do {
258
	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
259
	    (void) fprintf(csherr, "BUG: waiting for background job!\n");
260
    } while ((fp = fp->p_friends) != pp);
261
    /*
262
     * Now keep pausing as long as we are not interrupted (SIGINT), and the
263
     * target process, or any of its friends, are running
264
     */
265
    fp = pp;
266
    sigemptyset(&sigset);
267
    sigaddset(&sigset, SIGCHLD);
268
    sigprocmask(SIG_BLOCK, &sigset, &osigset);
269
    for (;;) {
270
	sigemptyset(&sigset);
271
	sigaddset(&sigset, SIGCHLD);
272
	sigprocmask(SIG_BLOCK, &sigset, NULL);
273
	jobflags = 0;
274
	do
275
	    jobflags |= fp->p_flags;
276
	while ((fp = (fp->p_friends)) != pp);
277
	if ((jobflags & PRUNNING) == 0)
278
	    break;
279
	sigset = osigset;
280
	sigdelset(&sigset, SIGCHLD);
281
	sigsuspend(&sigset);
282
    }
283
    sigprocmask(SIG_SETMASK, &osigset, NULL);
284
    if (tpgrp > 0)		/* get tty back */
285
	(void) tcsetpgrp(FSHTTY, tpgrp);
286
    if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
287
	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
288
	if (jobflags & PSTOPPED) {
289
	    (void) fputc('\n', cshout);
290
	    if (adrof(STRlistjobs)) {
291
		Char   *jobcommand[3];
292
293
		jobcommand[0] = STRjobs;
294
		if (eq(value(STRlistjobs), STRlong))
295
		    jobcommand[1] = STRml;
296
		else
297
		    jobcommand[1] = NULL;
298
		jobcommand[2] = NULL;
299
300
		dojobs(jobcommand, NULL);
301
		(void) pprint(pp, SHELLDIR);
302
	    }
303
	    else
304
		(void) pprint(pp, AREASON | SHELLDIR);
305
	}
306
	else
307
	    (void) pprint(pp, AREASON | SHELLDIR);
308
    }
309
    if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
310
	(!gointr || !eq(gointr, STRminus))) {
311
	if ((jobflags & PSTOPPED) == 0)
312
	    pflush(pp);
313
	pintr1(0);
314
	/* NOTREACHED */
315
    }
316
    reason = 0;
317
    fp = pp;
318
    do {
319
	if (fp->p_reason)
320
	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
321
		fp->p_reason | META : fp->p_reason;
322
    } while ((fp = fp->p_friends) != pp);
323
    if ((reason != 0) && (adrof(STRprintexitvalue))) {
324
	(void) fprintf(cshout, "Exit %d\n", reason);
325
    }
326
    set(STRstatus, putn(reason));
327
    if (reason && exiterr)
328
	exitstat();
329
    pflush(pp);
330
}
331
332
/*
333
 * dowait - wait for all processes to finish
334
 */
335
void
336
/*ARGSUSED*/
337
dowait(Char **v, struct command *t)
338
{
339
    struct process *pp;
340
    sigset_t sigset, osigset;
341
342
    pjobs++;
343
    sigemptyset(&sigset);
344
    sigaddset(&sigset, SIGCHLD);
345
    sigprocmask(SIG_BLOCK, &sigset, &osigset);
346
loop:
347
    for (pp = proclist.p_next; pp; pp = pp->p_next)
348
	if (pp->p_pid &&	/* pp->p_pid == pp->p_jobid && */
349
	    pp->p_flags & PRUNNING) {
350
	    sigemptyset(&sigset);
351
	    sigsuspend(&sigset);
352
	    goto loop;
353
	}
354
    sigprocmask(SIG_SETMASK, &osigset, NULL);
355
    pjobs = 0;
356
}
357
358
/*
359
 * pflushall - flush all jobs from list (e.g. at fork())
360
 */
361
static void
362
pflushall(void)
363
{
364
    struct process *pp;
365
366
    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
367
	if (pp->p_pid)
368
	    pflush(pp);
369
}
370
371
/*
372
 * pflush - flag all process structures in the same job as the
373
 *	the argument process for deletion.  The actual free of the
374
 *	space is not done here since pflush is called at interrupt level.
375
 */
376
static void
377
pflush(struct process *pp)
378
{
379
    struct process *np;
380
    int idx;
381
382
    if (pp->p_pid == 0) {
383
	(void) fprintf(csherr, "BUG: process flushed twice");
384
	return;
385
    }
386
    while (pp->p_pid != pp->p_jobid)
387
	pp = pp->p_friends;
388
    pclrcurr(pp);
389
    if (pp == pcurrjob)
390
	pcurrjob = 0;
391
    idx = pp->p_index;
392
    np = pp;
393
    do {
394
	np->p_index = np->p_pid = 0;
395
	np->p_flags &= ~PNEEDNOTE;
396
    } while ((np = np->p_friends) != pp);
397
    if (idx == pmaxindex) {
398
	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
399
	    if (np->p_index > idx)
400
		idx = np->p_index;
401
	pmaxindex = idx;
402
    }
403
}
404
405
/*
406
 * pclrcurr - make sure the given job is not the current or previous job;
407
 *	pp MUST be the job leader
408
 */
409
static void
410
pclrcurr(struct process *pp)
411
{
412
413
    if (pp == pcurrent)
414
	if (pprevious != NULL) {
415
	    pcurrent = pprevious;
416
	    pprevious = pgetcurr(pp);
417
	}
418
	else {
419
	    pcurrent = pgetcurr(pp);
420
	    pprevious = pgetcurr(pp);
421
	}
422
    else if (pp == pprevious)
423
	pprevious = pgetcurr(pp);
424
}
425
426
/* +4 here is 1 for '\0', 1 ea for << >& >> */
427
static Char command[PMAXLEN + 4];
428
static int cmdlen;
429
static Char *cmdp;
430
431
/*
432
 * palloc - allocate a process structure and fill it up.
433
 *	an important assumption is made that the process is running.
434
 */
435
void
436
palloc(int pid, struct command *t)
437
{
438
    struct process *pp;
439
    int     i;
440
441
    pp = xcalloc(1, (size_t) sizeof(struct process));
442
    pp->p_pid = pid;
443
    pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
444
    if (t->t_dflg & F_TIME)
445
	pp->p_flags |= PPTIME;
446
    cmdp = command;
447
    cmdlen = 0;
448
    padd(t);
449
    *cmdp++ = 0;
450
    if (t->t_dflg & F_PIPEOUT) {
451
	pp->p_flags |= PPOU;
452
	if (t->t_dflg & F_STDERR)
453
	    pp->p_flags |= PERR;
454
    }
455
    pp->p_command = Strsave(command);
456
    if (pcurrjob) {
457
	struct process *fp;
458
459
	/* careful here with interrupt level */
460
	pp->p_cwd = 0;
461
	pp->p_index = pcurrjob->p_index;
462
	pp->p_friends = pcurrjob;
463
	pp->p_jobid = pcurrjob->p_pid;
464
	for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
465
	    continue;
466
	fp->p_friends = pp;
467
    }
468
    else {
469
	pcurrjob = pp;
470
	pp->p_jobid = pid;
471
	pp->p_friends = pp;
472
	pp->p_cwd = dcwd;
473
	dcwd->di_count++;
474
	if (pmaxindex < BIGINDEX)
475
	    pp->p_index = ++pmaxindex;
476
	else {
477
	    struct process *np;
478
479
	    for (i = 1;; i++) {
480
		for (np = proclist.p_next; np; np = np->p_next)
481
		    if (np->p_index == i)
482
			goto tryagain;
483
		pp->p_index = i;
484
		if (i > pmaxindex)
485
		    pmaxindex = i;
486
		break;
487
	tryagain:;
488
	    }
489
	}
490
	if (pcurrent == NULL)
491
	    pcurrent = pp;
492
	else if (pprevious == NULL)
493
	    pprevious = pp;
494
    }
495
    pp->p_next = proclist.p_next;
496
    proclist.p_next = pp;
497
    (void) clock_gettime(CLOCK_MONOTONIC, &pp->p_btime);
498
}
499
500
static void
501
padd(struct command *t)
502
{
503
    Char  **argp;
504
505
    if (t == 0)
506
	return;
507
    switch (t->t_dtyp) {
508
509
    case NODE_PAREN:
510
	pads(STRLparensp);
511
	padd(t->t_dspr);
512
	pads(STRspRparen);
513
	break;
514
515
    case NODE_COMMAND:
516
	for (argp = t->t_dcom; *argp; argp++) {
517
	    pads(*argp);
518
	    if (argp[1])
519
		pads(STRspace);
520
	}
521
	break;
522
523
    case NODE_OR:
524
    case NODE_AND:
525
    case NODE_PIPE:
526
    case NODE_LIST:
527
	padd(t->t_dcar);
528
	switch (t->t_dtyp) {
529
	case NODE_OR:
530
	    pads(STRspor2sp);
531
	    break;
532
	case NODE_AND:
533
	    pads(STRspand2sp);
534
	    break;
535
	case NODE_PIPE:
536
	    pads(STRsporsp);
537
	    break;
538
	case NODE_LIST:
539
	    pads(STRsemisp);
540
	    break;
541
	}
542
	padd(t->t_dcdr);
543
	return;
544
    }
545
    if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
546
	pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
547
	pads(t->t_dlef);
548
    }
549
    if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
550
	pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
551
	if (t->t_dflg & F_STDERR)
552
	    pads(STRand);
553
	pads(STRspace);
554
	pads(t->t_drit);
555
    }
556
}
557
558
static void
559
pads(Char *cp)
560
{
561
    int i;
562
563
    /*
564
     * Avoid the Quoted Space alias hack! Reported by:
565
     * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
566
     */
567
    if (cp[0] == STRQNULL[0])
568
	cp++;
569
570
    i = Strlen(cp);
571
572
    if (cmdlen >= PMAXLEN)
573
	return;
574
    if (cmdlen + i >= PMAXLEN) {
575
	(void) Strlcpy(cmdp, STRsp3dots, PMAXLEN - cmdlen);
576
	cmdlen = PMAXLEN;
577
	cmdp += 4;
578
	return;
579
    }
580
    (void) Strlcpy(cmdp, cp, PMAXLEN - cmdlen);
581
    cmdp += i;
582
    cmdlen += i;
583
}
584
585
/*
586
 * psavejob - temporarily save the current job on a one level stack
587
 *	so another job can be created.  Used for { } in exp6
588
 *	and `` in globbing.
589
 */
590
void
591
psavejob(void)
592
{
593
594
    pholdjob = pcurrjob;
595
    pcurrjob = NULL;
596
}
597
598
/*
599
 * prestjob - opposite of psavejob.  This may be missed if we are interrupted
600
 *	somewhere, but pendjob cleans up anyway.
601
 */
602
void
603
prestjob(void)
604
{
605
606
    pcurrjob = pholdjob;
607
    pholdjob = NULL;
608
}
609
610
/*
611
 * pendjob - indicate that a job (set of commands) has been completed
612
 *	or is about to begin.
613
 */
614
void
615
pendjob(void)
616
{
617
    struct process *pp, *tp;
618
619
    if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
620
	pp = pcurrjob;
621
	while (pp->p_pid != pp->p_jobid)
622
	    pp = pp->p_friends;
623
	(void) fprintf(cshout, "[%d]", pp->p_index);
624
	tp = pp;
625
	do {
626
	    (void) fprintf(cshout, " %d", pp->p_pid);
627
	    pp = pp->p_friends;
628
	} while (pp != tp);
629
	(void) fputc('\n', cshout);
630
    }
631
    pholdjob = pcurrjob = 0;
632
}
633
634
/*
635
 * pprint - print a job
636
 */
637
static int
638
pprint(struct process *pp, bool flag)
639
{
640
    int status, reason;
641
    struct process *tp;
642
    int     jobflags, pstatus;
643
    bool hadnl = 1;	/* did we just have a newline */
644
645
    (void) fpurge(cshout);
646
647
    while (pp->p_pid != pp->p_jobid)
648
	pp = pp->p_friends;
649
    if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
650
	pp->p_flags &= ~PPTIME;
651
	pp->p_flags |= PTIME;
652
    }
653
    tp = pp;
654
    status = reason = -1;
655
    jobflags = 0;
656
    do {
657
	jobflags |= pp->p_flags;
658
	pstatus = pp->p_flags & PALLSTATES;
659
	if (tp != pp && !hadnl && !(flag & FANCY) &&
660
	    ((pstatus == status && pp->p_reason == reason) ||
661
	     !(flag & REASON))) {
662
	    (void) fputc(' ', cshout);
663
	    hadnl = 0;
664
	}
665
	else {
666
	    if (tp != pp && !hadnl) {
667
		(void) fputc('\n', cshout);
668
		hadnl = 1;
669
	    }
670
	    if (flag & NUMBER) {
671
		if (pp == tp)
672
		    (void) fprintf(cshout, "[%d]%s %c ", pp->p_index,
673
			    pp->p_index < 10 ? " " : "",
674
			    pp == pcurrent ? '+' :
675
			    (pp == pprevious ? '-' : ' '));
676
		else
677
		    (void) fprintf(cshout, "       ");
678
		hadnl = 0;
679
	    }
680
	    if (flag & FANCY) {
681
		(void) fprintf(cshout, "%5d ", pp->p_pid);
682
		hadnl = 0;
683
	    }
684
	    if (flag & (REASON | AREASON)) {
685
		int width = 0;
686
		if (flag & NAME)
687
		    width = -23;
688
		if (pstatus == status)
689
		    if (pp->p_reason == reason) {
690
			(void) fprintf(cshout, "%*s", width, "");
691
			hadnl = 0;
692
			goto prcomd;
693
		    }
694
		    else
695
			reason = pp->p_reason;
696
		else {
697
		    status = pstatus;
698
		    reason = pp->p_reason;
699
		}
700
		switch (status) {
701
702
		case PRUNNING:
703
		    (void) fprintf(cshout, "%*s", width, "Running ");
704
		    hadnl = 0;
705
		    break;
706
707
		case PINTERRUPTED:
708
		case PSTOPPED:
709
		case PSIGNALED:
710
		    /*
711
		     * tell what happened to the background job
712
		     * From: Michael Schroeder
713
		     * <mlschroe@immd4.informatik.uni-erlangen.de>
714
		     */
715
		    if ((flag & REASON)
716
			|| ((flag & AREASON)
717
			    && reason != SIGINT
718
			    && (reason != SIGPIPE
719
				|| (pp->p_flags & PPOU) == 0))) {
720
			(void) fprintf(cshout, "%*s", width,
721
				       sys_siglist[(unsigned char)
722
						   pp->p_reason]);
723
			hadnl = 0;
724
		    }
725
		    break;
726
727
		case PNEXITED:
728
		case PAEXITED:
729
		    if (flag & REASON) {
730
			if (pp->p_reason)
731
			    (void) fprintf(cshout, "Exit %-18d", pp->p_reason);
732
			else
733
			    (void) fprintf(cshout, "%*s", width, "Done");
734
			hadnl = 0;
735
		    }
736
		    break;
737
738
		default:
739
		    (void) fprintf(csherr, "BUG: status=%-9o", status);
740
		}
741
	    }
742
	}
743
prcomd:
744
	if (flag & NAME) {
745
	    (void) fprintf(cshout, "%s", vis_str(pp->p_command));
746
	    if (pp->p_flags & PPOU)
747
		(void) fprintf(cshout, " |");
748
	    if (pp->p_flags & PERR)
749
		(void) fputc('&', cshout);
750
	    hadnl = 0;
751
	}
752
	if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) {
753
	    (void) fprintf(cshout, " (core dumped)");
754
	    hadnl = 0;
755
	}
756
	if (tp == pp->p_friends) {
757
	    if (flag & AMPERSAND) {
758
		(void) fprintf(cshout, " &");
759
		hadnl = 0;
760
	    }
761
	    if (flag & JOBDIR &&
762
		!eq(tp->p_cwd->di_name, dcwd->di_name)) {
763
		(void) fprintf(cshout, " (wd: ");
764
		dtildepr(value(STRhome), tp->p_cwd->di_name);
765
		(void) fputc(')', cshout);
766
		hadnl = 0;
767
	    }
768
	}
769
	if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
770
	    if (!hadnl)
771
		(void) fprintf(cshout, "\n\t");
772
	    prusage(&zru, &pp->p_rusage, &pp->p_etime,
773
		    &pp->p_btime);
774
	    hadnl = 1;
775
	}
776
	if (tp == pp->p_friends) {
777
	    if (!hadnl) {
778
		(void) fputc('\n', cshout);
779
		hadnl = 1;
780
	    }
781
	    if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
782
		(void) fprintf(cshout, "(wd now: ");
783
		dtildepr(value(STRhome), dcwd->di_name);
784
		(void) fprintf(cshout, ")\n");
785
		hadnl = 1;
786
	    }
787
	}
788
    } while ((pp = pp->p_friends) != tp);
789
    if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
790
	if (jobflags & NUMBER)
791
	    (void) fprintf(cshout, "       ");
792
	ptprint(tp);
793
	hadnl = 1;
794
    }
795
    (void) fflush(cshout);
796
    return (jobflags);
797
}
798
799
static void
800
ptprint(struct process *tp)
801
{
802
    struct timespec tetime, diff;
803
    static struct timespec ztime;
804
    struct rusage ru;
805
    static struct rusage zru;
806
    struct process *pp = tp;
807
808
    ru = zru;
809
    tetime = ztime;
810
    do {
811
	ruadd(&ru, &pp->p_rusage);
812
	timespecsub(&pp->p_etime, &pp->p_btime, &diff);
813
	if (timespeccmp(&diff, &tetime, >))
814
	    tetime = diff;
815
    } while ((pp = pp->p_friends) != tp);
816
    prusage(&zru, &ru, &tetime, &ztime);
817
}
818
819
/*
820
 * dojobs - print all jobs
821
 */
822
void
823
/*ARGSUSED*/
824
dojobs(Char **v, struct command *t)
825
{
826
    struct process *pp;
827
    int flag = NUMBER | NAME | REASON;
828
    int     i;
829
830
    if (chkstop)
831
	chkstop = 2;
832
    if (*++v) {
833
	if (v[1] || !eq(*v, STRml))
834
	    stderror(ERR_JOBS);
835
	flag |= FANCY | JOBDIR;
836
    }
837
    for (i = 1; i <= pmaxindex; i++)
838
	for (pp = proclist.p_next; pp; pp = pp->p_next)
839
	    if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
840
		pp->p_flags &= ~PNEEDNOTE;
841
		if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
842
		    pflush(pp);
843
		break;
844
	    }
845
}
846
847
/*
848
 * dofg - builtin - put the job into the foreground
849
 */
850
void
851
/*ARGSUSED*/
852
dofg(Char **v, struct command *t)
853
{
854
    struct process *pp;
855
856
    okpcntl();
857
    ++v;
858
    do {
859
	pp = pfind(*v);
860
	pstart(pp, 1);
861
	pjwait(pp);
862
    } while (*v && *++v);
863
}
864
865
/*
866
 * %... - builtin - put the job into the foreground
867
 */
868
void
869
/*ARGSUSED*/
870
dofg1(Char **v, struct command *t)
871
{
872
    struct process *pp;
873
874
    okpcntl();
875
    pp = pfind(v[0]);
876
    pstart(pp, 1);
877
    pjwait(pp);
878
}
879
880
/*
881
 * dobg - builtin - put the job into the background
882
 */
883
void
884
/*ARGSUSED*/
885
dobg(Char **v, struct command *t)
886
{
887
    struct process *pp;
888
889
    okpcntl();
890
    ++v;
891
    do {
892
	pp = pfind(*v);
893
	pstart(pp, 0);
894
    } while (*v && *++v);
895
}
896
897
/*
898
 * %... & - builtin - put the job into the background
899
 */
900
void
901
/*ARGSUSED*/
902
dobg1(Char **v, struct command *t)
903
{
904
    struct process *pp;
905
906
    pp = pfind(v[0]);
907
    pstart(pp, 0);
908
}
909
910
/*
911
 * dostop - builtin - stop the job
912
 */
913
void
914
/*ARGSUSED*/
915
dostop(Char **v, struct command *t)
916
{
917
    pkill(++v, SIGSTOP);
918
}
919
920
/*
921
 * dokill - builtin - superset of kill (1)
922
 */
923
void
924
/*ARGSUSED*/
925
dokill(Char **v, struct command *t)
926
{
927
    int signum = SIGTERM;
928
    const char *errstr;
929
    char *name;
930
931
    v++;
932
    if (v[0] && v[0][0] == '-') {
933
	if (v[0][1] == 'l') {
934
	    if (v[1]) {
935
		if (!Isdigit(v[1][0]))
936
		    stderror(ERR_NAME | ERR_BADSIG);
937
938
		signum = strtonum(short2str(v[1]), 0, NSIG-1, &errstr);
939
		if (errstr)
940
		    stderror(ERR_NAME | ERR_BADSIG);
941
		else if (signum == 0)
942
		    (void) fputc('0', cshout); /* 0's symbolic name is '0' */
943
		else
944
		    (void) fprintf(cshout, "%s ", sys_signame[signum]);
945
	    } else {
946
		for (signum = 1; signum < NSIG; signum++) {
947
		    (void) fprintf(cshout, "%s ", sys_signame[signum]);
948
		    if (signum == NSIG / 2)
949
			(void) fputc('\n', cshout);
950
	    	}
951
	    }
952
	    (void) fputc('\n', cshout);
953
	    return;
954
	}
955
	if (Isdigit(v[0][1])) {
956
	    signum = strtonum(short2str(v[0] + 1), 0, NSIG-1, &errstr);
957
	    if (errstr)
958
		stderror(ERR_NAME | ERR_BADSIG);
959
	}
960
	else {
961
	    if (v[0][1] == 's' && (Isspace(v[0][2]) || v[0][2] == '\0')) {
962
		v++;
963
		name = short2str(&v[0][0]);
964
	    } else {
965
		name = short2str(&v[0][1]);
966
	    }
967
968
	    if (v[0] == NULL || v[1] == NULL) {
969
		stderror(ERR_NAME | ERR_TOOFEW);
970
		return;
971
	    }
972
973
	    for (signum = 1; signum < NSIG; signum++)
974
		if (!strcasecmp(sys_signame[signum], name) ||
975
		    (strlen(name) > 3 && !strncasecmp("SIG", name, 3) &&
976
		     !strcasecmp(sys_signame[signum], name + 3)))
977
			break;
978
979
	    if (signum == NSIG) {
980
		if (name[0] == '0')
981
		    signum = 0;
982
		else {
983
		    setname(vis_str(&v[0][0]));
984
		    stderror(ERR_NAME | ERR_UNKSIG);
985
		}
986
	    }
987
	}
988
	v++;
989
    }
990
    pkill(v, signum);
991
}
992
993
static void
994
pkill(Char **v, int signum)
995
{
996
    struct process *pp, *np;
997
    int jobflags = 0;
998
    int     pid, err1 = 0;
999
    sigset_t sigset;
1000
    Char   *cp;
1001
1002
    sigemptyset(&sigset);
1003
    sigaddset(&sigset, SIGCHLD);
1004
    if (setintr)
1005
	sigaddset(&sigset, SIGINT);
1006
    sigprocmask(SIG_BLOCK, &sigset, NULL);
1007
    gflag = 0, tglob(v);
1008
    if (gflag) {
1009
	v = globall(v);
1010
	if (v == 0)
1011
	    stderror(ERR_NAME | ERR_NOMATCH);
1012
    }
1013
    else {
1014
	v = gargv = saveblk(v);
1015
	trim(v);
1016
    }
1017
1018
    while (v && (cp = *v)) {
1019
	if (*cp == '%') {
1020
	    np = pp = pfind(cp);
1021
	    do
1022
		jobflags |= np->p_flags;
1023
	    while ((np = np->p_friends) != pp);
1024
	    switch (signum) {
1025
1026
	    case SIGSTOP:
1027
	    case SIGTSTP:
1028
	    case SIGTTIN:
1029
	    case SIGTTOU:
1030
		if ((jobflags & PRUNNING) == 0) {
1031
		    (void) fprintf(csherr, "%s: Already suspended\n",
1032
				   vis_str(cp));
1033
		    err1++;
1034
		    goto cont;
1035
		}
1036
		break;
1037
		/*
1038
		 * suspend a process, kill -CONT %, then type jobs; the shell
1039
		 * says it is suspended, but it is running; thanks jaap..
1040
		 */
1041
	    case SIGCONT:
1042
		pstart(pp, 0);
1043
		goto cont;
1044
	    }
1045
	    if (kill(-pp->p_jobid, signum) < 0) {
1046
		(void) fprintf(csherr, "%s: %s\n", vis_str(cp),
1047
			       strerror(errno));
1048
		err1++;
1049
	    }
1050
	    if (signum == SIGTERM || signum == SIGHUP)
1051
		(void) kill(-pp->p_jobid, SIGCONT);
1052
	}
1053
	else if (!(Isdigit(*cp) || *cp == '-'))
1054
	    stderror(ERR_NAME | ERR_JOBARGS);
1055
	else {
1056
	    char *ep;
1057
	    char *pidnam = short2str(cp);
1058
1059
	    pid = strtol(pidnam, &ep, 10);
1060
	    if (!*pidnam || *ep) {
1061
		(void) fprintf(csherr, "%s: illegal process id\n", pidnam);
1062
		err1++;
1063
		goto cont;
1064
	    }
1065
	    if (kill((pid_t) pid, signum) < 0) {
1066
		(void) fprintf(csherr, "%d: %s\n", pid, strerror(errno));
1067
		err1++;
1068
		goto cont;
1069
	    }
1070
	    if (signum == SIGTERM || signum == SIGHUP)
1071
		(void) kill((pid_t) pid, SIGCONT);
1072
	}
1073
cont:
1074
	v++;
1075
    }
1076
    if (gargv)
1077
	blkfree(gargv), gargv = 0;
1078
    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1079
    if (err1)
1080
	stderror(ERR_SILENT);
1081
}
1082
1083
/*
1084
 * pstart - start the job in foreground/background
1085
 */
1086
void
1087
pstart(struct process *pp, int foregnd)
1088
{
1089
    struct process *np;
1090
    sigset_t sigset, osigset;
1091
    long    jobflags = 0;
1092
1093
    sigemptyset(&sigset);
1094
    sigaddset(&sigset, SIGCHLD);
1095
    sigprocmask(SIG_BLOCK, &sigset, &osigset);
1096
    np = pp;
1097
    do {
1098
	jobflags |= np->p_flags;
1099
	if (np->p_flags & (PRUNNING | PSTOPPED)) {
1100
	    np->p_flags |= PRUNNING;
1101
	    np->p_flags &= ~PSTOPPED;
1102
	    if (foregnd)
1103
		np->p_flags |= PFOREGND;
1104
	    else
1105
		np->p_flags &= ~PFOREGND;
1106
	}
1107
    } while ((np = np->p_friends) != pp);
1108
    if (!foregnd)
1109
	pclrcurr(pp);
1110
    (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1111
    if (foregnd)
1112
	(void) tcsetpgrp(FSHTTY, pp->p_jobid);
1113
    if (jobflags & PSTOPPED)
1114
	(void) kill(-pp->p_jobid, SIGCONT);
1115
    sigprocmask(SIG_SETMASK, &osigset, NULL);
1116
}
1117
1118
void
1119
panystop(bool neednl)
1120
{
1121
    struct process *pp;
1122
1123
    chkstop = 2;
1124
    for (pp = proclist.p_next; pp; pp = pp->p_next)
1125
	if (pp->p_flags & PSTOPPED)
1126
	    stderror(ERR_STOPPED, neednl ? "\n" : "");
1127
}
1128
1129
struct process *
1130
pfind(Char *cp)
1131
{
1132
    struct process *pp, *np;
1133
1134
    if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1135
	if (pcurrent == NULL)
1136
	    stderror(ERR_NAME | ERR_JOBCUR);
1137
	return (pcurrent);
1138
    }
1139
    if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1140
	if (pprevious == NULL)
1141
	    stderror(ERR_NAME | ERR_JOBPREV);
1142
	return (pprevious);
1143
    }
1144
    if (Isdigit(cp[1])) {
1145
	const char *errstr;
1146
	int     idx = strtonum(short2str(cp + 1), 1, INT_MAX, &errstr);
1147
1148
	if (errstr) {
1149
		stderror(ERR_NAME | ERR_NOSUCHJOB);
1150
		return (0);
1151
	}
1152
	for (pp = proclist.p_next; pp; pp = pp->p_next)
1153
	    if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
1154
		return (pp);
1155
	stderror(ERR_NAME | ERR_NOSUCHJOB);
1156
	return (0);
1157
    }
1158
    np = NULL;
1159
    for (pp = proclist.p_next; pp; pp = pp->p_next)
1160
	if (pp->p_pid == pp->p_jobid) {
1161
	    if (cp[1] == '?') {
1162
		Char *dp;
1163
1164
		for (dp = pp->p_command; *dp; dp++) {
1165
		    if (*dp != cp[2])
1166
			continue;
1167
		    if (prefix(cp + 2, dp))
1168
			goto match;
1169
		}
1170
	    }
1171
	    else if (prefix(cp + 1, pp->p_command)) {
1172
	match:
1173
		if (np)
1174
		    stderror(ERR_NAME | ERR_AMBIG);
1175
		np = pp;
1176
	    }
1177
	}
1178
    if (np)
1179
	return (np);
1180
    stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
1181
    /* NOTREACHED */
1182
    return (0);
1183
}
1184
1185
1186
/*
1187
 * pgetcurr - find most recent job that is not pp, preferably stopped
1188
 */
1189
static struct process *
1190
pgetcurr(struct process *pp)
1191
{
1192
    struct process *np;
1193
    struct process *xp = NULL;
1194
1195
    for (np = proclist.p_next; np; np = np->p_next)
1196
	if (np != pcurrent && np != pp && np->p_pid &&
1197
	    np->p_pid == np->p_jobid) {
1198
	    if (np->p_flags & PSTOPPED)
1199
		return (np);
1200
	    if (xp == NULL)
1201
		xp = np;
1202
	}
1203
    return (xp);
1204
}
1205
1206
/*
1207
 * donotify - flag the job so as to report termination asynchronously
1208
 */
1209
void
1210
/*ARGSUSED*/
1211
donotify(Char **v, struct command *t)
1212
{
1213
    struct process *pp;
1214
1215
    pp = pfind(*++v);
1216
    pp->p_flags |= PNOTIFY;
1217
}
1218
1219
/*
1220
 * Do the fork and whatever should be done in the child side that
1221
 * should not be done if we are not forking at all (like for simple builtin's)
1222
 * Also do everything that needs any signals fiddled with in the parent side
1223
 *
1224
 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1225
 *	-1:	leave tty alone; inherit pgrp from parent
1226
 *	 0:	already have tty; manipulate process pgrps only
1227
 *	 1:	want to claim tty; manipulate process and tty pgrps
1228
 * It is usually just the value of tpgrp.
1229
 */
1230
1231
int
1232
pfork(struct command *t, int wanttty)
1233
{
1234
    int pid;
1235
    bool    ignint = 0;
1236
    int     pgrp;
1237
    sigset_t sigset, osigset;
1238
1239
    /*
1240
     * A child will be uninterruptible only under very special conditions.
1241
     * Remember that the semantics of '&' is implemented by disconnecting the
1242
     * process from the tty so signals do not need to ignored just for '&'.
1243
     * Thus signals are set to default action for children unless: we have had
1244
     * an "onintr -" (then specifically ignored) we are not playing with
1245
     * signals (inherit action)
1246
     */
1247
    if (setintr)
1248
	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1249
	    || (gointr && eq(gointr, STRminus));
1250
    /*
1251
     * Check for maximum nesting of 16 processes to avoid Forking loops
1252
     */
1253
    if (child == 16)
1254
	stderror(ERR_NESTING, 16);
1255
    /*
1256
     * Hold SIGCHLD until we have the process installed in our table.
1257
     */
1258
    sigemptyset(&sigset);
1259
    sigaddset(&sigset, SIGCHLD);
1260
    sigprocmask(SIG_BLOCK, &sigset, &osigset);
1261
    while ((pid = fork()) < 0)
1262
	if (setintr == 0)
1263
	    (void) sleep(FORKSLEEP);
1264
	else {
1265
	    sigprocmask(SIG_SETMASK, &osigset, NULL);
1266
	    stderror(ERR_NOPROC);
1267
	}
1268
    if (pid == 0) {
1269
	settimes();
1270
	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1271
	pflushall();
1272
	pcurrjob = NULL;
1273
	child++;
1274
	if (setintr) {
1275
	    setintr = 0;	/* until I think otherwise */
1276
	    /*
1277
	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1278
	     * -" seen.
1279
	     */
1280
	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1281
	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1282
	    if (wanttty >= 0) {
1283
		/* make stoppable */
1284
		(void) signal(SIGTSTP, SIG_DFL);
1285
		(void) signal(SIGTTIN, SIG_DFL);
1286
		(void) signal(SIGTTOU, SIG_DFL);
1287
	    }
1288
	    (void) signal(SIGTERM, parterm);
1289
	}
1290
	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1291
	    (void) signal(SIGINT, SIG_IGN);
1292
	    (void) signal(SIGQUIT, SIG_IGN);
1293
	}
1294
	pgetty(wanttty, pgrp);
1295
	/*
1296
	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1297
	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1298
	 * to know about nice/nohup/time
1299
	 */
1300
	if (t->t_dflg & F_NOHUP)
1301
	    (void) signal(SIGHUP, SIG_IGN);
1302
	if (t->t_dflg & F_NICE)
1303
	    (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1304
    }
1305
    else {
1306
	if (wanttty >= 0)
1307
	    (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
1308
	palloc(pid, t);
1309
	sigprocmask(SIG_SETMASK, &osigset, NULL);
1310
    }
1311
1312
    return (pid);
1313
}
1314
1315
static void
1316
okpcntl(void)
1317
{
1318
    if (tpgrp == -1)
1319
	stderror(ERR_JOBCONTROL);
1320
    if (tpgrp == 0)
1321
	stderror(ERR_JOBCTRLSUB);
1322
}
1323
1324
/*
1325
 * if we don't have vfork(), things can still go in the wrong order
1326
 * resulting in the famous 'Stopped (tty output)'. But some systems
1327
 * don't permit the setpgid() call, (these are more recent secure
1328
 * systems such as ibm's aix). Then we'd rather print an error message
1329
 * than hang the shell!
1330
 * I am open to suggestions how to fix that.
1331
 */
1332
void
1333
pgetty(int wanttty, int pgrp)
1334
{
1335
    sigset_t sigset, osigset;
1336
1337
    /*
1338
     * christos: I am blocking the tty signals till I've set things
1339
     * correctly....
1340
     */
1341
    if (wanttty > 0) {
1342
	sigemptyset(&sigset);
1343
	sigaddset(&sigset, SIGTSTP);
1344
	sigaddset(&sigset, SIGTTIN);
1345
	sigaddset(&sigset, SIGTTOU);
1346
	sigprocmask(SIG_BLOCK, &sigset, &osigset);
1347
    }
1348
    /*
1349
     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
1350
     * Don't check for tpgrp >= 0 so even non-interactive shells give
1351
     * background jobs process groups Same for the comparison in the other part
1352
     * of the #ifdef
1353
     */
1354
    if (wanttty >= 0)
1355
	if (setpgid(0, pgrp) == -1) {
1356
	    (void) fprintf(csherr, "csh: setpgid error.\n");
1357
	    xexit(0);
1358
	}
1359
1360
    if (wanttty > 0) {
1361
	(void) tcsetpgrp(FSHTTY, pgrp);
1362
	sigprocmask(SIG_SETMASK, &osigset, NULL);
1363
    }
1364
1365
    if (tpgrp > 0)
1366
	tpgrp = 0;		/* gave tty away */
1367
}