xref: /openbsd-src/games/hack/hack.pager.c (revision df69c215c7c66baf660f3f65414fd34796c96152)
1*df69c215Sderaadt /*	$OpenBSD: hack.pager.c,v 1.25 2019/06/28 13:32:52 deraadt Exp $	*/
2d0b779f3Sniklas 
3df930be7Sderaadt /*
4d25013f2Scamield  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield  * Amsterdam
6d25013f2Scamield  * All rights reserved.
7d25013f2Scamield  *
8d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield  * modification, are permitted provided that the following conditions are
10d25013f2Scamield  * met:
11d25013f2Scamield  *
12d25013f2Scamield  * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield  * this list of conditions and the following disclaimer.
14d25013f2Scamield  *
15d25013f2Scamield  * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield  * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield  * documentation and/or other materials provided with the distribution.
18d25013f2Scamield  *
19d25013f2Scamield  * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield  * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield  * promote products derived from this software without specific prior
22d25013f2Scamield  * written permission.
23d25013f2Scamield  *
24d25013f2Scamield  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield  */
36d25013f2Scamield 
37d25013f2Scamield /*
38d25013f2Scamield  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield  * All rights reserved.
40d25013f2Scamield  *
41d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield  * modification, are permitted provided that the following conditions
43d25013f2Scamield  * are met:
44d25013f2Scamield  * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield  *    notice, this list of conditions and the following disclaimer.
46d25013f2Scamield  * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield  *    notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield  *    documentation and/or other materials provided with the distribution.
49d25013f2Scamield  * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield  *    derived from this software without specific prior written permission.
51d25013f2Scamield  *
52d25013f2Scamield  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55d25013f2Scamield  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt  */
63df930be7Sderaadt 
64df930be7Sderaadt /* This file contains the command routine dowhatis() and a pager. */
65df930be7Sderaadt /* Also readmail() and doshell(), and generally the things that
66df930be7Sderaadt    contact the outside world. */
67df930be7Sderaadt 
68357d2205Sderaadt #include <libgen.h>
69df930be7Sderaadt #include <signal.h>
70df930be7Sderaadt #include <stdio.h>
71df930be7Sderaadt #include <stdlib.h>
72df930be7Sderaadt #include <unistd.h>
73aed906e4Smestre 
74df930be7Sderaadt #include "hack.h"
75aed906e4Smestre 
76df930be7Sderaadt extern int CO, LI;	/* usually COLNO and ROWNO+2 */
77df930be7Sderaadt extern char *CD;
78df930be7Sderaadt extern char quitchars[];
79df930be7Sderaadt 
804a5fbbc4Spjanzen static void page_more(FILE *, int);
814a5fbbc4Spjanzen 
824a5fbbc4Spjanzen int
dowhatis(void)83aed906e4Smestre dowhatis(void)
84df930be7Sderaadt {
85df930be7Sderaadt 	FILE *fp;
86df930be7Sderaadt 	char bufr[BUFSZ+6];
87148cf60fSchl 	char *buf = &bufr[6], q;
888c6fe208Sray 	size_t len;
89df930be7Sderaadt 	extern char readchar();
90df930be7Sderaadt 
91df930be7Sderaadt 	if (!(fp = fopen(DATAFILE, "r")))
92df930be7Sderaadt 		pline("Cannot open data file!");
93df930be7Sderaadt 	else {
94df930be7Sderaadt 		pline("Specify what? ");
95df930be7Sderaadt 		q = readchar();
96df930be7Sderaadt 		if (q != '\t')
97df930be7Sderaadt 			while (fgets(buf,BUFSZ,fp))
98df930be7Sderaadt 				if (*buf == q) {
998c6fe208Sray 					len = strcspn(buf, "\n");
1008c6fe208Sray 					/* bad data file */
1018c6fe208Sray 					if (len == 0)
1028c6fe208Sray 						continue;
1038c6fe208Sray 					buf[len] = '\0';
104df930be7Sderaadt 					/* Expand tab 'by hand' */
105df930be7Sderaadt 					if (buf[1] == '\t'){
106df930be7Sderaadt 						buf = bufr;
107df930be7Sderaadt 						buf[0] = q;
108df930be7Sderaadt 						(void) strncpy(buf+1, "       ", 7);
1098c6fe208Sray 						len = strlen(buf);
110df930be7Sderaadt 					}
111911134d2Sguenther 					pline("%s", buf);
1128c6fe208Sray 					if (buf[len - 1] == ';') {
113df930be7Sderaadt 						pline("More info? ");
114df930be7Sderaadt 						if (readchar() == 'y') {
115df930be7Sderaadt 							page_more(fp,1); /* does fclose() */
116df930be7Sderaadt 							return(0);
117df930be7Sderaadt 						}
118df930be7Sderaadt 					}
119df930be7Sderaadt 					(void) fclose(fp); 	/* kopper@psuvax1 */
120df930be7Sderaadt 					return(0);
121df930be7Sderaadt 				}
122df930be7Sderaadt 		pline("I've never heard of such things.");
123df930be7Sderaadt 		(void) fclose(fp);
124df930be7Sderaadt 	}
125df930be7Sderaadt 	return(0);
126df930be7Sderaadt }
127df930be7Sderaadt 
128df930be7Sderaadt /* make the paging of a file interruptible */
129df930be7Sderaadt static int got_intrup;
130df930be7Sderaadt 
131df930be7Sderaadt void
intruph(int notused)1324a5fbbc4Spjanzen intruph(int notused)
1334a5fbbc4Spjanzen {
134df930be7Sderaadt 	got_intrup++;
135df930be7Sderaadt }
136df930be7Sderaadt 
137df930be7Sderaadt /* simple pager, also used from dohelp() */
1384a5fbbc4Spjanzen /* strip: nr of chars to be stripped from each line (0 or 1) */
1394a5fbbc4Spjanzen static void
page_more(FILE * fp,int strip)1404a5fbbc4Spjanzen page_more(FILE *fp, int strip)
141df930be7Sderaadt {
142efba6f50Schl 	char *bufr;
143df930be7Sderaadt 	sig_t prevsig = signal(SIGINT, intruph);
144df930be7Sderaadt 
145df930be7Sderaadt 	set_pager(0);
146df930be7Sderaadt 	bufr = (char *) alloc((unsigned) CO);
147577f803eSray 	while (fgets(bufr, CO, fp) && (!strip || *bufr == '\t') &&
148577f803eSray 	    !got_intrup) {
149712678dfSgilles 		bufr[strcspn(bufr, "\n")] = '\0';
150357d2205Sderaadt 		if (page_line(bufr+strip)) {
151df930be7Sderaadt 			set_pager(2);
152df930be7Sderaadt 			goto ret;
153df930be7Sderaadt 		}
154df930be7Sderaadt 	}
155df930be7Sderaadt 	set_pager(1);
156df930be7Sderaadt ret:
157df930be7Sderaadt 	free(bufr);
158df930be7Sderaadt 	(void) fclose(fp);
159df930be7Sderaadt 	(void) signal(SIGINT, prevsig);
160df930be7Sderaadt 	got_intrup = 0;
161df930be7Sderaadt }
162df930be7Sderaadt 
163df930be7Sderaadt static boolean whole_screen = TRUE;
164df930be7Sderaadt #define	PAGMIN	12	/* minimum # of lines for page below level map */
165df930be7Sderaadt 
1664a5fbbc4Spjanzen void
set_whole_screen(void)167aed906e4Smestre set_whole_screen(void)
1684a5fbbc4Spjanzen {	/* called in termcap as soon as LI is known */
169df930be7Sderaadt 	whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
170df930be7Sderaadt }
171df930be7Sderaadt 
172df930be7Sderaadt #ifdef NEWS
1734a5fbbc4Spjanzen int
readnews(void)174aed906e4Smestre readnews(void)
1754a5fbbc4Spjanzen {
1764a5fbbc4Spjanzen 	int ret;
177df930be7Sderaadt 
178df930be7Sderaadt 	whole_screen = TRUE;	/* force a docrt(), our first */
179df930be7Sderaadt 	ret = page_file(NEWS, TRUE);
180df930be7Sderaadt 	set_whole_screen();
181df930be7Sderaadt 	return(ret);		/* report whether we did docrt() */
182df930be7Sderaadt }
18354da88e4Spjanzen #endif /* NEWS */
184df930be7Sderaadt 
1854a5fbbc4Spjanzen /* 0: open  1: wait+close  2: close */
1864a5fbbc4Spjanzen void
set_pager(int mode)1874a5fbbc4Spjanzen set_pager(int mode)
188df930be7Sderaadt {
189df930be7Sderaadt 	static boolean so;
190df930be7Sderaadt 	if(mode == 0) {
191df930be7Sderaadt 		if(!whole_screen) {
192df930be7Sderaadt 			/* clear topline */
193df930be7Sderaadt 			clrlin();
194df930be7Sderaadt 			/* use part of screen below level map */
195df930be7Sderaadt 			curs(1, ROWNO+4);
196df930be7Sderaadt 		} else {
197df930be7Sderaadt 			cls();
198df930be7Sderaadt 		}
199df930be7Sderaadt 		so = flags.standout;
200df930be7Sderaadt 		flags.standout = 1;
201df930be7Sderaadt 	} else {
202df930be7Sderaadt 		if(mode == 1) {
203df930be7Sderaadt 			curs(1, LI);
204df930be7Sderaadt 			more();
205df930be7Sderaadt 		}
206df930be7Sderaadt 		flags.standout = so;
207df930be7Sderaadt 		if(whole_screen)
208df930be7Sderaadt 			docrt();
209df930be7Sderaadt 		else {
210df930be7Sderaadt 			curs(1, ROWNO+4);
211df930be7Sderaadt 			cl_eos();
212df930be7Sderaadt 		}
213df930be7Sderaadt 	}
214df930be7Sderaadt }
215df930be7Sderaadt 
2164a5fbbc4Spjanzen int
page_line(char * s)2174a5fbbc4Spjanzen page_line(char *s)		/* returns 1 if we should quit */
218df930be7Sderaadt {
219df930be7Sderaadt 	extern char morc;
220df930be7Sderaadt 
221df930be7Sderaadt 	if(cury == LI-1) {
222df930be7Sderaadt 		if(!*s)
223df930be7Sderaadt 			return(0);	/* suppress blank lines at top */
224df930be7Sderaadt 		putchar('\n');
225df930be7Sderaadt 		cury++;
226df930be7Sderaadt 		cmore("q\033");
227df930be7Sderaadt 		if(morc) {
228df930be7Sderaadt 			morc = 0;
229df930be7Sderaadt 			return(1);
230df930be7Sderaadt 		}
231df930be7Sderaadt 		if(whole_screen)
232df930be7Sderaadt 			cls();
233df930be7Sderaadt 		else {
234df930be7Sderaadt 			curs(1, ROWNO+4);
235df930be7Sderaadt 			cl_eos();
236df930be7Sderaadt 		}
237df930be7Sderaadt 	}
238df930be7Sderaadt 	puts(s);
239df930be7Sderaadt 	cury++;
240df930be7Sderaadt 	return(0);
241df930be7Sderaadt }
242df930be7Sderaadt 
243df930be7Sderaadt /*
244df930be7Sderaadt  * Flexible pager: feed it with a number of lines and it will decide
245df930be7Sderaadt  * whether these should be fed to the pager above, or displayed in a
246df930be7Sderaadt  * corner.
247df930be7Sderaadt  * Call:
248df930be7Sderaadt  *	cornline(0, title or 0)	: initialize
249df930be7Sderaadt  *	cornline(1, text)	: add text to the chain of texts
250df930be7Sderaadt  *	cornline(2, morcs)	: output everything and cleanup
251df930be7Sderaadt  *	cornline(3, 0)		: cleanup
252df930be7Sderaadt  */
2534a5fbbc4Spjanzen void
cornline(int mode,char * text)2544a5fbbc4Spjanzen cornline(int mode, char *text)
255df930be7Sderaadt {
256df930be7Sderaadt 	static struct line {
257df930be7Sderaadt 		struct line *next_line;
258df930be7Sderaadt 		char *line_text;
259df930be7Sderaadt 	} *texthead, *texttail;
260df930be7Sderaadt 	static int maxlen;
261df930be7Sderaadt 	static int linect;
2624a5fbbc4Spjanzen 	struct line *tl;
263df930be7Sderaadt 
264df930be7Sderaadt 	if(mode == 0) {
265df930be7Sderaadt 		texthead = 0;
266df930be7Sderaadt 		maxlen = 0;
267df930be7Sderaadt 		linect = 0;
268df930be7Sderaadt 		if(text) {
269df930be7Sderaadt 			cornline(1, text);	/* title */
270df930be7Sderaadt 			cornline(1, "");	/* blank line */
271df930be7Sderaadt 		}
272df930be7Sderaadt 		return;
273df930be7Sderaadt 	}
274df930be7Sderaadt 
275df930be7Sderaadt 	if(mode == 1) {
2764a5fbbc4Spjanzen 	    int len;
277df930be7Sderaadt 
278df930be7Sderaadt 	    if(!text) return;	/* superfluous, just to be sure */
279df930be7Sderaadt 	    linect++;
280df930be7Sderaadt 	    len = strlen(text);
281df930be7Sderaadt 	    if(len > maxlen)
282df930be7Sderaadt 		maxlen = len;
283df930be7Sderaadt 	    tl = (struct line *)
284df930be7Sderaadt 		alloc((unsigned)(len + sizeof(struct line) + 1));
285df930be7Sderaadt 	    tl->next_line = 0;
286df930be7Sderaadt 	    tl->line_text = (char *)(tl + 1);
287846311fcStdeval 	    (void) strlcpy(tl->line_text, text, len + 1);
288df930be7Sderaadt 	    if(!texthead)
289df930be7Sderaadt 		texthead = tl;
290df930be7Sderaadt 	    else
291df930be7Sderaadt 		texttail->next_line = tl;
292df930be7Sderaadt 	    texttail = tl;
293df930be7Sderaadt 	    return;
294df930be7Sderaadt 	}
295df930be7Sderaadt 
296df930be7Sderaadt 	/* --- now we really do it --- */
297df930be7Sderaadt 	if(mode == 2 && linect == 1)			    /* topline only */
298911134d2Sguenther 		pline("%s", texthead->line_text);
299df930be7Sderaadt 	else
300df930be7Sderaadt 	if(mode == 2) {
3014a5fbbc4Spjanzen 	    int curline, lth;
302df930be7Sderaadt 
303df930be7Sderaadt 	    if(flags.toplin == 1) more();	/* ab@unido */
304df930be7Sderaadt 	    remember_topl();
305df930be7Sderaadt 
306df930be7Sderaadt 	    lth = CO - maxlen - 2;		   /* Use full screen width */
307df930be7Sderaadt 	    if (linect < LI && lth >= 10) {		     /* in a corner */
308df930be7Sderaadt 		home();
309df930be7Sderaadt 		cl_end();
310df930be7Sderaadt 		flags.toplin = 0;
311df930be7Sderaadt 		curline = 1;
312df930be7Sderaadt 		for (tl = texthead; tl; tl = tl->next_line) {
313df930be7Sderaadt 		    curs(lth, curline);
314df930be7Sderaadt 		    if(curline > 1)
315df930be7Sderaadt 			cl_end();
316df930be7Sderaadt 		    putsym(' ');
317df930be7Sderaadt 		    putstr (tl->line_text);
318df930be7Sderaadt 		    curline++;
319df930be7Sderaadt 		}
320df930be7Sderaadt 		curs(lth, curline);
321df930be7Sderaadt 		cl_end();
322df930be7Sderaadt 		cmore(text);
323df930be7Sderaadt 		home();
324df930be7Sderaadt 		cl_end();
325df930be7Sderaadt 		docorner(lth, curline-1);
326df930be7Sderaadt 	    } else {					/* feed to pager */
327df930be7Sderaadt 		set_pager(0);
328df930be7Sderaadt 		for (tl = texthead; tl; tl = tl->next_line) {
329df930be7Sderaadt 		    if (page_line (tl->line_text)) {
330df930be7Sderaadt 			set_pager(2);
331df930be7Sderaadt 			goto cleanup;
332df930be7Sderaadt 		    }
333df930be7Sderaadt 		}
334df930be7Sderaadt 		if(text) {
335df930be7Sderaadt 			cgetret(text);
336df930be7Sderaadt 			set_pager(2);
337df930be7Sderaadt 		} else
338df930be7Sderaadt 			set_pager(1);
339df930be7Sderaadt 	    }
340df930be7Sderaadt 	}
341df930be7Sderaadt 
342df930be7Sderaadt cleanup:
3434a5fbbc4Spjanzen 	while ((tl = texthead)) {
344df930be7Sderaadt 		texthead = tl->next_line;
345ebf3d589Sguenther 		free(tl);
346df930be7Sderaadt 	}
347df930be7Sderaadt }
348df930be7Sderaadt 
3494a5fbbc4Spjanzen int
dohelp(void)350aed906e4Smestre dohelp(void)
351df930be7Sderaadt {
352df930be7Sderaadt 	char c;
353df930be7Sderaadt 
354df930be7Sderaadt 	pline ("Long or short help? ");
355180acc8fSmillert 	while (((c = readchar ()) != 'l') && (c != 's') && !strchr(quitchars,c))
3564a5fbbc4Spjanzen 		hackbell ();
357180acc8fSmillert 	if (!strchr(quitchars, c))
358df930be7Sderaadt 		(void) page_file((c == 'l') ? HELP : SHELP, FALSE);
359df930be7Sderaadt 	return(0);
360df930be7Sderaadt }
361df930be7Sderaadt 
3624a5fbbc4Spjanzen /* return: 0 - cannot open fnam; 1 - otherwise */
3634a5fbbc4Spjanzen int
page_file(char * fnam,boolean silent)3644a5fbbc4Spjanzen page_file(char *fnam, boolean silent)
365df930be7Sderaadt {
366df930be7Sderaadt #ifdef DEF_PAGER			/* this implies that UNIX is defined */
367df930be7Sderaadt       {
368df930be7Sderaadt 	/* use external pager; this may give security problems */
369df930be7Sderaadt 
3704a5fbbc4Spjanzen 	int fd = open(fnam, O_RDONLY);
371df930be7Sderaadt 
372*df69c215Sderaadt 	if(fd == -1) {
373df930be7Sderaadt 		if(!silent) pline("Cannot open %s.", fnam);
374df930be7Sderaadt 		return(0);
375df930be7Sderaadt 	}
376df930be7Sderaadt 	if(child(1)){
377df930be7Sderaadt 		extern char *catmore;
378df930be7Sderaadt 
379df930be7Sderaadt 		/* Now that child() does a setuid(getuid()) and a chdir(),
380df930be7Sderaadt 		   we may not be able to open file fnam anymore, so make
381df930be7Sderaadt 		   it stdin. */
382df930be7Sderaadt 		(void) close(0);
383df930be7Sderaadt 		if(dup(fd)) {
384df930be7Sderaadt 			if(!silent) printf("Cannot open %s as stdin.\n", fnam);
385df930be7Sderaadt 		} else {
38664f0fa11Smestre 			execlp(catmore, basename(catmore), (char *)NULL);
387df930be7Sderaadt 			if(!silent) printf("Cannot exec %s.\n", catmore);
388df930be7Sderaadt 		}
389df930be7Sderaadt 		exit(1);
390df930be7Sderaadt 	}
391df930be7Sderaadt 	(void) close(fd);
392df930be7Sderaadt       }
39354da88e4Spjanzen #else /* DEF_PAGER */
394df930be7Sderaadt       {
395df930be7Sderaadt 	FILE *f;			/* free after Robert Viduya */
396df930be7Sderaadt 
397df930be7Sderaadt 	if ((f = fopen (fnam, "r")) == (FILE *) 0) {
398df930be7Sderaadt 		if(!silent) {
399df930be7Sderaadt 			home(); perror (fnam); flags.toplin = 1;
400df930be7Sderaadt 			pline ("Cannot open %s.", fnam);
401df930be7Sderaadt 		}
402df930be7Sderaadt 		return(0);
403df930be7Sderaadt 	}
404df930be7Sderaadt 	page_more(f, 0);
405df930be7Sderaadt       }
40654da88e4Spjanzen #endif /* DEF_PAGER */
407df930be7Sderaadt 
408df930be7Sderaadt 	return(1);
409df930be7Sderaadt }
410df930be7Sderaadt 
411df930be7Sderaadt #ifdef UNIX
412df930be7Sderaadt #ifdef SHELL
4134a5fbbc4Spjanzen int
dosh(void)414aed906e4Smestre dosh(void)
4154a5fbbc4Spjanzen {
4164a5fbbc4Spjanzen 	char *str;
4174a5fbbc4Spjanzen 
418df930be7Sderaadt 	if(child(0)) {
4194a5fbbc4Spjanzen 		if ((str = getenv("SHELL")))
42064f0fa11Smestre 			execlp(str, str, (char *)NULL);
421df930be7Sderaadt 		else
42264f0fa11Smestre 			execl("/bin/sh", "sh", (char *)NULL);
423df930be7Sderaadt 		pline("sh: cannot execute.");
424df930be7Sderaadt 		exit(1);
425df930be7Sderaadt 	}
426df930be7Sderaadt 	return(0);
427df930be7Sderaadt }
42854da88e4Spjanzen #endif /* SHELL */
429df930be7Sderaadt 
430df930be7Sderaadt #include <sys/wait.h>
431df930be7Sderaadt 
4324a5fbbc4Spjanzen int
child(int wt)4334a5fbbc4Spjanzen child(int wt)
4344a5fbbc4Spjanzen {
435df930be7Sderaadt 	int status;
4364a5fbbc4Spjanzen 	int f;
4375c85bdadSmillert 	char *home;
438f4878ebaSdjm 	gid_t gid;
439df930be7Sderaadt 
440df930be7Sderaadt 	f = fork();
441df930be7Sderaadt 	if(f == 0){		/* child */
4426acf840eSmestre 		settty(NULL);		/* also calls end_screen() */
443f4878ebaSdjm 		/* revoke privs */
444f4878ebaSdjm 		gid = getgid();
445f4878ebaSdjm 		setresgid(gid, gid, gid);
446df930be7Sderaadt #ifdef CHDIR
4475c85bdadSmillert 		home = getenv("HOME");
4485c85bdadSmillert 		if (home == NULL || *home == '\0')
4495c85bdadSmillert 			home = "/";
4505c85bdadSmillert 		(void) chdir(home);
45154da88e4Spjanzen #endif /* CHDIR */
452df930be7Sderaadt 		return(1);
453df930be7Sderaadt 	}
454df930be7Sderaadt 	if(f == -1) {	/* cannot fork */
455df930be7Sderaadt 		pline("Fork failed. Try again.");
456df930be7Sderaadt 		return(0);
457df930be7Sderaadt 	}
458df930be7Sderaadt 	/* fork succeeded; wait for child to exit */
459df930be7Sderaadt 	(void) signal(SIGINT,SIG_IGN);
460df930be7Sderaadt 	(void) signal(SIGQUIT,SIG_IGN);
461df930be7Sderaadt 	(void) wait(&status);
462df930be7Sderaadt 	gettty();
463df930be7Sderaadt 	setftty();
464df930be7Sderaadt 	(void) signal(SIGINT,done1);
465df930be7Sderaadt #ifdef WIZARD
466df930be7Sderaadt 	if(wizard) (void) signal(SIGQUIT,SIG_DFL);
46754da88e4Spjanzen #endif /* WIZARD */
468df930be7Sderaadt 	if(wt) getret();
469df930be7Sderaadt 	docrt();
470df930be7Sderaadt 	return(0);
471df930be7Sderaadt }
47254da88e4Spjanzen #endif /* UNIX */
473