xref: /csrg-svn/libexec/telnetd/sys_term.c (revision 38905)
1*38905Sborman /*
2*38905Sborman  * Copyright (c) 1989 Regents of the University of California.
3*38905Sborman  * All rights reserved.
4*38905Sborman  *
5*38905Sborman  * Redistribution and use in source and binary forms are permitted
6*38905Sborman  * provided that the above copyright notice and this paragraph are
7*38905Sborman  * duplicated in all such forms and that any documentation,
8*38905Sborman  * advertising materials, and other materials related to such
9*38905Sborman  * distribution and use acknowledge that the software was developed
10*38905Sborman  * by the University of California, Berkeley.  The name of the
11*38905Sborman  * University may not be used to endorse or promote products derived
12*38905Sborman  * from this software without specific prior written permission.
13*38905Sborman  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38905Sborman  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38905Sborman  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*38905Sborman  */
17*38905Sborman 
18*38905Sborman #ifndef lint
19*38905Sborman static char sccsid[] = "@(#)sys_term.c	5.1 (Berkeley) 09/01/89";
20*38905Sborman #endif /* not lint */
21*38905Sborman 
22*38905Sborman #include "telnetd.h"
23*38905Sborman #include "pathnames.h"
24*38905Sborman 
25*38905Sborman #ifdef	NEWINIT
26*38905Sborman #include <initreq.h>
27*38905Sborman #else	/* NEWINIT*/
28*38905Sborman #include <utmp.h>
29*38905Sborman struct	utmp wtmp;
30*38905Sborman 
31*38905Sborman # ifndef CRAY
32*38905Sborman char	wtmpf[]	= "/usr/adm/wtmp";
33*38905Sborman char	utmpf[] = "/etc/utmp";
34*38905Sborman # else	/* CRAY */
35*38905Sborman char	wtmpf[]	= "/etc/wtmp";
36*38905Sborman # endif	/* CRAY */
37*38905Sborman #endif	/* NEWINIT */
38*38905Sborman 
39*38905Sborman #define SCPYN(a, b)	(void) strncpy(a, b, sizeof(a))
40*38905Sborman #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
41*38905Sborman 
42*38905Sborman #include <sys/tty.h>
43*38905Sborman #ifdef	t_erase
44*38905Sborman #undef	t_erase
45*38905Sborman #undef	t_kill
46*38905Sborman #undef	t_intrc
47*38905Sborman #undef	t_quitc
48*38905Sborman #undef	t_startc
49*38905Sborman #undef	t_stopc
50*38905Sborman #undef	t_eofc
51*38905Sborman #undef	t_brkc
52*38905Sborman #undef	t_suspc
53*38905Sborman #undef	t_dsuspc
54*38905Sborman #undef	t_rprntc
55*38905Sborman #undef	t_flushc
56*38905Sborman #undef	t_werasc
57*38905Sborman #undef	t_lnextc
58*38905Sborman #endif
59*38905Sborman 
60*38905Sborman #ifndef	USE_TERMIO
61*38905Sborman struct termbuf {
62*38905Sborman 	struct sgttyb sg;
63*38905Sborman 	struct tchars tc;
64*38905Sborman 	struct ltchars ltc;
65*38905Sborman 	int state;
66*38905Sborman 	int lflags;
67*38905Sborman } termbuf, termbuf2;
68*38905Sborman #else	/* USE_TERMIO */
69*38905Sborman # ifndef EXTPROC
70*38905Sborman # define EXTPROC 0400
71*38905Sborman # endif
72*38905Sborman # ifdef	SYSV_TERMIO
73*38905Sborman #	define termios termio
74*38905Sborman # endif
75*38905Sborman struct termios termbuf, termbuf2;	/* pty control structure */
76*38905Sborman #endif	/* USE_TERMIO */
77*38905Sborman 
78*38905Sborman /*
79*38905Sborman  * init_termbuf()
80*38905Sborman  * copy_termbuf(cp)
81*38905Sborman  * set_termbuf()
82*38905Sborman  *
83*38905Sborman  * These three routines are used to get and set the "termbuf" structure
84*38905Sborman  * to and from the kernel.  init_termbuf() gets the current settings.
85*38905Sborman  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
86*38905Sborman  * set_termbuf() writes the structure into the kernel.
87*38905Sborman  */
88*38905Sborman 
89*38905Sborman init_termbuf()
90*38905Sborman {
91*38905Sborman #ifndef	USE_TERMIO
92*38905Sborman 	(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
93*38905Sborman 	(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
94*38905Sborman 	(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
95*38905Sborman # ifdef	TIOCGSTATE
96*38905Sborman 	(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
97*38905Sborman # endif
98*38905Sborman #else
99*38905Sborman 	(void) ioctl(pty, TCGETA, (char *)&termbuf);
100*38905Sborman #endif
101*38905Sborman 	termbuf2 = termbuf;
102*38905Sborman }
103*38905Sborman 
104*38905Sborman #if	defined(LINEMODE) && defined(TIOCPKT_IOCTL)
105*38905Sborman copy_termbuf(cp, len)
106*38905Sborman char *cp;
107*38905Sborman int len;
108*38905Sborman {
109*38905Sborman 	if (len > sizeof(termbuf))
110*38905Sborman 		len = sizeof(termbuf);
111*38905Sborman 	bcopy(cp, (char *)&termbuf, len);
112*38905Sborman 	termbuf2 = termbuf;
113*38905Sborman }
114*38905Sborman #endif	/* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
115*38905Sborman 
116*38905Sborman set_termbuf()
117*38905Sborman {
118*38905Sborman 	/*
119*38905Sborman 	 * Only make the necessary changes.
120*38905Sborman 	 */
121*38905Sborman #ifndef	USE_TERMIO
122*38905Sborman 	if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
123*38905Sborman 		(void) ioctl(pty, TIOCSETP, (char *)&termbuf.sg);
124*38905Sborman 	if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
125*38905Sborman 		(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
126*38905Sborman 	if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
127*38905Sborman 							sizeof(termbuf.ltc)))
128*38905Sborman 		(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
129*38905Sborman 	if (termbuf.lflags != termbuf2.lflags)
130*38905Sborman 		(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
131*38905Sborman #else	/* USE_TERMIO */
132*38905Sborman 	if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
133*38905Sborman 		(void) ioctl(pty, TCSETA, (char *)&termbuf);
134*38905Sborman # ifdef	CRAY2
135*38905Sborman 	needtermstat = 1;
136*38905Sborman # endif
137*38905Sborman #endif	/* USE_TERMIO */
138*38905Sborman }
139*38905Sborman 
140*38905Sborman 
141*38905Sborman /*
142*38905Sborman  * spcset(func, valp, valpp)
143*38905Sborman  *
144*38905Sborman  * This function takes various special characters (func), and
145*38905Sborman  * sets *valp to the current value of that character, and
146*38905Sborman  * *valpp to point to where in the "termbuf" structure that
147*38905Sborman  * value is kept.
148*38905Sborman  *
149*38905Sborman  * It returns the SLC_ level of support for this function.
150*38905Sborman  */
151*38905Sborman 
152*38905Sborman #ifndef	USE_TERMIO
153*38905Sborman spcset(func, valp, valpp)
154*38905Sborman int func;
155*38905Sborman unsigned char *valp;
156*38905Sborman unsigned char **valpp;
157*38905Sborman {
158*38905Sborman 	switch(func) {
159*38905Sborman 	case SLC_EOF:
160*38905Sborman 		*valp = termbuf.tc.t_eofc;
161*38905Sborman 		*valpp = (unsigned char *)&termbuf.tc.t_eofc;
162*38905Sborman 		return(SLC_VARIABLE);
163*38905Sborman 	case SLC_EC:
164*38905Sborman 		*valp = termbuf.sg.sg_erase;
165*38905Sborman 		*valpp = (unsigned char *)&termbuf.sg.sg_erase;
166*38905Sborman 		return(SLC_VARIABLE);
167*38905Sborman 	case SLC_EL:
168*38905Sborman 		*valp = termbuf.sg.sg_kill;
169*38905Sborman 		*valpp = (unsigned char *)&termbuf.sg.sg_kill;
170*38905Sborman 		return(SLC_VARIABLE);
171*38905Sborman 	case SLC_IP:
172*38905Sborman 		*valp = termbuf.tc.t_intrc;
173*38905Sborman 		*valpp = (unsigned char *)&termbuf.tc.t_intrc;
174*38905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
175*38905Sborman 	case SLC_ABORT:
176*38905Sborman 		*valp = termbuf.tc.t_quitc;
177*38905Sborman 		*valpp = (unsigned char *)&termbuf.tc.t_quitc;
178*38905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
179*38905Sborman 	case SLC_XON:
180*38905Sborman 		*valp = termbuf.tc.t_startc;
181*38905Sborman 		*valpp = (unsigned char *)&termbuf.tc.t_startc;
182*38905Sborman 		return(SLC_VARIABLE);
183*38905Sborman 	case SLC_XOFF:
184*38905Sborman 		*valp = termbuf.tc.t_stopc;
185*38905Sborman 		*valpp = (unsigned char *)&termbuf.tc.t_stopc;
186*38905Sborman 		return(SLC_VARIABLE);
187*38905Sborman 	case SLC_AO:
188*38905Sborman 		*valp = termbuf.ltc.t_flushc;
189*38905Sborman 		*valpp = (unsigned char *)&termbuf.ltc.t_flushc;
190*38905Sborman 		return(SLC_VARIABLE);
191*38905Sborman 	case SLC_SUSP:
192*38905Sborman 		*valp = termbuf.ltc.t_suspc;
193*38905Sborman 		*valpp = (unsigned char *)&termbuf.ltc.t_suspc;
194*38905Sborman 		return(SLC_VARIABLE);
195*38905Sborman 	case SLC_EW:
196*38905Sborman 		*valp = termbuf.ltc.t_werasc;
197*38905Sborman 		*valpp = (unsigned char *)&termbuf.ltc.t_werasc;
198*38905Sborman 		return(SLC_VARIABLE);
199*38905Sborman 	case SLC_RP:
200*38905Sborman 		*valp = termbuf.ltc.t_rprntc;
201*38905Sborman 		*valpp = (unsigned char *)&termbuf.ltc.t_rprntc;
202*38905Sborman 		return(SLC_VARIABLE);
203*38905Sborman 	case SLC_LNEXT:
204*38905Sborman 		*valp = termbuf.ltc.t_lnextc;
205*38905Sborman 		*valpp = (unsigned char *)&termbuf.ltc.t_lnextc;
206*38905Sborman 		return(SLC_VARIABLE);
207*38905Sborman 	case SLC_BRK:
208*38905Sborman 	case SLC_SYNCH:
209*38905Sborman 	case SLC_AYT:
210*38905Sborman 	case SLC_EOR:
211*38905Sborman 		*valp = 0;
212*38905Sborman 		*valpp = 0;
213*38905Sborman 		return(SLC_DEFAULT);
214*38905Sborman 	default:
215*38905Sborman 		*valp = 0;
216*38905Sborman 		*valpp = 0;
217*38905Sborman 		return(SLC_NOSUPPORT);
218*38905Sborman 	}
219*38905Sborman }
220*38905Sborman 
221*38905Sborman #else	/* USE_TERMIO */
222*38905Sborman 
223*38905Sborman spcset(func, valp, valpp)
224*38905Sborman int func;
225*38905Sborman unsigned char *valp;
226*38905Sborman unsigned char **valpp;
227*38905Sborman {
228*38905Sborman 	switch(func) {
229*38905Sborman 	case SLC_EOF:
230*38905Sborman 		*valp = termbuf.c_cc[VEOF];
231*38905Sborman 		*valpp = &termbuf.c_cc[VEOF];
232*38905Sborman 		return(SLC_VARIABLE);
233*38905Sborman 	case SLC_EC:
234*38905Sborman 		*valp = termbuf.c_cc[VERASE];
235*38905Sborman 		*valpp = &termbuf.c_cc[VERASE];
236*38905Sborman 		return(SLC_VARIABLE);
237*38905Sborman 	case SLC_EL:
238*38905Sborman 		*valp = termbuf.c_cc[VKILL];
239*38905Sborman 		*valpp = &termbuf.c_cc[VKILL];
240*38905Sborman 		return(SLC_VARIABLE);
241*38905Sborman 	case SLC_IP:
242*38905Sborman 		*valp = termbuf.c_cc[VINTR];
243*38905Sborman 		*valpp = &termbuf.c_cc[VINTR];
244*38905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
245*38905Sborman 	case SLC_ABORT:
246*38905Sborman 		*valp = termbuf.c_cc[VQUIT];
247*38905Sborman 		*valpp = &termbuf.c_cc[VQUIT];
248*38905Sborman 		return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
249*38905Sborman 	case SLC_XON:
250*38905Sborman 		*valp = 0x13;
251*38905Sborman 		*valpp = 0;
252*38905Sborman 		return(SLC_DEFAULT);
253*38905Sborman 	case SLC_XOFF:
254*38905Sborman 		*valp = 0x11;
255*38905Sborman 		*valpp = 0;
256*38905Sborman 		return(SLC_DEFAULT);
257*38905Sborman 	case SLC_EW:
258*38905Sborman 	case SLC_RP:
259*38905Sborman 	case SLC_LNEXT:
260*38905Sborman 	case SLC_BRK:
261*38905Sborman 	case SLC_SYNCH:
262*38905Sborman 	case SLC_AYT:
263*38905Sborman 	case SLC_EOR:
264*38905Sborman 		*valp = 0;
265*38905Sborman 		*valpp = 0;
266*38905Sborman 		return(SLC_DEFAULT);
267*38905Sborman 	case SLC_AO:
268*38905Sborman 	case SLC_SUSP:
269*38905Sborman 	default:
270*38905Sborman 		*valp = 0;
271*38905Sborman 		*valpp = 0;
272*38905Sborman 		return(SLC_NOSUPPORT);
273*38905Sborman 	}
274*38905Sborman }
275*38905Sborman #endif	/* USE_TERMIO */
276*38905Sborman 
277*38905Sborman /*
278*38905Sborman  * getpty()
279*38905Sborman  *
280*38905Sborman  * Allocate a pty.  As a side effect, the external character
281*38905Sborman  * array "line" contains the name of the slave side.
282*38905Sborman  *
283*38905Sborman  * Returns the file descriptor of the opened pty.
284*38905Sborman  */
285*38905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
286*38905Sborman 
287*38905Sborman getpty()
288*38905Sborman {
289*38905Sborman 	register int p;
290*38905Sborman #ifndef CRAY
291*38905Sborman 	register char c, *p1, *p2;
292*38905Sborman 	register int i;
293*38905Sborman 
294*38905Sborman 	(void) sprintf(line, "/dev/ptyXX");
295*38905Sborman 	p1 = &line[8];
296*38905Sborman 	p2 = &line[9];
297*38905Sborman 
298*38905Sborman 	for (c = 'p'; c <= 's'; c++) {
299*38905Sborman 		struct stat stb;
300*38905Sborman 
301*38905Sborman 		*p1 = c;
302*38905Sborman 		*p2 = '0';
303*38905Sborman 		if (stat(line, &stb) < 0)
304*38905Sborman 			break;
305*38905Sborman 		for (i = 0; i < 16; i++) {
306*38905Sborman 			*p2 = "0123456789abcdef"[i];
307*38905Sborman 			p = open(line, 2);
308*38905Sborman 			if (p > 0) {
309*38905Sborman 				line[5] = 't';
310*38905Sborman 				return(p);
311*38905Sborman 			}
312*38905Sborman 		}
313*38905Sborman 	}
314*38905Sborman #else	/* CRAY */
315*38905Sborman 	register int npty;
316*38905Sborman 	extern lowpty, highpty;
317*38905Sborman 
318*38905Sborman 	for (npty = lowpty; npty <= highpty; npty++) {
319*38905Sborman 		(void) sprintf(line, "/dev/pty/%03d", npty);
320*38905Sborman 		p = open(line, 2);
321*38905Sborman 		if (p < 0)
322*38905Sborman 			continue;
323*38905Sborman 		(void) sprintf(line, "/dev/ttyp%03d", npty);
324*38905Sborman 		if (access(line, 6) == 0)
325*38905Sborman 			return(p);
326*38905Sborman 		else {
327*38905Sborman 			/* no tty side to pty so skip it */
328*38905Sborman 			(void) close(p);
329*38905Sborman 		}
330*38905Sborman 	}
331*38905Sborman #endif	/* CRAY */
332*38905Sborman 	return(-1);
333*38905Sborman }
334*38905Sborman 
335*38905Sborman #ifdef	LINEMODE
336*38905Sborman /*
337*38905Sborman  * tty_flowmode()	Find out if flow control is enabled or disabled.
338*38905Sborman  * tty_linemode()	Find out if linemode (external processing) is enabled.
339*38905Sborman  * tty_setlinemod(on)	Turn on/off linemode.
340*38905Sborman  * tty_isecho()		Find out if echoing is turned on.
341*38905Sborman  * tty_setecho(on)	Enable/disable character echoing.
342*38905Sborman  * tty_israw()		Find out if terminal is in RAW mode.
343*38905Sborman  * tty_binaryin(on)	Turn on/off BINARY on input.
344*38905Sborman  * tty_binaryout(on)	Turn on/off BINARY on output.
345*38905Sborman  * tty_isediting()	Find out if line editing is enabled.
346*38905Sborman  * tty_istrapsig()	Find out if signal trapping is enabled.
347*38905Sborman  * tty_setedit(on)	Turn on/off line editing.
348*38905Sborman  * tty_setsig(on)	Turn on/off signal trapping.
349*38905Sborman  * tty_tspeed(val)	Set transmit speed to val.
350*38905Sborman  * tty_rspeed(val)	Set receive speed to val.
351*38905Sborman  */
352*38905Sborman 
353*38905Sborman tty_flowmode()
354*38905Sborman {
355*38905Sborman #ifndef USE_TERMIO
356*38905Sborman 	return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0);
357*38905Sborman #else
358*38905Sborman 	return(termbuf.c_iflag & IXON ? 1 : 0);
359*38905Sborman #endif
360*38905Sborman }
361*38905Sborman 
362*38905Sborman tty_linemode()
363*38905Sborman {
364*38905Sborman #ifndef	USE_TERMIO
365*38905Sborman 	return(termbuf.state & TS_EXTPROC);
366*38905Sborman #else
367*38905Sborman 	return(termbuf.c_lflag & EXTPROC);
368*38905Sborman #endif
369*38905Sborman }
370*38905Sborman 
371*38905Sborman tty_setlinemode(on)
372*38905Sborman int on;
373*38905Sborman {
374*38905Sborman #ifdef	TIOCEXT
375*38905Sborman 	(void) ioctl(pty, TIOCEXT, (char *)&on);
376*38905Sborman #else	/* !TIOCEXT */
377*38905Sborman #ifdef	EXTPROC
378*38905Sborman 	if (on)
379*38905Sborman 		termbuf.c_lflag |= EXTPROC;
380*38905Sborman 	else
381*38905Sborman 		termbuf.c_lflag &= ~EXTPROC;
382*38905Sborman #endif
383*38905Sborman 	set_termbuf();
384*38905Sborman #endif	/* TIOCEXT */
385*38905Sborman }
386*38905Sborman 
387*38905Sborman tty_isecho()
388*38905Sborman {
389*38905Sborman #ifndef USE_TERMIO
390*38905Sborman 	return (termbuf.sg.sg_flags & ECHO);
391*38905Sborman #else
392*38905Sborman 	return (termbuf.c_lflag & ECHO);
393*38905Sborman #endif
394*38905Sborman }
395*38905Sborman #endif	/* LINEMODE */
396*38905Sborman 
397*38905Sborman tty_setecho(on)
398*38905Sborman {
399*38905Sborman #ifndef	USE_TERMIO
400*38905Sborman 	if (on)
401*38905Sborman 		termbuf.sg.sg_flags |= ECHO|CRMOD;
402*38905Sborman 	else
403*38905Sborman 		termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
404*38905Sborman #else
405*38905Sborman 	if (on)
406*38905Sborman 		termbuf.c_lflag |= ECHO;
407*38905Sborman 	else
408*38905Sborman 		termbuf.c_lflag &= ~ECHO;
409*38905Sborman #endif
410*38905Sborman }
411*38905Sborman 
412*38905Sborman #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
413*38905Sborman tty_israw()
414*38905Sborman {
415*38905Sborman #ifndef USE_TERMIO
416*38905Sborman 	return(termbuf.sg.sg_flags & RAW);
417*38905Sborman #else
418*38905Sborman 	return(!(termbuf.c_lflag & ICANON));
419*38905Sborman #endif
420*38905Sborman }
421*38905Sborman #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
422*38905Sborman 
423*38905Sborman tty_binaryin(on)
424*38905Sborman {
425*38905Sborman #ifndef	USE_TERMIO
426*38905Sborman 	if (on)
427*38905Sborman 		termbuf.lflags |= LPASS8;
428*38905Sborman 	else
429*38905Sborman 		termbuf.lflags &= ~LPASS8;
430*38905Sborman #else
431*38905Sborman 	if (on) {
432*38905Sborman 		termbuf.c_lflag &= ~ISTRIP;
433*38905Sborman 	} else {
434*38905Sborman 		termbuf.c_lflag |= ISTRIP;
435*38905Sborman 	}
436*38905Sborman #endif
437*38905Sborman }
438*38905Sborman 
439*38905Sborman tty_binaryout(on)
440*38905Sborman {
441*38905Sborman #ifndef	USE_TERMIO
442*38905Sborman 	if (on)
443*38905Sborman 		termbuf.lflags |= LLITOUT;
444*38905Sborman 	else
445*38905Sborman 		termbuf.lflags &= ~LLITOUT;
446*38905Sborman #else
447*38905Sborman 	if (on) {
448*38905Sborman 		termbuf.c_cflag &= ~(CSIZE|PARENB);
449*38905Sborman 		termbuf.c_cflag |= CS8;
450*38905Sborman 		termbuf.c_oflag &= ~OPOST;
451*38905Sborman 	} else {
452*38905Sborman 		termbuf.c_cflag &= ~CSIZE;
453*38905Sborman 		termbuf.c_cflag |= CS7|PARENB;
454*38905Sborman 		termbuf.c_oflag |= OPOST;
455*38905Sborman 	}
456*38905Sborman #endif
457*38905Sborman }
458*38905Sborman 
459*38905Sborman tty_isbinaryin()
460*38905Sborman {
461*38905Sborman #ifndef	USE_TERMIO
462*38905Sborman 	return(termbuf.lflags & LPASS8);
463*38905Sborman #else
464*38905Sborman 	return(!(termbuf.c_lflag & ISTRIP));
465*38905Sborman #endif
466*38905Sborman }
467*38905Sborman 
468*38905Sborman tty_isbinaryout()
469*38905Sborman {
470*38905Sborman #ifndef	USE_TERMIO
471*38905Sborman 	return(termbuf.lflags & LLITOUT);
472*38905Sborman #else
473*38905Sborman 	return(mywants[TELOPT_BINARY] == OPT_YES);
474*38905Sborman #endif
475*38905Sborman }
476*38905Sborman 
477*38905Sborman #ifdef	LINEMODE
478*38905Sborman tty_isediting()
479*38905Sborman {
480*38905Sborman #ifndef USE_TERMIO
481*38905Sborman 	return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
482*38905Sborman #else
483*38905Sborman 	return(termbuf.c_lflag & ICANON);
484*38905Sborman #endif
485*38905Sborman }
486*38905Sborman 
487*38905Sborman tty_istrapsig()
488*38905Sborman {
489*38905Sborman #ifndef USE_TERMIO
490*38905Sborman 	return(!(termbuf.sg.sg_flags&RAW));
491*38905Sborman #else
492*38905Sborman 	return(termbuf.c_lflag & ISIG);
493*38905Sborman #endif
494*38905Sborman }
495*38905Sborman 
496*38905Sborman tty_setedit(on)
497*38905Sborman int on;
498*38905Sborman {
499*38905Sborman #ifndef USE_TERMIO
500*38905Sborman 	if (on)
501*38905Sborman 		termbuf.sg.sg_flags &= ~CBREAK;
502*38905Sborman 	else
503*38905Sborman 		termbuf.sg.sg_flags |= CBREAK;
504*38905Sborman #else
505*38905Sborman 	if (on)
506*38905Sborman 		termbuf.c_lflag |= ICANON;
507*38905Sborman 	else
508*38905Sborman 		termbuf.c_lflag &= ~ICANON;
509*38905Sborman #endif
510*38905Sborman }
511*38905Sborman 
512*38905Sborman tty_setsig(on)
513*38905Sborman int on;
514*38905Sborman {
515*38905Sborman #ifndef	USE_TERMIO
516*38905Sborman 	if (on)
517*38905Sborman 		;
518*38905Sborman #else
519*38905Sborman 	if (on)
520*38905Sborman 		termbuf.c_lflag |= ISIG;
521*38905Sborman 	else
522*38905Sborman 		termbuf.c_lflag &= ~ISIG;
523*38905Sborman #endif
524*38905Sborman }
525*38905Sborman #endif	/* LINEMODE */
526*38905Sborman 
527*38905Sborman /*
528*38905Sborman  * A table of available terminal speeds
529*38905Sborman  */
530*38905Sborman struct termspeeds {
531*38905Sborman 	int	speed;
532*38905Sborman 	int	value;
533*38905Sborman } termspeeds[] = {
534*38905Sborman 	{ 0,     B0 },    { 50,    B50 },   { 75,    B75 },
535*38905Sborman 	{ 110,   B110 },  { 134,   B134 },  { 150,   B150 },
536*38905Sborman 	{ 200,   B200 },  { 300,   B300 },  { 600,   B600 },
537*38905Sborman 	{ 1200,  B1200 }, { 1800,  B1800 }, { 2400,  B2400 },
538*38905Sborman 	{ 4800,  B4800 }, { 9600,  B9600 }, { 19200, B9600 },
539*38905Sborman 	{ 38400, B9600 }, { -1,    B9600 }
540*38905Sborman };
541*38905Sborman 
542*38905Sborman tty_tspeed(val)
543*38905Sborman {
544*38905Sborman 	register struct termspeeds *tp;
545*38905Sborman 
546*38905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
547*38905Sborman 		;
548*38905Sborman #ifndef	USE_TERMIO
549*38905Sborman 	termbuf.sg.sg_ospeed = tp->value;
550*38905Sborman #else
551*38905Sborman # ifdef	SYSV_TERMIO
552*38905Sborman 	termbuf.c_cflag &= ~CBAUD;
553*38905Sborman 	termbuf.c_cflag |= tp->value;
554*38905Sborman # else
555*38905Sborman 	termbuf.c_ospeed = tp->value;
556*38905Sborman # endif
557*38905Sborman #endif
558*38905Sborman }
559*38905Sborman 
560*38905Sborman tty_rspeed(val)
561*38905Sborman {
562*38905Sborman 	register struct termspeeds *tp;
563*38905Sborman 
564*38905Sborman 	for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
565*38905Sborman 		;
566*38905Sborman #ifndef	USE_TERMIO
567*38905Sborman 	termbuf.sg.sg_ispeed = tp->value;
568*38905Sborman #else
569*38905Sborman # ifdef	SYSV_TERMIO
570*38905Sborman 	termbuf.c_cflag &= ~CBAUD;
571*38905Sborman 	termbuf.c_cflag |= tp->value;
572*38905Sborman # else
573*38905Sborman 	termbuf.c_ispeed = tp->value;
574*38905Sborman # endif
575*38905Sborman #endif
576*38905Sborman }
577*38905Sborman 
578*38905Sborman #ifdef	CRAY2
579*38905Sborman tty_isnewmap()
580*38905Sborman {
581*38905Sborman 	return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
582*38905Sborman 			!(termbuf.c_oflag & ONLRET));
583*38905Sborman }
584*38905Sborman #endif
585*38905Sborman 
586*38905Sborman #ifdef	CRAY
587*38905Sborman # ifndef NEWINIT
588*38905Sborman extern	struct utmp wtmp;
589*38905Sborman extern char wtmpf[];
590*38905Sborman # else	/* NEWINIT */
591*38905Sborman int	gotalarm;
592*38905Sborman nologinproc()
593*38905Sborman {
594*38905Sborman 	gotalarm++;
595*38905Sborman }
596*38905Sborman # endif	/* NEWINIT */
597*38905Sborman #endif /* CRAY */
598*38905Sborman 
599*38905Sborman /*
600*38905Sborman  * getptyslave()
601*38905Sborman  *
602*38905Sborman  * Open the slave side of the pty, and do any initialization
603*38905Sborman  * that is necessary.  The return value is a file descriptor
604*38905Sborman  * for the slave side.
605*38905Sborman  */
606*38905Sborman getptyslave()
607*38905Sborman {
608*38905Sborman 	register int t = -1;
609*38905Sborman 
610*38905Sborman #ifndef	CRAY
611*38905Sborman 	/*
612*38905Sborman 	 * Disassociate self from control terminal and open ttyp side.
613*38905Sborman 	 * Set important flags on ttyp and ptyp.
614*38905Sborman 	 */
615*38905Sborman 	t = open(_PATH_TTY, O_RDWR);
616*38905Sborman 	if (t >= 0) {
617*38905Sborman 		(void) ioctl(t, TIOCNOTTY, (char *)0);
618*38905Sborman 		(void) close(t);
619*38905Sborman 	}
620*38905Sborman 
621*38905Sborman 	t = open(line, O_RDWR);
622*38905Sborman 	if (t < 0)
623*38905Sborman 		fatalperror(net, line);
624*38905Sborman 	if (fchmod(t, 0))
625*38905Sborman 		fatalperror(net, line);
626*38905Sborman 	(void) signal(SIGHUP, SIG_IGN);
627*38905Sborman 	vhangup();
628*38905Sborman 	(void) signal(SIGHUP, SIG_DFL);
629*38905Sborman 	t = open(line, O_RDWR);
630*38905Sborman 	if (t < 0)
631*38905Sborman 		fatalperror(net, line);
632*38905Sborman 
633*38905Sborman 	init_termbuf();
634*38905Sborman #ifndef	USE_TERMIO
635*38905Sborman 	termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO;
636*38905Sborman 	termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
637*38905Sborman #else
638*38905Sborman 	termbuf.c_lflag |= ECHO;
639*38905Sborman 	termbuf.c_oflag |= ONLCR|OXTABS;
640*38905Sborman 	termbuf.c_iflag |= ICRNL;
641*38905Sborman 	termbuf.c_iflag &= ~IXOFF;
642*38905Sborman # ifdef	SYSV_TERMIO
643*38905Sborman 	termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
644*38905Sborman # else SYSV_TERMIO
645*38905Sborman 	termbuf.c_ospeed = termbuf.c_ispeed = B9600;
646*38905Sborman # endif
647*38905Sborman #endif
648*38905Sborman 	set_termbuf();
649*38905Sborman #else	/* CRAY */
650*38905Sborman 	(void) chown(line, 0, 0);
651*38905Sborman 	(void) chmod(line, 0600);
652*38905Sborman #endif	/* CRAY */
653*38905Sborman 	return(t);
654*38905Sborman }
655*38905Sborman 
656*38905Sborman #ifdef	NEWINIT
657*38905Sborman char *gen_id = "fe";
658*38905Sborman #endif
659*38905Sborman 
660*38905Sborman /*
661*38905Sborman  * startslave(t, host)
662*38905Sborman  *
663*38905Sborman  * Given a file descriptor (t) for a tty, and a hostname, do whatever
664*38905Sborman  * is necessary to startup the login process on the slave side of the pty.
665*38905Sborman  */
666*38905Sborman 
667*38905Sborman /* ARGSUSED */
668*38905Sborman startslave(t, host)
669*38905Sborman int t;
670*38905Sborman char *host;
671*38905Sborman {
672*38905Sborman 	register int i;
673*38905Sborman 	long time();
674*38905Sborman 
675*38905Sborman #ifndef	NEWINIT
676*38905Sborman # ifdef	CRAY
677*38905Sborman 	utmp_sig_init();
678*38905Sborman # endif	/* CRAY */
679*38905Sborman 
680*38905Sborman 	if ((i = fork()) < 0)
681*38905Sborman 		fatalperror(net, "fork");
682*38905Sborman 	if (i) {
683*38905Sborman # ifdef	CRAY
684*38905Sborman 		/*
685*38905Sborman 		 * Cray parent will create utmp entry for child and send
686*38905Sborman 		 * signal to child to tell when done.  Child waits for signal
687*38905Sborman 		 * before doing anything important.
688*38905Sborman 		 */
689*38905Sborman 		register int pid = i;
690*38905Sborman 
691*38905Sborman 		setpgrp();
692*38905Sborman 		(void) signal(SIGUSR1, func);	/* reset handler to default */
693*38905Sborman 		/*
694*38905Sborman 		 * Create utmp entry for child
695*38905Sborman 		 */
696*38905Sborman 		(void) time(&wtmp.ut_time);
697*38905Sborman 		wtmp.ut_type = LOGIN_PROCESS;
698*38905Sborman 		wtmp.ut_pid = pid;
699*38905Sborman 		SCPYN(wtmp.ut_user, "LOGIN");
700*38905Sborman 		SCPYN(wtmp.ut_host, host);
701*38905Sborman 		SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
702*38905Sborman 		SCPYN(wtmp.ut_id, wtmp.ut_line+3);
703*38905Sborman 		pututline(&wtmp);
704*38905Sborman 		endutent();
705*38905Sborman 		if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
706*38905Sborman 			(void) write(i, (char *)&wtmp, sizeof(struct utmp));
707*38905Sborman 			(void) close(i);
708*38905Sborman 		}
709*38905Sborman 		utmp_sig_notify(pid);
710*38905Sborman # endif	/* CRAY */
711*38905Sborman 		(void) close(t);
712*38905Sborman 	} else {
713*38905Sborman 		start_login(t, host);
714*38905Sborman 		/*NOTREACHED*/
715*38905Sborman 	}
716*38905Sborman #else	/* NEWINIT */
717*38905Sborman 
718*38905Sborman 	extern char *ptyip;
719*38905Sborman 	struct init_request request;
720*38905Sborman 	int nologinproc();
721*38905Sborman 	register int n;
722*38905Sborman 
723*38905Sborman 	/*
724*38905Sborman 	 * Init will start up login process if we ask nicely.  We only wait
725*38905Sborman 	 * for it to start up and begin normal telnet operation.
726*38905Sborman 	 */
727*38905Sborman 	if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
728*38905Sborman 		char tbuf[128];
729*38905Sborman 		(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
730*38905Sborman 		fatalperror(net, tbuf);
731*38905Sborman 	}
732*38905Sborman 	memset((char *)&request, 0, sizeof(request));
733*38905Sborman 	request.magic = INIT_MAGIC;
734*38905Sborman 	SCPYN(request.gen_id, gen_id);
735*38905Sborman 	SCPYN(request.tty_id, &line[8]);
736*38905Sborman 	SCPYN(request.host, host);
737*38905Sborman 	SCPYN(request.term_type, &terminaltype[5]);
738*38905Sborman 	if (write(i, (char *)&request, sizeof(request)) < 0) {
739*38905Sborman 		char tbuf[128];
740*38905Sborman 		(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
741*38905Sborman 		fatalperror(net, tbuf);
742*38905Sborman 	}
743*38905Sborman 	(void) close(i);
744*38905Sborman 	(void) signal(SIGALRM, nologinproc);
745*38905Sborman 	for (i = 0; ; i++) {
746*38905Sborman 		alarm(15);
747*38905Sborman 		n = read(pty, ptyip, BUFSIZ);
748*38905Sborman 		if (i == 3 || n >= 0 || !gotalarm)
749*38905Sborman 			break;
750*38905Sborman 		gotalarm = 0;
751*38905Sborman 		(void) write(net, "telnetd: waiting for /etc/init to start login process.\r\n", 56);
752*38905Sborman 	}
753*38905Sborman 	if (n < 0 && gotalarm)
754*38905Sborman 		fatal(net, "/etc/init didn't start login process");
755*38905Sborman 	pcc += n;
756*38905Sborman 	alarm(0);
757*38905Sborman 	(void) signal(SIGALRM, SIG_DFL);
758*38905Sborman 
759*38905Sborman 	/*
760*38905Sborman 	 * Set tab expansion the way we like, in case init did something
761*38905Sborman 	 * different.
762*38905Sborman 	 */
763*38905Sborman 	init_termbuf();
764*38905Sborman 	termbuf.c_oflag &= ~TABDLY;
765*38905Sborman 	termbuf.c_oflag |= TAB0;
766*38905Sborman 	set_termbuf();
767*38905Sborman 	return;
768*38905Sborman #endif	/* NEWINIT */
769*38905Sborman }
770*38905Sborman 
771*38905Sborman #ifndef	NEWINIT
772*38905Sborman char	*envinit[3];
773*38905Sborman 
774*38905Sborman /*
775*38905Sborman  * start_login(t, host)
776*38905Sborman  *
777*38905Sborman  * Assuming that we are now running as a child processes, this
778*38905Sborman  * function will turn us into the login process.
779*38905Sborman  */
780*38905Sborman 
781*38905Sborman start_login(t, host)
782*38905Sborman int t;
783*38905Sborman char *host;
784*38905Sborman {
785*38905Sborman 	extern char *getenv();
786*38905Sborman 	char **envp;
787*38905Sborman 
788*38905Sborman #ifdef	CRAY
789*38905Sborman 	utmp_sig_wait();
790*38905Sborman # ifndef TCVHUP
791*38905Sborman 	setpgrp();
792*38905Sborman # endif
793*38905Sborman 	t = open(line, 2);	/* open ttyp */
794*38905Sborman 	if (t < 0)
795*38905Sborman 		fatalperror(net, line);
796*38905Sborman # ifdef	TCVHUP
797*38905Sborman 	/*
798*38905Sborman 	 * Hangup anybody else using this ttyp, then reopen it for
799*38905Sborman 	 * ourselves.
800*38905Sborman 	 */
801*38905Sborman 	(void) chown(line, 0, 0);
802*38905Sborman 	(void) chmod(line, 0600);
803*38905Sborman 	(void) signal(SIGHUP, SIG_IGN);
804*38905Sborman 	(void) ioctl(t, TCVHUP, (char *)0);
805*38905Sborman 	(void) signal(SIGHUP, SIG_DFL);
806*38905Sborman 	setpgrp();
807*38905Sborman 	i = open(line, 2);
808*38905Sborman 	if (i < 0)
809*38905Sborman 		fatalperror(net, line);
810*38905Sborman 	(void) close(t);
811*38905Sborman 	t = i;
812*38905Sborman # endif	/* TCVHUP */
813*38905Sborman 	/*
814*38905Sborman 	 * set ttyp modes as we like them to be
815*38905Sborman 	 */
816*38905Sborman 	init_termbuf();
817*38905Sborman 	termbuf.c_oflag = OPOST|ONLCR;
818*38905Sborman 	termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
819*38905Sborman 	termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
820*38905Sborman 	termbuf.c_cflag = EXTB|HUPCL|CS8;
821*38905Sborman 	set_termbuf();
822*38905Sborman #endif	/* CRAY */
823*38905Sborman 
824*38905Sborman 	/*
825*38905Sborman 	 * set up standard paths before forking to login
826*38905Sborman 	 */
827*38905Sborman #ifdef	BSD >43
828*38905Sborman 	if (setsid() < 0)
829*38905Sborman 		fatalperror(net, "setsid");
830*38905Sborman 	if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
831*38905Sborman 		fatalperror(net, "ioctl(sctty)");
832*38905Sborman #endif
833*38905Sborman 	(void) close(net);
834*38905Sborman 	(void) close(pty);
835*38905Sborman 	(void) dup2(t, 0);
836*38905Sborman 	(void) dup2(t, 1);
837*38905Sborman 	(void) dup2(t, 2);
838*38905Sborman 	(void) close(t);
839*38905Sborman 	envp = envinit;
840*38905Sborman 	*envp++ = terminaltype;
841*38905Sborman 	if (*envp = getenv("TZ"))
842*38905Sborman 		*envp++ -= 3;
843*38905Sborman #ifdef	CRAY
844*38905Sborman 	else
845*38905Sborman 		*envp++ = "TZ=GMT0";
846*38905Sborman #endif
847*38905Sborman 	*envp = 0;
848*38905Sborman 	environ = envinit;
849*38905Sborman 	/*
850*38905Sborman 	 * -h : pass on name of host.
851*38905Sborman 	 *		WARNING:  -h is accepted by login if and only if
852*38905Sborman 	 *			getuid() == 0.
853*38905Sborman 	 * -p : don't clobber the environment (so terminal type stays set).
854*38905Sborman 	 */
855*38905Sborman 	execl(_PATH_LOGIN, "login", "-h", host,
856*38905Sborman #ifndef CRAY
857*38905Sborman 					terminaltype ? "-p" : 0,
858*38905Sborman #endif
859*38905Sborman 								0);
860*38905Sborman 	syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
861*38905Sborman 	fatalperror(net, _PATH_LOGIN);
862*38905Sborman 	/*NOTREACHED*/
863*38905Sborman }
864*38905Sborman #endif	NEWINIT
865*38905Sborman 
866*38905Sborman /*
867*38905Sborman  * cleanup()
868*38905Sborman  *
869*38905Sborman  * This is the routine to call when we are all through, to
870*38905Sborman  * clean up anything that needs to be cleaned up.
871*38905Sborman  */
872*38905Sborman cleanup()
873*38905Sborman {
874*38905Sborman 
875*38905Sborman #ifndef	CRAY
876*38905Sborman # if BSD > 43
877*38905Sborman 	char *p;
878*38905Sborman 
879*38905Sborman 	p = line + sizeof("/dev/") - 1;
880*38905Sborman 	if (logout(p))
881*38905Sborman 		logwtmp(p, "", "");
882*38905Sborman 	(void)chmod(line, 0666);
883*38905Sborman 	(void)chown(line, 0, 0);
884*38905Sborman 	*p = 'p';
885*38905Sborman 	(void)chmod(line, 0666);
886*38905Sborman 	(void)chown(line, 0, 0);
887*38905Sborman # else
888*38905Sborman 	rmut();
889*38905Sborman 	vhangup();	/* XXX */
890*38905Sborman # endif
891*38905Sborman 	(void) shutdown(net, 2);
892*38905Sborman #else	/* CRAY */
893*38905Sborman # ifndef NEWINIT
894*38905Sborman 	rmut(line);
895*38905Sborman 	(void) shutdown(net, 2);
896*38905Sborman 	kill(0, SIGHUP);
897*38905Sborman # else	/* NEWINIT */
898*38905Sborman 	(void) shutdown(net, 2);
899*38905Sborman 	sleep(5);
900*38905Sborman # endif	/* NEWINT */
901*38905Sborman #endif	/* CRAY */
902*38905Sborman 	exit(1);
903*38905Sborman }
904*38905Sborman 
905*38905Sborman #if	defined(CRAY) && !defined(NEWINIT)
906*38905Sborman /*
907*38905Sborman  * _utmp_sig_rcv
908*38905Sborman  * utmp_sig_init
909*38905Sborman  * utmp_sig_wait
910*38905Sborman  *	These three functions are used to coordinate the handling of
911*38905Sborman  *	the utmp file between the server and the soon-to-be-login shell.
912*38905Sborman  *	The server actually creates the utmp structure, the child calls
913*38905Sborman  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
914*38905Sborman  *	signals the future-login shell to proceed.
915*38905Sborman  */
916*38905Sborman static int caught=0;		/* NZ when signal intercepted */
917*38905Sborman static void (*func)();		/* address of previous handler */
918*38905Sborman 
919*38905Sborman void
920*38905Sborman _utmp_sig_rcv(sig)
921*38905Sborman int sig;
922*38905Sborman {
923*38905Sborman 	caught = 1;
924*38905Sborman 	(void) signal(SIGUSR1, func);
925*38905Sborman }
926*38905Sborman 
927*38905Sborman utmp_sig_init()
928*38905Sborman {
929*38905Sborman 	/*
930*38905Sborman 	 * register signal handler for UTMP creation
931*38905Sborman 	 */
932*38905Sborman 	if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
933*38905Sborman 		fatalperror(net, "telnetd/signal");
934*38905Sborman }
935*38905Sborman 
936*38905Sborman utmp_sig_wait()
937*38905Sborman {
938*38905Sborman 	/*
939*38905Sborman 	 * Wait for parent to write our utmp entry.
940*38905Sborman 	 */
941*38905Sborman 	sigoff();
942*38905Sborman 	while (caught == 0) {
943*38905Sborman 		pause();	/* wait until we get a signal (sigon) */
944*38905Sborman 		sigoff();	/* turn off signals while we check caught */
945*38905Sborman 	}
946*38905Sborman 	sigon();		/* turn on signals again */
947*38905Sborman }
948*38905Sborman 
949*38905Sborman utmp_sig_notify(pid)
950*38905Sborman {
951*38905Sborman 	kill(pid, SIGUSR1);
952*38905Sborman }
953*38905Sborman #endif	/* defined(CRAY) && !defined(NEWINIT) */
954*38905Sborman 
955*38905Sborman /*
956*38905Sborman  * rmut()
957*38905Sborman  *
958*38905Sborman  * This is the function called by cleanup() to
959*38905Sborman  * remove the utmp entry for this person.
960*38905Sborman  */
961*38905Sborman 
962*38905Sborman #if	!defined(CRAY) && BSD <= 43
963*38905Sborman rmut()
964*38905Sborman {
965*38905Sborman 	register f;
966*38905Sborman 	int found = 0;
967*38905Sborman 	struct utmp *u, *utmp;
968*38905Sborman 	int nutmp;
969*38905Sborman 	struct stat statbf;
970*38905Sborman 	char *malloc();
971*38905Sborman 	long time();
972*38905Sborman 	off_t lseek();
973*38905Sborman 
974*38905Sborman 	f = open(utmpf, O_RDWR);
975*38905Sborman 	if (f >= 0) {
976*38905Sborman 		(void) fstat(f, &statbf);
977*38905Sborman 		utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
978*38905Sborman 		if (!utmp)
979*38905Sborman 			syslog(LOG_ERR, "utmp malloc failed");
980*38905Sborman 		if (statbf.st_size && utmp) {
981*38905Sborman 			nutmp = read(f, (char *)utmp, (int)statbf.st_size);
982*38905Sborman 			nutmp /= sizeof(struct utmp);
983*38905Sborman 
984*38905Sborman 			for (u = utmp ; u < &utmp[nutmp] ; u++) {
985*38905Sborman 				if (SCMPN(u->ut_line, line+5) ||
986*38905Sborman 				    u->ut_name[0]==0)
987*38905Sborman 					continue;
988*38905Sborman 				(void) lseek(f, ((long)u)-((long)utmp), L_SET);
989*38905Sborman 				SCPYN(u->ut_name, "");
990*38905Sborman 				SCPYN(u->ut_host, "");
991*38905Sborman 				(void) time(&u->ut_time);
992*38905Sborman 				(void) write(f, (char *)u, sizeof(wtmp));
993*38905Sborman 				found++;
994*38905Sborman 			}
995*38905Sborman 		}
996*38905Sborman 		(void) close(f);
997*38905Sborman 	}
998*38905Sborman 	if (found) {
999*38905Sborman 		f = open(wtmpf, O_WRONLY|O_APPEND);
1000*38905Sborman 		if (f >= 0) {
1001*38905Sborman 			SCPYN(wtmp.ut_line, line+5);
1002*38905Sborman 			SCPYN(wtmp.ut_name, "");
1003*38905Sborman 			SCPYN(wtmp.ut_host, "");
1004*38905Sborman 			(void) time(&wtmp.ut_time);
1005*38905Sborman 			(void) write(f, (char *)&wtmp, sizeof(wtmp));
1006*38905Sborman 			(void) close(f);
1007*38905Sborman 		}
1008*38905Sborman 	}
1009*38905Sborman 	(void) chmod(line, 0666);
1010*38905Sborman 	(void) chown(line, 0, 0);
1011*38905Sborman 	line[strlen("/dev/")] = 'p';
1012*38905Sborman 	(void) chmod(line, 0666);
1013*38905Sborman 	(void) chown(line, 0, 0);
1014*38905Sborman }  /* end of rmut */
1015*38905Sborman #endif	/* CRAY */
1016