[BACK]Return to common.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rdist

Annotation of src/usr.bin/rdist/common.c, Revision 1.19

1.19    ! millert     1: /*     $OpenBSD: common.c,v 1.18 2003/04/19 17:22:29 millert Exp $     */
1.3       deraadt     2:
1.1       dm          3: /*
                      4:  * Copyright (c) 1983 Regents of the University of California.
                      5:  * All rights reserved.
                      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:
                     36: #ifndef lint
1.6       millert    37: #if 0
1.1       dm         38: static char RCSid[] =
1.6       millert    39: "$From: common.c,v 6.82 1998/03/23 23:27:33 michaelc Exp $";
                     40: #else
                     41: static char RCSid[] =
1.19    ! millert    42: "$OpenBSD: common.c,v 1.18 2003/04/19 17:22:29 millert Exp $";
1.6       millert    43: #endif
1.1       dm         44:
                     45: static char sccsid[] = "@(#)common.c";
                     46:
                     47: static char copyright[] =
                     48: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     49:  All rights reserved.\n";
                     50: #endif /* !lint */
                     51:
                     52: /*
                     53:  * Things common to both the client and server.
                     54:  */
                     55:
                     56: #include "defs.h"
                     57: #if    defined(NEED_UTIME_H)
                     58: #include <utime.h>
                     59: #endif /* defined(NEED_UTIME_H) */
1.6       millert    60: #include <sys/socket.h>
                     61: #include <sys/wait.h>
1.1       dm         62:
                     63: /*
                     64:  * Variables common to both client and server
                     65:  */
                     66: char                   host[MAXHOSTNAMELEN];   /* Name of this host */
                     67: UID_T                  userid = (UID_T)-1;     /* User's UID */
                     68: GID_T                  groupid = (GID_T)-1;    /* User's GID */
                     69: char                  *homedir = NULL;         /* User's $HOME */
                     70: char                  *locuser = NULL;         /* Local User's name */
                     71: int                    isserver = FALSE;       /* We're the server */
                     72: int                    amchild = 0;            /* This PID is a child */
                     73: int                    do_fork = 1;            /* Fork child process */
                     74: char                  *currenthost = NULL;     /* Current client hostname */
                     75: char                  *progname = NULL;        /* Name of this program */
                     76: int                    rem_r = -1;             /* Client file descriptor */
                     77: int                    rem_w = -1;             /* Client file descriptor */
                     78: struct passwd         *pw = NULL;              /* Local user's pwd entry */
                     79: int                    contimedout = FALSE;    /* Connection timed out */
                     80: int                    proto_version = -1;     /* Protocol version */
                     81: int                    rtimeout = RTIMEOUT;    /* Response time out */
                     82: jmp_buf                        finish_jmpbuf;          /* Finish() jmp buffer */
1.2       dm         83: int                    setjmp_ok = FALSE;      /* setjmp()/longjmp() status */
1.1       dm         84: char                 **realargv;               /* Real main() argv */
                     85: int                    realargc;               /* Real main() argc */
                     86: opt_t                  options = 0;            /* Global install options */
                     87:
                     88: /*
                     89:  * Front end to write() that handles partial write() requests.
                     90:  */
                     91: extern WRITE_RETURN_T xwrite(fd, buf, len)
                     92:        int fd;
                     93:        void *buf;
                     94:        WRITE_AMT_T len;
                     95: {
                     96:        WRITE_AMT_T nleft = len;
                     97:        WRITE_RETURN_T nwritten;
1.12      mpech      98:        char *ptr = buf;
1.1       dm         99:
                    100:        while (nleft > 0) {
                    101:                if ((nwritten = write(fd, ptr, nleft)) <= 0) {
                    102:                        return nwritten;
                    103:                }
                    104:                nleft -= nwritten;
                    105:                ptr += nwritten;
                    106:        }
                    107:
                    108:        return len;
                    109: }
                    110:
                    111: /*
                    112:  * Set program name
                    113:  */
                    114: extern void setprogname(argv)
                    115:        char **argv;
                    116: {
1.12      mpech     117:        char *cp;
1.1       dm        118:
                    119:        if (!progname) {
1.8       millert   120:                progname = xstrdup(argv[0]);
1.6       millert   121:                if ((cp = strrchr(progname, '/')))
1.1       dm        122:                        progname = cp + 1;
                    123:        }
                    124: }
                    125:
                    126: /*
                    127:  * Do run-time initialization
                    128:  */
                    129: extern int init(argc, argv, envp)
                    130:        /*ARGSUSED*/
                    131:        int argc;
                    132:        char **argv;
                    133:        char **envp;
                    134: {
1.12      mpech     135:        int i;
                    136:        char *cp;
1.1       dm        137:
1.13      millert   138: #ifdef SIGSEGV_CHECK
1.1       dm        139:        if (!isserver)
                    140:                (void) signal(SIGSEGV, sighandler);
1.13      millert   141: #endif
1.1       dm        142:
                    143:        setprogname(argv);
                    144:
                    145:        /*
                    146:         * Save a copy of our argc and argv before setargs() overwrites them
                    147:         */
                    148:        realargc = argc;
                    149:        realargv = (char **) xmalloc(sizeof(char *) * (argc+1));
                    150:        for (i = 0; i < argc; i++)
1.8       millert   151:                realargv[i] = xstrdup(argv[i]);
1.1       dm        152:
1.6       millert   153: #if    defined(SETARGS)
1.1       dm        154:        setargs_settup(argc, argv, envp);
                    155: #endif /* SETARGS */
                    156:
                    157:        pw = getpwuid(userid = getuid());
                    158:        if (pw == NULL) {
1.16      deraadt   159:                error("Your user id (%u) is not known to this system.",
1.1       dm        160:                      getuid());
                    161:                return(-1);
                    162:        }
                    163:
                    164:        debugmsg(DM_MISC, "UserID = %d pwname = '%s' home = '%s'\n",
                    165:                 userid, pw->pw_name, pw->pw_dir);
1.8       millert   166:        homedir = xstrdup(pw->pw_dir);
                    167:        locuser = xstrdup(pw->pw_name);
1.1       dm        168:        groupid = pw->pw_gid;
                    169:        gethostname(host, sizeof(host));
                    170:        if ((cp = strchr(host, '.')) != NULL)
                    171:                *cp = CNULL;
                    172:
                    173:        /*
                    174:         * If we're not root, disable paranoid ownership checks
                    175:         * since normal users cannot chown() files.
                    176:         */
                    177:        if (!isserver && userid != 0) {
                    178:                FLAG_ON(options, DO_NOCHKOWNER);
                    179:                FLAG_ON(options, DO_NOCHKGROUP);
                    180:        }
                    181:
                    182:        return(0);
                    183: }
                    184:
                    185: /*
                    186:  * Finish things up before ending.
                    187:  */
                    188: extern void finish()
                    189: {
                    190:        extern jmp_buf finish_jmpbuf;
                    191:
                    192:        debugmsg(DM_CALL,
                    193:                 "finish() called: do_fork = %d amchild = %d isserver = %d",
                    194:                 do_fork, amchild, isserver);
                    195:        cleanup();
                    196:
                    197:        /*
                    198:         * There's no valid finish_jmpbuf for the rdist master parent.
                    199:         */
                    200:        if (!do_fork || amchild || isserver) {
1.2       dm        201:
                    202:                if (!setjmp_ok) {
                    203: #ifdef DEBUG_SETJMP
                    204:                        error("attemping longjmp() without target");
                    205:                        abort();
                    206: #else
                    207:                        exit(1);
                    208: #endif
                    209:                }
                    210:
1.1       dm        211:                longjmp(finish_jmpbuf, 1);
                    212:                /*NOTREACHED*/
                    213:                error("Unexpected failure of longjmp() in finish()");
                    214:                exit(2);
                    215:        } else
                    216:                exit(1);
                    217: }
                    218:
                    219: /*
                    220:  * Handle lost connections
                    221:  */
                    222: extern void lostconn()
                    223: {
                    224:        /* Prevent looping */
                    225:        (void) signal(SIGPIPE, SIG_IGN);
                    226:
                    227:        rem_r = rem_w = -1;     /* Ensure we don't try to send to server */
                    228:        checkhostname();
                    229:        error("Lost connection to %s",
                    230:              (currenthost) ? currenthost : "(unknown)");
                    231:
                    232:        finish();
                    233: }
                    234:
1.13      millert   235: #ifdef SIGSEGV_CHECK
1.1       dm        236: /*
                    237:  * Do a core dump
                    238:  */
                    239: extern void coredump()
                    240: {
1.15      mpech     241:        error("Segmentation violation - dumping core [PID = %ld, %s]",
                    242:              (long)getpid(),
1.1       dm        243:              (isserver) ? "isserver" : ((amchild) ? "amchild" : "parent"));
                    244:        abort();
                    245:        /*NOTREACHED*/
                    246:        fatalerr("Abort failed - no core dump.  Exiting...");
                    247: }
1.13      millert   248: #endif
1.1       dm        249:
                    250: /*
                    251:  * General signal handler
                    252:  */
                    253: extern void sighandler(sig)
                    254:        int sig;
                    255: {
1.7       millert   256:        int save_errno = errno;
                    257:
1.1       dm        258:        debugmsg(DM_CALL, "sighandler() received signal %d\n", sig);
                    259:
                    260:        switch (sig) {
                    261:        case SIGALRM:
                    262:                contimedout = TRUE;
                    263:                checkhostname();
                    264:                error("Response time out");
                    265:                finish();
                    266:                break;
                    267:
                    268:        case SIGPIPE:
                    269:                lostconn();
                    270:                break;
                    271:
                    272:        case SIGFPE:
                    273:                debug = !debug;
                    274:                break;
                    275:
1.13      millert   276: #ifdef SIGSEGV_CHECK
1.1       dm        277:        case SIGSEGV:
                    278:                coredump();
                    279:                break;
1.13      millert   280: #endif
1.1       dm        281:
                    282:        case SIGHUP:
                    283:        case SIGINT:
                    284:        case SIGQUIT:
                    285:        case SIGTERM:
                    286:                finish();
                    287:                break;
                    288:
                    289:        default:
                    290:                fatalerr("No signal handler defined for signal %d.", sig);
                    291:        }
1.7       millert   292:        errno = save_errno;
1.1       dm        293: }
                    294:
                    295: /*
                    296:  * Function to actually send the command char and message to the
                    297:  * remote host.
                    298:  */
1.18      millert   299: static int sendcmdmsg(cmd, msg, msgsize)
1.1       dm        300:        char cmd;
                    301:        char *msg;
1.18      millert   302:        size_t msgsize;
1.1       dm        303: {
                    304:        int len;
                    305:
                    306:        if (rem_w < 0)
                    307:                return(-1);
                    308:
                    309:        /*
                    310:         * All commands except C_NONE should have a newline
                    311:         */
                    312:        if (cmd != C_NONE && !strchr(msg + 1, '\n'))
1.18      millert   313:                (void) strlcat(msg + 1, "\n", msgsize - 1);
1.1       dm        314:
                    315:        if (cmd == C_NONE)
                    316:                len = strlen(msg);
                    317:        else {
                    318:                len = strlen(msg + 1) + 1;
                    319:                msg[0] = cmd;
                    320:        }
                    321:
                    322:        debugmsg(DM_PROTO, ">>> Cmd = %c (\\%3.3o) Msg = \"%.*s\"",
                    323:                 cmd, cmd,
                    324:                 (cmd == C_NONE) ? len-1 : len-2,
                    325:                 (cmd == C_NONE) ? msg : msg + 1);
                    326:
                    327:        return(!(xwrite(rem_w, msg, len) == len));
                    328: }
                    329:
                    330: /*
                    331:  * Send a command message to the remote host.
                    332:  * Called as sendcmd(char cmdchar, char *fmt, arg1, arg2, ...)
                    333:  * The fmt and arg? arguments are optional.
                    334:  */
                    335: #if    defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG
                    336: /*
                    337:  * Stdarg frontend to sendcmdmsg()
                    338:  */
                    339: extern int sendcmd(char cmd, char *fmt, ...)
                    340: {
                    341:        static char buf[BUFSIZ];
                    342:        va_list args;
                    343:
                    344:        va_start(args, fmt);
                    345:        if (fmt)
1.18      millert   346:                (void) vsnprintf(buf + (cmd != C_NONE),
                    347:                    sizeof(buf) - (cmd != C_NONE), fmt, args);
1.1       dm        348:        else
                    349:                buf[1] = CNULL;
                    350:        va_end(args);
                    351:
1.18      millert   352:        return(sendcmdmsg(cmd, buf, sizeof(buf)));
1.1       dm        353: }
                    354: #endif /* ARG_TYPE == ARG_STDARG */
                    355:
                    356: #if    defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS
                    357: /*
                    358:  * Varargs frontend to sendcmdmsg()
                    359:  */
                    360: extern int sendcmd(va_alist)
                    361:        va_dcl
                    362: {
                    363:        static char buf[BUFSIZ];
                    364:        va_list args;
                    365:        char cmd;
                    366:        char *fmt;
                    367:
                    368:        va_start(args);
                    369:        /* XXX The "int" is necessary as a workaround for broken varargs */
                    370:        cmd = (char) va_arg(args, int);
                    371:        fmt = va_arg(args, char *);
                    372:        if (fmt)
1.18      millert   373:                (void) vsnprintf(buf + (cmd != C_NONE),
                    374:                    sizeof(buf) - (cmd != C_NONE), fmt, args);
1.1       dm        375:        else
                    376:                buf[1] = CNULL;
                    377:        va_end(args);
                    378:
1.18      millert   379:        return(sendcmdmsg(cmd, buf, sizeof(buf)));
1.1       dm        380: }
                    381: #endif /* ARG_TYPE == ARG_VARARGS */
                    382:
                    383: #if    !defined(ARG_TYPE)
                    384: /*
                    385:  * Stupid frontend to sendcmdmsg()
                    386:  */
                    387: /*VARARGS2*/
                    388: extern int sendcmd(cmd, fmt, a1, a2, a3, a4, a5, a6, a7, a8)
                    389:        char cmd;
                    390:        char *fmt;
                    391: {
                    392:        static char buf[BUFSIZ];
                    393:
                    394:        if (fmt)
1.18      millert   395:                (void) snprintf(buf + (cmd != C_NONE),
                    396:                    sizeof(buf) - (cmd != C_NONE),
                    397:                    fmt, a1, a2, a3, a4, a5, a6, a7, a8);
1.1       dm        398:        else
                    399:                buf[1] = CNULL;
                    400:
1.18      millert   401:        return(sendcmdmsg(cmd, buf, sizeof(buf)));
1.1       dm        402: }
                    403: #endif /* !ARG_TYPE */
                    404:
                    405: /*
                    406:  * Internal variables and routines for reading lines from the remote.
                    407:  */
                    408: static u_char rembuf[BUFSIZ];
                    409: static u_char *remptr;
                    410: static int remleft;
                    411:
                    412: #define remc() (--remleft < 0 ? remmore() : *remptr++)
                    413:
                    414: /*
                    415:  * Back end to remote read()
                    416:  */
                    417: static int remread(fd, buf, bufsiz)
                    418:        int fd;
                    419:        u_char *buf;
                    420:        int bufsiz;
                    421: {
                    422:        return(read(fd, (char *)buf, bufsiz));
                    423: }
                    424:
                    425: static int remmore()
                    426: {
                    427:        (void) signal(SIGALRM, sighandler);
                    428:        (void) alarm(rtimeout);
                    429:
                    430:        remleft = remread(rem_r, rembuf, sizeof(rembuf));
                    431:
                    432:        (void) alarm(0);
                    433:
                    434:        if (remleft < 0)
                    435:                return (-2);    /* error */
                    436:        if (remleft == 0)
                    437:                return (-1);    /* EOF */
                    438:        remptr = rembuf;
                    439:        remleft--;
                    440:        return (*remptr++);
                    441: }
                    442:
                    443: /*
                    444:  * Read an input line from the remote.  Return the number of bytes
                    445:  * stored (equivalent to strlen(p)).  If `cleanup' is set, EOF at
                    446:  * the beginning of a line is returned as EOF (-1); other EOFs, or
                    447:  * errors, call cleanup() or lostconn().  In other words, unless
                    448:  * the third argument is nonzero, this routine never returns failure.
                    449:  */
                    450: extern int remline(buffer, space, doclean)
1.12      mpech     451:        u_char *buffer;
1.1       dm        452:        int space;
                    453:        int doclean;
                    454: {
1.12      mpech     455:        int c, left = space;
                    456:        u_char *p = buffer;
1.1       dm        457:
                    458:        if (rem_r < 0) {
                    459:                error("Cannot read remote input: Remote descriptor not open.");
                    460:                return(-1);
                    461:        }
                    462:
                    463:        while (left > 0) {
                    464:                if ((c = remc()) < -1) {        /* error */
                    465:                        if (doclean) {
                    466:                                finish();
                    467:                                /*NOTREACHED*/
                    468:                        }
                    469:                        lostconn();
                    470:                        /*NOTREACHED*/
                    471:                }
                    472:                if (c == -1) {                  /* got EOF */
                    473:                        if (doclean) {
                    474:                                if (left == space)
                    475:                                        return (-1);/* signal proper EOF */
                    476:                                finish();       /* improper EOF */
                    477:                                /*NOTREACHED*/
                    478:                        }
                    479:                        lostconn();
                    480:                        /*NOTREACHED*/
                    481:                }
                    482:                if (c == '\n') {
                    483:                        *p = CNULL;
                    484:
                    485:                        if (debug) {
                    486:                                static char mbuf[BUFSIZ];
                    487:
1.17      deraadt   488:                                (void) snprintf(mbuf, sizeof mbuf,
1.1       dm        489:                                        "<<< Cmd = %c (\\%3.3o) Msg = \"%s\"",
                    490:                                               buffer[0], buffer[0],
                    491:                                               buffer + 1);
                    492:
                    493:                                debugmsg(DM_PROTO, "%s", mbuf);
                    494:                        }
                    495:
                    496:                        return (space - left);
                    497:                }
                    498:                *p++ = c;
                    499:                left--;
                    500:        }
                    501:
                    502:        /* this will probably blow the entire session */
                    503:        error("remote input line too long");
                    504:        p[-1] = CNULL;          /* truncate */
                    505:        return (space);
                    506: }
                    507:
                    508: /*
                    509:  * Non-line-oriented remote read.
                    510:  */
1.6       millert   511: int
1.1       dm        512: readrem(p, space)
                    513:        char *p;
1.12      mpech     514:        int space;
1.1       dm        515: {
                    516:        if (remleft <= 0) {
                    517:                /*
                    518:                 * Set remote time out alarm.
                    519:                 */
                    520:                (void) signal(SIGALRM, sighandler);
                    521:                (void) alarm(rtimeout);
                    522:
                    523:                remleft = remread(rem_r, rembuf, sizeof(rembuf));
                    524:
                    525:                (void) alarm(0);
                    526:                remptr = rembuf;
                    527:        }
                    528:
                    529:        if (remleft <= 0)
                    530:                return (remleft);
                    531:        if (remleft < space)
                    532:                space = remleft;
                    533:
                    534:        bcopy((char *) remptr, p, space);
                    535:
                    536:        remptr += space;
                    537:        remleft -= space;
                    538:
                    539:        return (space);
                    540: }
                    541:
                    542: /*
                    543:  * Get the user name for the uid.
                    544:  */
                    545: extern char *getusername(uid, file, opts)
                    546:        UID_T uid;
                    547:        char *file;
                    548:        opt_t opts;
                    549: {
                    550:        static char buf[100];
                    551:        static UID_T lastuid = (UID_T)-1;
                    552:        struct passwd *pwd = NULL;
                    553:
                    554:        /*
                    555:         * The value of opts may have changed so we always
                    556:         * do the opts check.
                    557:         */
                    558:        if (IS_ON(opts, DO_NUMCHKOWNER)) {
1.17      deraadt   559:                (void) snprintf(buf, sizeof buf, ":%u", uid);
1.1       dm        560:                return(buf);
                    561:        }
                    562:
                    563:        /*
                    564:         * Try to avoid getpwuid() call.
                    565:         */
1.6       millert   566:        if (lastuid == uid && buf[0] != '\0' && buf[0] != ':')
1.1       dm        567:                return(buf);
                    568:
                    569:        lastuid = uid;
                    570:
                    571:        if ((pwd = getpwuid(uid)) == NULL) {
                    572:                message(MT_WARNING,
1.16      deraadt   573:                        "%s: No password entry for uid %u", file, uid);
1.17      deraadt   574:                (void) snprintf(buf, sizeof buf, ":%u", uid);
1.1       dm        575:        } else
1.17      deraadt   576:                (void) strlcpy(buf, pwd->pw_name, sizeof buf);
1.1       dm        577:
                    578:        return(buf);
                    579: }
                    580:
                    581: /*
                    582:  * Get the group name for the gid.
                    583:  */
                    584: extern char *getgroupname(gid, file, opts)
                    585:        GID_T gid;
                    586:        char *file;
                    587:        opt_t opts;
                    588: {
                    589:        static char buf[100];
                    590:        static GID_T lastgid = (GID_T)-1;
                    591:        struct group *grp = NULL;
                    592:
                    593:        /*
                    594:         * The value of opts may have changed so we always
                    595:         * do the opts check.
                    596:         */
                    597:        if (IS_ON(opts, DO_NUMCHKGROUP)) {
1.17      deraadt   598:                (void) snprintf(buf, sizeof buf, ":%u", gid);
1.1       dm        599:                return(buf);
                    600:        }
                    601:
                    602:        /*
                    603:         * Try to avoid getgrgid() call.
                    604:         */
1.6       millert   605:        if (lastgid == gid && buf[0] != '\0' && buf[0] != ':')
1.1       dm        606:                return(buf);
                    607:
                    608:        lastgid = gid;
                    609:
                    610:        if ((grp = (struct group *)getgrgid(gid)) == NULL) {
1.16      deraadt   611:                message(MT_WARNING, "%s: No name for group %u", file, gid);
1.17      deraadt   612:                (void) snprintf(buf, sizeof buf, ":%u", gid);
1.1       dm        613:        } else
1.17      deraadt   614:                (void) strlcpy(buf, grp->gr_name, sizeof buf);
1.1       dm        615:
                    616:        return(buf);
                    617: }
                    618:
                    619: /*
                    620:  * Read a response from the remote host.
                    621:  */
                    622: extern int response()
                    623: {
                    624:        static u_char resp[BUFSIZ];
                    625:        u_char *s;
                    626:        int n;
                    627:
                    628:        debugmsg(DM_CALL, "response() start\n");
                    629:
                    630:        n = remline(s = resp, sizeof(resp), 0);
                    631:
                    632:        n--;
                    633:        switch (*s++) {
                    634:         case C_ACK:
                    635:                debugmsg(DM_PROTO, "received ACK\n");
                    636:                return(0);
                    637:        case C_LOGMSG:
                    638:                if (n > 0) {
                    639:                        message(MT_CHANGE, "%s", s);
                    640:                        return(1);
                    641:                }
                    642:                debugmsg(DM_PROTO, "received EMPTY logmsg\n");
                    643:                return(0);
                    644:        case C_NOTEMSG:
                    645:                if (s)
                    646:                        message(MT_NOTICE, "%s", s);
                    647:                return(response());
                    648:
                    649:        default:
                    650:                s--;
                    651:                n++;
                    652:                /* fall into... */
                    653:
                    654:        case C_ERRMSG:  /* Normal error message */
                    655:                if (s)
                    656:                        message(MT_NERROR, "%s", s);
                    657:                return(-1);
                    658:
                    659:        case C_FERRMSG: /* Fatal error message */
                    660:                if (s)
                    661:                        message(MT_FERROR, "%s", s);
                    662:                finish();
                    663:        }
                    664:        /*NOTREACHED*/
                    665: }
                    666:
                    667: /*
                    668:  * This should be in expand.c but the other routines call other modules
                    669:  * that we don't want to load in.
                    670:  *
                    671:  * Expand file names beginning with `~' into the
                    672:  * user's home directory path name. Return a pointer in buf to the
                    673:  * part corresponding to `file'.
                    674:  */
1.18      millert   675: extern char *exptilde(ebuf, file, ebufsize)
1.1       dm        676:        char *ebuf;
1.18      millert   677:        size_t ebufsize;
1.12      mpech     678:        char *file;
1.1       dm        679: {
1.18      millert   680:        char *pw_dir, *rest;
                    681:        size_t len;
1.1       dm        682:        extern char *homedir;
                    683:
                    684:        if (*file != '~') {
1.18      millert   685: notilde:
                    686:                (void) strlcpy(ebuf, file, ebufsize);
1.1       dm        687:                return(ebuf);
                    688:        }
                    689:        if (*++file == CNULL) {
1.18      millert   690:                pw_dir = homedir;
                    691:                rest = NULL;
1.1       dm        692:        } else if (*file == '/') {
1.18      millert   693:                pw_dir = homedir;
                    694:                rest = file;
1.1       dm        695:        } else {
1.18      millert   696:                rest = file;
                    697:                while (*rest && *rest != '/')
                    698:                        rest++;
                    699:                if (*rest == '/')
                    700:                        *rest = CNULL;
1.1       dm        701:                else
1.18      millert   702:                        rest = NULL;
1.1       dm        703:                if (pw == NULL || strcmp(pw->pw_name, file) != 0) {
                    704:                        if ((pw = getpwnam(file)) == NULL) {
                    705:                                error("%s: unknown user name", file);
1.18      millert   706:                                if (rest != NULL)
                    707:                                        *rest = '/';
1.1       dm        708:                                return(NULL);
                    709:                        }
                    710:                }
1.18      millert   711:                if (rest != NULL)
                    712:                        *rest = '/';
                    713:                pw_dir = pw->pw_dir;
                    714:        }
                    715:        if ((len = strlcpy(ebuf, pw_dir, ebufsize)) >= ebufsize)
                    716:                goto notilde;
                    717:        pw_dir = ebuf + len;
                    718:        if (rest != NULL) {
                    719:                pw_dir++;
                    720:                if ((len = strlcat(ebuf, rest, ebufsize)) >= ebufsize)
                    721:                        goto notilde;
1.1       dm        722:        }
1.18      millert   723:        return(pw_dir);
1.1       dm        724: }
                    725:
                    726: #if    defined(DIRECT_RCMD)
                    727: /*
                    728:  * Set our effective user id to the user running us.
                    729:  * This should be the uid we do most of our work as.
                    730:  */
                    731: extern int becomeuser()
                    732: {
                    733:        int r = 0;
                    734:
                    735: #if    defined(HAVE_SAVED_IDS)
                    736:        r = seteuid(userid);
                    737: #else
                    738:        r = setreuid(0, userid);
                    739: #endif /* HAVE_SAVED_IDS */
                    740:
                    741:        if (r < 0)
1.16      deraadt   742:                error("becomeuser %d failed: %s (ruid = %u euid = %u)",
1.1       dm        743:                      userid, SYSERR, getuid(), geteuid());
                    744:
                    745:        return(r);
                    746: }
                    747: #endif /* DIRECT_RCMD */
                    748:
                    749: #if    defined(DIRECT_RCMD)
                    750: /*
                    751:  * Set our effective user id to "root" (uid = 0)
                    752:  */
                    753: extern int becomeroot()
                    754: {
                    755:        int r = 0;
                    756:
                    757: #if    defined(HAVE_SAVED_IDS)
                    758:        r = seteuid(0);
                    759: #else
                    760:        r = setreuid(userid, 0);
                    761: #endif /* HAVE_SAVED_IDS */
                    762:
                    763:        if (r < 0)
1.16      deraadt   764:                error("becomeroot failed: %s (ruid = %u euid = %u)",
1.1       dm        765:                      SYSERR, getuid(), geteuid());
                    766:
                    767:        return(r);
                    768: }
                    769: #endif /* DIRECT_RCMD */
                    770:
                    771: /*
                    772:  * Set access and modify times of a given file
                    773:  */
                    774: extern int setfiletime(file, atime, mtime)
                    775:        char *file;
                    776:        time_t atime;
                    777:        time_t mtime;
                    778: {
                    779: #if    SETFTIME_TYPE == SETFTIME_UTIMES
                    780:        struct timeval tv[2];
                    781:
                    782:        if (atime != 0 && mtime != 0) {
                    783:                tv[0].tv_sec = atime;
                    784:                tv[1].tv_sec = mtime;
                    785:                tv[0].tv_usec = tv[1].tv_usec = (time_t) 0;
                    786:                return(utimes(file, tv));
                    787:        } else  /* Set to current time */
1.6       millert   788:                return(utimes(file, NULL));
1.1       dm        789:
                    790: #endif /* SETFTIME_UTIMES */
                    791:
                    792: #if    SETFTIME_TYPE == SETFTIME_UTIME
                    793:        struct utimbuf utbuf;
                    794:
                    795:        if (atime != 0 && mtime != 0) {
                    796:                utbuf.actime = atime;
                    797:                utbuf.modtime = mtime;
                    798:                return(utime(file, &utbuf));
                    799:        } else  /* Set to current time */
1.6       millert   800:                return(utime(file, NULL));
1.1       dm        801: #endif /* SETFTIME_UTIME */
                    802:
                    803: #if    !defined(SETFTIME_TYPE)
                    804:        There is no "SETFTIME_TYPE" defined!
                    805: #endif /* SETFTIME_TYPE */
                    806: }
                    807:
                    808: /*
                    809:  * Get version info
                    810:  */
                    811: extern char *getversion()
                    812: {
                    813:        static char buff[BUFSIZ];
                    814:
1.17      deraadt   815:        (void) snprintf(buff, sizeof buff,
1.1       dm        816:        "Version %s.%d (%s) - Protocol Version %d, Release %s, Patch level %d",
                    817:                       DISTVERSION, PATCHLEVEL, DISTSTATUS,
                    818:                       VERSION, DISTVERSION, PATCHLEVEL);
                    819:
                    820:        return(buff);
                    821: }
                    822:
                    823: /*
                    824:  * Execute a shell command to handle special cases.
                    825:  * This is now common to both server and client
                    826:  */
                    827: void runcommand(cmd)
                    828:        char *cmd;
                    829: {
1.15      mpech     830:        int fd[2];
1.1       dm        831:        int status;
1.12      mpech     832:        char *cp, *s;
1.1       dm        833:        char sbuf[BUFSIZ], buf[BUFSIZ];
1.15      mpech     834:        pid_t pid, i;
                    835:
1.1       dm        836:        if (pipe(fd) < 0) {
                    837:                error("pipe of %s failed: %s", cmd, SYSERR);
                    838:                return;
                    839:        }
                    840:
                    841:        if ((pid = fork()) == 0) {
                    842:                /*
                    843:                 * Return everything the shell commands print.
                    844:                 */
                    845:                (void) close(0);
                    846:                (void) close(1);
                    847:                (void) close(2);
                    848:                (void) open(_PATH_DEVNULL, O_RDONLY);
                    849:                (void) dup(fd[PIPE_WRITE]);
                    850:                (void) dup(fd[PIPE_WRITE]);
                    851:                (void) close(fd[PIPE_READ]);
                    852:                (void) close(fd[PIPE_WRITE]);
1.11      deraadt   853:                (void) execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL);
1.1       dm        854:                _exit(127);
                    855:        }
                    856:        (void) close(fd[PIPE_WRITE]);
                    857:        s = sbuf;
                    858:        *s++ = C_LOGMSG;
                    859:        while ((i = read(fd[PIPE_READ], buf, sizeof(buf))) > 0) {
                    860:                cp = buf;
                    861:                do {
                    862:                        *s++ = *cp++;
                    863:                        if (cp[-1] != '\n') {
                    864:                                if (s < (char *) &sbuf[sizeof(sbuf)-1])
                    865:                                        continue;
                    866:                                *s++ = '\n';
                    867:                        }
                    868:                        /*
                    869:                         * Throw away blank lines.
                    870:                         */
                    871:                        if (s == &sbuf[2]) {
                    872:                                s--;
                    873:                                continue;
                    874:                        }
                    875:                        if (isserver)
                    876:                                (void) xwrite(rem_w, sbuf, s - sbuf);
                    877:                        else {
                    878:                                *s = CNULL;
                    879:                                message(MT_INFO, "%s", sbuf+1);
                    880:                        }
                    881:                        s = &sbuf[1];
                    882:                } while (--i);
                    883:        }
                    884:        if (s > (char *) &sbuf[1]) {
                    885:                *s++ = '\n';
                    886:                if (isserver)
                    887:                        (void) xwrite(rem_w, sbuf, s - sbuf);
                    888:                else {
                    889:                        *s = CNULL;
                    890:                        message(MT_INFO, "%s", sbuf+1);
                    891:                }
                    892:        }
                    893:        while ((i = wait(&status)) != pid && i != -1)
                    894:                ;
                    895:        if (i == -1)
                    896:                status = -1;
                    897:        (void) close(fd[PIPE_READ]);
                    898:        if (status)
                    899:                error("shell returned %d", status);
                    900:        else if (isserver)
                    901:                ack();
                    902: }
                    903:
                    904: /*
                    905:  * Malloc with error checking
                    906:  */
                    907: char *xmalloc(amt)
                    908:        int amt;
                    909: {
                    910:        char *ptr;
                    911:        extern POINTER *malloc();
                    912:
                    913:        if ((ptr = (char *)malloc(amt)) == NULL)
                    914:                fatalerr("Cannot malloc %d bytes of memory.", amt);
                    915:
                    916:        return(ptr);
                    917: }
                    918:
                    919: /*
                    920:  * realloc with error checking
                    921:  */
                    922: char *xrealloc(baseptr, amt)
                    923:        char *baseptr;
                    924:        unsigned int amt;
                    925: {
                    926:        char *new;
                    927:        extern POINTER *realloc();
                    928:
                    929:        if ((new = (char *)realloc(baseptr, amt)) == NULL)
                    930:                fatalerr("Cannot realloc %d bytes of memory.", amt);
                    931:
                    932:        return(new);
                    933: }
                    934:
                    935: /*
                    936:  * calloc with error checking
                    937:  */
                    938: char *xcalloc(num, esize)
1.14      deraadt   939:        unsigned int num;
                    940:        unsigned int esize;
1.1       dm        941: {
                    942:        char *ptr;
                    943:        extern POINTER *calloc();
                    944:
                    945:        if ((ptr = (char *)calloc(num, esize)) == NULL)
                    946:                fatalerr("Cannot calloc %d * %d = %d bytes of memory.",
                    947:                      num, esize, num * esize);
                    948:
                    949:        return(ptr);
1.8       millert   950: }
                    951:
                    952: /*
                    953:  * Strdup with error checking
                    954:  */
                    955: char *xstrdup(str)
                    956:        char *str;
                    957: {
                    958:        char *nstr;
                    959:
                    960:        if ((nstr = strdup(str)) == NULL)
1.9       aaron     961:                fatalerr("Cannot malloc %d bytes of memory.", strlen(str) + 1);
1.8       millert   962:
                    963:        return(nstr);
1.1       dm        964: }
                    965:
                    966: /*
                    967:  * Private version of basename()
                    968:  */
                    969: extern char *xbasename(path)
                    970:        char *path;
                    971: {
1.12      mpech     972:        char *cp;
1.1       dm        973:
1.6       millert   974:        if ((cp = strrchr(path, '/')))
1.1       dm        975:                return(cp+1);
                    976:        else
                    977:                return(path);
                    978: }
                    979:
                    980: /*
1.10      provos    981:  * Take a colon (':') separated path to a file and
1.1       dm        982:  * search until a component of that path is found and
                    983:  * return the found file name.
                    984:  */
                    985: extern char *searchpath(path)
                    986:        char *path;
                    987: {
1.12      mpech     988:        char *file;
1.19    ! millert   989:        char *space;
        !           990:        int found;
1.1       dm        991:        struct stat statbuf;
                    992:
1.19    ! millert   993:        for (found = 0; !found && (file = strsep(&path, ":")) != NULL; ) {
        !           994:                if ((space = strchr(file, ' ')) != NULL)
        !           995:                        *space = CNULL;
        !           996:                found = stat(file, &statbuf) == 0;
        !           997:                if (space)
        !           998:                        *space = ' ';           /* Put back what we zapped */
1.1       dm        999:        }
1.19    ! millert  1000:        return (file);
1.1       dm       1001: }
                   1002:
                   1003: /*
                   1004:  * Set line buffering.
                   1005:  */
1.6       millert  1006: extern void
1.1       dm       1007: mysetlinebuf(fp)
                   1008:        FILE *fp;
                   1009: {
                   1010: #if    SETBUF_TYPE == SETBUF_SETLINEBUF
1.6       millert  1011:        setlinebuf(fp);
1.1       dm       1012: #endif /* SETBUF_SETLINEBUF */
                   1013: #if    SETBUF_TYPE == SETBUF_SETVBUF
1.6       millert  1014:        setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1.1       dm       1015: #endif /* SETBUF_SETVBUF */
                   1016: #if    !defined(SETBUF_TYPE)
                   1017:        No SETBUF_TYPE is defined!
                   1018: #endif /* SETBUF_TYPE */
                   1019: }
                   1020:
                   1021: /*
                   1022:  * Our interface to system call to get a socket pair.
                   1023:  */
                   1024: int
                   1025: getsocketpair(domain, type, protocol, sv)
                   1026:        int domain;
                   1027:        int type;
                   1028:        int protocol;
                   1029:        int sv[];
                   1030: {
                   1031: #if    SOCKPAIR_TYPE == SOCKPAIR_SOCKETPAIR
                   1032:        return(socketpair(domain, type, protocol, sv));
                   1033: #endif /* SOCKPAIR_SOCKETPAIR */
                   1034: #if    SOCKPAIR_TYPE == SOCKPAIR_SPIPE
                   1035:        return(spipe(sv));
                   1036: #endif /* SOCKPAIR_SPIPE */
                   1037: #if    !defined(SOCKPAIR_TYPE)
                   1038:        No SOCKPAIR_TYPE is defined!
                   1039: #endif /* SOCKPAIR_TYPE */
                   1040: }