Deleted Added
full compact
sys_term.c (69825) sys_term.c (81965)
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95";
37#endif
38static const char rcsid[] =
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95";
37#endif
38static const char rcsid[] =
39 "$FreeBSD: head/contrib/telnet/telnetd/sys_term.c 69825 2000-12-10 20:50:20Z assar $";
39 "$FreeBSD: head/contrib/telnet/telnetd/sys_term.c 81965 2001-08-20 12:28:40Z markm $";
40#endif /* not lint */
41
42#include "telnetd.h"
43#include "pathnames.h"
44
45#if defined(AUTHENTICATION)
46#include <libtelnet/auth.h>
47#endif
48
49extern char *altlogin;
50int cleanopen(char *line);
51void scrub_env(void);
52
53#if defined(CRAY) || defined(__hpux)
54# define PARENT_DOES_UTMP
55#endif
56
57#ifdef NEWINIT
58#include <initreq.h>
59#else /* NEWINIT*/
60# ifdef UTMPX
61# include <utmpx.h>
62struct utmpx wtmp;
63# else
64# include <utmp.h>
65struct utmp wtmp;
66# endif /* UTMPX */
67
68# ifndef PARENT_DOES_UTMP
69#ifdef _PATH_WTMP
70char wtmpf[] = _PATH_WTMP;
71#else
72char wtmpf[] = "/usr/adm/wtmp";
73#endif
74#ifdef _PATH_UTMP
75char utmpf[] = _PATH_UTMP;
76#else
77char utmpf[] = "/etc/utmp";
78#endif
79# else /* PARENT_DOES_UTMP */
80char wtmpf[] = "/etc/wtmp";
81# endif /* PARENT_DOES_UTMP */
82
83#include <libutil.h>
84
85# ifdef CRAY
86#include <tmpdir.h>
87#include <sys/wait.h>
88# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
89# define UNICOS7x
90# endif
91
92# ifdef UNICOS7x
93#include <sys/sysv.h>
94#include <sys/secstat.h>
95extern int secflag;
96extern struct sysv sysv;
97# endif /* UNICOS7x */
98# endif /* CRAY */
99#endif /* NEWINIT */
100
101#ifdef STREAMSPTY
102#include <sac.h>
103#include <sys/stropts.h>
104#endif
105
106#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
107#define SCMPN(a, b) strncmp(a, b, sizeof(a))
108
109#ifdef STREAMS
110#include <sys/stream.h>
111#endif
112#ifdef __hpux
113#include <sys/resource.h>
114#include <sys/proc.h>
115#endif
116#include <sys/tty.h>
117#ifdef t_erase
118#undef t_erase
119#undef t_kill
120#undef t_intrc
121#undef t_quitc
122#undef t_startc
123#undef t_stopc
124#undef t_eofc
125#undef t_brkc
126#undef t_suspc
127#undef t_dsuspc
128#undef t_rprntc
129#undef t_flushc
130#undef t_werasc
131#undef t_lnextc
132#endif
133
134#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
135# define EXTPROC 0400
136#endif
137
138#ifndef USE_TERMIO
139struct termbuf {
140 struct sgttyb sg;
141 struct tchars tc;
142 struct ltchars ltc;
143 int state;
144 int lflags;
145} termbuf, termbuf2;
146# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val)
147# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val)
148# define cfgetospeed(tp) (tp)->sg.sg_ospeed
149# define cfgetispeed(tp) (tp)->sg.sg_ispeed
150#else /* USE_TERMIO */
151# ifdef SYSV_TERMIO
152# define termios termio
153# endif
154# ifndef TCSANOW
155# ifdef TCSETS
156# define TCSANOW TCSETS
157# define TCSADRAIN TCSETSW
158# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
159# else
160# ifdef TCSETA
161# define TCSANOW TCSETA
162# define TCSADRAIN TCSETAW
163# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
164# else
165# define TCSANOW TIOCSETA
166# define TCSADRAIN TIOCSETAW
167# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
168# endif
169# endif
170# define tcsetattr(f, a, t) ioctl(f, a, t)
171# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
172 (tp)->c_cflag |= (val)
173# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
174# ifdef CIBAUD
175# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
176 (tp)->c_cflag |= ((val)<<IBSHIFT)
177# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
178# else
179# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
180 (tp)->c_cflag |= (val)
181# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
182# endif
183# endif /* TCSANOW */
184struct termios termbuf, termbuf2; /* pty control structure */
185# ifdef STREAMSPTY
186int ttyfd = -1;
187# endif
188#endif /* USE_TERMIO */
189
190#include <sys/types.h>
191#include <libutil.h>
192
193int cleanopen __P((char *));
194void scrub_env __P((void));
195
196/*
197 * init_termbuf()
198 * copy_termbuf(cp)
199 * set_termbuf()
200 *
201 * These three routines are used to get and set the "termbuf" structure
202 * to and from the kernel. init_termbuf() gets the current settings.
203 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
204 * set_termbuf() writes the structure into the kernel.
205 */
206
207 void
208init_termbuf()
209{
210#ifndef USE_TERMIO
211 (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
212 (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
213 (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
214# ifdef TIOCGSTATE
215 (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
216# endif
217#else
218# ifdef STREAMSPTY
219 (void) tcgetattr(ttyfd, &termbuf);
220# else
221 (void) tcgetattr(pty, &termbuf);
222# endif
223#endif
224 termbuf2 = termbuf;
225}
226
227#if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
228 void
229copy_termbuf(cp, len)
230 char *cp;
231 int len;
232{
233 if (len > sizeof(termbuf))
234 len = sizeof(termbuf);
235 memmove((char *)&termbuf, cp, len);
236 termbuf2 = termbuf;
237}
238#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
239
240 void
241set_termbuf()
242{
243 /*
244 * Only make the necessary changes.
245 */
246#ifndef USE_TERMIO
247 if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
248 sizeof(termbuf.sg)))
249 (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
250 if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
251 sizeof(termbuf.tc)))
252 (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
253 if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
254 sizeof(termbuf.ltc)))
255 (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
256 if (termbuf.lflags != termbuf2.lflags)
257 (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
258#else /* USE_TERMIO */
259 if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
260# ifdef STREAMSPTY
261 (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
262# else
263 (void) tcsetattr(pty, TCSANOW, &termbuf);
264# endif
265# if defined(CRAY2) && defined(UNICOS5)
266 needtermstat = 1;
267# endif
268#endif /* USE_TERMIO */
269}
270
271
272/*
273 * spcset(func, valp, valpp)
274 *
275 * This function takes various special characters (func), and
276 * sets *valp to the current value of that character, and
277 * *valpp to point to where in the "termbuf" structure that
278 * value is kept.
279 *
280 * It returns the SLC_ level of support for this function.
281 */
282
283#ifndef USE_TERMIO
284 int
285spcset(func, valp, valpp)
286 int func;
287 cc_t *valp;
288 cc_t **valpp;
289{
290 switch(func) {
291 case SLC_EOF:
292 *valp = termbuf.tc.t_eofc;
293 *valpp = (cc_t *)&termbuf.tc.t_eofc;
294 return(SLC_VARIABLE);
295 case SLC_EC:
296 *valp = termbuf.sg.sg_erase;
297 *valpp = (cc_t *)&termbuf.sg.sg_erase;
298 return(SLC_VARIABLE);
299 case SLC_EL:
300 *valp = termbuf.sg.sg_kill;
301 *valpp = (cc_t *)&termbuf.sg.sg_kill;
302 return(SLC_VARIABLE);
303 case SLC_IP:
304 *valp = termbuf.tc.t_intrc;
305 *valpp = (cc_t *)&termbuf.tc.t_intrc;
306 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
307 case SLC_ABORT:
308 *valp = termbuf.tc.t_quitc;
309 *valpp = (cc_t *)&termbuf.tc.t_quitc;
310 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
311 case SLC_XON:
312 *valp = termbuf.tc.t_startc;
313 *valpp = (cc_t *)&termbuf.tc.t_startc;
314 return(SLC_VARIABLE);
315 case SLC_XOFF:
316 *valp = termbuf.tc.t_stopc;
317 *valpp = (cc_t *)&termbuf.tc.t_stopc;
318 return(SLC_VARIABLE);
319 case SLC_AO:
320 *valp = termbuf.ltc.t_flushc;
321 *valpp = (cc_t *)&termbuf.ltc.t_flushc;
322 return(SLC_VARIABLE);
323 case SLC_SUSP:
324 *valp = termbuf.ltc.t_suspc;
325 *valpp = (cc_t *)&termbuf.ltc.t_suspc;
326 return(SLC_VARIABLE);
327 case SLC_EW:
328 *valp = termbuf.ltc.t_werasc;
329 *valpp = (cc_t *)&termbuf.ltc.t_werasc;
330 return(SLC_VARIABLE);
331 case SLC_RP:
332 *valp = termbuf.ltc.t_rprntc;
333 *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
334 return(SLC_VARIABLE);
335 case SLC_LNEXT:
336 *valp = termbuf.ltc.t_lnextc;
337 *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
338 return(SLC_VARIABLE);
339 case SLC_FORW1:
340 *valp = termbuf.tc.t_brkc;
341 *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
342 return(SLC_VARIABLE);
343 case SLC_BRK:
344 case SLC_SYNCH:
345 case SLC_AYT:
346 case SLC_EOR:
347 *valp = (cc_t)0;
348 *valpp = (cc_t *)0;
349 return(SLC_DEFAULT);
350 default:
351 *valp = (cc_t)0;
352 *valpp = (cc_t *)0;
353 return(SLC_NOSUPPORT);
354 }
355}
356
357#else /* USE_TERMIO */
358
359 int
360spcset(func, valp, valpp)
361 int func;
362 cc_t *valp;
363 cc_t **valpp;
364{
365
366#define setval(a, b) *valp = termbuf.c_cc[a]; \
367 *valpp = &termbuf.c_cc[a]; \
368 return(b);
369#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
370
371 switch(func) {
372 case SLC_EOF:
373 setval(VEOF, SLC_VARIABLE);
374 case SLC_EC:
375 setval(VERASE, SLC_VARIABLE);
376 case SLC_EL:
377 setval(VKILL, SLC_VARIABLE);
378 case SLC_IP:
379 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
380 case SLC_ABORT:
381 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
382 case SLC_XON:
383#ifdef VSTART
384 setval(VSTART, SLC_VARIABLE);
385#else
386 defval(0x13);
387#endif
388 case SLC_XOFF:
389#ifdef VSTOP
390 setval(VSTOP, SLC_VARIABLE);
391#else
392 defval(0x11);
393#endif
394 case SLC_EW:
395#ifdef VWERASE
396 setval(VWERASE, SLC_VARIABLE);
397#else
398 defval(0);
399#endif
400 case SLC_RP:
401#ifdef VREPRINT
402 setval(VREPRINT, SLC_VARIABLE);
403#else
404 defval(0);
405#endif
406 case SLC_LNEXT:
407#ifdef VLNEXT
408 setval(VLNEXT, SLC_VARIABLE);
409#else
410 defval(0);
411#endif
412 case SLC_AO:
413#if !defined(VDISCARD) && defined(VFLUSHO)
414# define VDISCARD VFLUSHO
415#endif
416#ifdef VDISCARD
417 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
418#else
419 defval(0);
420#endif
421 case SLC_SUSP:
422#ifdef VSUSP
423 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
424#else
425 defval(0);
426#endif
427#ifdef VEOL
428 case SLC_FORW1:
429 setval(VEOL, SLC_VARIABLE);
430#endif
431#ifdef VEOL2
432 case SLC_FORW2:
433 setval(VEOL2, SLC_VARIABLE);
434#endif
435 case SLC_AYT:
436#ifdef VSTATUS
437 setval(VSTATUS, SLC_VARIABLE);
438#else
439 defval(0);
440#endif
441
442 case SLC_BRK:
443 case SLC_SYNCH:
444 case SLC_EOR:
445 defval(0);
446
447 default:
448 *valp = 0;
449 *valpp = 0;
450 return(SLC_NOSUPPORT);
451 }
452}
453#endif /* USE_TERMIO */
454
455#ifdef CRAY
456/*
457 * getnpty()
458 *
459 * Return the number of pty's configured into the system.
460 */
461 int
462getnpty()
463{
464#ifdef _SC_CRAY_NPTY
465 int numptys;
466
467 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
468 return numptys;
469 else
470#endif /* _SC_CRAY_NPTY */
471 return 128;
472}
473#endif /* CRAY */
474
475#ifndef convex
476/*
477 * getpty()
478 *
479 * Allocate a pty. As a side effect, the external character
480 * array "line" contains the name of the slave side.
481 *
482 * Returns the file descriptor of the opened pty.
483 */
40#endif /* not lint */
41
42#include "telnetd.h"
43#include "pathnames.h"
44
45#if defined(AUTHENTICATION)
46#include <libtelnet/auth.h>
47#endif
48
49extern char *altlogin;
50int cleanopen(char *line);
51void scrub_env(void);
52
53#if defined(CRAY) || defined(__hpux)
54# define PARENT_DOES_UTMP
55#endif
56
57#ifdef NEWINIT
58#include <initreq.h>
59#else /* NEWINIT*/
60# ifdef UTMPX
61# include <utmpx.h>
62struct utmpx wtmp;
63# else
64# include <utmp.h>
65struct utmp wtmp;
66# endif /* UTMPX */
67
68# ifndef PARENT_DOES_UTMP
69#ifdef _PATH_WTMP
70char wtmpf[] = _PATH_WTMP;
71#else
72char wtmpf[] = "/usr/adm/wtmp";
73#endif
74#ifdef _PATH_UTMP
75char utmpf[] = _PATH_UTMP;
76#else
77char utmpf[] = "/etc/utmp";
78#endif
79# else /* PARENT_DOES_UTMP */
80char wtmpf[] = "/etc/wtmp";
81# endif /* PARENT_DOES_UTMP */
82
83#include <libutil.h>
84
85# ifdef CRAY
86#include <tmpdir.h>
87#include <sys/wait.h>
88# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
89# define UNICOS7x
90# endif
91
92# ifdef UNICOS7x
93#include <sys/sysv.h>
94#include <sys/secstat.h>
95extern int secflag;
96extern struct sysv sysv;
97# endif /* UNICOS7x */
98# endif /* CRAY */
99#endif /* NEWINIT */
100
101#ifdef STREAMSPTY
102#include <sac.h>
103#include <sys/stropts.h>
104#endif
105
106#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
107#define SCMPN(a, b) strncmp(a, b, sizeof(a))
108
109#ifdef STREAMS
110#include <sys/stream.h>
111#endif
112#ifdef __hpux
113#include <sys/resource.h>
114#include <sys/proc.h>
115#endif
116#include <sys/tty.h>
117#ifdef t_erase
118#undef t_erase
119#undef t_kill
120#undef t_intrc
121#undef t_quitc
122#undef t_startc
123#undef t_stopc
124#undef t_eofc
125#undef t_brkc
126#undef t_suspc
127#undef t_dsuspc
128#undef t_rprntc
129#undef t_flushc
130#undef t_werasc
131#undef t_lnextc
132#endif
133
134#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
135# define EXTPROC 0400
136#endif
137
138#ifndef USE_TERMIO
139struct termbuf {
140 struct sgttyb sg;
141 struct tchars tc;
142 struct ltchars ltc;
143 int state;
144 int lflags;
145} termbuf, termbuf2;
146# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val)
147# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val)
148# define cfgetospeed(tp) (tp)->sg.sg_ospeed
149# define cfgetispeed(tp) (tp)->sg.sg_ispeed
150#else /* USE_TERMIO */
151# ifdef SYSV_TERMIO
152# define termios termio
153# endif
154# ifndef TCSANOW
155# ifdef TCSETS
156# define TCSANOW TCSETS
157# define TCSADRAIN TCSETSW
158# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
159# else
160# ifdef TCSETA
161# define TCSANOW TCSETA
162# define TCSADRAIN TCSETAW
163# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
164# else
165# define TCSANOW TIOCSETA
166# define TCSADRAIN TIOCSETAW
167# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
168# endif
169# endif
170# define tcsetattr(f, a, t) ioctl(f, a, t)
171# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
172 (tp)->c_cflag |= (val)
173# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
174# ifdef CIBAUD
175# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
176 (tp)->c_cflag |= ((val)<<IBSHIFT)
177# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
178# else
179# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
180 (tp)->c_cflag |= (val)
181# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
182# endif
183# endif /* TCSANOW */
184struct termios termbuf, termbuf2; /* pty control structure */
185# ifdef STREAMSPTY
186int ttyfd = -1;
187# endif
188#endif /* USE_TERMIO */
189
190#include <sys/types.h>
191#include <libutil.h>
192
193int cleanopen __P((char *));
194void scrub_env __P((void));
195
196/*
197 * init_termbuf()
198 * copy_termbuf(cp)
199 * set_termbuf()
200 *
201 * These three routines are used to get and set the "termbuf" structure
202 * to and from the kernel. init_termbuf() gets the current settings.
203 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
204 * set_termbuf() writes the structure into the kernel.
205 */
206
207 void
208init_termbuf()
209{
210#ifndef USE_TERMIO
211 (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
212 (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
213 (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
214# ifdef TIOCGSTATE
215 (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
216# endif
217#else
218# ifdef STREAMSPTY
219 (void) tcgetattr(ttyfd, &termbuf);
220# else
221 (void) tcgetattr(pty, &termbuf);
222# endif
223#endif
224 termbuf2 = termbuf;
225}
226
227#if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
228 void
229copy_termbuf(cp, len)
230 char *cp;
231 int len;
232{
233 if (len > sizeof(termbuf))
234 len = sizeof(termbuf);
235 memmove((char *)&termbuf, cp, len);
236 termbuf2 = termbuf;
237}
238#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
239
240 void
241set_termbuf()
242{
243 /*
244 * Only make the necessary changes.
245 */
246#ifndef USE_TERMIO
247 if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
248 sizeof(termbuf.sg)))
249 (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
250 if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
251 sizeof(termbuf.tc)))
252 (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
253 if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
254 sizeof(termbuf.ltc)))
255 (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
256 if (termbuf.lflags != termbuf2.lflags)
257 (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
258#else /* USE_TERMIO */
259 if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
260# ifdef STREAMSPTY
261 (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
262# else
263 (void) tcsetattr(pty, TCSANOW, &termbuf);
264# endif
265# if defined(CRAY2) && defined(UNICOS5)
266 needtermstat = 1;
267# endif
268#endif /* USE_TERMIO */
269}
270
271
272/*
273 * spcset(func, valp, valpp)
274 *
275 * This function takes various special characters (func), and
276 * sets *valp to the current value of that character, and
277 * *valpp to point to where in the "termbuf" structure that
278 * value is kept.
279 *
280 * It returns the SLC_ level of support for this function.
281 */
282
283#ifndef USE_TERMIO
284 int
285spcset(func, valp, valpp)
286 int func;
287 cc_t *valp;
288 cc_t **valpp;
289{
290 switch(func) {
291 case SLC_EOF:
292 *valp = termbuf.tc.t_eofc;
293 *valpp = (cc_t *)&termbuf.tc.t_eofc;
294 return(SLC_VARIABLE);
295 case SLC_EC:
296 *valp = termbuf.sg.sg_erase;
297 *valpp = (cc_t *)&termbuf.sg.sg_erase;
298 return(SLC_VARIABLE);
299 case SLC_EL:
300 *valp = termbuf.sg.sg_kill;
301 *valpp = (cc_t *)&termbuf.sg.sg_kill;
302 return(SLC_VARIABLE);
303 case SLC_IP:
304 *valp = termbuf.tc.t_intrc;
305 *valpp = (cc_t *)&termbuf.tc.t_intrc;
306 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
307 case SLC_ABORT:
308 *valp = termbuf.tc.t_quitc;
309 *valpp = (cc_t *)&termbuf.tc.t_quitc;
310 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
311 case SLC_XON:
312 *valp = termbuf.tc.t_startc;
313 *valpp = (cc_t *)&termbuf.tc.t_startc;
314 return(SLC_VARIABLE);
315 case SLC_XOFF:
316 *valp = termbuf.tc.t_stopc;
317 *valpp = (cc_t *)&termbuf.tc.t_stopc;
318 return(SLC_VARIABLE);
319 case SLC_AO:
320 *valp = termbuf.ltc.t_flushc;
321 *valpp = (cc_t *)&termbuf.ltc.t_flushc;
322 return(SLC_VARIABLE);
323 case SLC_SUSP:
324 *valp = termbuf.ltc.t_suspc;
325 *valpp = (cc_t *)&termbuf.ltc.t_suspc;
326 return(SLC_VARIABLE);
327 case SLC_EW:
328 *valp = termbuf.ltc.t_werasc;
329 *valpp = (cc_t *)&termbuf.ltc.t_werasc;
330 return(SLC_VARIABLE);
331 case SLC_RP:
332 *valp = termbuf.ltc.t_rprntc;
333 *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
334 return(SLC_VARIABLE);
335 case SLC_LNEXT:
336 *valp = termbuf.ltc.t_lnextc;
337 *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
338 return(SLC_VARIABLE);
339 case SLC_FORW1:
340 *valp = termbuf.tc.t_brkc;
341 *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
342 return(SLC_VARIABLE);
343 case SLC_BRK:
344 case SLC_SYNCH:
345 case SLC_AYT:
346 case SLC_EOR:
347 *valp = (cc_t)0;
348 *valpp = (cc_t *)0;
349 return(SLC_DEFAULT);
350 default:
351 *valp = (cc_t)0;
352 *valpp = (cc_t *)0;
353 return(SLC_NOSUPPORT);
354 }
355}
356
357#else /* USE_TERMIO */
358
359 int
360spcset(func, valp, valpp)
361 int func;
362 cc_t *valp;
363 cc_t **valpp;
364{
365
366#define setval(a, b) *valp = termbuf.c_cc[a]; \
367 *valpp = &termbuf.c_cc[a]; \
368 return(b);
369#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
370
371 switch(func) {
372 case SLC_EOF:
373 setval(VEOF, SLC_VARIABLE);
374 case SLC_EC:
375 setval(VERASE, SLC_VARIABLE);
376 case SLC_EL:
377 setval(VKILL, SLC_VARIABLE);
378 case SLC_IP:
379 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
380 case SLC_ABORT:
381 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
382 case SLC_XON:
383#ifdef VSTART
384 setval(VSTART, SLC_VARIABLE);
385#else
386 defval(0x13);
387#endif
388 case SLC_XOFF:
389#ifdef VSTOP
390 setval(VSTOP, SLC_VARIABLE);
391#else
392 defval(0x11);
393#endif
394 case SLC_EW:
395#ifdef VWERASE
396 setval(VWERASE, SLC_VARIABLE);
397#else
398 defval(0);
399#endif
400 case SLC_RP:
401#ifdef VREPRINT
402 setval(VREPRINT, SLC_VARIABLE);
403#else
404 defval(0);
405#endif
406 case SLC_LNEXT:
407#ifdef VLNEXT
408 setval(VLNEXT, SLC_VARIABLE);
409#else
410 defval(0);
411#endif
412 case SLC_AO:
413#if !defined(VDISCARD) && defined(VFLUSHO)
414# define VDISCARD VFLUSHO
415#endif
416#ifdef VDISCARD
417 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
418#else
419 defval(0);
420#endif
421 case SLC_SUSP:
422#ifdef VSUSP
423 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
424#else
425 defval(0);
426#endif
427#ifdef VEOL
428 case SLC_FORW1:
429 setval(VEOL, SLC_VARIABLE);
430#endif
431#ifdef VEOL2
432 case SLC_FORW2:
433 setval(VEOL2, SLC_VARIABLE);
434#endif
435 case SLC_AYT:
436#ifdef VSTATUS
437 setval(VSTATUS, SLC_VARIABLE);
438#else
439 defval(0);
440#endif
441
442 case SLC_BRK:
443 case SLC_SYNCH:
444 case SLC_EOR:
445 defval(0);
446
447 default:
448 *valp = 0;
449 *valpp = 0;
450 return(SLC_NOSUPPORT);
451 }
452}
453#endif /* USE_TERMIO */
454
455#ifdef CRAY
456/*
457 * getnpty()
458 *
459 * Return the number of pty's configured into the system.
460 */
461 int
462getnpty()
463{
464#ifdef _SC_CRAY_NPTY
465 int numptys;
466
467 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
468 return numptys;
469 else
470#endif /* _SC_CRAY_NPTY */
471 return 128;
472}
473#endif /* CRAY */
474
475#ifndef convex
476/*
477 * getpty()
478 *
479 * Allocate a pty. As a side effect, the external character
480 * array "line" contains the name of the slave side.
481 *
482 * Returns the file descriptor of the opened pty.
483 */
484#ifndef __GNUC__
485char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
486#else
487static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
488char *line = Xline;
489#endif
490#ifdef CRAY
484#ifdef CRAY
491char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
485char myline[16];
486#else
487char line[16];
492#endif /* CRAY */
493
494 int
495getpty(ptynum)
496int *ptynum;
497{
498 register int p;
499#ifdef STREAMSPTY
500 int t;
501 char *ptsname();
502
503 p = open("/dev/ptmx", 2);
504 if (p > 0) {
505 grantpt(p);
506 unlockpt(p);
507 strcpy(line, ptsname(p));
508 return(p);
509 }
510
511#else /* ! STREAMSPTY */
512#ifndef CRAY
513 register char *cp, *p1, *p2;
514 register int i;
515#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
516 int dummy;
517#endif
518
519#ifndef __hpux
488#endif /* CRAY */
489
490 int
491getpty(ptynum)
492int *ptynum;
493{
494 register int p;
495#ifdef STREAMSPTY
496 int t;
497 char *ptsname();
498
499 p = open("/dev/ptmx", 2);
500 if (p > 0) {
501 grantpt(p);
502 unlockpt(p);
503 strcpy(line, ptsname(p));
504 return(p);
505 }
506
507#else /* ! STREAMSPTY */
508#ifndef CRAY
509 register char *cp, *p1, *p2;
510 register int i;
511#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
512 int dummy;
513#endif
514
515#ifndef __hpux
520 (void) strcpy(line, "/dev/ptyXX");
516 (void) strcpy(line, _PATH_DEV);
517 (void) strcat(line, "ptyXX");
521 p1 = &line[8];
522 p2 = &line[9];
523#else
524 (void) strcpy(line, "/dev/ptym/ptyXX");
525 p1 = &line[13];
526 p2 = &line[14];
527#endif
528
529 for (cp = "pqrsPQRS"; *cp; cp++) {
530 struct stat stb;
531
532 *p1 = *cp;
533 *p2 = '0';
534 /*
535 * This stat() check is just to keep us from
536 * looping through all 256 combinations if there
537 * aren't that many ptys available.
538 */
539 if (stat(line, &stb) < 0)
540 break;
541 for (i = 0; i < 32; i++) {
542 *p2 = "0123456789abcdefghijklmnopqrstuv"[i];
543 p = open(line, 2);
544 if (p > 0) {
545#ifndef __hpux
546 line[5] = 't';
547#else
548 for (p1 = &line[8]; *p1; p1++)
549 *p1 = *(p1+1);
550 line[9] = 't';
551#endif
552 chown(line, 0, 0);
553 chmod(line, 0600);
554#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
555 if (ioctl(p, TIOCGPGRP, &dummy) == 0
556 || errno != EIO) {
557 chmod(line, 0666);
558 close(p);
559 line[5] = 'p';
560 } else
561#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
562 return(p);
563 }
564 }
565 }
566#else /* CRAY */
567 extern lowpty, highpty;
568 struct stat sb;
569
570 for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
518 p1 = &line[8];
519 p2 = &line[9];
520#else
521 (void) strcpy(line, "/dev/ptym/ptyXX");
522 p1 = &line[13];
523 p2 = &line[14];
524#endif
525
526 for (cp = "pqrsPQRS"; *cp; cp++) {
527 struct stat stb;
528
529 *p1 = *cp;
530 *p2 = '0';
531 /*
532 * This stat() check is just to keep us from
533 * looping through all 256 combinations if there
534 * aren't that many ptys available.
535 */
536 if (stat(line, &stb) < 0)
537 break;
538 for (i = 0; i < 32; i++) {
539 *p2 = "0123456789abcdefghijklmnopqrstuv"[i];
540 p = open(line, 2);
541 if (p > 0) {
542#ifndef __hpux
543 line[5] = 't';
544#else
545 for (p1 = &line[8]; *p1; p1++)
546 *p1 = *(p1+1);
547 line[9] = 't';
548#endif
549 chown(line, 0, 0);
550 chmod(line, 0600);
551#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
552 if (ioctl(p, TIOCGPGRP, &dummy) == 0
553 || errno != EIO) {
554 chmod(line, 0666);
555 close(p);
556 line[5] = 'p';
557 } else
558#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
559 return(p);
560 }
561 }
562 }
563#else /* CRAY */
564 extern lowpty, highpty;
565 struct stat sb;
566
567 for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
571 (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
568 (void) sprintf(myline, "%spty/%03d", _PATH_DEV, *ptynum);
572 p = open(myline, 2);
573 if (p < 0)
574 continue;
569 p = open(myline, 2);
570 if (p < 0)
571 continue;
575 (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
572 (void) sprintf(line, "%sp%03d", _PATH_TTY, *ptynum);
576 /*
577 * Here are some shenanigans to make sure that there
578 * are no listeners lurking on the line.
579 */
580 if(stat(line, &sb) < 0) {
581 (void) close(p);
582 continue;
583 }
584 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
585 chown(line, 0, 0);
586 chmod(line, 0600);
587 (void)close(p);
588 p = open(myline, 2);
589 if (p < 0)
590 continue;
591 }
592 /*
593 * Now it should be safe...check for accessability.
594 */
595 if (access(line, 6) == 0)
596 return(p);
597 else {
598 /* no tty side to pty so skip it */
599 (void) close(p);
600 }
601 }
602#endif /* CRAY */
603#endif /* STREAMSPTY */
604 return(-1);
605}
606#endif /* convex */
607
608#ifdef LINEMODE
609/*
610 * tty_flowmode() Find out if flow control is enabled or disabled.
611 * tty_linemode() Find out if linemode (external processing) is enabled.
612 * tty_setlinemod(on) Turn on/off linemode.
613 * tty_isecho() Find out if echoing is turned on.
614 * tty_setecho(on) Enable/disable character echoing.
615 * tty_israw() Find out if terminal is in RAW mode.
616 * tty_binaryin(on) Turn on/off BINARY on input.
617 * tty_binaryout(on) Turn on/off BINARY on output.
618 * tty_isediting() Find out if line editing is enabled.
619 * tty_istrapsig() Find out if signal trapping is enabled.
620 * tty_setedit(on) Turn on/off line editing.
621 * tty_setsig(on) Turn on/off signal trapping.
622 * tty_issofttab() Find out if tab expansion is enabled.
623 * tty_setsofttab(on) Turn on/off soft tab expansion.
624 * tty_islitecho() Find out if typed control chars are echoed literally
625 * tty_setlitecho() Turn on/off literal echo of control chars
626 * tty_tspeed(val) Set transmit speed to val.
627 * tty_rspeed(val) Set receive speed to val.
628 */
629
630#ifdef convex
631static int linestate;
632#endif
633
634 int
635tty_linemode()
636{
637#ifndef convex
638#ifndef USE_TERMIO
639 return(termbuf.state & TS_EXTPROC);
640#else
641 return(termbuf.c_lflag & EXTPROC);
642#endif
643#else
644 return(linestate);
645#endif
646}
647
648 void
649tty_setlinemode(on)
650 int on;
651{
652#ifdef TIOCEXT
653# ifndef convex
654 set_termbuf();
655# else
656 linestate = on;
657# endif
658 (void) ioctl(pty, TIOCEXT, (char *)&on);
659# ifndef convex
660 init_termbuf();
661# endif
662#else /* !TIOCEXT */
663# ifdef EXTPROC
664 if (on)
665 termbuf.c_lflag |= EXTPROC;
666 else
667 termbuf.c_lflag &= ~EXTPROC;
668# endif
669#endif /* TIOCEXT */
670}
671#endif /* LINEMODE */
672
673 int
674tty_isecho()
675{
676#ifndef USE_TERMIO
677 return (termbuf.sg.sg_flags & ECHO);
678#else
679 return (termbuf.c_lflag & ECHO);
680#endif
681}
682
683 int
684tty_flowmode()
685{
686#ifndef USE_TERMIO
687 return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
688#else
689 return((termbuf.c_iflag & IXON) ? 1 : 0);
690#endif
691}
692
693 int
694tty_restartany()
695{
696#ifndef USE_TERMIO
697# ifdef DECCTQ
698 return((termbuf.lflags & DECCTQ) ? 0 : 1);
699# else
700 return(-1);
701# endif
702#else
703 return((termbuf.c_iflag & IXANY) ? 1 : 0);
704#endif
705}
706
707 void
708tty_setecho(on)
709 int on;
710{
711#ifndef USE_TERMIO
712 if (on)
713 termbuf.sg.sg_flags |= ECHO|CRMOD;
714 else
715 termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
716#else
717 if (on)
718 termbuf.c_lflag |= ECHO;
719 else
720 termbuf.c_lflag &= ~ECHO;
721#endif
722}
723
724 int
725tty_israw()
726{
727#ifndef USE_TERMIO
728 return(termbuf.sg.sg_flags & RAW);
729#else
730 return(!(termbuf.c_lflag & ICANON));
731#endif
732}
733
734#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
735 int
736tty_setraw(on)
737{
738# ifndef USE_TERMIO
739 if (on)
740 termbuf.sg.sg_flags |= RAW;
741 else
742 termbuf.sg.sg_flags &= ~RAW;
743# else
744 if (on)
745 termbuf.c_lflag &= ~ICANON;
746 else
747 termbuf.c_lflag |= ICANON;
748# endif
749}
750#endif
751
752 void
753tty_binaryin(on)
754 int on;
755{
756#ifndef USE_TERMIO
757 if (on)
758 termbuf.lflags |= LPASS8;
759 else
760 termbuf.lflags &= ~LPASS8;
761#else
762 if (on) {
763 termbuf.c_iflag &= ~ISTRIP;
764 } else {
765 termbuf.c_iflag |= ISTRIP;
766 }
767#endif
768}
769
770 void
771tty_binaryout(on)
772 int on;
773{
774#ifndef USE_TERMIO
775 if (on)
776 termbuf.lflags |= LLITOUT;
777 else
778 termbuf.lflags &= ~LLITOUT;
779#else
780 if (on) {
781 termbuf.c_cflag &= ~(CSIZE|PARENB);
782 termbuf.c_cflag |= CS8;
783 termbuf.c_oflag &= ~OPOST;
784 } else {
785 termbuf.c_cflag &= ~CSIZE;
786 termbuf.c_cflag |= CS7|PARENB;
787 termbuf.c_oflag |= OPOST;
788 }
789#endif
790}
791
792 int
793tty_isbinaryin()
794{
795#ifndef USE_TERMIO
796 return(termbuf.lflags & LPASS8);
797#else
798 return(!(termbuf.c_iflag & ISTRIP));
799#endif
800}
801
802 int
803tty_isbinaryout()
804{
805#ifndef USE_TERMIO
806 return(termbuf.lflags & LLITOUT);
807#else
808 return(!(termbuf.c_oflag&OPOST));
809#endif
810}
811
812#ifdef LINEMODE
813 int
814tty_isediting()
815{
816#ifndef USE_TERMIO
817 return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
818#else
819 return(termbuf.c_lflag & ICANON);
820#endif
821}
822
823 int
824tty_istrapsig()
825{
826#ifndef USE_TERMIO
827 return(!(termbuf.sg.sg_flags&RAW));
828#else
829 return(termbuf.c_lflag & ISIG);
830#endif
831}
832
833 void
834tty_setedit(on)
835 int on;
836{
837#ifndef USE_TERMIO
838 if (on)
839 termbuf.sg.sg_flags &= ~CBREAK;
840 else
841 termbuf.sg.sg_flags |= CBREAK;
842#else
843 if (on)
844 termbuf.c_lflag |= ICANON;
845 else
846 termbuf.c_lflag &= ~ICANON;
847#endif
848}
849
850 void
851tty_setsig(on)
852 int on;
853{
854#ifndef USE_TERMIO
855 if (on)
856 ;
857#else
858 if (on)
859 termbuf.c_lflag |= ISIG;
860 else
861 termbuf.c_lflag &= ~ISIG;
862#endif
863}
864#endif /* LINEMODE */
865
866 int
867tty_issofttab()
868{
869#ifndef USE_TERMIO
870 return (termbuf.sg.sg_flags & XTABS);
871#else
872# ifdef OXTABS
873 return (termbuf.c_oflag & OXTABS);
874# endif
875# ifdef TABDLY
876 return ((termbuf.c_oflag & TABDLY) == TAB3);
877# endif
878#endif
879}
880
881 void
882tty_setsofttab(on)
883 int on;
884{
885#ifndef USE_TERMIO
886 if (on)
887 termbuf.sg.sg_flags |= XTABS;
888 else
889 termbuf.sg.sg_flags &= ~XTABS;
890#else
891 if (on) {
892# ifdef OXTABS
893 termbuf.c_oflag |= OXTABS;
894# endif
895# ifdef TABDLY
896 termbuf.c_oflag &= ~TABDLY;
897 termbuf.c_oflag |= TAB3;
898# endif
899 } else {
900# ifdef OXTABS
901 termbuf.c_oflag &= ~OXTABS;
902# endif
903# ifdef TABDLY
904 termbuf.c_oflag &= ~TABDLY;
905 termbuf.c_oflag |= TAB0;
906# endif
907 }
908#endif
909}
910
911 int
912tty_islitecho()
913{
914#ifndef USE_TERMIO
915 return (!(termbuf.lflags & LCTLECH));
916#else
917# ifdef ECHOCTL
918 return (!(termbuf.c_lflag & ECHOCTL));
919# endif
920# ifdef TCTLECH
921 return (!(termbuf.c_lflag & TCTLECH));
922# endif
923# if !defined(ECHOCTL) && !defined(TCTLECH)
924 return (0); /* assumes ctl chars are echoed '^x' */
925# endif
926#endif
927}
928
929 void
930tty_setlitecho(on)
931 int on;
932{
933#ifndef USE_TERMIO
934 if (on)
935 termbuf.lflags &= ~LCTLECH;
936 else
937 termbuf.lflags |= LCTLECH;
938#else
939# ifdef ECHOCTL
940 if (on)
941 termbuf.c_lflag &= ~ECHOCTL;
942 else
943 termbuf.c_lflag |= ECHOCTL;
944# endif
945# ifdef TCTLECH
946 if (on)
947 termbuf.c_lflag &= ~TCTLECH;
948 else
949 termbuf.c_lflag |= TCTLECH;
950# endif
951#endif
952}
953
954 int
955tty_iscrnl()
956{
957#ifndef USE_TERMIO
958 return (termbuf.sg.sg_flags & CRMOD);
959#else
960 return (termbuf.c_iflag & ICRNL);
961#endif
962}
963
964/*
965 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
966 */
967#if B4800 != 4800
968#define DECODE_BAUD
969#endif
970
971#ifdef DECODE_BAUD
972
973/*
974 * A table of available terminal speeds
975 */
976struct termspeeds {
977 int speed;
978 int value;
979} termspeeds[] = {
980 { 0, B0 }, { 50, B50 }, { 75, B75 },
981 { 110, B110 }, { 134, B134 }, { 150, B150 },
982 { 200, B200 }, { 300, B300 }, { 600, B600 },
983 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
984 { 4800, B4800 },
985#ifdef B7200
986 { 7200, B7200 },
987#endif
988 { 9600, B9600 },
989#ifdef B14400
990 { 14400, B14400 },
991#endif
992#ifdef B19200
993 { 19200, B19200 },
994#endif
995#ifdef B28800
996 { 28800, B28800 },
997#endif
998#ifdef B38400
999 { 38400, B38400 },
1000#endif
1001#ifdef B57600
1002 { 57600, B57600 },
1003#endif
1004#ifdef B115200
1005 { 115200, B115200 },
1006#endif
1007#ifdef B230400
1008 { 230400, B230400 },
1009#endif
1010 { -1, 0 }
1011};
1012#endif /* DECODE_BAUD */
1013
1014 void
1015tty_tspeed(val)
1016 int val;
1017{
1018#ifdef DECODE_BAUD
1019 register struct termspeeds *tp;
1020
1021 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
1022 ;
1023 if (tp->speed == -1) /* back up to last valid value */
1024 --tp;
1025 cfsetospeed(&termbuf, tp->value);
1026#else /* DECODE_BAUD */
1027 cfsetospeed(&termbuf, val);
1028#endif /* DECODE_BAUD */
1029}
1030
1031 void
1032tty_rspeed(val)
1033 int val;
1034{
1035#ifdef DECODE_BAUD
1036 register struct termspeeds *tp;
1037
1038 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
1039 ;
1040 if (tp->speed == -1) /* back up to last valid value */
1041 --tp;
1042 cfsetispeed(&termbuf, tp->value);
1043#else /* DECODE_BAUD */
1044 cfsetispeed(&termbuf, val);
1045#endif /* DECODE_BAUD */
1046}
1047
1048#if defined(CRAY2) && defined(UNICOS5)
1049 int
1050tty_isnewmap()
1051{
1052 return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
1053 !(termbuf.c_oflag & ONLRET));
1054}
1055#endif
1056
1057#ifdef PARENT_DOES_UTMP
1058# ifndef NEWINIT
1059extern struct utmp wtmp;
1060extern char wtmpf[];
1061# else /* NEWINIT */
1062int gotalarm;
1063
1064 /* ARGSUSED */
1065 void
1066nologinproc(sig)
1067 int sig;
1068{
1069 gotalarm++;
1070}
1071# endif /* NEWINIT */
1072#endif /* PARENT_DOES_UTMP */
1073
1074#ifndef NEWINIT
1075# ifdef PARENT_DOES_UTMP
1076extern void utmp_sig_init P((void));
1077extern void utmp_sig_reset P((void));
1078extern void utmp_sig_wait P((void));
1079extern void utmp_sig_notify P((int));
1080# endif /* PARENT_DOES_UTMP */
1081#endif
1082
1083/*
1084 * getptyslave()
1085 *
1086 * Open the slave side of the pty, and do any initialization
1087 * that is necessary.
1088 */
1089 void
1090getptyslave()
1091{
1092 register int t = -1;
1093 char erase;
1094
1095#if !defined(CRAY) || !defined(NEWINIT)
1096# ifdef LINEMODE
1097 int waslm;
1098# endif
1099# ifdef TIOCGWINSZ
1100 struct winsize ws;
1101 extern int def_row, def_col;
1102# endif
1103 extern int def_tspeed, def_rspeed;
1104 /*
1105 * Opening the slave side may cause initilization of the
1106 * kernel tty structure. We need remember the state of
1107 * if linemode was turned on
1108 * terminal window size
1109 * terminal speed
1110 * erase character
1111 * so that we can re-set them if we need to.
1112 */
1113# ifdef LINEMODE
1114 waslm = tty_linemode();
1115# endif
1116 erase = termbuf.c_cc[VERASE];
1117
1118 /*
1119 * Make sure that we don't have a controlling tty, and
1120 * that we are the session (process group) leader.
1121 */
1122# ifdef TIOCNOTTY
1123 t = open(_PATH_TTY, O_RDWR);
1124 if (t >= 0) {
1125 (void) ioctl(t, TIOCNOTTY, (char *)0);
1126 (void) close(t);
1127 }
1128# endif
1129
1130
1131# ifdef PARENT_DOES_UTMP
1132 /*
1133 * Wait for our parent to get the utmp stuff to get done.
1134 */
1135 utmp_sig_wait();
1136# endif
1137
1138 t = cleanopen(line);
1139 if (t < 0)
1140 fatalperror(net, line);
1141
1142#ifdef STREAMSPTY
1143#ifdef USE_TERMIO
1144 ttyfd = t;
1145#endif
1146 if (ioctl(t, I_PUSH, "ptem") < 0)
1147 fatal(net, "I_PUSH ptem");
1148 if (ioctl(t, I_PUSH, "ldterm") < 0)
1149 fatal(net, "I_PUSH ldterm");
1150 if (ioctl(t, I_PUSH, "ttcompat") < 0)
1151 fatal(net, "I_PUSH ttcompat");
1152 if (ioctl(pty, I_PUSH, "pckt") < 0)
1153 fatal(net, "I_PUSH pckt");
1154#endif
1155
1156 /*
1157 * set up the tty modes as we like them to be.
1158 */
1159 init_termbuf();
1160# ifdef TIOCGWINSZ
1161 if (def_row || def_col) {
1162 memset((char *)&ws, 0, sizeof(ws));
1163 ws.ws_col = def_col;
1164 ws.ws_row = def_row;
1165 (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
1166 }
1167# endif
1168
1169 /*
1170 * Settings for sgtty based systems
1171 */
1172# ifndef USE_TERMIO
1173 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
1174# endif /* USE_TERMIO */
1175
1176 /*
1177 * Settings for UNICOS (and HPUX)
1178 */
1179# if defined(CRAY) || defined(__hpux)
1180 termbuf.c_oflag = OPOST|ONLCR|TAB3;
1181 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
1182 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
1183 termbuf.c_cflag = EXTB|HUPCL|CS8;
1184# endif
1185
1186 /*
1187 * Settings for all other termios/termio based
1188 * systems, other than 4.4BSD. In 4.4BSD the
1189 * kernel does the initial terminal setup.
1190 */
1191# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
1192# ifndef OXTABS
1193# define OXTABS 0
1194# endif
1195 termbuf.c_lflag |= ECHO;
1196 termbuf.c_oflag |= ONLCR|OXTABS;
1197 termbuf.c_iflag |= ICRNL;
1198 termbuf.c_iflag &= ~IXOFF;
1199# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
1200 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
1201 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
1202 if (erase)
1203 termbuf.c_cc[VERASE] = erase;
1204# ifdef LINEMODE
1205 if (waslm)
1206 tty_setlinemode(1);
1207# endif /* LINEMODE */
1208
1209 /*
1210 * Set the tty modes, and make this our controlling tty.
1211 */
1212 set_termbuf();
1213 if (login_tty(t) == -1)
1214 fatalperror(net, "login_tty");
1215#endif /* !defined(CRAY) || !defined(NEWINIT) */
1216 if (net > 2)
1217 (void) close(net);
1218#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1219 /*
1220 * Leave the pty open so that we can write out the rlogin
1221 * protocol for /bin/login, if the authentication works.
1222 */
1223#else
1224 if (pty > 2) {
1225 (void) close(pty);
1226 pty = -1;
1227 }
1228#endif
1229}
1230
1231#if !defined(CRAY) || !defined(NEWINIT)
1232#ifndef O_NOCTTY
1233#define O_NOCTTY 0
1234#endif
1235/*
1236 * Open the specified slave side of the pty,
1237 * making sure that we have a clean tty.
1238 */
1239 int
1240cleanopen(line)
1241 char *line;
1242{
1243 register int t;
1244#ifdef UNICOS7x
1245 struct secstat secbuf;
1246#endif /* UNICOS7x */
1247
1248#ifndef STREAMSPTY
1249 /*
1250 * Make sure that other people can't open the
1251 * slave side of the connection.
1252 */
1253 (void) chown(line, 0, 0);
1254 (void) chmod(line, 0600);
1255#endif
1256
1257# if !defined(CRAY) && (BSD > 43)
1258 (void) revoke(line);
1259# endif
1260#ifdef UNICOS7x
1261 if (secflag) {
1262 if (secstat(line, &secbuf) < 0)
1263 return(-1);
1264 if (setulvl(secbuf.st_slevel) < 0)
1265 return(-1);
1266 if (setucmp(secbuf.st_compart) < 0)
1267 return(-1);
1268 }
1269#endif /* UNICOS7x */
1270
1271 t = open(line, O_RDWR|O_NOCTTY);
1272
1273#ifdef UNICOS7x
1274 if (secflag) {
1275 if (setulvl(sysv.sy_minlvl) < 0)
1276 return(-1);
1277 if (setucmp(0) < 0)
1278 return(-1);
1279 }
1280#endif /* UNICOS7x */
1281
1282 if (t < 0)
1283 return(-1);
1284
1285 /*
1286 * Hangup anybody else using this ttyp, then reopen it for
1287 * ourselves.
1288 */
1289# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
1290 (void) signal(SIGHUP, SIG_IGN);
1291 vhangup();
1292 (void) signal(SIGHUP, SIG_DFL);
1293 t = open(line, O_RDWR|O_NOCTTY);
1294 if (t < 0)
1295 return(-1);
1296# endif
1297# if defined(CRAY) && defined(TCVHUP)
1298 {
1299 register int i;
1300 (void) signal(SIGHUP, SIG_IGN);
1301 (void) ioctl(t, TCVHUP, (char *)0);
1302 (void) signal(SIGHUP, SIG_DFL);
573 /*
574 * Here are some shenanigans to make sure that there
575 * are no listeners lurking on the line.
576 */
577 if(stat(line, &sb) < 0) {
578 (void) close(p);
579 continue;
580 }
581 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
582 chown(line, 0, 0);
583 chmod(line, 0600);
584 (void)close(p);
585 p = open(myline, 2);
586 if (p < 0)
587 continue;
588 }
589 /*
590 * Now it should be safe...check for accessability.
591 */
592 if (access(line, 6) == 0)
593 return(p);
594 else {
595 /* no tty side to pty so skip it */
596 (void) close(p);
597 }
598 }
599#endif /* CRAY */
600#endif /* STREAMSPTY */
601 return(-1);
602}
603#endif /* convex */
604
605#ifdef LINEMODE
606/*
607 * tty_flowmode() Find out if flow control is enabled or disabled.
608 * tty_linemode() Find out if linemode (external processing) is enabled.
609 * tty_setlinemod(on) Turn on/off linemode.
610 * tty_isecho() Find out if echoing is turned on.
611 * tty_setecho(on) Enable/disable character echoing.
612 * tty_israw() Find out if terminal is in RAW mode.
613 * tty_binaryin(on) Turn on/off BINARY on input.
614 * tty_binaryout(on) Turn on/off BINARY on output.
615 * tty_isediting() Find out if line editing is enabled.
616 * tty_istrapsig() Find out if signal trapping is enabled.
617 * tty_setedit(on) Turn on/off line editing.
618 * tty_setsig(on) Turn on/off signal trapping.
619 * tty_issofttab() Find out if tab expansion is enabled.
620 * tty_setsofttab(on) Turn on/off soft tab expansion.
621 * tty_islitecho() Find out if typed control chars are echoed literally
622 * tty_setlitecho() Turn on/off literal echo of control chars
623 * tty_tspeed(val) Set transmit speed to val.
624 * tty_rspeed(val) Set receive speed to val.
625 */
626
627#ifdef convex
628static int linestate;
629#endif
630
631 int
632tty_linemode()
633{
634#ifndef convex
635#ifndef USE_TERMIO
636 return(termbuf.state & TS_EXTPROC);
637#else
638 return(termbuf.c_lflag & EXTPROC);
639#endif
640#else
641 return(linestate);
642#endif
643}
644
645 void
646tty_setlinemode(on)
647 int on;
648{
649#ifdef TIOCEXT
650# ifndef convex
651 set_termbuf();
652# else
653 linestate = on;
654# endif
655 (void) ioctl(pty, TIOCEXT, (char *)&on);
656# ifndef convex
657 init_termbuf();
658# endif
659#else /* !TIOCEXT */
660# ifdef EXTPROC
661 if (on)
662 termbuf.c_lflag |= EXTPROC;
663 else
664 termbuf.c_lflag &= ~EXTPROC;
665# endif
666#endif /* TIOCEXT */
667}
668#endif /* LINEMODE */
669
670 int
671tty_isecho()
672{
673#ifndef USE_TERMIO
674 return (termbuf.sg.sg_flags & ECHO);
675#else
676 return (termbuf.c_lflag & ECHO);
677#endif
678}
679
680 int
681tty_flowmode()
682{
683#ifndef USE_TERMIO
684 return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
685#else
686 return((termbuf.c_iflag & IXON) ? 1 : 0);
687#endif
688}
689
690 int
691tty_restartany()
692{
693#ifndef USE_TERMIO
694# ifdef DECCTQ
695 return((termbuf.lflags & DECCTQ) ? 0 : 1);
696# else
697 return(-1);
698# endif
699#else
700 return((termbuf.c_iflag & IXANY) ? 1 : 0);
701#endif
702}
703
704 void
705tty_setecho(on)
706 int on;
707{
708#ifndef USE_TERMIO
709 if (on)
710 termbuf.sg.sg_flags |= ECHO|CRMOD;
711 else
712 termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
713#else
714 if (on)
715 termbuf.c_lflag |= ECHO;
716 else
717 termbuf.c_lflag &= ~ECHO;
718#endif
719}
720
721 int
722tty_israw()
723{
724#ifndef USE_TERMIO
725 return(termbuf.sg.sg_flags & RAW);
726#else
727 return(!(termbuf.c_lflag & ICANON));
728#endif
729}
730
731#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
732 int
733tty_setraw(on)
734{
735# ifndef USE_TERMIO
736 if (on)
737 termbuf.sg.sg_flags |= RAW;
738 else
739 termbuf.sg.sg_flags &= ~RAW;
740# else
741 if (on)
742 termbuf.c_lflag &= ~ICANON;
743 else
744 termbuf.c_lflag |= ICANON;
745# endif
746}
747#endif
748
749 void
750tty_binaryin(on)
751 int on;
752{
753#ifndef USE_TERMIO
754 if (on)
755 termbuf.lflags |= LPASS8;
756 else
757 termbuf.lflags &= ~LPASS8;
758#else
759 if (on) {
760 termbuf.c_iflag &= ~ISTRIP;
761 } else {
762 termbuf.c_iflag |= ISTRIP;
763 }
764#endif
765}
766
767 void
768tty_binaryout(on)
769 int on;
770{
771#ifndef USE_TERMIO
772 if (on)
773 termbuf.lflags |= LLITOUT;
774 else
775 termbuf.lflags &= ~LLITOUT;
776#else
777 if (on) {
778 termbuf.c_cflag &= ~(CSIZE|PARENB);
779 termbuf.c_cflag |= CS8;
780 termbuf.c_oflag &= ~OPOST;
781 } else {
782 termbuf.c_cflag &= ~CSIZE;
783 termbuf.c_cflag |= CS7|PARENB;
784 termbuf.c_oflag |= OPOST;
785 }
786#endif
787}
788
789 int
790tty_isbinaryin()
791{
792#ifndef USE_TERMIO
793 return(termbuf.lflags & LPASS8);
794#else
795 return(!(termbuf.c_iflag & ISTRIP));
796#endif
797}
798
799 int
800tty_isbinaryout()
801{
802#ifndef USE_TERMIO
803 return(termbuf.lflags & LLITOUT);
804#else
805 return(!(termbuf.c_oflag&OPOST));
806#endif
807}
808
809#ifdef LINEMODE
810 int
811tty_isediting()
812{
813#ifndef USE_TERMIO
814 return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
815#else
816 return(termbuf.c_lflag & ICANON);
817#endif
818}
819
820 int
821tty_istrapsig()
822{
823#ifndef USE_TERMIO
824 return(!(termbuf.sg.sg_flags&RAW));
825#else
826 return(termbuf.c_lflag & ISIG);
827#endif
828}
829
830 void
831tty_setedit(on)
832 int on;
833{
834#ifndef USE_TERMIO
835 if (on)
836 termbuf.sg.sg_flags &= ~CBREAK;
837 else
838 termbuf.sg.sg_flags |= CBREAK;
839#else
840 if (on)
841 termbuf.c_lflag |= ICANON;
842 else
843 termbuf.c_lflag &= ~ICANON;
844#endif
845}
846
847 void
848tty_setsig(on)
849 int on;
850{
851#ifndef USE_TERMIO
852 if (on)
853 ;
854#else
855 if (on)
856 termbuf.c_lflag |= ISIG;
857 else
858 termbuf.c_lflag &= ~ISIG;
859#endif
860}
861#endif /* LINEMODE */
862
863 int
864tty_issofttab()
865{
866#ifndef USE_TERMIO
867 return (termbuf.sg.sg_flags & XTABS);
868#else
869# ifdef OXTABS
870 return (termbuf.c_oflag & OXTABS);
871# endif
872# ifdef TABDLY
873 return ((termbuf.c_oflag & TABDLY) == TAB3);
874# endif
875#endif
876}
877
878 void
879tty_setsofttab(on)
880 int on;
881{
882#ifndef USE_TERMIO
883 if (on)
884 termbuf.sg.sg_flags |= XTABS;
885 else
886 termbuf.sg.sg_flags &= ~XTABS;
887#else
888 if (on) {
889# ifdef OXTABS
890 termbuf.c_oflag |= OXTABS;
891# endif
892# ifdef TABDLY
893 termbuf.c_oflag &= ~TABDLY;
894 termbuf.c_oflag |= TAB3;
895# endif
896 } else {
897# ifdef OXTABS
898 termbuf.c_oflag &= ~OXTABS;
899# endif
900# ifdef TABDLY
901 termbuf.c_oflag &= ~TABDLY;
902 termbuf.c_oflag |= TAB0;
903# endif
904 }
905#endif
906}
907
908 int
909tty_islitecho()
910{
911#ifndef USE_TERMIO
912 return (!(termbuf.lflags & LCTLECH));
913#else
914# ifdef ECHOCTL
915 return (!(termbuf.c_lflag & ECHOCTL));
916# endif
917# ifdef TCTLECH
918 return (!(termbuf.c_lflag & TCTLECH));
919# endif
920# if !defined(ECHOCTL) && !defined(TCTLECH)
921 return (0); /* assumes ctl chars are echoed '^x' */
922# endif
923#endif
924}
925
926 void
927tty_setlitecho(on)
928 int on;
929{
930#ifndef USE_TERMIO
931 if (on)
932 termbuf.lflags &= ~LCTLECH;
933 else
934 termbuf.lflags |= LCTLECH;
935#else
936# ifdef ECHOCTL
937 if (on)
938 termbuf.c_lflag &= ~ECHOCTL;
939 else
940 termbuf.c_lflag |= ECHOCTL;
941# endif
942# ifdef TCTLECH
943 if (on)
944 termbuf.c_lflag &= ~TCTLECH;
945 else
946 termbuf.c_lflag |= TCTLECH;
947# endif
948#endif
949}
950
951 int
952tty_iscrnl()
953{
954#ifndef USE_TERMIO
955 return (termbuf.sg.sg_flags & CRMOD);
956#else
957 return (termbuf.c_iflag & ICRNL);
958#endif
959}
960
961/*
962 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
963 */
964#if B4800 != 4800
965#define DECODE_BAUD
966#endif
967
968#ifdef DECODE_BAUD
969
970/*
971 * A table of available terminal speeds
972 */
973struct termspeeds {
974 int speed;
975 int value;
976} termspeeds[] = {
977 { 0, B0 }, { 50, B50 }, { 75, B75 },
978 { 110, B110 }, { 134, B134 }, { 150, B150 },
979 { 200, B200 }, { 300, B300 }, { 600, B600 },
980 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
981 { 4800, B4800 },
982#ifdef B7200
983 { 7200, B7200 },
984#endif
985 { 9600, B9600 },
986#ifdef B14400
987 { 14400, B14400 },
988#endif
989#ifdef B19200
990 { 19200, B19200 },
991#endif
992#ifdef B28800
993 { 28800, B28800 },
994#endif
995#ifdef B38400
996 { 38400, B38400 },
997#endif
998#ifdef B57600
999 { 57600, B57600 },
1000#endif
1001#ifdef B115200
1002 { 115200, B115200 },
1003#endif
1004#ifdef B230400
1005 { 230400, B230400 },
1006#endif
1007 { -1, 0 }
1008};
1009#endif /* DECODE_BAUD */
1010
1011 void
1012tty_tspeed(val)
1013 int val;
1014{
1015#ifdef DECODE_BAUD
1016 register struct termspeeds *tp;
1017
1018 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
1019 ;
1020 if (tp->speed == -1) /* back up to last valid value */
1021 --tp;
1022 cfsetospeed(&termbuf, tp->value);
1023#else /* DECODE_BAUD */
1024 cfsetospeed(&termbuf, val);
1025#endif /* DECODE_BAUD */
1026}
1027
1028 void
1029tty_rspeed(val)
1030 int val;
1031{
1032#ifdef DECODE_BAUD
1033 register struct termspeeds *tp;
1034
1035 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
1036 ;
1037 if (tp->speed == -1) /* back up to last valid value */
1038 --tp;
1039 cfsetispeed(&termbuf, tp->value);
1040#else /* DECODE_BAUD */
1041 cfsetispeed(&termbuf, val);
1042#endif /* DECODE_BAUD */
1043}
1044
1045#if defined(CRAY2) && defined(UNICOS5)
1046 int
1047tty_isnewmap()
1048{
1049 return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
1050 !(termbuf.c_oflag & ONLRET));
1051}
1052#endif
1053
1054#ifdef PARENT_DOES_UTMP
1055# ifndef NEWINIT
1056extern struct utmp wtmp;
1057extern char wtmpf[];
1058# else /* NEWINIT */
1059int gotalarm;
1060
1061 /* ARGSUSED */
1062 void
1063nologinproc(sig)
1064 int sig;
1065{
1066 gotalarm++;
1067}
1068# endif /* NEWINIT */
1069#endif /* PARENT_DOES_UTMP */
1070
1071#ifndef NEWINIT
1072# ifdef PARENT_DOES_UTMP
1073extern void utmp_sig_init P((void));
1074extern void utmp_sig_reset P((void));
1075extern void utmp_sig_wait P((void));
1076extern void utmp_sig_notify P((int));
1077# endif /* PARENT_DOES_UTMP */
1078#endif
1079
1080/*
1081 * getptyslave()
1082 *
1083 * Open the slave side of the pty, and do any initialization
1084 * that is necessary.
1085 */
1086 void
1087getptyslave()
1088{
1089 register int t = -1;
1090 char erase;
1091
1092#if !defined(CRAY) || !defined(NEWINIT)
1093# ifdef LINEMODE
1094 int waslm;
1095# endif
1096# ifdef TIOCGWINSZ
1097 struct winsize ws;
1098 extern int def_row, def_col;
1099# endif
1100 extern int def_tspeed, def_rspeed;
1101 /*
1102 * Opening the slave side may cause initilization of the
1103 * kernel tty structure. We need remember the state of
1104 * if linemode was turned on
1105 * terminal window size
1106 * terminal speed
1107 * erase character
1108 * so that we can re-set them if we need to.
1109 */
1110# ifdef LINEMODE
1111 waslm = tty_linemode();
1112# endif
1113 erase = termbuf.c_cc[VERASE];
1114
1115 /*
1116 * Make sure that we don't have a controlling tty, and
1117 * that we are the session (process group) leader.
1118 */
1119# ifdef TIOCNOTTY
1120 t = open(_PATH_TTY, O_RDWR);
1121 if (t >= 0) {
1122 (void) ioctl(t, TIOCNOTTY, (char *)0);
1123 (void) close(t);
1124 }
1125# endif
1126
1127
1128# ifdef PARENT_DOES_UTMP
1129 /*
1130 * Wait for our parent to get the utmp stuff to get done.
1131 */
1132 utmp_sig_wait();
1133# endif
1134
1135 t = cleanopen(line);
1136 if (t < 0)
1137 fatalperror(net, line);
1138
1139#ifdef STREAMSPTY
1140#ifdef USE_TERMIO
1141 ttyfd = t;
1142#endif
1143 if (ioctl(t, I_PUSH, "ptem") < 0)
1144 fatal(net, "I_PUSH ptem");
1145 if (ioctl(t, I_PUSH, "ldterm") < 0)
1146 fatal(net, "I_PUSH ldterm");
1147 if (ioctl(t, I_PUSH, "ttcompat") < 0)
1148 fatal(net, "I_PUSH ttcompat");
1149 if (ioctl(pty, I_PUSH, "pckt") < 0)
1150 fatal(net, "I_PUSH pckt");
1151#endif
1152
1153 /*
1154 * set up the tty modes as we like them to be.
1155 */
1156 init_termbuf();
1157# ifdef TIOCGWINSZ
1158 if (def_row || def_col) {
1159 memset((char *)&ws, 0, sizeof(ws));
1160 ws.ws_col = def_col;
1161 ws.ws_row = def_row;
1162 (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
1163 }
1164# endif
1165
1166 /*
1167 * Settings for sgtty based systems
1168 */
1169# ifndef USE_TERMIO
1170 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
1171# endif /* USE_TERMIO */
1172
1173 /*
1174 * Settings for UNICOS (and HPUX)
1175 */
1176# if defined(CRAY) || defined(__hpux)
1177 termbuf.c_oflag = OPOST|ONLCR|TAB3;
1178 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
1179 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
1180 termbuf.c_cflag = EXTB|HUPCL|CS8;
1181# endif
1182
1183 /*
1184 * Settings for all other termios/termio based
1185 * systems, other than 4.4BSD. In 4.4BSD the
1186 * kernel does the initial terminal setup.
1187 */
1188# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
1189# ifndef OXTABS
1190# define OXTABS 0
1191# endif
1192 termbuf.c_lflag |= ECHO;
1193 termbuf.c_oflag |= ONLCR|OXTABS;
1194 termbuf.c_iflag |= ICRNL;
1195 termbuf.c_iflag &= ~IXOFF;
1196# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
1197 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
1198 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
1199 if (erase)
1200 termbuf.c_cc[VERASE] = erase;
1201# ifdef LINEMODE
1202 if (waslm)
1203 tty_setlinemode(1);
1204# endif /* LINEMODE */
1205
1206 /*
1207 * Set the tty modes, and make this our controlling tty.
1208 */
1209 set_termbuf();
1210 if (login_tty(t) == -1)
1211 fatalperror(net, "login_tty");
1212#endif /* !defined(CRAY) || !defined(NEWINIT) */
1213 if (net > 2)
1214 (void) close(net);
1215#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1216 /*
1217 * Leave the pty open so that we can write out the rlogin
1218 * protocol for /bin/login, if the authentication works.
1219 */
1220#else
1221 if (pty > 2) {
1222 (void) close(pty);
1223 pty = -1;
1224 }
1225#endif
1226}
1227
1228#if !defined(CRAY) || !defined(NEWINIT)
1229#ifndef O_NOCTTY
1230#define O_NOCTTY 0
1231#endif
1232/*
1233 * Open the specified slave side of the pty,
1234 * making sure that we have a clean tty.
1235 */
1236 int
1237cleanopen(line)
1238 char *line;
1239{
1240 register int t;
1241#ifdef UNICOS7x
1242 struct secstat secbuf;
1243#endif /* UNICOS7x */
1244
1245#ifndef STREAMSPTY
1246 /*
1247 * Make sure that other people can't open the
1248 * slave side of the connection.
1249 */
1250 (void) chown(line, 0, 0);
1251 (void) chmod(line, 0600);
1252#endif
1253
1254# if !defined(CRAY) && (BSD > 43)
1255 (void) revoke(line);
1256# endif
1257#ifdef UNICOS7x
1258 if (secflag) {
1259 if (secstat(line, &secbuf) < 0)
1260 return(-1);
1261 if (setulvl(secbuf.st_slevel) < 0)
1262 return(-1);
1263 if (setucmp(secbuf.st_compart) < 0)
1264 return(-1);
1265 }
1266#endif /* UNICOS7x */
1267
1268 t = open(line, O_RDWR|O_NOCTTY);
1269
1270#ifdef UNICOS7x
1271 if (secflag) {
1272 if (setulvl(sysv.sy_minlvl) < 0)
1273 return(-1);
1274 if (setucmp(0) < 0)
1275 return(-1);
1276 }
1277#endif /* UNICOS7x */
1278
1279 if (t < 0)
1280 return(-1);
1281
1282 /*
1283 * Hangup anybody else using this ttyp, then reopen it for
1284 * ourselves.
1285 */
1286# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
1287 (void) signal(SIGHUP, SIG_IGN);
1288 vhangup();
1289 (void) signal(SIGHUP, SIG_DFL);
1290 t = open(line, O_RDWR|O_NOCTTY);
1291 if (t < 0)
1292 return(-1);
1293# endif
1294# if defined(CRAY) && defined(TCVHUP)
1295 {
1296 register int i;
1297 (void) signal(SIGHUP, SIG_IGN);
1298 (void) ioctl(t, TCVHUP, (char *)0);
1299 (void) signal(SIGHUP, SIG_DFL);
1300 setpgrp();
1303
1304#ifdef UNICOS7x
1305 if (secflag) {
1306 if (secstat(line, &secbuf) < 0)
1307 return(-1);
1308 if (setulvl(secbuf.st_slevel) < 0)
1309 return(-1);
1310 if (setucmp(secbuf.st_compart) < 0)
1311 return(-1);
1312 }
1313#endif /* UNICOS7x */
1314
1315 i = open(line, O_RDWR);
1316
1317#ifdef UNICOS7x
1318 if (secflag) {
1319 if (setulvl(sysv.sy_minlvl) < 0)
1320 return(-1);
1321 if (setucmp(0) < 0)
1322 return(-1);
1323 }
1324#endif /* UNICOS7x */
1325
1326 if (i < 0)
1327 return(-1);
1328 (void) close(t);
1329 t = i;
1330 }
1331# endif /* defined(CRAY) && defined(TCVHUP) */
1332 return(t);
1333}
1334#endif /* !defined(CRAY) || !defined(NEWINIT) */
1335
1336#if BSD <= 43
1337
1338 int
1339login_tty(t)
1340 int t;
1341{
1342 if (setsid() < 0) {
1343#ifdef ultrix
1344 /*
1345 * The setsid() may have failed because we
1346 * already have a pgrp == pid. Zero out
1347 * our pgrp and try again...
1348 */
1349 if ((setpgrp(0, 0) < 0) || (setsid() < 0))
1350#endif
1351 fatalperror(net, "setsid()");
1352 }
1353# ifdef TIOCSCTTY
1354 if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
1355 fatalperror(net, "ioctl(sctty)");
1356# if defined(CRAY)
1357 /*
1358 * Close the hard fd to /dev/ttypXXX, and re-open through
1359 * the indirect /dev/tty interface.
1360 */
1361 close(t);
1301
1302#ifdef UNICOS7x
1303 if (secflag) {
1304 if (secstat(line, &secbuf) < 0)
1305 return(-1);
1306 if (setulvl(secbuf.st_slevel) < 0)
1307 return(-1);
1308 if (setucmp(secbuf.st_compart) < 0)
1309 return(-1);
1310 }
1311#endif /* UNICOS7x */
1312
1313 i = open(line, O_RDWR);
1314
1315#ifdef UNICOS7x
1316 if (secflag) {
1317 if (setulvl(sysv.sy_minlvl) < 0)
1318 return(-1);
1319 if (setucmp(0) < 0)
1320 return(-1);
1321 }
1322#endif /* UNICOS7x */
1323
1324 if (i < 0)
1325 return(-1);
1326 (void) close(t);
1327 t = i;
1328 }
1329# endif /* defined(CRAY) && defined(TCVHUP) */
1330 return(t);
1331}
1332#endif /* !defined(CRAY) || !defined(NEWINIT) */
1333
1334#if BSD <= 43
1335
1336 int
1337login_tty(t)
1338 int t;
1339{
1340 if (setsid() < 0) {
1341#ifdef ultrix
1342 /*
1343 * The setsid() may have failed because we
1344 * already have a pgrp == pid. Zero out
1345 * our pgrp and try again...
1346 */
1347 if ((setpgrp(0, 0) < 0) || (setsid() < 0))
1348#endif
1349 fatalperror(net, "setsid()");
1350 }
1351# ifdef TIOCSCTTY
1352 if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
1353 fatalperror(net, "ioctl(sctty)");
1354# if defined(CRAY)
1355 /*
1356 * Close the hard fd to /dev/ttypXXX, and re-open through
1357 * the indirect /dev/tty interface.
1358 */
1359 close(t);
1362 if ((t = open("/dev/tty", O_RDWR)) < 0)
1360 if ((t = open(_PATH_TTY, O_RDWR)) < 0)
1363 fatalperror(net, "open(/dev/tty)");
1364# endif
1365# else
1366 /*
1367 * We get our controlling tty assigned as a side-effect
1368 * of opening up a tty device. But on BSD based systems,
1369 * this only happens if our process group is zero. The
1370 * setsid() call above may have set our pgrp, so clear
1371 * it out before opening the tty...
1372 */
1373# ifndef SOLARIS
1374 (void) setpgrp(0, 0);
1375# else
1376 (void) setpgrp();
1377# endif
1378 close(open(line, O_RDWR));
1379# endif
1380 if (t != 0)
1381 (void) dup2(t, 0);
1382 if (t != 1)
1383 (void) dup2(t, 1);
1384 if (t != 2)
1385 (void) dup2(t, 2);
1386 if (t > 2)
1387 close(t);
1388 return(0);
1389}
1390#endif /* BSD <= 43 */
1391
1392#ifdef NEWINIT
1393char *gen_id = "fe";
1394#endif
1395
1396/*
1397 * startslave(host)
1398 *
1399 * Given a hostname, do whatever
1400 * is necessary to startup the login process on the slave side of the pty.
1401 */
1402
1403/* ARGSUSED */
1404 void
1405startslave(host, autologin, autoname)
1406 char *host;
1407 int autologin;
1408 char *autoname;
1409{
1410 register int i;
1411#ifdef NEWINIT
1412 extern char *ptyip;
1413 struct init_request request;
1414 void nologinproc();
1415 register int n;
1416#endif /* NEWINIT */
1417
1418#if defined(AUTHENTICATION)
1419 if (!autoname || !autoname[0])
1420 autologin = 0;
1421
1422 if (autologin < auth_level) {
1423 fatal(net, "Authorization failed");
1424 exit(1);
1425 }
1426#endif
1427
1428#ifndef NEWINIT
1429# ifdef PARENT_DOES_UTMP
1430 utmp_sig_init();
1431# endif /* PARENT_DOES_UTMP */
1432
1433 if ((i = fork()) < 0)
1434 fatalperror(net, "fork");
1435 if (i) {
1436# ifdef PARENT_DOES_UTMP
1437 /*
1438 * Cray parent will create utmp entry for child and send
1439 * signal to child to tell when done. Child waits for signal
1440 * before doing anything important.
1441 */
1442 register int pid = i;
1443 void sigjob P((int));
1444
1445 setpgrp();
1446 utmp_sig_reset(); /* reset handler to default */
1447 /*
1448 * Create utmp entry for child
1449 */
1450 (void) time(&wtmp.ut_time);
1451 wtmp.ut_type = LOGIN_PROCESS;
1452 wtmp.ut_pid = pid;
1453 SCPYN(wtmp.ut_user, "LOGIN");
1454 SCPYN(wtmp.ut_host, host);
1361 fatalperror(net, "open(/dev/tty)");
1362# endif
1363# else
1364 /*
1365 * We get our controlling tty assigned as a side-effect
1366 * of opening up a tty device. But on BSD based systems,
1367 * this only happens if our process group is zero. The
1368 * setsid() call above may have set our pgrp, so clear
1369 * it out before opening the tty...
1370 */
1371# ifndef SOLARIS
1372 (void) setpgrp(0, 0);
1373# else
1374 (void) setpgrp();
1375# endif
1376 close(open(line, O_RDWR));
1377# endif
1378 if (t != 0)
1379 (void) dup2(t, 0);
1380 if (t != 1)
1381 (void) dup2(t, 1);
1382 if (t != 2)
1383 (void) dup2(t, 2);
1384 if (t > 2)
1385 close(t);
1386 return(0);
1387}
1388#endif /* BSD <= 43 */
1389
1390#ifdef NEWINIT
1391char *gen_id = "fe";
1392#endif
1393
1394/*
1395 * startslave(host)
1396 *
1397 * Given a hostname, do whatever
1398 * is necessary to startup the login process on the slave side of the pty.
1399 */
1400
1401/* ARGSUSED */
1402 void
1403startslave(host, autologin, autoname)
1404 char *host;
1405 int autologin;
1406 char *autoname;
1407{
1408 register int i;
1409#ifdef NEWINIT
1410 extern char *ptyip;
1411 struct init_request request;
1412 void nologinproc();
1413 register int n;
1414#endif /* NEWINIT */
1415
1416#if defined(AUTHENTICATION)
1417 if (!autoname || !autoname[0])
1418 autologin = 0;
1419
1420 if (autologin < auth_level) {
1421 fatal(net, "Authorization failed");
1422 exit(1);
1423 }
1424#endif
1425
1426#ifndef NEWINIT
1427# ifdef PARENT_DOES_UTMP
1428 utmp_sig_init();
1429# endif /* PARENT_DOES_UTMP */
1430
1431 if ((i = fork()) < 0)
1432 fatalperror(net, "fork");
1433 if (i) {
1434# ifdef PARENT_DOES_UTMP
1435 /*
1436 * Cray parent will create utmp entry for child and send
1437 * signal to child to tell when done. Child waits for signal
1438 * before doing anything important.
1439 */
1440 register int pid = i;
1441 void sigjob P((int));
1442
1443 setpgrp();
1444 utmp_sig_reset(); /* reset handler to default */
1445 /*
1446 * Create utmp entry for child
1447 */
1448 (void) time(&wtmp.ut_time);
1449 wtmp.ut_type = LOGIN_PROCESS;
1450 wtmp.ut_pid = pid;
1451 SCPYN(wtmp.ut_user, "LOGIN");
1452 SCPYN(wtmp.ut_host, host);
1455 SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
1453 SCPYN(wtmp.ut_line, line + sizeof(_PATH_DEV) - 1);
1456#ifndef __hpux
1457 SCPYN(wtmp.ut_id, wtmp.ut_line+3);
1458#else
1459 SCPYN(wtmp.ut_id, wtmp.ut_line+7);
1460#endif
1461 pututline(&wtmp);
1462 endutent();
1463 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
1464 (void) write(i, (char *)&wtmp, sizeof(struct utmp));
1465 (void) close(i);
1466 }
1467#ifdef CRAY
1468 (void) signal(WJSIGNAL, sigjob);
1469#endif
1470 utmp_sig_notify(pid);
1471# endif /* PARENT_DOES_UTMP */
1472 } else {
1473 getptyslave(autologin);
1474 start_login(host, autologin, autoname);
1475 /*NOTREACHED*/
1476 }
1477#else /* NEWINIT */
1478
1479 /*
1480 * Init will start up login process if we ask nicely. We only wait
1481 * for it to start up and begin normal telnet operation.
1482 */
1483 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
1484 char tbuf[128];
1485 (void) snprintf(tbuf, sizeof(tbuf), "Can't open %s\n", INIT_FIFO);
1486 fatalperror(net, tbuf);
1487 }
1488 memset((char *)&request, 0, sizeof(request));
1489 request.magic = INIT_MAGIC;
1490 SCPYN(request.gen_id, gen_id);
1491 SCPYN(request.tty_id, &line[8]);
1492 SCPYN(request.host, host);
1493 SCPYN(request.term_type, terminaltype ? terminaltype : "network");
1494#if !defined(UNICOS5)
1495 request.signal = SIGCLD;
1496 request.pid = getpid();
1497#endif
1498#ifdef BFTPDAEMON
1499 /*
1500 * Are we working as the bftp daemon?
1501 */
1502 if (bftpd) {
1503 SCPYN(request.exec_name, BFTPPATH);
1504 }
1505#endif /* BFTPDAEMON */
1506 if (write(i, (char *)&request, sizeof(request)) < 0) {
1507 char tbuf[128];
1508 (void) snprintf(tbuf, sizeof(tbuf), "Can't write to %s\n", INIT_FIFO);
1509 fatalperror(net, tbuf);
1510 }
1511 (void) close(i);
1512 (void) signal(SIGALRM, nologinproc);
1513 for (i = 0; ; i++) {
1514 char tbuf[128];
1515 alarm(15);
1516 n = read(pty, ptyip, BUFSIZ);
1517 if (i == 3 || n >= 0 || !gotalarm)
1518 break;
1519 gotalarm = 0;
1520 snprintf(tbuf, sizeof(tbuf), "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
1521 (void) write(net, tbuf, strlen(tbuf));
1522 }
1523 if (n < 0 && gotalarm)
1524 fatal(net, "/etc/init didn't start login process");
1525 pcc += n;
1526 alarm(0);
1527 (void) signal(SIGALRM, SIG_DFL);
1528
1529 return;
1530#endif /* NEWINIT */
1531}
1532
1533char *envinit[3];
1534extern char **environ;
1535
1536 void
1537init_env()
1538{
1539 extern char *getenv();
1540 char **envp;
1541
1542 envp = envinit;
1543 if ((*envp = getenv("TZ")))
1544 *envp++ -= 3;
1545#if defined(CRAY) || defined(__hpux)
1546 else
1547 *envp++ = "TZ=GMT0";
1548#endif
1549 *envp = 0;
1550 environ = envinit;
1551}
1552
1553#ifndef NEWINIT
1554
1555/*
1556 * start_login(host)
1557 *
1558 * Assuming that we are now running as a child processes, this
1559 * function will turn us into the login process.
1560 */
1561
1562 void
1563start_login(host, autologin, name)
1564 char *host;
1565 int autologin;
1566 char *name;
1567{
1568 register char **argv;
1569 char **addarg(), *user;
1570 extern char *getenv();
1571#ifdef UTMPX
1572 register int pid = getpid();
1573 struct utmpx utmpx;
1574#endif
1575#ifdef SOLARIS
1576 char *term;
1577 char termbuf[64];
1578#endif
1579
1580#ifdef UTMPX
1581 /*
1582 * Create utmp entry for child
1583 */
1584
1585 memset(&utmpx, 0, sizeof(utmpx));
1586 SCPYN(utmpx.ut_user, ".telnet");
1454#ifndef __hpux
1455 SCPYN(wtmp.ut_id, wtmp.ut_line+3);
1456#else
1457 SCPYN(wtmp.ut_id, wtmp.ut_line+7);
1458#endif
1459 pututline(&wtmp);
1460 endutent();
1461 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
1462 (void) write(i, (char *)&wtmp, sizeof(struct utmp));
1463 (void) close(i);
1464 }
1465#ifdef CRAY
1466 (void) signal(WJSIGNAL, sigjob);
1467#endif
1468 utmp_sig_notify(pid);
1469# endif /* PARENT_DOES_UTMP */
1470 } else {
1471 getptyslave(autologin);
1472 start_login(host, autologin, autoname);
1473 /*NOTREACHED*/
1474 }
1475#else /* NEWINIT */
1476
1477 /*
1478 * Init will start up login process if we ask nicely. We only wait
1479 * for it to start up and begin normal telnet operation.
1480 */
1481 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
1482 char tbuf[128];
1483 (void) snprintf(tbuf, sizeof(tbuf), "Can't open %s\n", INIT_FIFO);
1484 fatalperror(net, tbuf);
1485 }
1486 memset((char *)&request, 0, sizeof(request));
1487 request.magic = INIT_MAGIC;
1488 SCPYN(request.gen_id, gen_id);
1489 SCPYN(request.tty_id, &line[8]);
1490 SCPYN(request.host, host);
1491 SCPYN(request.term_type, terminaltype ? terminaltype : "network");
1492#if !defined(UNICOS5)
1493 request.signal = SIGCLD;
1494 request.pid = getpid();
1495#endif
1496#ifdef BFTPDAEMON
1497 /*
1498 * Are we working as the bftp daemon?
1499 */
1500 if (bftpd) {
1501 SCPYN(request.exec_name, BFTPPATH);
1502 }
1503#endif /* BFTPDAEMON */
1504 if (write(i, (char *)&request, sizeof(request)) < 0) {
1505 char tbuf[128];
1506 (void) snprintf(tbuf, sizeof(tbuf), "Can't write to %s\n", INIT_FIFO);
1507 fatalperror(net, tbuf);
1508 }
1509 (void) close(i);
1510 (void) signal(SIGALRM, nologinproc);
1511 for (i = 0; ; i++) {
1512 char tbuf[128];
1513 alarm(15);
1514 n = read(pty, ptyip, BUFSIZ);
1515 if (i == 3 || n >= 0 || !gotalarm)
1516 break;
1517 gotalarm = 0;
1518 snprintf(tbuf, sizeof(tbuf), "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
1519 (void) write(net, tbuf, strlen(tbuf));
1520 }
1521 if (n < 0 && gotalarm)
1522 fatal(net, "/etc/init didn't start login process");
1523 pcc += n;
1524 alarm(0);
1525 (void) signal(SIGALRM, SIG_DFL);
1526
1527 return;
1528#endif /* NEWINIT */
1529}
1530
1531char *envinit[3];
1532extern char **environ;
1533
1534 void
1535init_env()
1536{
1537 extern char *getenv();
1538 char **envp;
1539
1540 envp = envinit;
1541 if ((*envp = getenv("TZ")))
1542 *envp++ -= 3;
1543#if defined(CRAY) || defined(__hpux)
1544 else
1545 *envp++ = "TZ=GMT0";
1546#endif
1547 *envp = 0;
1548 environ = envinit;
1549}
1550
1551#ifndef NEWINIT
1552
1553/*
1554 * start_login(host)
1555 *
1556 * Assuming that we are now running as a child processes, this
1557 * function will turn us into the login process.
1558 */
1559
1560 void
1561start_login(host, autologin, name)
1562 char *host;
1563 int autologin;
1564 char *name;
1565{
1566 register char **argv;
1567 char **addarg(), *user;
1568 extern char *getenv();
1569#ifdef UTMPX
1570 register int pid = getpid();
1571 struct utmpx utmpx;
1572#endif
1573#ifdef SOLARIS
1574 char *term;
1575 char termbuf[64];
1576#endif
1577
1578#ifdef UTMPX
1579 /*
1580 * Create utmp entry for child
1581 */
1582
1583 memset(&utmpx, 0, sizeof(utmpx));
1584 SCPYN(utmpx.ut_user, ".telnet");
1587 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
1585 SCPYN(utmpx.ut_line, line + sizeof(_PATH_DEV) - 1);
1588 utmpx.ut_pid = pid;
1589 utmpx.ut_id[0] = 't';
1590 utmpx.ut_id[1] = 'n';
1591 utmpx.ut_id[2] = SC_WILDC;
1592 utmpx.ut_id[3] = SC_WILDC;
1593 utmpx.ut_type = LOGIN_PROCESS;
1594 (void) time(&utmpx.ut_tv.tv_sec);
1595 if (makeutx(&utmpx) == NULL)
1596 fatal(net, "makeutx failed");
1597#endif
1598
1599 scrub_env();
1600
1601 /*
1602 * -h : pass on name of host.
1603 * WARNING: -h is accepted by login if and only if
1604 * getuid() == 0.
1605 * -p : don't clobber the environment (so terminal type stays set).
1606 *
1607 * -f : force this login, he has already been authenticated
1608 */
1609 argv = addarg(0, "login");
1610
1611#if !defined(NO_LOGIN_H)
1612
1613# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1614 /*
1615 * Don't add the "-h host" option if we are going
1616 * to be adding the "-r host" option down below...
1617 */
1618 if ((auth_level < 0) || (autologin != AUTH_VALID))
1619# endif
1620 {
1621 argv = addarg(argv, "-h");
1622 argv = addarg(argv, host);
1623#ifdef SOLARIS
1624 /*
1625 * SVR4 version of -h takes TERM= as second arg, or -
1626 */
1627 term = getenv("TERM");
1628 if (term == NULL || term[0] == 0) {
1629 term = "-";
1630 } else {
1631 strcpy(termbuf, "TERM=");
1632 strncat(termbuf, term, sizeof(termbuf) - 6);
1633 term = termbuf;
1634 }
1635 argv = addarg(argv, term);
1636#endif
1637 }
1638#endif
1639#if !defined(NO_LOGIN_P)
1640 argv = addarg(argv, "-p");
1641#endif
1642#ifdef LINEMODE
1643 /*
1644 * Set the environment variable "LINEMODE" to either
1645 * "real" or "kludge" if we are operating in either
1646 * real or kludge linemode.
1647 */
1648 if (lmodetype == REAL_LINEMODE)
1649 setenv("LINEMODE", "real", 1);
1650# ifdef KLUDGELINEMODE
1651 else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
1652 setenv("LINEMODE", "kludge", 1);
1653# endif
1654#endif
1655#ifdef BFTPDAEMON
1656 /*
1657 * Are we working as the bftp daemon? If so, then ask login
1658 * to start bftp instead of shell.
1659 */
1660 if (bftpd) {
1661 argv = addarg(argv, "-e");
1662 argv = addarg(argv, BFTPPATH);
1663 } else
1664#endif
1665#if defined (SecurID)
1666 /*
1667 * don't worry about the -f that might get sent.
1668 * A -s is supposed to override it anyhow.
1669 */
1670 if (require_SecurID)
1671 argv = addarg(argv, "-s");
1672#endif
1673#if defined (AUTHENTICATION)
1674 if (auth_level >= 0 && autologin == AUTH_VALID) {
1675# if !defined(NO_LOGIN_F)
1676 argv = addarg(argv, "-f");
1677 argv = addarg(argv, "--");
1678 argv = addarg(argv, name);
1679# else
1680# if defined(LOGIN_R)
1681 /*
1682 * We don't have support for "login -f", but we
1683 * can fool /bin/login into thinking that we are
1684 * rlogind, and allow us to log in without a
1685 * password. The rlogin protocol expects
1686 * local-user\0remote-user\0term/speed\0
1687 */
1688
1689 if (pty > 2) {
1690 register char *cp;
1691 char speed[128];
1692 int isecho, israw, xpty, len;
1693 extern int def_rspeed;
1694# ifndef LOGIN_HOST
1695 /*
1696 * Tell login that we are coming from "localhost".
1697 * If we passed in the real host name, then the
1698 * user would have to allow .rhost access from
1699 * every machine that they want authenticated
1700 * access to work from, which sort of defeats
1701 * the purpose of an authenticated login...
1702 * So, we tell login that the session is coming
1703 * from "localhost", and the user will only have
1704 * to have "localhost" in their .rhost file.
1705 */
1706# define LOGIN_HOST "localhost"
1707# endif
1708 argv = addarg(argv, "-r");
1709 argv = addarg(argv, LOGIN_HOST);
1710
1711 xpty = pty;
1712# ifndef STREAMSPTY
1713 pty = 0;
1714# else
1715 ttyfd = 0;
1716# endif
1717 init_termbuf();
1718 isecho = tty_isecho();
1719 israw = tty_israw();
1720 if (isecho || !israw) {
1721 tty_setecho(0); /* Turn off echo */
1722 tty_setraw(1); /* Turn on raw */
1723 set_termbuf();
1724 }
1725 len = strlen(name)+1;
1726 write(xpty, name, len);
1727 write(xpty, name, len);
1728 snprintf(speed, sizeof(speed),
1729 "%s/%d", (cp = getenv("TERM")) ? cp : "",
1730 (def_rspeed > 0) ? def_rspeed : 9600);
1731 len = strlen(speed)+1;
1732 write(xpty, speed, len);
1733
1734 if (isecho || !israw) {
1735 init_termbuf();
1736 tty_setecho(isecho);
1737 tty_setraw(israw);
1738 set_termbuf();
1739 if (!israw) {
1740 /*
1741 * Write a newline to ensure
1742 * that login will be able to
1743 * read the line...
1744 */
1745 write(xpty, "\n", 1);
1746 }
1747 }
1748 pty = xpty;
1749 }
1750# else
1751 argv = addarg(argv, "--");
1752 argv = addarg(argv, name);
1753# endif
1754# endif
1755 } else
1756#endif
1757 if (getenv("USER")) {
1758 argv = addarg(argv, "--");
1759 argv = addarg(argv, getenv("USER"));
1760#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
1761 {
1762 register char **cpp;
1763 for (cpp = environ; *cpp; cpp++)
1764 argv = addarg(argv, *cpp);
1765 }
1766#endif
1767 /*
1768 * Assume that login will set the USER variable
1769 * correctly. For SysV systems, this means that
1770 * USER will no longer be set, just LOGNAME by
1771 * login. (The problem is that if the auto-login
1772 * fails, and the user then specifies a different
1773 * account name, he can get logged in with both
1774 * LOGNAME and USER in his environment, but the
1775 * USER value will be wrong.
1776 */
1777 unsetenv("USER");
1778 }
1779#ifdef SOLARIS
1780 else {
1781 char **p;
1782
1783 argv = addarg(argv, ""); /* no login name */
1784 for (p = environ; *p; p++) {
1785 argv = addarg(argv, *p);
1786 }
1787 }
1788#endif /* SOLARIS */
1789#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1790 if (pty > 2)
1791 close(pty);
1792#endif
1793 closelog();
1794
1795 if (altlogin == NULL) {
1796 altlogin = _PATH_LOGIN;
1797 }
1798 execv(altlogin, argv);
1799
1800 syslog(LOG_ERR, "%s: %m", altlogin);
1801 fatalperror(net, altlogin);
1802 /*NOTREACHED*/
1803}
1804
1805 char **
1806addarg(argv, val)
1807 register char **argv;
1808 register char *val;
1809{
1810 register char **cpp;
1811
1812 if (argv == NULL) {
1813 /*
1814 * 10 entries, a leading length, and a null
1815 */
1816 argv = (char **)malloc(sizeof(*argv) * 12);
1817 if (argv == NULL)
1818 return(NULL);
1819 *argv++ = (char *)10;
1820 *argv = (char *)0;
1821 }
1822 for (cpp = argv; *cpp; cpp++)
1823 ;
1824 if (cpp == &argv[(int)argv[-1]]) {
1825 --argv;
1826 *argv = (char *)((int)(*argv) + 10);
1827 argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
1828 if (argv == NULL)
1829 return(NULL);
1830 argv++;
1831 cpp = &argv[(int)argv[-1] - 10];
1832 }
1833 *cpp++ = val;
1834 *cpp = 0;
1835 return(argv);
1836}
1837#endif /* NEWINIT */
1838
1839/*
1840 * scrub_env()
1841 *
1842 * We only accept the environment variables listed below.
1843 */
1844 void
1845scrub_env()
1846{
1847 static const char *reject[] = {
1848 "TERMCAP=/",
1849 NULL
1850 };
1851
1852 static const char *accept[] = {
1853 "XAUTH=", "XAUTHORITY=", "DISPLAY=",
1854 "TERM=",
1855 "EDITOR=",
1856 "PAGER=",
1857 "LOGNAME=",
1858 "POSIXLY_CORRECT=",
1859 "PRINTER=",
1860 NULL
1861 };
1862
1863 char **cpp, **cpp2;
1864 const char **p;
1865
1866 for (cpp2 = cpp = environ; *cpp; cpp++) {
1867 int reject_it = 0;
1868
1869 for(p = reject; *p; p++)
1870 if(strncmp(*cpp, *p, strlen(*p)) == 0) {
1871 reject_it = 1;
1872 break;
1873 }
1874 if (reject_it)
1875 continue;
1876
1877 for(p = accept; *p; p++)
1878 if(strncmp(*cpp, *p, strlen(*p)) == 0)
1879 break;
1880 if(*p != NULL)
1881 *cpp2++ = *cpp;
1882 }
1883 *cpp2 = NULL;
1884}
1885
1886/*
1887 * cleanup()
1888 *
1889 * This is the routine to call when we are all through, to
1890 * clean up anything that needs to be cleaned up.
1891 */
1892 /* ARGSUSED */
1893 void
1894cleanup(sig)
1895 int sig;
1896{
1897#ifndef PARENT_DOES_UTMP
1898# if (BSD > 43) || defined(convex)
1899 char *p;
1900
1586 utmpx.ut_pid = pid;
1587 utmpx.ut_id[0] = 't';
1588 utmpx.ut_id[1] = 'n';
1589 utmpx.ut_id[2] = SC_WILDC;
1590 utmpx.ut_id[3] = SC_WILDC;
1591 utmpx.ut_type = LOGIN_PROCESS;
1592 (void) time(&utmpx.ut_tv.tv_sec);
1593 if (makeutx(&utmpx) == NULL)
1594 fatal(net, "makeutx failed");
1595#endif
1596
1597 scrub_env();
1598
1599 /*
1600 * -h : pass on name of host.
1601 * WARNING: -h is accepted by login if and only if
1602 * getuid() == 0.
1603 * -p : don't clobber the environment (so terminal type stays set).
1604 *
1605 * -f : force this login, he has already been authenticated
1606 */
1607 argv = addarg(0, "login");
1608
1609#if !defined(NO_LOGIN_H)
1610
1611# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1612 /*
1613 * Don't add the "-h host" option if we are going
1614 * to be adding the "-r host" option down below...
1615 */
1616 if ((auth_level < 0) || (autologin != AUTH_VALID))
1617# endif
1618 {
1619 argv = addarg(argv, "-h");
1620 argv = addarg(argv, host);
1621#ifdef SOLARIS
1622 /*
1623 * SVR4 version of -h takes TERM= as second arg, or -
1624 */
1625 term = getenv("TERM");
1626 if (term == NULL || term[0] == 0) {
1627 term = "-";
1628 } else {
1629 strcpy(termbuf, "TERM=");
1630 strncat(termbuf, term, sizeof(termbuf) - 6);
1631 term = termbuf;
1632 }
1633 argv = addarg(argv, term);
1634#endif
1635 }
1636#endif
1637#if !defined(NO_LOGIN_P)
1638 argv = addarg(argv, "-p");
1639#endif
1640#ifdef LINEMODE
1641 /*
1642 * Set the environment variable "LINEMODE" to either
1643 * "real" or "kludge" if we are operating in either
1644 * real or kludge linemode.
1645 */
1646 if (lmodetype == REAL_LINEMODE)
1647 setenv("LINEMODE", "real", 1);
1648# ifdef KLUDGELINEMODE
1649 else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
1650 setenv("LINEMODE", "kludge", 1);
1651# endif
1652#endif
1653#ifdef BFTPDAEMON
1654 /*
1655 * Are we working as the bftp daemon? If so, then ask login
1656 * to start bftp instead of shell.
1657 */
1658 if (bftpd) {
1659 argv = addarg(argv, "-e");
1660 argv = addarg(argv, BFTPPATH);
1661 } else
1662#endif
1663#if defined (SecurID)
1664 /*
1665 * don't worry about the -f that might get sent.
1666 * A -s is supposed to override it anyhow.
1667 */
1668 if (require_SecurID)
1669 argv = addarg(argv, "-s");
1670#endif
1671#if defined (AUTHENTICATION)
1672 if (auth_level >= 0 && autologin == AUTH_VALID) {
1673# if !defined(NO_LOGIN_F)
1674 argv = addarg(argv, "-f");
1675 argv = addarg(argv, "--");
1676 argv = addarg(argv, name);
1677# else
1678# if defined(LOGIN_R)
1679 /*
1680 * We don't have support for "login -f", but we
1681 * can fool /bin/login into thinking that we are
1682 * rlogind, and allow us to log in without a
1683 * password. The rlogin protocol expects
1684 * local-user\0remote-user\0term/speed\0
1685 */
1686
1687 if (pty > 2) {
1688 register char *cp;
1689 char speed[128];
1690 int isecho, israw, xpty, len;
1691 extern int def_rspeed;
1692# ifndef LOGIN_HOST
1693 /*
1694 * Tell login that we are coming from "localhost".
1695 * If we passed in the real host name, then the
1696 * user would have to allow .rhost access from
1697 * every machine that they want authenticated
1698 * access to work from, which sort of defeats
1699 * the purpose of an authenticated login...
1700 * So, we tell login that the session is coming
1701 * from "localhost", and the user will only have
1702 * to have "localhost" in their .rhost file.
1703 */
1704# define LOGIN_HOST "localhost"
1705# endif
1706 argv = addarg(argv, "-r");
1707 argv = addarg(argv, LOGIN_HOST);
1708
1709 xpty = pty;
1710# ifndef STREAMSPTY
1711 pty = 0;
1712# else
1713 ttyfd = 0;
1714# endif
1715 init_termbuf();
1716 isecho = tty_isecho();
1717 israw = tty_israw();
1718 if (isecho || !israw) {
1719 tty_setecho(0); /* Turn off echo */
1720 tty_setraw(1); /* Turn on raw */
1721 set_termbuf();
1722 }
1723 len = strlen(name)+1;
1724 write(xpty, name, len);
1725 write(xpty, name, len);
1726 snprintf(speed, sizeof(speed),
1727 "%s/%d", (cp = getenv("TERM")) ? cp : "",
1728 (def_rspeed > 0) ? def_rspeed : 9600);
1729 len = strlen(speed)+1;
1730 write(xpty, speed, len);
1731
1732 if (isecho || !israw) {
1733 init_termbuf();
1734 tty_setecho(isecho);
1735 tty_setraw(israw);
1736 set_termbuf();
1737 if (!israw) {
1738 /*
1739 * Write a newline to ensure
1740 * that login will be able to
1741 * read the line...
1742 */
1743 write(xpty, "\n", 1);
1744 }
1745 }
1746 pty = xpty;
1747 }
1748# else
1749 argv = addarg(argv, "--");
1750 argv = addarg(argv, name);
1751# endif
1752# endif
1753 } else
1754#endif
1755 if (getenv("USER")) {
1756 argv = addarg(argv, "--");
1757 argv = addarg(argv, getenv("USER"));
1758#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
1759 {
1760 register char **cpp;
1761 for (cpp = environ; *cpp; cpp++)
1762 argv = addarg(argv, *cpp);
1763 }
1764#endif
1765 /*
1766 * Assume that login will set the USER variable
1767 * correctly. For SysV systems, this means that
1768 * USER will no longer be set, just LOGNAME by
1769 * login. (The problem is that if the auto-login
1770 * fails, and the user then specifies a different
1771 * account name, he can get logged in with both
1772 * LOGNAME and USER in his environment, but the
1773 * USER value will be wrong.
1774 */
1775 unsetenv("USER");
1776 }
1777#ifdef SOLARIS
1778 else {
1779 char **p;
1780
1781 argv = addarg(argv, ""); /* no login name */
1782 for (p = environ; *p; p++) {
1783 argv = addarg(argv, *p);
1784 }
1785 }
1786#endif /* SOLARIS */
1787#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1788 if (pty > 2)
1789 close(pty);
1790#endif
1791 closelog();
1792
1793 if (altlogin == NULL) {
1794 altlogin = _PATH_LOGIN;
1795 }
1796 execv(altlogin, argv);
1797
1798 syslog(LOG_ERR, "%s: %m", altlogin);
1799 fatalperror(net, altlogin);
1800 /*NOTREACHED*/
1801}
1802
1803 char **
1804addarg(argv, val)
1805 register char **argv;
1806 register char *val;
1807{
1808 register char **cpp;
1809
1810 if (argv == NULL) {
1811 /*
1812 * 10 entries, a leading length, and a null
1813 */
1814 argv = (char **)malloc(sizeof(*argv) * 12);
1815 if (argv == NULL)
1816 return(NULL);
1817 *argv++ = (char *)10;
1818 *argv = (char *)0;
1819 }
1820 for (cpp = argv; *cpp; cpp++)
1821 ;
1822 if (cpp == &argv[(int)argv[-1]]) {
1823 --argv;
1824 *argv = (char *)((int)(*argv) + 10);
1825 argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
1826 if (argv == NULL)
1827 return(NULL);
1828 argv++;
1829 cpp = &argv[(int)argv[-1] - 10];
1830 }
1831 *cpp++ = val;
1832 *cpp = 0;
1833 return(argv);
1834}
1835#endif /* NEWINIT */
1836
1837/*
1838 * scrub_env()
1839 *
1840 * We only accept the environment variables listed below.
1841 */
1842 void
1843scrub_env()
1844{
1845 static const char *reject[] = {
1846 "TERMCAP=/",
1847 NULL
1848 };
1849
1850 static const char *accept[] = {
1851 "XAUTH=", "XAUTHORITY=", "DISPLAY=",
1852 "TERM=",
1853 "EDITOR=",
1854 "PAGER=",
1855 "LOGNAME=",
1856 "POSIXLY_CORRECT=",
1857 "PRINTER=",
1858 NULL
1859 };
1860
1861 char **cpp, **cpp2;
1862 const char **p;
1863
1864 for (cpp2 = cpp = environ; *cpp; cpp++) {
1865 int reject_it = 0;
1866
1867 for(p = reject; *p; p++)
1868 if(strncmp(*cpp, *p, strlen(*p)) == 0) {
1869 reject_it = 1;
1870 break;
1871 }
1872 if (reject_it)
1873 continue;
1874
1875 for(p = accept; *p; p++)
1876 if(strncmp(*cpp, *p, strlen(*p)) == 0)
1877 break;
1878 if(*p != NULL)
1879 *cpp2++ = *cpp;
1880 }
1881 *cpp2 = NULL;
1882}
1883
1884/*
1885 * cleanup()
1886 *
1887 * This is the routine to call when we are all through, to
1888 * clean up anything that needs to be cleaned up.
1889 */
1890 /* ARGSUSED */
1891 void
1892cleanup(sig)
1893 int sig;
1894{
1895#ifndef PARENT_DOES_UTMP
1896# if (BSD > 43) || defined(convex)
1897 char *p;
1898
1901 p = line + sizeof("/dev/") - 1;
1899 p = line + sizeof(_PATH_DEV) - 1;
1902 if (logout(p))
1903 logwtmp(p, "", "");
1904 (void)chmod(line, 0666);
1905 (void)chown(line, 0, 0);
1906 *p = 'p';
1907 (void)chmod(line, 0666);
1908 (void)chown(line, 0, 0);
1909 (void) shutdown(net, 2);
1910 exit(1);
1911# else
1912 void rmut();
1913
1914 rmut();
1915 vhangup(); /* XXX */
1916 (void) shutdown(net, 2);
1917 exit(1);
1918# endif
1919#else /* PARENT_DOES_UTMP */
1920# ifdef NEWINIT
1921 (void) shutdown(net, 2);
1922 exit(1);
1923# else /* NEWINIT */
1924# ifdef CRAY
1925 static int incleanup = 0;
1926 register int t;
1927 int child_status; /* status of child process as returned by waitpid */
1928 int flags = WNOHANG|WUNTRACED;
1929
1930 /*
1931 * 1: Pick up the zombie, if we are being called
1932 * as the signal handler.
1933 * 2: If we are a nested cleanup(), return.
1934 * 3: Try to clean up TMPDIR.
1935 * 4: Fill in utmp with shutdown of process.
1936 * 5: Close down the network and pty connections.
1937 * 6: Finish up the TMPDIR cleanup, if needed.
1938 */
1939 if (sig == SIGCHLD) {
1940 while (waitpid(-1, &child_status, flags) > 0)
1941 ; /* VOID */
1942 /* Check if the child process was stopped
1943 * rather than exited. We want cleanup only if
1944 * the child has died.
1945 */
1946 if (WIFSTOPPED(child_status)) {
1947 return;
1948 }
1949 }
1950 t = sigblock(sigmask(SIGCHLD));
1951 if (incleanup) {
1952 sigsetmask(t);
1953 return;
1954 }
1955 incleanup = 1;
1956 sigsetmask(t);
1957#ifdef UNICOS7x
1958 if (secflag) {
1959 /*
1960 * We need to set ourselves back to a null
1961 * label to clean up.
1962 */
1963
1964 setulvl(sysv.sy_minlvl);
1965 setucmp((long)0);
1966 }
1967#endif /* UNICOS7x */
1968
1969 t = cleantmp(&wtmp);
1970 setutent(); /* just to make sure */
1971# endif /* CRAY */
1972 rmut(line);
1973 close(pty);
1974 (void) shutdown(net, 2);
1975# ifdef CRAY
1976 if (t == 0)
1977 cleantmp(&wtmp);
1978# endif /* CRAY */
1979 exit(1);
1980# endif /* NEWINT */
1981#endif /* PARENT_DOES_UTMP */
1982}
1983
1984#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
1985/*
1986 * _utmp_sig_rcv
1987 * utmp_sig_init
1988 * utmp_sig_wait
1989 * These three functions are used to coordinate the handling of
1990 * the utmp file between the server and the soon-to-be-login shell.
1991 * The server actually creates the utmp structure, the child calls
1992 * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1993 * signals the future-login shell to proceed.
1994 */
1995static int caught=0; /* NZ when signal intercepted */
1996static void (*func)(); /* address of previous handler */
1997
1998 void
1999_utmp_sig_rcv(sig)
2000 int sig;
2001{
2002 caught = 1;
2003 (void) signal(SIGUSR1, func);
2004}
2005
2006 void
2007utmp_sig_init()
2008{
2009 /*
2010 * register signal handler for UTMP creation
2011 */
2012 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
2013 fatalperror(net, "telnetd/signal");
2014}
2015
2016 void
2017utmp_sig_reset()
2018{
2019 (void) signal(SIGUSR1, func); /* reset handler to default */
2020}
2021
2022# ifdef __hpux
2023# define sigoff() /* do nothing */
2024# define sigon() /* do nothing */
2025# endif
2026
2027 void
2028utmp_sig_wait()
2029{
2030 /*
2031 * Wait for parent to write our utmp entry.
2032 */
2033 sigoff();
2034 while (caught == 0) {
2035 pause(); /* wait until we get a signal (sigon) */
2036 sigoff(); /* turn off signals while we check caught */
2037 }
2038 sigon(); /* turn on signals again */
2039}
2040
2041 void
2042utmp_sig_notify(pid)
2043{
2044 kill(pid, SIGUSR1);
2045}
2046
2047# ifdef CRAY
2048static int gotsigjob = 0;
2049
2050 /*ARGSUSED*/
2051 void
2052sigjob(sig)
2053 int sig;
2054{
2055 register int jid;
2056 register struct jobtemp *jp;
2057
2058 while ((jid = waitjob(NULL)) != -1) {
2059 if (jid == 0) {
2060 return;
2061 }
2062 gotsigjob++;
2063 jobend(jid, NULL, NULL);
2064 }
2065}
2066
2067/*
2068 * jid_getutid:
2069 * called by jobend() before calling cleantmp()
2070 * to find the correct $TMPDIR to cleanup.
2071 */
2072
2073 struct utmp *
2074jid_getutid(jid)
2075 int jid;
2076{
2077 struct utmp *cur = NULL;
2078
2079 setutent(); /* just to make sure */
2080 while (cur = getutent()) {
2081 if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
2082 return(cur);
2083 }
2084 }
2085
2086 return(0);
2087}
2088
2089/*
2090 * Clean up the TMPDIR that login created.
2091 * The first time this is called we pick up the info
2092 * from the utmp. If the job has already gone away,
2093 * then we'll clean up and be done. If not, then
2094 * when this is called the second time it will wait
2095 * for the signal that the job is done.
2096 */
2097 int
2098cleantmp(wtp)
2099 register struct utmp *wtp;
2100{
2101 struct utmp *utp;
2102 static int first = 1;
2103 register int mask, omask, ret;
2104 extern struct utmp *getutid P((const struct utmp *_Id));
2105
2106
2107 mask = sigmask(WJSIGNAL);
2108
2109 if (first == 0) {
2110 omask = sigblock(mask);
2111 while (gotsigjob == 0)
2112 sigpause(omask);
2113 return(1);
2114 }
2115 first = 0;
2116 setutent(); /* just to make sure */
2117
2118 utp = getutid(wtp);
2119 if (utp == 0) {
2120 syslog(LOG_ERR, "can't get /etc/utmp entry to clean TMPDIR");
2121 return(-1);
2122 }
2123 /*
2124 * Nothing to clean up if the user shell was never started.
2125 */
2126 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
2127 return(1);
2128
2129 /*
2130 * Block the WJSIGNAL while we are in jobend().
2131 */
2132 omask = sigblock(mask);
2133 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
2134 sigsetmask(omask);
2135 return(ret);
2136}
2137
2138 int
2139jobend(jid, path, user)
2140 register int jid;
2141 register char *path;
2142 register char *user;
2143{
2144 static int saved_jid = 0;
2145 static int pty_saved_jid = 0;
2146 static char saved_path[sizeof(wtmp.ut_tpath)+1];
2147 static char saved_user[sizeof(wtmp.ut_user)+1];
2148
2149 /*
2150 * this little piece of code comes into play
2151 * only when ptyreconnect is used to reconnect
2152 * to an previous session.
2153 *
2154 * this is the only time when the
2155 * "saved_jid != jid" code is executed.
2156 */
2157
2158 if ( saved_jid && saved_jid != jid ) {
2159 if (!path) { /* called from signal handler */
2160 pty_saved_jid = jid;
2161 } else {
2162 pty_saved_jid = saved_jid;
2163 }
2164 }
2165
2166 if (path) {
2167 strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
2168 strncpy(saved_user, user, sizeof(wtmp.ut_user));
2169 saved_path[sizeof(saved_path)] = '\0';
2170 saved_user[sizeof(saved_user)] = '\0';
2171 }
2172 if (saved_jid == 0) {
2173 saved_jid = jid;
2174 return(0);
2175 }
2176
2177 /* if the jid has changed, get the correct entry from the utmp file */
2178
2179 if ( saved_jid != jid ) {
2180 struct utmp *utp = NULL;
2181 struct utmp *jid_getutid();
2182
2183 utp = jid_getutid(pty_saved_jid);
2184
2185 if (utp == 0) {
2186 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
2187 return(-1);
2188 }
2189
2190 cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
2191 return(1);
2192 }
2193
2194 cleantmpdir(jid, saved_path, saved_user);
2195 return(1);
2196}
2197
2198/*
2199 * Fork a child process to clean up the TMPDIR
2200 */
2201cleantmpdir(jid, tpath, user)
2202 register int jid;
2203 register char *tpath;
2204 register char *user;
2205{
2206 switch(fork()) {
2207 case -1:
2208 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m",
2209 tpath);
2210 break;
2211 case 0:
1900 if (logout(p))
1901 logwtmp(p, "", "");
1902 (void)chmod(line, 0666);
1903 (void)chown(line, 0, 0);
1904 *p = 'p';
1905 (void)chmod(line, 0666);
1906 (void)chown(line, 0, 0);
1907 (void) shutdown(net, 2);
1908 exit(1);
1909# else
1910 void rmut();
1911
1912 rmut();
1913 vhangup(); /* XXX */
1914 (void) shutdown(net, 2);
1915 exit(1);
1916# endif
1917#else /* PARENT_DOES_UTMP */
1918# ifdef NEWINIT
1919 (void) shutdown(net, 2);
1920 exit(1);
1921# else /* NEWINIT */
1922# ifdef CRAY
1923 static int incleanup = 0;
1924 register int t;
1925 int child_status; /* status of child process as returned by waitpid */
1926 int flags = WNOHANG|WUNTRACED;
1927
1928 /*
1929 * 1: Pick up the zombie, if we are being called
1930 * as the signal handler.
1931 * 2: If we are a nested cleanup(), return.
1932 * 3: Try to clean up TMPDIR.
1933 * 4: Fill in utmp with shutdown of process.
1934 * 5: Close down the network and pty connections.
1935 * 6: Finish up the TMPDIR cleanup, if needed.
1936 */
1937 if (sig == SIGCHLD) {
1938 while (waitpid(-1, &child_status, flags) > 0)
1939 ; /* VOID */
1940 /* Check if the child process was stopped
1941 * rather than exited. We want cleanup only if
1942 * the child has died.
1943 */
1944 if (WIFSTOPPED(child_status)) {
1945 return;
1946 }
1947 }
1948 t = sigblock(sigmask(SIGCHLD));
1949 if (incleanup) {
1950 sigsetmask(t);
1951 return;
1952 }
1953 incleanup = 1;
1954 sigsetmask(t);
1955#ifdef UNICOS7x
1956 if (secflag) {
1957 /*
1958 * We need to set ourselves back to a null
1959 * label to clean up.
1960 */
1961
1962 setulvl(sysv.sy_minlvl);
1963 setucmp((long)0);
1964 }
1965#endif /* UNICOS7x */
1966
1967 t = cleantmp(&wtmp);
1968 setutent(); /* just to make sure */
1969# endif /* CRAY */
1970 rmut(line);
1971 close(pty);
1972 (void) shutdown(net, 2);
1973# ifdef CRAY
1974 if (t == 0)
1975 cleantmp(&wtmp);
1976# endif /* CRAY */
1977 exit(1);
1978# endif /* NEWINT */
1979#endif /* PARENT_DOES_UTMP */
1980}
1981
1982#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
1983/*
1984 * _utmp_sig_rcv
1985 * utmp_sig_init
1986 * utmp_sig_wait
1987 * These three functions are used to coordinate the handling of
1988 * the utmp file between the server and the soon-to-be-login shell.
1989 * The server actually creates the utmp structure, the child calls
1990 * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1991 * signals the future-login shell to proceed.
1992 */
1993static int caught=0; /* NZ when signal intercepted */
1994static void (*func)(); /* address of previous handler */
1995
1996 void
1997_utmp_sig_rcv(sig)
1998 int sig;
1999{
2000 caught = 1;
2001 (void) signal(SIGUSR1, func);
2002}
2003
2004 void
2005utmp_sig_init()
2006{
2007 /*
2008 * register signal handler for UTMP creation
2009 */
2010 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
2011 fatalperror(net, "telnetd/signal");
2012}
2013
2014 void
2015utmp_sig_reset()
2016{
2017 (void) signal(SIGUSR1, func); /* reset handler to default */
2018}
2019
2020# ifdef __hpux
2021# define sigoff() /* do nothing */
2022# define sigon() /* do nothing */
2023# endif
2024
2025 void
2026utmp_sig_wait()
2027{
2028 /*
2029 * Wait for parent to write our utmp entry.
2030 */
2031 sigoff();
2032 while (caught == 0) {
2033 pause(); /* wait until we get a signal (sigon) */
2034 sigoff(); /* turn off signals while we check caught */
2035 }
2036 sigon(); /* turn on signals again */
2037}
2038
2039 void
2040utmp_sig_notify(pid)
2041{
2042 kill(pid, SIGUSR1);
2043}
2044
2045# ifdef CRAY
2046static int gotsigjob = 0;
2047
2048 /*ARGSUSED*/
2049 void
2050sigjob(sig)
2051 int sig;
2052{
2053 register int jid;
2054 register struct jobtemp *jp;
2055
2056 while ((jid = waitjob(NULL)) != -1) {
2057 if (jid == 0) {
2058 return;
2059 }
2060 gotsigjob++;
2061 jobend(jid, NULL, NULL);
2062 }
2063}
2064
2065/*
2066 * jid_getutid:
2067 * called by jobend() before calling cleantmp()
2068 * to find the correct $TMPDIR to cleanup.
2069 */
2070
2071 struct utmp *
2072jid_getutid(jid)
2073 int jid;
2074{
2075 struct utmp *cur = NULL;
2076
2077 setutent(); /* just to make sure */
2078 while (cur = getutent()) {
2079 if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
2080 return(cur);
2081 }
2082 }
2083
2084 return(0);
2085}
2086
2087/*
2088 * Clean up the TMPDIR that login created.
2089 * The first time this is called we pick up the info
2090 * from the utmp. If the job has already gone away,
2091 * then we'll clean up and be done. If not, then
2092 * when this is called the second time it will wait
2093 * for the signal that the job is done.
2094 */
2095 int
2096cleantmp(wtp)
2097 register struct utmp *wtp;
2098{
2099 struct utmp *utp;
2100 static int first = 1;
2101 register int mask, omask, ret;
2102 extern struct utmp *getutid P((const struct utmp *_Id));
2103
2104
2105 mask = sigmask(WJSIGNAL);
2106
2107 if (first == 0) {
2108 omask = sigblock(mask);
2109 while (gotsigjob == 0)
2110 sigpause(omask);
2111 return(1);
2112 }
2113 first = 0;
2114 setutent(); /* just to make sure */
2115
2116 utp = getutid(wtp);
2117 if (utp == 0) {
2118 syslog(LOG_ERR, "can't get /etc/utmp entry to clean TMPDIR");
2119 return(-1);
2120 }
2121 /*
2122 * Nothing to clean up if the user shell was never started.
2123 */
2124 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
2125 return(1);
2126
2127 /*
2128 * Block the WJSIGNAL while we are in jobend().
2129 */
2130 omask = sigblock(mask);
2131 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
2132 sigsetmask(omask);
2133 return(ret);
2134}
2135
2136 int
2137jobend(jid, path, user)
2138 register int jid;
2139 register char *path;
2140 register char *user;
2141{
2142 static int saved_jid = 0;
2143 static int pty_saved_jid = 0;
2144 static char saved_path[sizeof(wtmp.ut_tpath)+1];
2145 static char saved_user[sizeof(wtmp.ut_user)+1];
2146
2147 /*
2148 * this little piece of code comes into play
2149 * only when ptyreconnect is used to reconnect
2150 * to an previous session.
2151 *
2152 * this is the only time when the
2153 * "saved_jid != jid" code is executed.
2154 */
2155
2156 if ( saved_jid && saved_jid != jid ) {
2157 if (!path) { /* called from signal handler */
2158 pty_saved_jid = jid;
2159 } else {
2160 pty_saved_jid = saved_jid;
2161 }
2162 }
2163
2164 if (path) {
2165 strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
2166 strncpy(saved_user, user, sizeof(wtmp.ut_user));
2167 saved_path[sizeof(saved_path)] = '\0';
2168 saved_user[sizeof(saved_user)] = '\0';
2169 }
2170 if (saved_jid == 0) {
2171 saved_jid = jid;
2172 return(0);
2173 }
2174
2175 /* if the jid has changed, get the correct entry from the utmp file */
2176
2177 if ( saved_jid != jid ) {
2178 struct utmp *utp = NULL;
2179 struct utmp *jid_getutid();
2180
2181 utp = jid_getutid(pty_saved_jid);
2182
2183 if (utp == 0) {
2184 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
2185 return(-1);
2186 }
2187
2188 cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
2189 return(1);
2190 }
2191
2192 cleantmpdir(jid, saved_path, saved_user);
2193 return(1);
2194}
2195
2196/*
2197 * Fork a child process to clean up the TMPDIR
2198 */
2199cleantmpdir(jid, tpath, user)
2200 register int jid;
2201 register char *tpath;
2202 register char *user;
2203{
2204 switch(fork()) {
2205 case -1:
2206 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m",
2207 tpath);
2208 break;
2209 case 0:
2212 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
2210 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, (char *)0);
2213 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m",
2214 tpath, CLEANTMPCMD);
2215 exit(1);
2216 default:
2217 /*
2218 * Forget about child. We will exit, and
2219 * /etc/init will pick it up.
2220 */
2221 break;
2222 }
2223}
2224# endif /* CRAY */
2225#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
2226
2227/*
2228 * rmut()
2229 *
2230 * This is the function called by cleanup() to
2231 * remove the utmp entry for this person.
2232 */
2233
2234#ifdef UTMPX
2235 void
2236rmut()
2237{
2238 register f;
2239 int found = 0;
2240 struct utmp *u, *utmp;
2241 int nutmp;
2242 struct stat statbf;
2243
2244 struct utmpx *utxp, utmpx;
2245
2246 /*
2247 * This updates the utmpx and utmp entries and make a wtmp/x entry
2248 */
2249
2211 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m",
2212 tpath, CLEANTMPCMD);
2213 exit(1);
2214 default:
2215 /*
2216 * Forget about child. We will exit, and
2217 * /etc/init will pick it up.
2218 */
2219 break;
2220 }
2221}
2222# endif /* CRAY */
2223#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
2224
2225/*
2226 * rmut()
2227 *
2228 * This is the function called by cleanup() to
2229 * remove the utmp entry for this person.
2230 */
2231
2232#ifdef UTMPX
2233 void
2234rmut()
2235{
2236 register f;
2237 int found = 0;
2238 struct utmp *u, *utmp;
2239 int nutmp;
2240 struct stat statbf;
2241
2242 struct utmpx *utxp, utmpx;
2243
2244 /*
2245 * This updates the utmpx and utmp entries and make a wtmp/x entry
2246 */
2247
2250 SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
2248 SCPYN(utmpx.ut_line, line + sizeof(_PATH_DEV) - 1);
2251 utxp = getutxline(&utmpx);
2252 if (utxp) {
2253 utxp->ut_type = DEAD_PROCESS;
2254 utxp->ut_exit.e_termination = 0;
2255 utxp->ut_exit.e_exit = 0;
2256 (void) time(&utmpx.ut_tv.tv_sec);
2257 utmpx.ut_tv.tv_usec = 0;
2258 modutx(utxp);
2259 }
2260 endutxent();
2261} /* end of rmut */
2262#endif
2263
2264#if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
2265 void
2266rmut()
2267{
2268 register f;
2269 int found = 0;
2270 struct utmp *u, *utmp;
2271 int nutmp;
2272 struct stat statbf;
2273
2274 f = open(utmpf, O_RDWR);
2275 if (f >= 0) {
2276 (void) fstat(f, &statbf);
2277 utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
2278 if (!utmp)
2279 syslog(LOG_ERR, "utmp malloc failed");
2280 if (statbf.st_size && utmp) {
2281 nutmp = read(f, (char *)utmp, (int)statbf.st_size);
2282 nutmp /= sizeof(struct utmp);
2283
2284 for (u = utmp ; u < &utmp[nutmp] ; u++) {
2285 if (SCMPN(u->ut_line, line+5) ||
2286 u->ut_name[0]==0)
2287 continue;
2288 (void) lseek(f, ((long)u)-((long)utmp), L_SET);
2289 SCPYN(u->ut_name, "");
2290 SCPYN(u->ut_host, "");
2291 (void) time(&u->ut_time);
2292 (void) write(f, (char *)u, sizeof(wtmp));
2293 found++;
2294 }
2295 }
2296 (void) close(f);
2297 }
2298 if (found) {
2299 f = open(wtmpf, O_WRONLY|O_APPEND);
2300 if (f >= 0) {
2301 SCPYN(wtmp.ut_line, line+5);
2302 SCPYN(wtmp.ut_name, "");
2303 SCPYN(wtmp.ut_host, "");
2304 (void) time(&wtmp.ut_time);
2305 (void) write(f, (char *)&wtmp, sizeof(wtmp));
2306 (void) close(f);
2307 }
2308 }
2309 (void) chmod(line, 0666);
2310 (void) chown(line, 0, 0);
2249 utxp = getutxline(&utmpx);
2250 if (utxp) {
2251 utxp->ut_type = DEAD_PROCESS;
2252 utxp->ut_exit.e_termination = 0;
2253 utxp->ut_exit.e_exit = 0;
2254 (void) time(&utmpx.ut_tv.tv_sec);
2255 utmpx.ut_tv.tv_usec = 0;
2256 modutx(utxp);
2257 }
2258 endutxent();
2259} /* end of rmut */
2260#endif
2261
2262#if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
2263 void
2264rmut()
2265{
2266 register f;
2267 int found = 0;
2268 struct utmp *u, *utmp;
2269 int nutmp;
2270 struct stat statbf;
2271
2272 f = open(utmpf, O_RDWR);
2273 if (f >= 0) {
2274 (void) fstat(f, &statbf);
2275 utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
2276 if (!utmp)
2277 syslog(LOG_ERR, "utmp malloc failed");
2278 if (statbf.st_size && utmp) {
2279 nutmp = read(f, (char *)utmp, (int)statbf.st_size);
2280 nutmp /= sizeof(struct utmp);
2281
2282 for (u = utmp ; u < &utmp[nutmp] ; u++) {
2283 if (SCMPN(u->ut_line, line+5) ||
2284 u->ut_name[0]==0)
2285 continue;
2286 (void) lseek(f, ((long)u)-((long)utmp), L_SET);
2287 SCPYN(u->ut_name, "");
2288 SCPYN(u->ut_host, "");
2289 (void) time(&u->ut_time);
2290 (void) write(f, (char *)u, sizeof(wtmp));
2291 found++;
2292 }
2293 }
2294 (void) close(f);
2295 }
2296 if (found) {
2297 f = open(wtmpf, O_WRONLY|O_APPEND);
2298 if (f >= 0) {
2299 SCPYN(wtmp.ut_line, line+5);
2300 SCPYN(wtmp.ut_name, "");
2301 SCPYN(wtmp.ut_host, "");
2302 (void) time(&wtmp.ut_time);
2303 (void) write(f, (char *)&wtmp, sizeof(wtmp));
2304 (void) close(f);
2305 }
2306 }
2307 (void) chmod(line, 0666);
2308 (void) chown(line, 0, 0);
2311 line[strlen("/dev/")] = 'p';
2309 line[strlen(_PATH_DEV)] = 'p';
2312 (void) chmod(line, 0666);
2313 (void) chown(line, 0, 0);
2314} /* end of rmut */
2315#endif /* CRAY */
2316
2317#ifdef __hpux
2318rmut (line)
2319char *line;
2320{
2321 struct utmp utmp;
2322 struct utmp *utptr;
2323 int fd; /* for /etc/wtmp */
2324
2325 utmp.ut_type = USER_PROCESS;
2326 (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
2327 (void) setutent();
2328 utptr = getutid(&utmp);
2329 /* write it out only if it exists */
2330 if (utptr) {
2331 utptr->ut_type = DEAD_PROCESS;
2332 utptr->ut_time = time((long *) 0);
2333 (void) pututline(utptr);
2334 /* set wtmp entry if wtmp file exists */
2335 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
2336 (void) write(fd, utptr, sizeof(utmp));
2337 (void) close(fd);
2338 }
2339 }
2340 (void) endutent();
2341
2342 (void) chmod(line, 0666);
2343 (void) chown(line, 0, 0);
2344 line[14] = line[13];
2345 line[13] = line[12];
2346 line[8] = 'm';
2347 line[9] = '/';
2348 line[10] = 'p';
2349 line[11] = 't';
2350 line[12] = 'y';
2351 (void) chmod(line, 0666);
2352 (void) chown(line, 0, 0);
2353}
2354#endif
2310 (void) chmod(line, 0666);
2311 (void) chown(line, 0, 0);
2312} /* end of rmut */
2313#endif /* CRAY */
2314
2315#ifdef __hpux
2316rmut (line)
2317char *line;
2318{
2319 struct utmp utmp;
2320 struct utmp *utptr;
2321 int fd; /* for /etc/wtmp */
2322
2323 utmp.ut_type = USER_PROCESS;
2324 (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
2325 (void) setutent();
2326 utptr = getutid(&utmp);
2327 /* write it out only if it exists */
2328 if (utptr) {
2329 utptr->ut_type = DEAD_PROCESS;
2330 utptr->ut_time = time((long *) 0);
2331 (void) pututline(utptr);
2332 /* set wtmp entry if wtmp file exists */
2333 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
2334 (void) write(fd, utptr, sizeof(utmp));
2335 (void) close(fd);
2336 }
2337 }
2338 (void) endutent();
2339
2340 (void) chmod(line, 0666);
2341 (void) chown(line, 0, 0);
2342 line[14] = line[13];
2343 line[13] = line[12];
2344 line[8] = 'm';
2345 line[9] = '/';
2346 line[10] = 'p';
2347 line[11] = 't';
2348 line[12] = 'y';
2349 (void) chmod(line, 0666);
2350 (void) chown(line, 0, 0);
2351}
2352#endif