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