[BACK]Return to sys_term.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / telnetd

Annotation of src/libexec/telnetd/sys_term.c, Revision 1.13

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

CVSweb <webmaster@jp.NetBSD.org>