138905Sborman /*
261451Sbostic * Copyright (c) 1989, 1993
361451Sbostic * The Regents of the University of California. All rights reserved.
438905Sborman *
542673Sbostic * %sccs.include.redist.c%
638905Sborman */
738905Sborman
838905Sborman #ifndef lint
9*69786Sdab static char sccsid[] = "@(#)sys_term.c 8.4 (Berkeley) 05/30/95";
1038905Sborman #endif /* not lint */
1138905Sborman
1238905Sborman #include "telnetd.h"
1338905Sborman #include "pathnames.h"
1438905Sborman
1557212Sdab #if defined(AUTHENTICATION)
1646809Sdab #include <libtelnet/auth.h>
1746809Sdab #endif
1846809Sdab
1960151Sdab #if defined(CRAY) || defined(__hpux)
2060151Sdab # define PARENT_DOES_UTMP
2160151Sdab #endif
2260151Sdab
2338905Sborman #ifdef NEWINIT
2438905Sborman #include <initreq.h>
2560151Sdab int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */
2638905Sborman #else /* NEWINIT*/
2757212Sdab # ifdef UTMPX
2857212Sdab # include <utmpx.h>
2965158Sdab struct utmpx wtmp;
3057212Sdab # else
3157212Sdab # include <utmp.h>
3265158Sdab struct utmp wtmp;
3357212Sdab # endif /* UTMPX */
3438905Sborman
3557212Sdab int utmp_len = sizeof(wtmp.ut_host);
3660151Sdab # ifndef PARENT_DOES_UTMP
3738905Sborman char wtmpf[] = "/usr/adm/wtmp";
3838905Sborman char utmpf[] = "/etc/utmp";
3960151Sdab # else /* PARENT_DOES_UTMP */
4038905Sborman char wtmpf[] = "/etc/wtmp";
4160151Sdab # endif /* PARENT_DOES_UTMP */
4260151Sdab
4360151Sdab # ifdef CRAY
4446809Sdab #include <tmpdir.h>
4546809Sdab #include <sys/wait.h>
46*69786Sdab # if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
47*69786Sdab # define UNICOS7x
4860151Sdab # endif
4960151Sdab
50*69786Sdab # ifdef UNICOS7x
5157212Sdab #include <sys/sysv.h>
5257212Sdab #include <sys/secstat.h>
5357212Sdab extern int secflag;
5457212Sdab extern struct sysv sysv;
55*69786Sdab # endif /* UNICOS7x */
5638905Sborman # endif /* CRAY */
5738905Sborman #endif /* NEWINIT */
5838905Sborman
5957212Sdab #ifdef STREAMSPTY
6057212Sdab #include <sac.h>
6157212Sdab #include <sys/stropts.h>
6257212Sdab #endif
6357212Sdab
6438905Sborman #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
6538905Sborman #define SCMPN(a, b) strncmp(a, b, sizeof(a))
6638905Sborman
6744364Sborman #ifdef STREAMS
6844364Sborman #include <sys/stream.h>
6944364Sborman #endif
7060151Sdab #ifdef __hpux
7160151Sdab #include <sys/resource.h>
7260151Sdab #include <sys/proc.h>
7360151Sdab #endif
7438905Sborman #include <sys/tty.h>
7538905Sborman #ifdef t_erase
7638905Sborman #undef t_erase
7738905Sborman #undef t_kill
7838905Sborman #undef t_intrc
7938905Sborman #undef t_quitc
8038905Sborman #undef t_startc
8138905Sborman #undef t_stopc
8238905Sborman #undef t_eofc
8338905Sborman #undef t_brkc
8438905Sborman #undef t_suspc
8538905Sborman #undef t_dsuspc
8638905Sborman #undef t_rprntc
8738905Sborman #undef t_flushc
8838905Sborman #undef t_werasc
8938905Sborman #undef t_lnextc
9038905Sborman #endif
9138905Sborman
9244364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
9344364Sborman # define EXTPROC 0400
9444364Sborman #endif
9544364Sborman
9638905Sborman #ifndef USE_TERMIO
9738905Sborman struct termbuf {
9838905Sborman struct sgttyb sg;
9938905Sborman struct tchars tc;
10038905Sborman struct ltchars ltc;
10138905Sborman int state;
10238905Sborman int lflags;
10338905Sborman } termbuf, termbuf2;
10445234Sborman # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val)
10545234Sborman # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val)
10646809Sdab # define cfgetospeed(tp) (tp)->sg.sg_ospeed
10746809Sdab # define cfgetispeed(tp) (tp)->sg.sg_ispeed
10838905Sborman #else /* USE_TERMIO */
10938905Sborman # ifdef SYSV_TERMIO
11038905Sborman # define termios termio
11138905Sborman # endif
11245234Sborman # ifndef TCSANOW
11344364Sborman # ifdef TCSETS
11445234Sborman # define TCSANOW TCSETS
11545234Sborman # define TCSADRAIN TCSETSW
11646809Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
11744364Sborman # else
11845234Sborman # ifdef TCSETA
11945234Sborman # define TCSANOW TCSETA
12045234Sborman # define TCSADRAIN TCSETAW
12146809Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
12245234Sborman # else
12345234Sborman # define TCSANOW TIOCSETA
12445234Sborman # define TCSADRAIN TIOCSETAW
12546809Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
12645234Sborman # endif
12744364Sborman # endif
12845234Sborman # define tcsetattr(f, a, t) ioctl(f, a, t)
12945234Sborman # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
13045234Sborman (tp)->c_cflag |= (val)
13146809Sdab # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
13245234Sborman # ifdef CIBAUD
13345234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
13445234Sborman (tp)->c_cflag |= ((val)<<IBSHIFT)
13546809Sdab # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
13645234Sborman # else
13745234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
13845234Sborman (tp)->c_cflag |= (val)
13946809Sdab # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
14045234Sborman # endif
14145234Sborman # endif /* TCSANOW */
14238905Sborman struct termios termbuf, termbuf2; /* pty control structure */
14357592Sdab # ifdef STREAMSPTY
14457212Sdab int ttyfd = -1;
14557592Sdab # endif
14638905Sborman #endif /* USE_TERMIO */
14738905Sborman
14838905Sborman /*
14938905Sborman * init_termbuf()
15038905Sborman * copy_termbuf(cp)
15138905Sborman * set_termbuf()
15238905Sborman *
15338905Sborman * These three routines are used to get and set the "termbuf" structure
15438905Sborman * to and from the kernel. init_termbuf() gets the current settings.
15538905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
15638905Sborman * set_termbuf() writes the structure into the kernel.
15738905Sborman */
15838905Sborman
15946809Sdab void
init_termbuf()16038905Sborman init_termbuf()
16138905Sborman {
16238905Sborman #ifndef USE_TERMIO
16338905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
16438905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
16538905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
16638905Sborman # ifdef TIOCGSTATE
16738905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
16838905Sborman # endif
16938905Sborman #else
17057592Sdab # ifdef STREAMSPTY
17157212Sdab (void) tcgetattr(ttyfd, &termbuf);
17257592Sdab # else
17357592Sdab (void) tcgetattr(pty, &termbuf);
17457592Sdab # endif
17538905Sborman #endif
17638905Sborman termbuf2 = termbuf;
17738905Sborman }
17838905Sborman
17938905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
18046809Sdab void
copy_termbuf(cp,len)18138905Sborman copy_termbuf(cp, len)
18246809Sdab char *cp;
18346809Sdab int len;
18438905Sborman {
18538905Sborman if (len > sizeof(termbuf))
18638905Sborman len = sizeof(termbuf);
187*69786Sdab memmove((char *)&termbuf, cp, len);
18838905Sborman termbuf2 = termbuf;
18938905Sborman }
19038905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
19138905Sborman
19246809Sdab void
set_termbuf()19338905Sborman set_termbuf()
19438905Sborman {
19538905Sborman /*
19638905Sborman * Only make the necessary changes.
19738905Sborman */
19838905Sborman #ifndef USE_TERMIO
199*69786Sdab if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
200*69786Sdab sizeof(termbuf.sg)))
20145234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
202*69786Sdab if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
203*69786Sdab sizeof(termbuf.tc)))
20438905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
205*69786Sdab if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
20638905Sborman sizeof(termbuf.ltc)))
20738905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
20838905Sborman if (termbuf.lflags != termbuf2.lflags)
20938905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
21038905Sborman #else /* USE_TERMIO */
211*69786Sdab if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
21257592Sdab # ifdef STREAMSPTY
21357212Sdab (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
21457592Sdab # else
21557592Sdab (void) tcsetattr(pty, TCSANOW, &termbuf);
21657592Sdab # endif
21757212Sdab # if defined(CRAY2) && defined(UNICOS5)
21838905Sborman needtermstat = 1;
21938905Sborman # endif
22038905Sborman #endif /* USE_TERMIO */
22138905Sborman }
22238905Sborman
22338905Sborman
22438905Sborman /*
22538905Sborman * spcset(func, valp, valpp)
22638905Sborman *
22738905Sborman * This function takes various special characters (func), and
22838905Sborman * sets *valp to the current value of that character, and
22938905Sborman * *valpp to point to where in the "termbuf" structure that
23038905Sborman * value is kept.
23138905Sborman *
23238905Sborman * It returns the SLC_ level of support for this function.
23338905Sborman */
23438905Sborman
23538905Sborman #ifndef USE_TERMIO
23646809Sdab int
spcset(func,valp,valpp)23738905Sborman spcset(func, valp, valpp)
23846809Sdab int func;
23946809Sdab cc_t *valp;
24046809Sdab cc_t **valpp;
24138905Sborman {
24238905Sborman switch(func) {
24338905Sborman case SLC_EOF:
24438905Sborman *valp = termbuf.tc.t_eofc;
24540242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc;
24638905Sborman return(SLC_VARIABLE);
24738905Sborman case SLC_EC:
24838905Sborman *valp = termbuf.sg.sg_erase;
24940242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase;
25038905Sborman return(SLC_VARIABLE);
25138905Sborman case SLC_EL:
25238905Sborman *valp = termbuf.sg.sg_kill;
25340242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill;
25438905Sborman return(SLC_VARIABLE);
25538905Sborman case SLC_IP:
25638905Sborman *valp = termbuf.tc.t_intrc;
25740242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc;
25838905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
25938905Sborman case SLC_ABORT:
26038905Sborman *valp = termbuf.tc.t_quitc;
26140242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc;
26238905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
26338905Sborman case SLC_XON:
26438905Sborman *valp = termbuf.tc.t_startc;
26540242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc;
26638905Sborman return(SLC_VARIABLE);
26738905Sborman case SLC_XOFF:
26838905Sborman *valp = termbuf.tc.t_stopc;
26940242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc;
27038905Sborman return(SLC_VARIABLE);
27138905Sborman case SLC_AO:
27238905Sborman *valp = termbuf.ltc.t_flushc;
27340242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc;
27438905Sborman return(SLC_VARIABLE);
27538905Sborman case SLC_SUSP:
27638905Sborman *valp = termbuf.ltc.t_suspc;
27740242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc;
27838905Sborman return(SLC_VARIABLE);
27938905Sborman case SLC_EW:
28038905Sborman *valp = termbuf.ltc.t_werasc;
28140242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc;
28238905Sborman return(SLC_VARIABLE);
28338905Sborman case SLC_RP:
28438905Sborman *valp = termbuf.ltc.t_rprntc;
28540242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
28638905Sborman return(SLC_VARIABLE);
28738905Sborman case SLC_LNEXT:
28838905Sborman *valp = termbuf.ltc.t_lnextc;
28940242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
29038905Sborman return(SLC_VARIABLE);
29140242Sborman case SLC_FORW1:
29240242Sborman *valp = termbuf.tc.t_brkc;
29340242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
29440242Sborman return(SLC_VARIABLE);
29538905Sborman case SLC_BRK:
29638905Sborman case SLC_SYNCH:
29738905Sborman case SLC_AYT:
29838905Sborman case SLC_EOR:
29940242Sborman *valp = (cc_t)0;
30040242Sborman *valpp = (cc_t *)0;
30138905Sborman return(SLC_DEFAULT);
30238905Sborman default:
30340242Sborman *valp = (cc_t)0;
30440242Sborman *valpp = (cc_t *)0;
30538905Sborman return(SLC_NOSUPPORT);
30638905Sborman }
30738905Sborman }
30838905Sborman
30938905Sborman #else /* USE_TERMIO */
31038905Sborman
31146809Sdab int
spcset(func,valp,valpp)31238905Sborman spcset(func, valp, valpp)
31346809Sdab int func;
31446809Sdab cc_t *valp;
31546809Sdab cc_t **valpp;
31638905Sborman {
31739503Sborman
31839503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \
31939503Sborman *valpp = &termbuf.c_cc[a]; \
32039503Sborman return(b);
32140242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
32239503Sborman
32338905Sborman switch(func) {
32438905Sborman case SLC_EOF:
32539503Sborman setval(VEOF, SLC_VARIABLE);
32638905Sborman case SLC_EC:
32739503Sborman setval(VERASE, SLC_VARIABLE);
32838905Sborman case SLC_EL:
32939503Sborman setval(VKILL, SLC_VARIABLE);
33038905Sborman case SLC_IP:
33139503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
33238905Sborman case SLC_ABORT:
33339503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
33438905Sborman case SLC_XON:
33539503Sborman #ifdef VSTART
33639503Sborman setval(VSTART, SLC_VARIABLE);
33739503Sborman #else
33839503Sborman defval(0x13);
33939503Sborman #endif
34038905Sborman case SLC_XOFF:
34139503Sborman #ifdef VSTOP
34239503Sborman setval(VSTOP, SLC_VARIABLE);
34339503Sborman #else
34439503Sborman defval(0x11);
34539503Sborman #endif
34638905Sborman case SLC_EW:
34739503Sborman #ifdef VWERASE
34839503Sborman setval(VWERASE, SLC_VARIABLE);
34939503Sborman #else
35039503Sborman defval(0);
35139503Sborman #endif
35238905Sborman case SLC_RP:
35339503Sborman #ifdef VREPRINT
35439503Sborman setval(VREPRINT, SLC_VARIABLE);
35539503Sborman #else
35639503Sborman defval(0);
35739503Sborman #endif
35838905Sborman case SLC_LNEXT:
35939503Sborman #ifdef VLNEXT
36039503Sborman setval(VLNEXT, SLC_VARIABLE);
36139503Sborman #else
36239503Sborman defval(0);
36339503Sborman #endif
36439503Sborman case SLC_AO:
36545234Sborman #if !defined(VDISCARD) && defined(VFLUSHO)
36645234Sborman # define VDISCARD VFLUSHO
36745234Sborman #endif
36845234Sborman #ifdef VDISCARD
36945234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
37039503Sborman #else
37139503Sborman defval(0);
37239503Sborman #endif
37339503Sborman case SLC_SUSP:
37439503Sborman #ifdef VSUSP
37539503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
37639503Sborman #else
37739503Sborman defval(0);
37839503Sborman #endif
37940242Sborman #ifdef VEOL
38040242Sborman case SLC_FORW1:
38140242Sborman setval(VEOL, SLC_VARIABLE);
38240242Sborman #endif
38340242Sborman #ifdef VEOL2
38440242Sborman case SLC_FORW2:
38540242Sborman setval(VEOL2, SLC_VARIABLE);
38640242Sborman #endif
38745234Sborman case SLC_AYT:
38845234Sborman #ifdef VSTATUS
38945234Sborman setval(VSTATUS, SLC_VARIABLE);
39045234Sborman #else
39145234Sborman defval(0);
39245234Sborman #endif
39339503Sborman
39438905Sborman case SLC_BRK:
39538905Sborman case SLC_SYNCH:
39638905Sborman case SLC_EOR:
39739503Sborman defval(0);
39839503Sborman
39938905Sborman default:
40038905Sborman *valp = 0;
40138905Sborman *valpp = 0;
40238905Sborman return(SLC_NOSUPPORT);
40338905Sborman }
40438905Sborman }
40538905Sborman #endif /* USE_TERMIO */
40638905Sborman
40740242Sborman #ifdef CRAY
40838905Sborman /*
40940242Sborman * getnpty()
41040242Sborman *
41140242Sborman * Return the number of pty's configured into the system.
41240242Sborman */
41346809Sdab int
getnpty()41440242Sborman getnpty()
41540242Sborman {
41640242Sborman #ifdef _SC_CRAY_NPTY
41746809Sdab int numptys;
41846809Sdab
41946809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
42046809Sdab return numptys;
42146809Sdab else
42240242Sborman #endif /* _SC_CRAY_NPTY */
42346809Sdab return 128;
42440242Sborman }
42540242Sborman #endif /* CRAY */
42640242Sborman
42745234Sborman #ifndef convex
42840242Sborman /*
42938905Sborman * getpty()
43038905Sborman *
43138905Sborman * Allocate a pty. As a side effect, the external character
43238905Sborman * array "line" contains the name of the slave side.
43338905Sborman *
43438905Sborman * Returns the file descriptor of the opened pty.
43538905Sborman */
43645234Sborman #ifndef __GNUC__
43738905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
43845234Sborman #else
43945234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44045234Sborman char *line = Xline;
44145234Sborman #endif
44245234Sborman #ifdef CRAY
44345234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
44445234Sborman #endif /* CRAY */
44538905Sborman
44646809Sdab int
getpty(ptynum)44760151Sdab getpty(ptynum)
44860151Sdab int *ptynum;
44938905Sborman {
45038905Sborman register int p;
45157212Sdab #ifdef STREAMSPTY
45257212Sdab int t;
45357212Sdab char *ptsname();
45457212Sdab
45557212Sdab p = open("/dev/ptmx", 2);
45657212Sdab if (p > 0) {
45757212Sdab grantpt(p);
45857212Sdab unlockpt(p);
45957212Sdab strcpy(line, ptsname(p));
46057212Sdab return(p);
46157212Sdab }
46257212Sdab
46357212Sdab #else /* ! STREAMSPTY */
46438905Sborman #ifndef CRAY
46557212Sdab register char *cp, *p1, *p2;
46638905Sborman register int i;
46759050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
46857212Sdab int dummy;
46957212Sdab #endif
47038905Sborman
47160151Sdab #ifndef __hpux
47238905Sborman (void) sprintf(line, "/dev/ptyXX");
47338905Sborman p1 = &line[8];
47438905Sborman p2 = &line[9];
47560151Sdab #else
47660151Sdab (void) sprintf(line, "/dev/ptym/ptyXX");
47760151Sdab p1 = &line[13];
47860151Sdab p2 = &line[14];
47960151Sdab #endif
48038905Sborman
48157212Sdab for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
48238905Sborman struct stat stb;
48338905Sborman
48457212Sdab *p1 = *cp;
48538905Sborman *p2 = '0';
48657212Sdab /*
48757212Sdab * This stat() check is just to keep us from
48857212Sdab * looping through all 256 combinations if there
48957212Sdab * aren't that many ptys available.
49057212Sdab */
49138905Sborman if (stat(line, &stb) < 0)
49238905Sborman break;
49338905Sborman for (i = 0; i < 16; i++) {
49438905Sborman *p2 = "0123456789abcdef"[i];
49538905Sborman p = open(line, 2);
49638905Sborman if (p > 0) {
49760151Sdab #ifndef __hpux
49838905Sborman line[5] = 't';
49960151Sdab #else
50060151Sdab for (p1 = &line[8]; *p1; p1++)
50160151Sdab *p1 = *(p1+1);
50260151Sdab line[9] = 't';
50360151Sdab #endif
50457212Sdab chown(line, 0, 0);
50557212Sdab chmod(line, 0600);
50659050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
50757212Sdab if (ioctl(p, TIOCGPGRP, &dummy) == 0
50857212Sdab || errno != EIO) {
50957212Sdab chmod(line, 0666);
51057212Sdab close(p);
51157212Sdab line[5] = 'p';
51257212Sdab } else
51359050Storek #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
51457212Sdab return(p);
51538905Sborman }
51638905Sborman }
51738905Sborman }
51838905Sborman #else /* CRAY */
51938905Sborman extern lowpty, highpty;
52045234Sborman struct stat sb;
52138905Sborman
52260151Sdab for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
52360151Sdab (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
52445234Sborman p = open(myline, 2);
52538905Sborman if (p < 0)
52638905Sborman continue;
52760151Sdab (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
52845234Sborman /*
52945234Sborman * Here are some shenanigans to make sure that there
53045234Sborman * are no listeners lurking on the line.
53145234Sborman */
53245234Sborman if(stat(line, &sb) < 0) {
53345234Sborman (void) close(p);
53445234Sborman continue;
53545234Sborman }
53645234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
53745234Sborman chown(line, 0, 0);
53845234Sborman chmod(line, 0600);
53945234Sborman (void)close(p);
54045234Sborman p = open(myline, 2);
54145234Sborman if (p < 0)
54245234Sborman continue;
54345234Sborman }
54445234Sborman /*
54545234Sborman * Now it should be safe...check for accessability.
54645234Sborman */
54738905Sborman if (access(line, 6) == 0)
54838905Sborman return(p);
54938905Sborman else {
55038905Sborman /* no tty side to pty so skip it */
55138905Sborman (void) close(p);
55238905Sborman }
55338905Sborman }
55438905Sborman #endif /* CRAY */
55557212Sdab #endif /* STREAMSPTY */
55638905Sborman return(-1);
55738905Sborman }
55845234Sborman #endif /* convex */
55938905Sborman
56038905Sborman #ifdef LINEMODE
56138905Sborman /*
56238905Sborman * tty_flowmode() Find out if flow control is enabled or disabled.
56338905Sborman * tty_linemode() Find out if linemode (external processing) is enabled.
56438905Sborman * tty_setlinemod(on) Turn on/off linemode.
56538905Sborman * tty_isecho() Find out if echoing is turned on.
56638905Sborman * tty_setecho(on) Enable/disable character echoing.
56738905Sborman * tty_israw() Find out if terminal is in RAW mode.
56838905Sborman * tty_binaryin(on) Turn on/off BINARY on input.
56938905Sborman * tty_binaryout(on) Turn on/off BINARY on output.
57038905Sborman * tty_isediting() Find out if line editing is enabled.
57138905Sborman * tty_istrapsig() Find out if signal trapping is enabled.
57238905Sborman * tty_setedit(on) Turn on/off line editing.
57338905Sborman * tty_setsig(on) Turn on/off signal trapping.
57444364Sborman * tty_issofttab() Find out if tab expansion is enabled.
57544364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion.
57644364Sborman * tty_islitecho() Find out if typed control chars are echoed literally
57744364Sborman * tty_setlitecho() Turn on/off literal echo of control chars
57838905Sborman * tty_tspeed(val) Set transmit speed to val.
57938905Sborman * tty_rspeed(val) Set receive speed to val.
58038905Sborman */
58138905Sborman
58245234Sborman #ifdef convex
58345234Sborman static int linestate;
58445234Sborman #endif
58545234Sborman
58646809Sdab int
tty_linemode()58738905Sborman tty_linemode()
58838905Sborman {
58945234Sborman #ifndef convex
59038905Sborman #ifndef USE_TERMIO
59138905Sborman return(termbuf.state & TS_EXTPROC);
59238905Sborman #else
59338905Sborman return(termbuf.c_lflag & EXTPROC);
59438905Sborman #endif
59545234Sborman #else
59645234Sborman return(linestate);
59745234Sborman #endif
59838905Sborman }
59938905Sborman
60046809Sdab void
tty_setlinemode(on)60138905Sborman tty_setlinemode(on)
60246809Sdab int on;
60338905Sborman {
60438905Sborman #ifdef TIOCEXT
60545234Sborman # ifndef convex
60645234Sborman set_termbuf();
60745234Sborman # else
60845234Sborman linestate = on;
60945234Sborman # endif
61038905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on);
61145234Sborman # ifndef convex
61245234Sborman init_termbuf();
61345234Sborman # endif
61438905Sborman #else /* !TIOCEXT */
61545234Sborman # ifdef EXTPROC
61638905Sborman if (on)
61738905Sborman termbuf.c_lflag |= EXTPROC;
61838905Sborman else
61938905Sborman termbuf.c_lflag &= ~EXTPROC;
62045234Sborman # endif
62138905Sborman #endif /* TIOCEXT */
62238905Sborman }
62365158Sdab #endif /* LINEMODE */
62438905Sborman
62546809Sdab int
tty_isecho()62638905Sborman tty_isecho()
62738905Sborman {
62838905Sborman #ifndef USE_TERMIO
62938905Sborman return (termbuf.sg.sg_flags & ECHO);
63038905Sborman #else
63138905Sborman return (termbuf.c_lflag & ECHO);
63238905Sborman #endif
63338905Sborman }
63438905Sborman
63558971Sdab int
tty_flowmode()63658971Sdab tty_flowmode()
63758971Sdab {
63858971Sdab #ifndef USE_TERMIO
63958971Sdab return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
64058971Sdab #else
64158971Sdab return((termbuf.c_iflag & IXON) ? 1 : 0);
64258971Sdab #endif
64358971Sdab }
64458971Sdab
64558971Sdab int
tty_restartany()64658971Sdab tty_restartany()
64758971Sdab {
64858971Sdab #ifndef USE_TERMIO
64958971Sdab # ifdef DECCTQ
65058971Sdab return((termbuf.lflags & DECCTQ) ? 0 : 1);
65158971Sdab # else
65258971Sdab return(-1);
65358971Sdab # endif
65458971Sdab #else
65558971Sdab return((termbuf.c_iflag & IXANY) ? 1 : 0);
65658971Sdab #endif
65758971Sdab }
65858971Sdab
65946809Sdab void
tty_setecho(on)66038905Sborman tty_setecho(on)
66146809Sdab int on;
66238905Sborman {
66338905Sborman #ifndef USE_TERMIO
66438905Sborman if (on)
66538905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD;
66638905Sborman else
66738905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
66838905Sborman #else
66938905Sborman if (on)
67038905Sborman termbuf.c_lflag |= ECHO;
67138905Sborman else
67238905Sborman termbuf.c_lflag &= ~ECHO;
67338905Sborman #endif
67438905Sborman }
67538905Sborman
67646809Sdab int
tty_israw()67738905Sborman tty_israw()
67838905Sborman {
67938905Sborman #ifndef USE_TERMIO
68038905Sborman return(termbuf.sg.sg_flags & RAW);
68138905Sborman #else
68238905Sborman return(!(termbuf.c_lflag & ICANON));
68338905Sborman #endif
68438905Sborman }
68538905Sborman
68665158Sdab #if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
68765158Sdab int
tty_setraw(on)68865158Sdab tty_setraw(on)
68965158Sdab {
69065158Sdab # ifndef USE_TERMIO
69165158Sdab if (on)
69265158Sdab termbuf.sg.sg_flags |= RAW;
69365158Sdab else
69465158Sdab termbuf.sg.sg_flags &= ~RAW;
69565158Sdab # else
69665158Sdab if (on)
69765158Sdab termbuf.c_lflag &= ~ICANON;
69865158Sdab else
69965158Sdab termbuf.c_lflag |= ICANON;
70065158Sdab # endif
70165158Sdab }
70265158Sdab #endif
70365158Sdab
70446809Sdab void
tty_binaryin(on)70538905Sborman tty_binaryin(on)
70646809Sdab int on;
70738905Sborman {
70838905Sborman #ifndef USE_TERMIO
70938905Sborman if (on)
71038905Sborman termbuf.lflags |= LPASS8;
71138905Sborman else
71238905Sborman termbuf.lflags &= ~LPASS8;
71338905Sborman #else
71438905Sborman if (on) {
71546809Sdab termbuf.c_iflag &= ~ISTRIP;
71638905Sborman } else {
71746809Sdab termbuf.c_iflag |= ISTRIP;
71838905Sborman }
71938905Sborman #endif
72038905Sborman }
72138905Sborman
72246809Sdab void
tty_binaryout(on)72338905Sborman tty_binaryout(on)
72446809Sdab int on;
72538905Sborman {
72638905Sborman #ifndef USE_TERMIO
72738905Sborman if (on)
72838905Sborman termbuf.lflags |= LLITOUT;
72938905Sborman else
73038905Sborman termbuf.lflags &= ~LLITOUT;
73138905Sborman #else
73238905Sborman if (on) {
73338905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB);
73438905Sborman termbuf.c_cflag |= CS8;
73538905Sborman termbuf.c_oflag &= ~OPOST;
73638905Sborman } else {
73738905Sborman termbuf.c_cflag &= ~CSIZE;
73838905Sborman termbuf.c_cflag |= CS7|PARENB;
73938905Sborman termbuf.c_oflag |= OPOST;
74038905Sborman }
74138905Sborman #endif
74238905Sborman }
74338905Sborman
74446809Sdab int
tty_isbinaryin()74538905Sborman tty_isbinaryin()
74638905Sborman {
74738905Sborman #ifndef USE_TERMIO
74838905Sborman return(termbuf.lflags & LPASS8);
74938905Sborman #else
75039503Sborman return(!(termbuf.c_iflag & ISTRIP));
75138905Sborman #endif
75238905Sborman }
75338905Sborman
75446809Sdab int
tty_isbinaryout()75538905Sborman tty_isbinaryout()
75638905Sborman {
75738905Sborman #ifndef USE_TERMIO
75838905Sborman return(termbuf.lflags & LLITOUT);
75938905Sborman #else
76039503Sborman return(!(termbuf.c_oflag&OPOST));
76138905Sborman #endif
76238905Sborman }
76338905Sborman
76438905Sborman #ifdef LINEMODE
76546809Sdab int
tty_isediting()76638905Sborman tty_isediting()
76738905Sborman {
76838905Sborman #ifndef USE_TERMIO
76938905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
77038905Sborman #else
77138905Sborman return(termbuf.c_lflag & ICANON);
77238905Sborman #endif
77338905Sborman }
77438905Sborman
77546809Sdab int
tty_istrapsig()77638905Sborman tty_istrapsig()
77738905Sborman {
77838905Sborman #ifndef USE_TERMIO
77938905Sborman return(!(termbuf.sg.sg_flags&RAW));
78038905Sborman #else
78138905Sborman return(termbuf.c_lflag & ISIG);
78238905Sborman #endif
78338905Sborman }
78438905Sborman
78546809Sdab void
tty_setedit(on)78638905Sborman tty_setedit(on)
78746809Sdab int on;
78838905Sborman {
78938905Sborman #ifndef USE_TERMIO
79038905Sborman if (on)
79138905Sborman termbuf.sg.sg_flags &= ~CBREAK;
79238905Sborman else
79338905Sborman termbuf.sg.sg_flags |= CBREAK;
79438905Sborman #else
79538905Sborman if (on)
79638905Sborman termbuf.c_lflag |= ICANON;
79738905Sborman else
79838905Sborman termbuf.c_lflag &= ~ICANON;
79938905Sborman #endif
80038905Sborman }
80138905Sborman
80246809Sdab void
tty_setsig(on)80338905Sborman tty_setsig(on)
80446809Sdab int on;
80538905Sborman {
80638905Sborman #ifndef USE_TERMIO
80738905Sborman if (on)
80838905Sborman ;
80938905Sborman #else
81038905Sborman if (on)
81138905Sborman termbuf.c_lflag |= ISIG;
81238905Sborman else
81338905Sborman termbuf.c_lflag &= ~ISIG;
81438905Sborman #endif
81538905Sborman }
81638905Sborman #endif /* LINEMODE */
81738905Sborman
81846809Sdab int
tty_issofttab()81944364Sborman tty_issofttab()
82044364Sborman {
82144364Sborman #ifndef USE_TERMIO
82244364Sborman return (termbuf.sg.sg_flags & XTABS);
82344364Sborman #else
82444364Sborman # ifdef OXTABS
82544364Sborman return (termbuf.c_oflag & OXTABS);
82644364Sborman # endif
82744364Sborman # ifdef TABDLY
82844364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3);
82944364Sborman # endif
83044364Sborman #endif
83144364Sborman }
83244364Sborman
83346809Sdab void
tty_setsofttab(on)83444364Sborman tty_setsofttab(on)
83546809Sdab int on;
83644364Sborman {
83744364Sborman #ifndef USE_TERMIO
83844364Sborman if (on)
83944364Sborman termbuf.sg.sg_flags |= XTABS;
84044364Sborman else
84144364Sborman termbuf.sg.sg_flags &= ~XTABS;
84244364Sborman #else
84344364Sborman if (on) {
84444364Sborman # ifdef OXTABS
84544364Sborman termbuf.c_oflag |= OXTABS;
84644364Sborman # endif
84744364Sborman # ifdef TABDLY
84844364Sborman termbuf.c_oflag &= ~TABDLY;
84944364Sborman termbuf.c_oflag |= TAB3;
85044364Sborman # endif
85144364Sborman } else {
85244364Sborman # ifdef OXTABS
85344364Sborman termbuf.c_oflag &= ~OXTABS;
85444364Sborman # endif
85544364Sborman # ifdef TABDLY
85644364Sborman termbuf.c_oflag &= ~TABDLY;
85744364Sborman termbuf.c_oflag |= TAB0;
85844364Sborman # endif
85944364Sborman }
86044364Sborman #endif
86144364Sborman }
86244364Sborman
86346809Sdab int
tty_islitecho()86444364Sborman tty_islitecho()
86544364Sborman {
86644364Sborman #ifndef USE_TERMIO
86746809Sdab return (!(termbuf.lflags & LCTLECH));
86844364Sborman #else
86944364Sborman # ifdef ECHOCTL
87044364Sborman return (!(termbuf.c_lflag & ECHOCTL));
87144364Sborman # endif
87244364Sborman # ifdef TCTLECH
87344364Sborman return (!(termbuf.c_lflag & TCTLECH));
87444364Sborman # endif
87544364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH)
87644364Sborman return (0); /* assumes ctl chars are echoed '^x' */
87744364Sborman # endif
87844364Sborman #endif
87944364Sborman }
88044364Sborman
88146809Sdab void
tty_setlitecho(on)88244364Sborman tty_setlitecho(on)
88346809Sdab int on;
88444364Sborman {
88544364Sborman #ifndef USE_TERMIO
88644364Sborman if (on)
88746809Sdab termbuf.lflags &= ~LCTLECH;
88844364Sborman else
88946809Sdab termbuf.lflags |= LCTLECH;
89044364Sborman #else
89144364Sborman # ifdef ECHOCTL
89244364Sborman if (on)
89344364Sborman termbuf.c_lflag &= ~ECHOCTL;
89444364Sborman else
89544364Sborman termbuf.c_lflag |= ECHOCTL;
89644364Sborman # endif
89744364Sborman # ifdef TCTLECH
89844364Sborman if (on)
89944364Sborman termbuf.c_lflag &= ~TCTLECH;
90044364Sborman else
90144364Sborman termbuf.c_lflag |= TCTLECH;
90244364Sborman # endif
90344364Sborman #endif
90444364Sborman }
90544364Sborman
90646809Sdab int
tty_iscrnl()90746809Sdab tty_iscrnl()
90846809Sdab {
90946809Sdab #ifndef USE_TERMIO
91046809Sdab return (termbuf.sg.sg_flags & CRMOD);
91146809Sdab #else
91246809Sdab return (termbuf.c_iflag & ICRNL);
91346809Sdab #endif
91446809Sdab }
91546809Sdab
91638905Sborman /*
91768348Sdab * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
91868348Sdab */
91968348Sdab #if B4800 != 4800
92068348Sdab #define DECODE_BAUD
92168348Sdab #endif
92268348Sdab
92368348Sdab #ifdef DECODE_BAUD
92468348Sdab
92568348Sdab /*
92638905Sborman * A table of available terminal speeds
92738905Sborman */
92838905Sborman struct termspeeds {
92938905Sborman int speed;
93038905Sborman int value;
93138905Sborman } termspeeds[] = {
93268348Sdab { 0, B0 }, { 50, B50 }, { 75, B75 },
93368348Sdab { 110, B110 }, { 134, B134 }, { 150, B150 },
93468348Sdab { 200, B200 }, { 300, B300 }, { 600, B600 },
93568348Sdab { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
936*69786Sdab { 4800, B4800 },
93768348Sdab #ifdef B7200
938*69786Sdab { 7200, B7200 },
93968348Sdab #endif
94068348Sdab { 9600, B9600 },
94168348Sdab #ifdef B14400
94268348Sdab { 14400, B14400 },
94368348Sdab #endif
94468348Sdab #ifdef B19200
94568348Sdab { 19200, B19200 },
94668348Sdab #endif
94768348Sdab #ifdef B28800
94868348Sdab { 28800, B28800 },
94968348Sdab #endif
95068348Sdab #ifdef B38400
95168348Sdab { 38400, B38400 },
95268348Sdab #endif
95368348Sdab #ifdef B57600
95468348Sdab { 57600, B57600 },
95568348Sdab #endif
95668348Sdab #ifdef B115200
95768348Sdab { 115200, B115200 },
95868348Sdab #endif
95968348Sdab #ifdef B230400
96068348Sdab { 230400, B230400 },
96168348Sdab #endif
96268348Sdab { -1, 0 }
96338905Sborman };
96468348Sdab #endif /* DECODE_BUAD */
96538905Sborman
96646809Sdab void
tty_tspeed(val)96738905Sborman tty_tspeed(val)
96846809Sdab int val;
96938905Sborman {
97068348Sdab #ifdef DECODE_BAUD
97138905Sborman register struct termspeeds *tp;
97238905Sborman
97338905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
97438905Sborman ;
97568348Sdab if (tp->speed == -1) /* back up to last valid value */
97668348Sdab --tp;
97745234Sborman cfsetospeed(&termbuf, tp->value);
97868348Sdab #else /* DECODE_BUAD */
97968348Sdab cfsetospeed(&termbuf, val);
98068348Sdab #endif /* DECODE_BUAD */
98138905Sborman }
98238905Sborman
98346809Sdab void
tty_rspeed(val)98438905Sborman tty_rspeed(val)
98546809Sdab int val;
98638905Sborman {
98768348Sdab #ifdef DECODE_BAUD
98838905Sborman register struct termspeeds *tp;
98938905Sborman
99038905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
99138905Sborman ;
99268348Sdab if (tp->speed == -1) /* back up to last valid value */
99368348Sdab --tp;
99445234Sborman cfsetispeed(&termbuf, tp->value);
99568348Sdab #else /* DECODE_BAUD */
99668348Sdab cfsetispeed(&termbuf, val);
99768348Sdab #endif /* DECODE_BAUD */
99838905Sborman }
99938905Sborman
100040242Sborman #if defined(CRAY2) && defined(UNICOS5)
100146809Sdab int
tty_isnewmap()100238905Sborman tty_isnewmap()
100338905Sborman {
100438905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
100538905Sborman !(termbuf.c_oflag & ONLRET));
100638905Sborman }
100738905Sborman #endif
100838905Sborman
100960151Sdab #ifdef PARENT_DOES_UTMP
101038905Sborman # ifndef NEWINIT
101138905Sborman extern struct utmp wtmp;
101238905Sborman extern char wtmpf[];
101338905Sborman # else /* NEWINIT */
101438905Sborman int gotalarm;
101546809Sdab
101646809Sdab /* ARGSUSED */
101746809Sdab void
nologinproc(sig)101840242Sborman nologinproc(sig)
101946809Sdab int sig;
102038905Sborman {
102138905Sborman gotalarm++;
102238905Sborman }
102338905Sborman # endif /* NEWINIT */
102460151Sdab #endif /* PARENT_DOES_UTMP */
102538905Sborman
102646809Sdab #ifndef NEWINIT
102760151Sdab # ifdef PARENT_DOES_UTMP
102846809Sdab extern void utmp_sig_init P((void));
102946809Sdab extern void utmp_sig_reset P((void));
103046809Sdab extern void utmp_sig_wait P((void));
103146809Sdab extern void utmp_sig_notify P((int));
103260151Sdab # endif /* PARENT_DOES_UTMP */
103346809Sdab #endif
103446809Sdab
103538905Sborman /*
103638905Sborman * getptyslave()
103738905Sborman *
103838905Sborman * Open the slave side of the pty, and do any initialization
103938905Sborman * that is necessary. The return value is a file descriptor
104038905Sborman * for the slave side.
104138905Sborman */
104246809Sdab int
getptyslave()104338905Sborman getptyslave()
104438905Sborman {
104538905Sborman register int t = -1;
104638905Sborman
104745234Sborman #if !defined(CRAY) || !defined(NEWINIT)
104845234Sborman # ifdef LINEMODE
104946809Sdab int waslm;
105046809Sdab # endif
105146809Sdab # ifdef TIOCGWINSZ
105246809Sdab struct winsize ws;
105346809Sdab extern int def_row, def_col;
105446809Sdab # endif
105546809Sdab extern int def_tspeed, def_rspeed;
105638905Sborman /*
105745234Sborman * Opening the slave side may cause initilization of the
105846809Sdab * kernel tty structure. We need remember the state of
105946809Sdab * if linemode was turned on
106046809Sdab * terminal window size
106146809Sdab * terminal speed
106246809Sdab * so that we can re-set them if we need to.
106338905Sborman */
106446809Sdab # ifdef LINEMODE
106546809Sdab waslm = tty_linemode();
106645234Sborman # endif
106745234Sborman
106845234Sborman
106945234Sborman /*
107045234Sborman * Make sure that we don't have a controlling tty, and
107145234Sborman * that we are the session (process group) leader.
107245234Sborman */
107345234Sborman # ifdef TIOCNOTTY
107438905Sborman t = open(_PATH_TTY, O_RDWR);
107538905Sborman if (t >= 0) {
107638905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0);
107738905Sborman (void) close(t);
107838905Sborman }
107945234Sborman # endif
108038905Sborman
108145234Sborman
108260151Sdab # ifdef PARENT_DOES_UTMP
108345234Sborman /*
108445234Sborman * Wait for our parent to get the utmp stuff to get done.
108545234Sborman */
108645234Sborman utmp_sig_wait();
108745234Sborman # endif
108845234Sborman
108945234Sborman t = cleanopen(line);
109038905Sborman if (t < 0)
109138905Sborman fatalperror(net, line);
109238905Sborman
109357592Sdab #ifdef STREAMSPTY
109457212Sdab #ifdef USE_TERMIO
109557212Sdab ttyfd = t;
109657212Sdab #endif
1097*69786Sdab if (ioctl(t, I_PUSH, "ptem") < 0)
109857212Sdab fatal(net, "I_PUSH ptem");
109957212Sdab if (ioctl(t, I_PUSH, "ldterm") < 0)
110057212Sdab fatal(net, "I_PUSH ldterm");
110157212Sdab if (ioctl(t, I_PUSH, "ttcompat") < 0)
110257212Sdab fatal(net, "I_PUSH ttcompat");
110357212Sdab if (ioctl(pty, I_PUSH, "pckt") < 0)
110457212Sdab fatal(net, "I_PUSH pckt");
110557212Sdab #endif
110657212Sdab
110745234Sborman /*
110845234Sborman * set up the tty modes as we like them to be.
110945234Sborman */
111038905Sborman init_termbuf();
111146809Sdab # ifdef TIOCGWINSZ
111246809Sdab if (def_row || def_col) {
1113*69786Sdab memset((char *)&ws, 0, sizeof(ws));
111446809Sdab ws.ws_col = def_col;
111546809Sdab ws.ws_row = def_row;
111646809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
111746809Sdab }
111846809Sdab # endif
111945234Sborman
112045234Sborman /*
112145234Sborman * Settings for sgtty based systems
112245234Sborman */
112345234Sborman # ifndef USE_TERMIO
112440242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
112545234Sborman # endif /* USE_TERMIO */
112645234Sborman
112745234Sborman /*
112860151Sdab * Settings for UNICOS (and HPUX)
112945234Sborman */
113060151Sdab # if defined(CRAY) || defined(__hpux)
113145234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3;
113245234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
113345234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
113445234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8;
113545234Sborman # endif
113645234Sborman
113745234Sborman /*
113845234Sborman * Settings for all other termios/termio based
113945234Sborman * systems, other than 4.4BSD. In 4.4BSD the
114045234Sborman * kernel does the initial terminal setup.
114145234Sborman */
114260151Sdab # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
114345234Sborman # ifndef OXTABS
114445234Sborman # define OXTABS 0
114545234Sborman # endif
114638905Sborman termbuf.c_lflag |= ECHO;
114738905Sborman termbuf.c_oflag |= ONLCR|OXTABS;
114838905Sborman termbuf.c_iflag |= ICRNL;
114938905Sborman termbuf.c_iflag &= ~IXOFF;
115045234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
115146996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
115246996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
115346809Sdab # ifdef LINEMODE
115446809Sdab if (waslm)
115546809Sdab tty_setlinemode(1);
115646809Sdab # endif /* LINEMODE */
115745234Sborman
115845234Sborman /*
115945234Sborman * Set the tty modes, and make this our controlling tty.
116045234Sborman */
116145234Sborman set_termbuf();
116245234Sborman if (login_tty(t) == -1)
116345234Sborman fatalperror(net, "login_tty");
116445234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */
116545234Sborman if (net > 2)
116645234Sborman (void) close(net);
116765158Sdab #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
116865158Sdab /*
116965158Sdab * Leave the pty open so that we can write out the rlogin
117065158Sdab * protocol for /bin/login, if the authentication works.
117165158Sdab */
117265158Sdab #else
117365158Sdab if (pty > 2) {
117445234Sborman (void) close(pty);
117565158Sdab pty = -1;
117665158Sdab }
117765158Sdab #endif
117845234Sborman }
117945234Sborman
118045234Sborman #if !defined(CRAY) || !defined(NEWINIT)
118145234Sborman #ifndef O_NOCTTY
118245234Sborman #define O_NOCTTY 0
118338905Sborman #endif
118445234Sborman /*
118545234Sborman * Open the specified slave side of the pty,
118645234Sborman * making sure that we have a clean tty.
118745234Sborman */
118846809Sdab int
cleanopen(line)118945234Sborman cleanopen(line)
119046809Sdab char *line;
119145234Sborman {
119245234Sborman register int t;
1193*69786Sdab #ifdef UNICOS7x
119457212Sdab struct secstat secbuf;
1195*69786Sdab #endif /* UNICOS7x */
119645234Sborman
119757212Sdab #ifndef STREAMSPTY
119845234Sborman /*
119945234Sborman * Make sure that other people can't open the
120045234Sborman * slave side of the connection.
120145234Sborman */
120238905Sborman (void) chown(line, 0, 0);
120338905Sborman (void) chmod(line, 0600);
120457212Sdab #endif
120545234Sborman
120645234Sborman # if !defined(CRAY) && (BSD > 43)
120745234Sborman (void) revoke(line);
120845234Sborman # endif
1209*69786Sdab #ifdef UNICOS7x
121057212Sdab if (secflag) {
121157212Sdab if (secstat(line, &secbuf) < 0)
121257212Sdab return(-1);
121357212Sdab if (setulvl(secbuf.st_slevel) < 0)
121457212Sdab return(-1);
121557212Sdab if (setucmp(secbuf.st_compart) < 0)
121657212Sdab return(-1);
121757212Sdab }
1218*69786Sdab #endif /* UNICOS7x */
121957212Sdab
122045234Sborman t = open(line, O_RDWR|O_NOCTTY);
122157212Sdab
1222*69786Sdab #ifdef UNICOS7x
122357212Sdab if (secflag) {
122457212Sdab if (setulvl(sysv.sy_minlvl) < 0)
122557212Sdab return(-1);
122657212Sdab if (setucmp(0) < 0)
122757212Sdab return(-1);
122857212Sdab }
1229*69786Sdab #endif /* UNICOS7x */
123057212Sdab
123145234Sborman if (t < 0)
123245234Sborman return(-1);
123345234Sborman
123445234Sborman /*
123545234Sborman * Hangup anybody else using this ttyp, then reopen it for
123645234Sborman * ourselves.
123745234Sborman */
123860151Sdab # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
123945234Sborman (void) signal(SIGHUP, SIG_IGN);
124045234Sborman vhangup();
124145234Sborman (void) signal(SIGHUP, SIG_DFL);
124245234Sborman t = open(line, O_RDWR|O_NOCTTY);
124345234Sborman if (t < 0)
124445234Sborman return(-1);
124545234Sborman # endif
124645234Sborman # if defined(CRAY) && defined(TCVHUP)
124745234Sborman {
124845234Sborman register int i;
124945234Sborman (void) signal(SIGHUP, SIG_IGN);
125045234Sborman (void) ioctl(t, TCVHUP, (char *)0);
125145234Sborman (void) signal(SIGHUP, SIG_DFL);
125257212Sdab
1253*69786Sdab #ifdef UNICOS7x
125457212Sdab if (secflag) {
125557212Sdab if (secstat(line, &secbuf) < 0)
125657212Sdab return(-1);
125757212Sdab if (setulvl(secbuf.st_slevel) < 0)
125857212Sdab return(-1);
125957212Sdab if (setucmp(secbuf.st_compart) < 0)
126057212Sdab return(-1);
126157212Sdab }
1262*69786Sdab #endif /* UNICOS7x */
126357212Sdab
126445234Sborman i = open(line, O_RDWR);
126557212Sdab
1266*69786Sdab #ifdef UNICOS7x
126757212Sdab if (secflag) {
126857212Sdab if (setulvl(sysv.sy_minlvl) < 0)
126957212Sdab return(-1);
127057212Sdab if (setucmp(0) < 0)
127157212Sdab return(-1);
127257212Sdab }
1273*69786Sdab #endif /* UNICOS7x */
127457212Sdab
127545234Sborman if (i < 0)
127646809Sdab return(-1);
127745234Sborman (void) close(t);
127845234Sborman t = i;
127945234Sborman }
128045234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */
128138905Sborman return(t);
128238905Sborman }
128345234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */
128438905Sborman
128545234Sborman #if BSD <= 43
128665158Sdab
128746809Sdab int
login_tty(t)128845234Sborman login_tty(t)
128946809Sdab int t;
129045234Sborman {
129165158Sdab if (setsid() < 0) {
129265158Sdab #ifdef ultrix
129365158Sdab /*
129465158Sdab * The setsid() may have failed because we
129565158Sdab * already have a pgrp == pid. Zero out
129665158Sdab * our pgrp and try again...
129765158Sdab */
129865158Sdab if ((setpgrp(0, 0) < 0) || (setsid() < 0))
129965158Sdab #endif
130065158Sdab fatalperror(net, "setsid()");
130165158Sdab }
130245234Sborman # ifdef TIOCSCTTY
130345234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
130445234Sborman fatalperror(net, "ioctl(sctty)");
130557212Sdab # if defined(CRAY)
130647613Sdab /*
130747613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through
130847613Sdab * the indirect /dev/tty interface.
130947613Sdab */
131047613Sdab close(t);
131147613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0)
131247613Sdab fatalperror(net, "open(/dev/tty)");
131347613Sdab # endif
131445234Sborman # else
131565158Sdab /*
131665158Sdab * We get our controlling tty assigned as a side-effect
131765158Sdab * of opening up a tty device. But on BSD based systems,
131865158Sdab * this only happens if our process group is zero. The
131965158Sdab * setsid() call above may have set our pgrp, so clear
132065158Sdab * it out before opening the tty...
132165158Sdab */
1322*69786Sdab # ifndef SOLARIS
132365158Sdab (void) setpgrp(0, 0);
1324*69786Sdab # else
1325*69786Sdab (void) setpgrp();
1326*69786Sdab # endif
132745234Sborman close(open(line, O_RDWR));
132845234Sborman # endif
132947613Sdab if (t != 0)
133047613Sdab (void) dup2(t, 0);
133147613Sdab if (t != 1)
133247613Sdab (void) dup2(t, 1);
133347613Sdab if (t != 2)
133447613Sdab (void) dup2(t, 2);
133547613Sdab if (t > 2)
133647613Sdab close(t);
133746809Sdab return(0);
133845234Sborman }
133945234Sborman #endif /* BSD <= 43 */
134045234Sborman
134138905Sborman #ifdef NEWINIT
134238905Sborman char *gen_id = "fe";
134338905Sborman #endif
134438905Sborman
134538905Sborman /*
134645234Sborman * startslave(host)
134738905Sborman *
134845234Sborman * Given a hostname, do whatever
134938905Sborman * is necessary to startup the login process on the slave side of the pty.
135038905Sborman */
135138905Sborman
135238905Sborman /* ARGSUSED */
135346809Sdab void
startslave(host,autologin,autoname)135446809Sdab startslave(host, autologin, autoname)
135546809Sdab char *host;
135646809Sdab int autologin;
135746809Sdab char *autoname;
135838905Sborman {
135938905Sborman register int i;
136038905Sborman long time();
136146809Sdab char name[256];
136246809Sdab #ifdef NEWINIT
136346809Sdab extern char *ptyip;
136446809Sdab struct init_request request;
136546809Sdab void nologinproc();
136646809Sdab register int n;
136746809Sdab #endif /* NEWINIT */
136838905Sborman
136957212Sdab #if defined(AUTHENTICATION)
137046809Sdab if (!autoname || !autoname[0])
137146809Sdab autologin = 0;
137246809Sdab
137346809Sdab if (autologin < auth_level) {
137446809Sdab fatal(net, "Authorization failed");
137546809Sdab exit(1);
137646809Sdab }
137746809Sdab #endif
137846809Sdab
137938905Sborman #ifndef NEWINIT
138060151Sdab # ifdef PARENT_DOES_UTMP
138138905Sborman utmp_sig_init();
138260151Sdab # endif /* PARENT_DOES_UTMP */
138338905Sborman
138438905Sborman if ((i = fork()) < 0)
138538905Sborman fatalperror(net, "fork");
138638905Sborman if (i) {
138760151Sdab # ifdef PARENT_DOES_UTMP
138838905Sborman /*
138938905Sborman * Cray parent will create utmp entry for child and send
139038905Sborman * signal to child to tell when done. Child waits for signal
139138905Sborman * before doing anything important.
139238905Sborman */
139338905Sborman register int pid = i;
139446809Sdab void sigjob P((int));
139538905Sborman
139638905Sborman setpgrp();
139744364Sborman utmp_sig_reset(); /* reset handler to default */
139838905Sborman /*
139938905Sborman * Create utmp entry for child
140038905Sborman */
140138905Sborman (void) time(&wtmp.ut_time);
140238905Sborman wtmp.ut_type = LOGIN_PROCESS;
140338905Sborman wtmp.ut_pid = pid;
140438905Sborman SCPYN(wtmp.ut_user, "LOGIN");
140538905Sborman SCPYN(wtmp.ut_host, host);
140638905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
140760151Sdab #ifndef __hpux
140838905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3);
140960151Sdab #else
141060151Sdab SCPYN(wtmp.ut_id, wtmp.ut_line+7);
141160151Sdab #endif
141238905Sborman pututline(&wtmp);
141338905Sborman endutent();
141438905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
141538905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp));
141638905Sborman (void) close(i);
141738905Sborman }
141860151Sdab #ifdef CRAY
141946809Sdab (void) signal(WJSIGNAL, sigjob);
142060151Sdab #endif
142138905Sborman utmp_sig_notify(pid);
142260151Sdab # endif /* PARENT_DOES_UTMP */
142338905Sborman } else {
142465158Sdab getptyslave(autologin);
142546809Sdab start_login(host, autologin, autoname);
142638905Sborman /*NOTREACHED*/
142738905Sborman }
142838905Sborman #else /* NEWINIT */
142938905Sborman
143038905Sborman /*
143138905Sborman * Init will start up login process if we ask nicely. We only wait
143238905Sborman * for it to start up and begin normal telnet operation.
143338905Sborman */
143438905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
143538905Sborman char tbuf[128];
143638905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
143738905Sborman fatalperror(net, tbuf);
143838905Sborman }
143938905Sborman memset((char *)&request, 0, sizeof(request));
144038905Sborman request.magic = INIT_MAGIC;
144138905Sborman SCPYN(request.gen_id, gen_id);
144238905Sborman SCPYN(request.tty_id, &line[8]);
144338905Sborman SCPYN(request.host, host);
144446809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network");
144544364Sborman #if !defined(UNICOS5)
144640242Sborman request.signal = SIGCLD;
144740242Sborman request.pid = getpid();
144840242Sborman #endif
144944364Sborman #ifdef BFTPDAEMON
145044364Sborman /*
145144364Sborman * Are we working as the bftp daemon?
145244364Sborman */
145344364Sborman if (bftpd) {
145444364Sborman SCPYN(request.exec_name, BFTPPATH);
145544364Sborman }
145644364Sborman #endif /* BFTPDAEMON */
145738905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) {
145838905Sborman char tbuf[128];
145938905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
146038905Sborman fatalperror(net, tbuf);
146138905Sborman }
146238905Sborman (void) close(i);
146338905Sborman (void) signal(SIGALRM, nologinproc);
146438905Sborman for (i = 0; ; i++) {
146540242Sborman char tbuf[128];
146638905Sborman alarm(15);
146738905Sborman n = read(pty, ptyip, BUFSIZ);
146838905Sborman if (i == 3 || n >= 0 || !gotalarm)
146938905Sborman break;
147038905Sborman gotalarm = 0;
147140242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
147240242Sborman (void) write(net, tbuf, strlen(tbuf));
147338905Sborman }
147438905Sborman if (n < 0 && gotalarm)
147538905Sborman fatal(net, "/etc/init didn't start login process");
147638905Sborman pcc += n;
147738905Sborman alarm(0);
147838905Sborman (void) signal(SIGALRM, SIG_DFL);
147938905Sborman
148038905Sborman return;
148138905Sborman #endif /* NEWINIT */
148238905Sborman }
148338905Sborman
148438905Sborman char *envinit[3];
148544364Sborman extern char **environ;
148638905Sborman
148746809Sdab void
init_env()148844364Sborman init_env()
148944364Sborman {
149044364Sborman extern char *getenv();
149144364Sborman char **envp;
149244364Sborman
149344364Sborman envp = envinit;
149444364Sborman if (*envp = getenv("TZ"))
149544364Sborman *envp++ -= 3;
149660151Sdab #if defined(CRAY) || defined(__hpux)
149744364Sborman else
149844364Sborman *envp++ = "TZ=GMT0";
149944364Sborman #endif
150044364Sborman *envp = 0;
150144364Sborman environ = envinit;
150244364Sborman }
150344364Sborman
150444364Sborman #ifndef NEWINIT
150544364Sborman
150644364Sborman /*
150745234Sborman * start_login(host)
150838905Sborman *
150938905Sborman * Assuming that we are now running as a child processes, this
151038905Sborman * function will turn us into the login process.
151138905Sborman */
151238905Sborman
151346809Sdab void
start_login(host,autologin,name)151446809Sdab start_login(host, autologin, name)
151546809Sdab char *host;
151646809Sdab int autologin;
151746809Sdab char *name;
151838905Sborman {
151944364Sborman register char *cp;
152044364Sborman register char **argv;
152144364Sborman char **addarg();
152265158Sdab extern char *getenv();
152357212Sdab #ifdef UTMPX
152457212Sdab register int pid = getpid();
152557212Sdab struct utmpx utmpx;
152657212Sdab #endif
152765158Sdab #ifdef SOLARIS
152857212Sdab char *term;
152957212Sdab char termbuf[64];
153057212Sdab #endif
153138905Sborman
153257212Sdab #ifdef UTMPX
153338905Sborman /*
153457212Sdab * Create utmp entry for child
153557212Sdab */
153657212Sdab
1537*69786Sdab memset(&utmpx, 0, sizeof(utmpx));
153857212Sdab SCPYN(utmpx.ut_user, ".telnet");
153957212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
154057212Sdab utmpx.ut_pid = pid;
154157212Sdab utmpx.ut_id[0] = 't';
154257212Sdab utmpx.ut_id[1] = 'n';
154357212Sdab utmpx.ut_id[2] = SC_WILDC;
154457212Sdab utmpx.ut_id[3] = SC_WILDC;
154557212Sdab utmpx.ut_type = LOGIN_PROCESS;
154657212Sdab (void) time(&utmpx.ut_tv.tv_sec);
154768348Sdab if (pututxline(&utmpx) == NULL)
154868348Sdab fatal(net, "pututxline failed");
154957212Sdab #endif
155057212Sdab
155157212Sdab /*
155238905Sborman * -h : pass on name of host.
155338905Sborman * WARNING: -h is accepted by login if and only if
155438905Sborman * getuid() == 0.
155538905Sborman * -p : don't clobber the environment (so terminal type stays set).
155646809Sdab *
155746809Sdab * -f : force this login, he has already been authenticated
155838905Sborman */
155944364Sborman argv = addarg(0, "login");
156065158Sdab
156160151Sdab #if !defined(NO_LOGIN_H)
156265158Sdab
156365158Sdab # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
156457212Sdab /*
156565158Sdab * Don't add the "-h host" option if we are going
156665158Sdab * to be adding the "-r host" option down below...
156757212Sdab */
156865158Sdab if ((auth_level < 0) || (autologin != AUTH_VALID))
156965158Sdab # endif
157065158Sdab {
157165158Sdab argv = addarg(argv, "-h");
157265158Sdab argv = addarg(argv, host);
157365158Sdab #ifdef SOLARIS
157465158Sdab /*
157565158Sdab * SVR4 version of -h takes TERM= as second arg, or -
157665158Sdab */
157765158Sdab term = getenv("TERM");
157865158Sdab if (term == NULL || term[0] == 0) {
157965158Sdab term = "-";
158065158Sdab } else {
158165158Sdab strcpy(termbuf, "TERM=");
158265158Sdab strncat(termbuf, term, sizeof(termbuf) - 6);
158365158Sdab term = termbuf;
158465158Sdab }
158565158Sdab argv = addarg(argv, term);
158665158Sdab #endif
158757212Sdab }
158857212Sdab #endif
158946809Sdab #if !defined(NO_LOGIN_P)
159044364Sborman argv = addarg(argv, "-p");
159138905Sborman #endif
1592*69786Sdab #ifdef LINEMODE
1593*69786Sdab /*
1594*69786Sdab * Set the environment variable "LINEMODE" to either
1595*69786Sdab * "real" or "kludge" if we are operating in either
1596*69786Sdab * real or kludge linemode.
1597*69786Sdab */
1598*69786Sdab if (lmodetype == REAL_LINEMODE)
1599*69786Sdab setenv("LINEMODE", "real", 1);
1600*69786Sdab # ifdef KLUDGELINEMODE
1601*69786Sdab else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
1602*69786Sdab setenv("LINEMODE", "kludge", 1);
1603*69786Sdab # endif
1604*69786Sdab #endif
160544364Sborman #ifdef BFTPDAEMON
160644364Sborman /*
160744364Sborman * Are we working as the bftp daemon? If so, then ask login
160844364Sborman * to start bftp instead of shell.
160944364Sborman */
161044364Sborman if (bftpd) {
161144364Sborman argv = addarg(argv, "-e");
161244364Sborman argv = addarg(argv, BFTPPATH);
1613*69786Sdab } else
161444364Sborman #endif
161546809Sdab #if defined (SecurID)
161646809Sdab /*
161746809Sdab * don't worry about the -f that might get sent.
161846809Sdab * A -s is supposed to override it anyhow.
161946809Sdab */
162046809Sdab if (require_SecurID)
162146809Sdab argv = addarg(argv, "-s");
162246809Sdab #endif
162357212Sdab #if defined (AUTHENTICATION)
162446809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) {
162546809Sdab # if !defined(NO_LOGIN_F)
162646809Sdab argv = addarg(argv, "-f");
162765158Sdab argv = addarg(argv, name);
162865158Sdab # else
162965158Sdab # if defined(LOGIN_R)
163065158Sdab /*
163165158Sdab * We don't have support for "login -f", but we
163265158Sdab * can fool /bin/login into thinking that we are
163365158Sdab * rlogind, and allow us to log in without a
163465158Sdab * password. The rlogin protocol expects
163565158Sdab * local-user\0remote-user\0term/speed\0
163665158Sdab */
163765158Sdab
163865158Sdab if (pty > 2) {
163965158Sdab register char *cp;
164065158Sdab char speed[128];
164165158Sdab int isecho, israw, xpty, len;
164265158Sdab extern int def_rspeed;
164365158Sdab # ifndef LOGIN_HOST
164465158Sdab /*
164565158Sdab * Tell login that we are coming from "localhost".
164665158Sdab * If we passed in the real host name, then the
164765158Sdab * user would have to allow .rhost access from
164865158Sdab * every machine that they want authenticated
164965158Sdab * access to work from, which sort of defeats
165065158Sdab * the purpose of an authenticated login...
165165158Sdab * So, we tell login that the session is coming
165265158Sdab * from "localhost", and the user will only have
165365158Sdab * to have "localhost" in their .rhost file.
165465158Sdab */
165565158Sdab # define LOGIN_HOST "localhost"
165665158Sdab # endif
165765158Sdab argv = addarg(argv, "-r");
165865158Sdab argv = addarg(argv, LOGIN_HOST);
165965158Sdab
166065158Sdab xpty = pty;
166165158Sdab # ifndef STREAMSPTY
166265158Sdab pty = 0;
166365158Sdab # else
166465158Sdab ttyfd = 0;
166546809Sdab # endif
166665158Sdab init_termbuf();
166765158Sdab isecho = tty_isecho();
166865158Sdab israw = tty_israw();
166965158Sdab if (isecho || !israw) {
167065158Sdab tty_setecho(0); /* Turn off echo */
167165158Sdab tty_setraw(1); /* Turn on raw */
167265158Sdab set_termbuf();
167365158Sdab }
167465158Sdab len = strlen(name)+1;
167565158Sdab write(xpty, name, len);
167665158Sdab write(xpty, name, len);
167765158Sdab sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
167865158Sdab (def_rspeed > 0) ? def_rspeed : 9600);
167965158Sdab len = strlen(speed)+1;
168065158Sdab write(xpty, speed, len);
168165158Sdab
168265158Sdab if (isecho || !israw) {
168365158Sdab init_termbuf();
168465158Sdab tty_setecho(isecho);
168565158Sdab tty_setraw(israw);
168665158Sdab set_termbuf();
168765158Sdab if (!israw) {
168865158Sdab /*
168965158Sdab * Write a newline to ensure
169065158Sdab * that login will be able to
169165158Sdab * read the line...
169265158Sdab */
169365158Sdab write(xpty, "\n", 1);
169465158Sdab }
169565158Sdab }
169665158Sdab pty = xpty;
169765158Sdab }
169865158Sdab # else
169946809Sdab argv = addarg(argv, name);
170065158Sdab # endif
170165158Sdab # endif
170246809Sdab } else
170346809Sdab #endif
170444364Sborman if (getenv("USER")) {
170544364Sborman argv = addarg(argv, getenv("USER"));
170665158Sdab #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
170746809Sdab {
170846809Sdab register char **cpp;
170946809Sdab for (cpp = environ; *cpp; cpp++)
171046809Sdab argv = addarg(argv, *cpp);
171146809Sdab }
171246809Sdab #endif
171357212Sdab /*
171457212Sdab * Assume that login will set the USER variable
171557212Sdab * correctly. For SysV systems, this means that
171657212Sdab * USER will no longer be set, just LOGNAME by
171757212Sdab * login. (The problem is that if the auto-login
171857212Sdab * fails, and the user then specifies a different
171957212Sdab * account name, he can get logged in with both
172057212Sdab * LOGNAME and USER in his environment, but the
172157212Sdab * USER value will be wrong.
172257212Sdab */
172357212Sdab unsetenv("USER");
172444364Sborman }
172568348Sdab #ifdef SOLARIS
172668348Sdab else {
172768348Sdab char **p;
1728*69786Sdab
172968348Sdab argv = addarg(argv, ""); /* no login name */
173068348Sdab for (p = environ; *p; p++) {
173168348Sdab argv = addarg(argv, *p);
173268348Sdab }
173368348Sdab }
173468348Sdab #endif /* SOLARIS */
173565158Sdab #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
173665158Sdab if (pty > 2)
173765158Sdab close(pty);
173865158Sdab #endif
173946809Sdab closelog();
174068348Sdab /*
174168348Sdab * This sleep(1) is in here so that telnetd can
174268348Sdab * finish up with the tty. There's a race condition
174368348Sdab * the login banner message gets lost...
174468348Sdab */
174568348Sdab sleep(1);
174644364Sborman execv(_PATH_LOGIN, argv);
174744364Sborman
174838905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
174938905Sborman fatalperror(net, _PATH_LOGIN);
175038905Sborman /*NOTREACHED*/
175138905Sborman }
175244364Sborman
175346809Sdab char **
addarg(argv,val)175444364Sborman addarg(argv, val)
175546809Sdab register char **argv;
175646809Sdab register char *val;
175744364Sborman {
175844364Sborman register char **cpp;
175944364Sborman
176044364Sborman if (argv == NULL) {
176144364Sborman /*
176244364Sborman * 10 entries, a leading length, and a null
176344364Sborman */
176444364Sborman argv = (char **)malloc(sizeof(*argv) * 12);
176544364Sborman if (argv == NULL)
176644364Sborman return(NULL);
176744364Sborman *argv++ = (char *)10;
176844364Sborman *argv = (char *)0;
176944364Sborman }
177044364Sborman for (cpp = argv; *cpp; cpp++)
177144364Sborman ;
177244364Sborman if (cpp == &argv[(int)argv[-1]]) {
177344364Sborman --argv;
177444364Sborman *argv = (char *)((int)(*argv) + 10);
177568348Sdab argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2));
177644364Sborman if (argv == NULL)
177744364Sborman return(NULL);
177844364Sborman argv++;
177944364Sborman cpp = &argv[(int)argv[-1] - 10];
178044364Sborman }
178144364Sborman *cpp++ = val;
178244364Sborman *cpp = 0;
178344364Sborman return(argv);
178444364Sborman }
178546809Sdab #endif /* NEWINIT */
178638905Sborman
178738905Sborman /*
178838905Sborman * cleanup()
178938905Sborman *
179038905Sborman * This is the routine to call when we are all through, to
179138905Sborman * clean up anything that needs to be cleaned up.
179238905Sborman */
179346809Sdab /* ARGSUSED */
179446809Sdab void
cleanup(sig)179546809Sdab cleanup(sig)
179646809Sdab int sig;
179738905Sborman {
179860151Sdab #ifndef PARENT_DOES_UTMP
179945234Sborman # if (BSD > 43) || defined(convex)
180038905Sborman char *p;
180138905Sborman
180238905Sborman p = line + sizeof("/dev/") - 1;
180338905Sborman if (logout(p))
180438905Sborman logwtmp(p, "", "");
180538905Sborman (void)chmod(line, 0666);
180638905Sborman (void)chown(line, 0, 0);
180738905Sborman *p = 'p';
180838905Sborman (void)chmod(line, 0666);
180938905Sborman (void)chown(line, 0, 0);
181046809Sdab (void) shutdown(net, 2);
181146809Sdab exit(1);
181238905Sborman # else
181346809Sdab void rmut();
181446809Sdab
181538905Sborman rmut();
181638905Sborman vhangup(); /* XXX */
181746809Sdab (void) shutdown(net, 2);
181846809Sdab exit(1);
181938905Sborman # endif
182060151Sdab #else /* PARENT_DOES_UTMP */
182146809Sdab # ifdef NEWINIT
182238905Sborman (void) shutdown(net, 2);
182346809Sdab exit(1);
182438905Sborman # else /* NEWINIT */
182560151Sdab # ifdef CRAY
182646809Sdab static int incleanup = 0;
182746809Sdab register int t;
1828*69786Sdab int child_status; /* status of child process as returned by waitpid */
1829*69786Sdab int flags = WNOHANG|WUNTRACED;
183046809Sdab
183146809Sdab /*
183246809Sdab * 1: Pick up the zombie, if we are being called
183346809Sdab * as the signal handler.
183446809Sdab * 2: If we are a nested cleanup(), return.
183546809Sdab * 3: Try to clean up TMPDIR.
183646809Sdab * 4: Fill in utmp with shutdown of process.
183746809Sdab * 5: Close down the network and pty connections.
183846809Sdab * 6: Finish up the TMPDIR cleanup, if needed.
183946809Sdab */
1840*69786Sdab if (sig == SIGCHLD) {
1841*69786Sdab while (waitpid(-1, &child_status, flags) > 0)
184246809Sdab ; /* VOID */
1843*69786Sdab /* Check if the child process was stopped
1844*69786Sdab * rather than exited. We want cleanup only if
1845*69786Sdab * the child has died.
1846*69786Sdab */
1847*69786Sdab if (WIFSTOPPED(child_status)) {
1848*69786Sdab return;
1849*69786Sdab }
1850*69786Sdab }
185146809Sdab t = sigblock(sigmask(SIGCHLD));
185246809Sdab if (incleanup) {
185346809Sdab sigsetmask(t);
185446809Sdab return;
185546809Sdab }
185646809Sdab incleanup = 1;
185746809Sdab sigsetmask(t);
1858*69786Sdab #ifdef UNICOS7x
185960151Sdab if (secflag) {
186060151Sdab /*
186160151Sdab * We need to set ourselves back to a null
186260151Sdab * label to clean up.
186360151Sdab */
186446809Sdab
186560151Sdab setulvl(sysv.sy_minlvl);
186660151Sdab setucmp((long)0);
186760151Sdab }
1868*69786Sdab #endif /* UNICOS7x */
186960151Sdab
187046809Sdab t = cleantmp(&wtmp);
187146809Sdab setutent(); /* just to make sure */
187260151Sdab # endif /* CRAY */
187346809Sdab rmut(line);
187446809Sdab close(pty);
187538905Sborman (void) shutdown(net, 2);
187660151Sdab # ifdef CRAY
187746809Sdab if (t == 0)
187846809Sdab cleantmp(&wtmp);
187960151Sdab # endif /* CRAY */
188046809Sdab exit(1);
188138905Sborman # endif /* NEWINT */
188260151Sdab #endif /* PARENT_DOES_UTMP */
188338905Sborman }
188438905Sborman
188560151Sdab #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
188638905Sborman /*
188738905Sborman * _utmp_sig_rcv
188838905Sborman * utmp_sig_init
188938905Sborman * utmp_sig_wait
189038905Sborman * These three functions are used to coordinate the handling of
189138905Sborman * the utmp file between the server and the soon-to-be-login shell.
189238905Sborman * The server actually creates the utmp structure, the child calls
189338905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and
189438905Sborman * signals the future-login shell to proceed.
189538905Sborman */
189638905Sborman static int caught=0; /* NZ when signal intercepted */
189738905Sborman static void (*func)(); /* address of previous handler */
189838905Sborman
189946809Sdab void
_utmp_sig_rcv(sig)190038905Sborman _utmp_sig_rcv(sig)
190146809Sdab int sig;
190238905Sborman {
190338905Sborman caught = 1;
190438905Sborman (void) signal(SIGUSR1, func);
190538905Sborman }
190638905Sborman
190746809Sdab void
utmp_sig_init()190838905Sborman utmp_sig_init()
190938905Sborman {
191038905Sborman /*
191138905Sborman * register signal handler for UTMP creation
191238905Sborman */
191338905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
191438905Sborman fatalperror(net, "telnetd/signal");
191538905Sborman }
191638905Sborman
191746809Sdab void
utmp_sig_reset()191844364Sborman utmp_sig_reset()
191944364Sborman {
192044364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */
192144364Sborman }
192244364Sborman
192360151Sdab # ifdef __hpux
192460151Sdab # define sigoff() /* do nothing */
192560151Sdab # define sigon() /* do nothing */
192660151Sdab # endif
192760151Sdab
192846809Sdab void
utmp_sig_wait()192938905Sborman utmp_sig_wait()
193038905Sborman {
193138905Sborman /*
193238905Sborman * Wait for parent to write our utmp entry.
193338905Sborman */
193438905Sborman sigoff();
193538905Sborman while (caught == 0) {
193638905Sborman pause(); /* wait until we get a signal (sigon) */
193738905Sborman sigoff(); /* turn off signals while we check caught */
193838905Sborman }
193938905Sborman sigon(); /* turn on signals again */
194038905Sborman }
194138905Sborman
194246809Sdab void
utmp_sig_notify(pid)194338905Sborman utmp_sig_notify(pid)
194438905Sborman {
194538905Sborman kill(pid, SIGUSR1);
194638905Sborman }
194746809Sdab
194860151Sdab # ifdef CRAY
194946809Sdab static int gotsigjob = 0;
195046809Sdab
195146809Sdab /*ARGSUSED*/
195246809Sdab void
sigjob(sig)195346809Sdab sigjob(sig)
195446809Sdab int sig;
195546809Sdab {
195646809Sdab register int jid;
195746809Sdab register struct jobtemp *jp;
195846809Sdab
195946809Sdab while ((jid = waitjob(NULL)) != -1) {
196046809Sdab if (jid == 0) {
196146809Sdab return;
196246809Sdab }
196346809Sdab gotsigjob++;
196446809Sdab jobend(jid, NULL, NULL);
196546809Sdab }
196646809Sdab }
196746809Sdab
196846809Sdab /*
1969*69786Sdab * jid_getutid:
1970*69786Sdab * called by jobend() before calling cleantmp()
1971*69786Sdab * to find the correct $TMPDIR to cleanup.
1972*69786Sdab */
1973*69786Sdab
1974*69786Sdab struct utmp *
jid_getutid(jid)1975*69786Sdab jid_getutid(jid)
1976*69786Sdab int jid;
1977*69786Sdab {
1978*69786Sdab struct utmp *cur = NULL;
1979*69786Sdab
1980*69786Sdab setutent(); /* just to make sure */
1981*69786Sdab while (cur = getutent()) {
1982*69786Sdab if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
1983*69786Sdab return(cur);
1984*69786Sdab }
1985*69786Sdab }
1986*69786Sdab
1987*69786Sdab return(0);
1988*69786Sdab }
1989*69786Sdab
1990*69786Sdab /*
199146809Sdab * Clean up the TMPDIR that login created.
199246809Sdab * The first time this is called we pick up the info
199346809Sdab * from the utmp. If the job has already gone away,
199446809Sdab * then we'll clean up and be done. If not, then
199546809Sdab * when this is called the second time it will wait
199646809Sdab * for the signal that the job is done.
199746809Sdab */
199846809Sdab int
cleantmp(wtp)199946809Sdab cleantmp(wtp)
200046809Sdab register struct utmp *wtp;
200146809Sdab {
200246809Sdab struct utmp *utp;
200346809Sdab static int first = 1;
200446809Sdab register int mask, omask, ret;
200565158Sdab extern struct utmp *getutid P((const struct utmp *_Id));
200646809Sdab
200765158Sdab
200846809Sdab mask = sigmask(WJSIGNAL);
200946809Sdab
201046809Sdab if (first == 0) {
201146809Sdab omask = sigblock(mask);
201246809Sdab while (gotsigjob == 0)
201346809Sdab sigpause(omask);
201446809Sdab return(1);
201546809Sdab }
201646809Sdab first = 0;
201746809Sdab setutent(); /* just to make sure */
201846809Sdab
201946809Sdab utp = getutid(wtp);
202046809Sdab if (utp == 0) {
202146809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
202246809Sdab return(-1);
202346809Sdab }
202446809Sdab /*
202546809Sdab * Nothing to clean up if the user shell was never started.
202646809Sdab */
202746809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
202846809Sdab return(1);
202946809Sdab
203046809Sdab /*
203146809Sdab * Block the WJSIGNAL while we are in jobend().
203246809Sdab */
203346809Sdab omask = sigblock(mask);
203446809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
203546809Sdab sigsetmask(omask);
203646809Sdab return(ret);
203746809Sdab }
203846809Sdab
203946809Sdab int
jobend(jid,path,user)204046809Sdab jobend(jid, path, user)
204146809Sdab register int jid;
204246809Sdab register char *path;
204346809Sdab register char *user;
204446809Sdab {
204546809Sdab static int saved_jid = 0;
2046*69786Sdab static int pty_saved_jid = 0;
204746809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1];
204846809Sdab static char saved_user[sizeof(wtmp.ut_user)+1];
204946809Sdab
2050*69786Sdab /*
2051*69786Sdab * this little piece of code comes into play
2052*69786Sdab * only when ptyreconnect is used to reconnect
2053*69786Sdab * to an previous session.
2054*69786Sdab *
2055*69786Sdab * this is the only time when the
2056*69786Sdab * "saved_jid != jid" code is executed.
2057*69786Sdab */
2058*69786Sdab
2059*69786Sdab if ( saved_jid && saved_jid != jid ) {
2060*69786Sdab if (!path) { /* called from signal handler */
2061*69786Sdab pty_saved_jid = jid;
2062*69786Sdab } else {
2063*69786Sdab pty_saved_jid = saved_jid;
2064*69786Sdab }
2065*69786Sdab }
2066*69786Sdab
206746809Sdab if (path) {
206846809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
206946809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user));
207046809Sdab saved_path[sizeof(saved_path)] = '\0';
207146809Sdab saved_user[sizeof(saved_user)] = '\0';
207246809Sdab }
207346809Sdab if (saved_jid == 0) {
207446809Sdab saved_jid = jid;
207546809Sdab return(0);
207646809Sdab }
2077*69786Sdab
2078*69786Sdab /* if the jid has changed, get the correct entry from the utmp file */
2079*69786Sdab
2080*69786Sdab if ( saved_jid != jid ) {
2081*69786Sdab struct utmp *utp = NULL;
2082*69786Sdab struct utmp *jid_getutid();
2083*69786Sdab
2084*69786Sdab utp = jid_getutid(pty_saved_jid);
2085*69786Sdab
2086*69786Sdab if (utp == 0) {
2087*69786Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
2088*69786Sdab return(-1);
2089*69786Sdab }
2090*69786Sdab
2091*69786Sdab cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
2092*69786Sdab return(1);
2093*69786Sdab }
2094*69786Sdab
209546809Sdab cleantmpdir(jid, saved_path, saved_user);
209646809Sdab return(1);
209746809Sdab }
209846809Sdab
209946809Sdab /*
210046809Sdab * Fork a child process to clean up the TMPDIR
210146809Sdab */
cleantmpdir(jid,tpath,user)210246809Sdab cleantmpdir(jid, tpath, user)
210346809Sdab register int jid;
210446809Sdab register char *tpath;
210546809Sdab register char *user;
210646809Sdab {
210746809Sdab switch(fork()) {
210846809Sdab case -1:
210946809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
211046809Sdab tpath);
211146809Sdab break;
211246809Sdab case 0:
211346809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
211446809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
211546809Sdab tpath, CLEANTMPCMD);
211646809Sdab exit(1);
211746809Sdab default:
211846809Sdab /*
211946809Sdab * Forget about child. We will exit, and
212046809Sdab * /etc/init will pick it up.
212146809Sdab */
212246809Sdab break;
212346809Sdab }
212446809Sdab }
212560151Sdab # endif /* CRAY */
212660151Sdab #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
212738905Sborman
212838905Sborman /*
212938905Sborman * rmut()
213038905Sborman *
213138905Sborman * This is the function called by cleanup() to
213238905Sborman * remove the utmp entry for this person.
213338905Sborman */
213438905Sborman
213557212Sdab #ifdef UTMPX
213665158Sdab void
rmut()213757212Sdab rmut()
213857212Sdab {
213957212Sdab register f;
214057212Sdab int found = 0;
214157212Sdab struct utmp *u, *utmp;
214257212Sdab int nutmp;
214357212Sdab struct stat statbf;
214457212Sdab
214557212Sdab struct utmpx *utxp, utmpx;
214657212Sdab
214757212Sdab /*
214857212Sdab * This updates the utmpx and utmp entries and make a wtmp/x entry
214957212Sdab */
215057212Sdab
215157212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
215257212Sdab utxp = getutxline(&utmpx);
215357212Sdab if (utxp) {
215457212Sdab utxp->ut_type = DEAD_PROCESS;
215557212Sdab utxp->ut_exit.e_termination = 0;
215657212Sdab utxp->ut_exit.e_exit = 0;
215757212Sdab (void) time(&utmpx.ut_tv.tv_sec);
215857212Sdab utmpx.ut_tv.tv_usec = 0;
215957212Sdab modutx(utxp);
216057212Sdab }
216157212Sdab endutxent();
216257212Sdab } /* end of rmut */
216357212Sdab #endif
216457212Sdab
216560151Sdab #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
216646809Sdab void
rmut()216738905Sborman rmut()
216838905Sborman {
216938905Sborman register f;
217038905Sborman int found = 0;
217138905Sborman struct utmp *u, *utmp;
217238905Sborman int nutmp;
217338905Sborman struct stat statbf;
217438905Sborman
217538905Sborman f = open(utmpf, O_RDWR);
217638905Sborman if (f >= 0) {
217738905Sborman (void) fstat(f, &statbf);
217838905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
217938905Sborman if (!utmp)
218038905Sborman syslog(LOG_ERR, "utmp malloc failed");
218138905Sborman if (statbf.st_size && utmp) {
218238905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size);
218338905Sborman nutmp /= sizeof(struct utmp);
2184*69786Sdab
218538905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) {
218638905Sborman if (SCMPN(u->ut_line, line+5) ||
218738905Sborman u->ut_name[0]==0)
218838905Sborman continue;
218938905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET);
219038905Sborman SCPYN(u->ut_name, "");
219138905Sborman SCPYN(u->ut_host, "");
219238905Sborman (void) time(&u->ut_time);
219338905Sborman (void) write(f, (char *)u, sizeof(wtmp));
219438905Sborman found++;
219538905Sborman }
219638905Sborman }
219738905Sborman (void) close(f);
219838905Sborman }
219938905Sborman if (found) {
220038905Sborman f = open(wtmpf, O_WRONLY|O_APPEND);
220138905Sborman if (f >= 0) {
220238905Sborman SCPYN(wtmp.ut_line, line+5);
220338905Sborman SCPYN(wtmp.ut_name, "");
220438905Sborman SCPYN(wtmp.ut_host, "");
220538905Sborman (void) time(&wtmp.ut_time);
220638905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp));
220738905Sborman (void) close(f);
220838905Sborman }
220938905Sborman }
221038905Sborman (void) chmod(line, 0666);
221138905Sborman (void) chown(line, 0, 0);
221238905Sborman line[strlen("/dev/")] = 'p';
221338905Sborman (void) chmod(line, 0666);
221438905Sborman (void) chown(line, 0, 0);
221538905Sborman } /* end of rmut */
221638905Sborman #endif /* CRAY */
221760151Sdab
221860151Sdab #ifdef __hpux
rmut(line)221960151Sdab rmut (line)
222060151Sdab char *line;
222160151Sdab {
222260151Sdab struct utmp utmp;
222360151Sdab struct utmp *utptr;
222460151Sdab int fd; /* for /etc/wtmp */
222560151Sdab
222660151Sdab utmp.ut_type = USER_PROCESS;
222760151Sdab (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
222860151Sdab (void) setutent();
222960151Sdab utptr = getutid(&utmp);
223060151Sdab /* write it out only if it exists */
223160151Sdab if (utptr) {
223260151Sdab utptr->ut_type = DEAD_PROCESS;
223360151Sdab utptr->ut_time = time((long *) 0);
223460151Sdab (void) pututline(utptr);
223560151Sdab /* set wtmp entry if wtmp file exists */
223660151Sdab if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
223760151Sdab (void) write(fd, utptr, sizeof(utmp));
223860151Sdab (void) close(fd);
223960151Sdab }
224060151Sdab }
224160151Sdab (void) endutent();
224260151Sdab
224360151Sdab (void) chmod(line, 0666);
224460151Sdab (void) chown(line, 0, 0);
224560151Sdab line[14] = line[13];
224660151Sdab line[13] = line[12];
224760151Sdab line[8] = 'm';
224860151Sdab line[9] = '/';
224960151Sdab line[10] = 'p';
225060151Sdab line[11] = 't';
225160151Sdab line[12] = 'y';
225260151Sdab (void) chmod(line, 0666);
225360151Sdab (void) chown(line, 0, 0);
225460151Sdab }
225560151Sdab #endif
2256