Annotation of 43BSDReno/contrib/mh/support/pop/popser.c, revision 1.1

1.1     ! root        1: /* popser.c - the POP service */
        !             2: 
        !             3: #include "../h/mh.h"
        !             4: #include "../h/dropsbr.h"
        !             5: #include "../zotnet/bboards.h"
        !             6: #include <stdio.h>
        !             7: #include "../zotnet/mts.h"
        !             8: #include <ctype.h>
        !             9: #include <errno.h>
        !            10: #include <pwd.h>
        !            11: #include <signal.h>
        !            12: #include <syslog.h>
        !            13: #include <sys/types.h>
        !            14: #include <sys/stat.h>
        !            15: 
        !            16: 
        !            17: #define        TRUE    1
        !            18: #define        FALSE   0
        !            19: 
        !            20: #define        NVEC    4
        !            21: 
        !            22: /*  */
        !            23: 
        !            24: extern int  errno;
        !            25: 
        !            26: extern int  debug;
        !            27: extern char myhost[];
        !            28: extern char *myname;
        !            29: 
        !            30: static enum state {
        !            31:     auth1, auth2, trans, update, halt, error
        !            32: } mystate;
        !            33: 
        !            34: 
        !            35: int     user (), pass ();
        !            36: #ifdef RPOP
        !            37: int    rpop ();
        !            38: #endif RPOP
        !            39: int     status (), list (), retrieve (), delete (), reset ();
        !            40: int    top ();
        !            41: #ifdef BPOP
        !            42: int    xtnd ();
        !            43: #endif BPOP
        !            44: int     quit ();
        !            45: 
        !            46: static struct vector {
        !            47:     char   *v_cmd;
        !            48:     int     v_min, v_max;
        !            49:     int     (*v_vec) ();
        !            50:     enum state v_valid;
        !            51:     enum state v_win, v_lose;
        !            52: }               vectors[] = {
        !            53:     "user", 1, 1, user, auth1, auth2, auth1,
        !            54:     "pass", 1, 1, pass, auth2, trans, auth1,
        !            55: #ifdef RPOP
        !            56:     "rpop", 1, 1, rpop, auth2, trans, auth1,
        !            57: #endif RPOP
        !            58:     "quit", 0, 0, NULL, auth1, halt, halt,
        !            59:     "quit", 0, 0, NULL, auth2, halt, halt,
        !            60: 
        !            61:     "stat", 0, 0, status, trans, trans, trans,
        !            62:     "list", 0, 1, list, trans, trans, trans,
        !            63:     "retr", 1, 1, retrieve, trans, trans, trans,
        !            64:     "dele", 1, 1, delete, trans, trans, trans,
        !            65:     "noop", 0, 0, NULL, trans, trans, trans,
        !            66:     "rset", 0, 0, reset, trans, trans, trans,
        !            67: 
        !            68:     "top",  2, 2, top,  trans, trans, trans,
        !            69: #ifdef BPOP
        !            70:     "xtnd", 1, 2, xtnd, trans, trans, trans,
        !            71: #endif BPOP
        !            72: 
        !            73:     "quit", 0, 0, quit, trans, halt, halt,
        !            74: 
        !            75:     NULL
        !            76: };
        !            77: 
        !            78: struct vector  *getvector ();
        !            79: 
        !            80: /*  */
        !            81: 
        !            82: #ifdef DPOP
        !            83: static int pop_uid;
        !            84: static int pop_gid;
        !            85: #endif DPOP
        !            86: 
        !            87: static int  rproto;
        !            88: static char *hostname;
        !            89: static char server[BUFSIZ];
        !            90: 
        !            91: static char username[BUFSIZ];
        !            92: 
        !            93: static char maildrop[BUFSIZ];
        !            94: static int  mode;
        !            95: static time_t mtime;
        !            96: static FILE *dp;
        !            97: 
        !            98: #ifdef BPOP
        !            99: static int xtnded;
        !           100: 
        !           101: static int guest_uid;
        !           102: static int guest_gid;
        !           103: 
        !           104: static struct bboard *BBhead = NULL;
        !           105: static struct bboard *BBtail = NULL;
        !           106: 
        !           107: static long BBtime = 0L;
        !           108: 
        !           109: struct bboard *getbbaux ();
        !           110: #endif BPOP
        !           111: 
        !           112: 
        !           113: struct Msg {                   /* Msgs[0] contains info for entire maildrop */
        !           114:     struct drop m_drop;
        !           115: #define        m_id    m_drop.d_id
        !           116: #define        m_size  m_drop.d_size
        !           117: #define        m_start m_drop.d_start
        !           118: #define        m_stop  m_drop.d_stop
        !           119: 
        !           120:     unsigned    m_flags;
        !           121: #define        MNULL   0x00
        !           122: #define        MDELE   0x01
        !           123: #define        MREAD   0x02
        !           124: };
        !           125: 
        !           126: static int nMsgs = 0;
        !           127: static struct Msg *Msgs = NULL;
        !           128: 
        !           129: static int  nmsgs;
        !           130: static int  dmsgs;
        !           131: 
        !           132: 
        !           133: #define        TRM     "."
        !           134: #define        TRMLEN  (sizeof TRM - 1)
        !           135: #define        IAC     255
        !           136: 
        !           137: int    pipeser ();
        !           138: 
        !           139: FILE   *input;
        !           140: FILE   *output;
        !           141: 
        !           142: 
        !           143: void   padvise (), padios ();
        !           144: long   lseek ();
        !           145: char   *crypt ();
        !           146: 
        !           147: /*  */
        !           148: 
        !           149: popinit () {
        !           150: #ifdef BPOP
        !           151:     padvise (NULLCP, LOG_INFO, "initialize list of BBoards");
        !           152: 
        !           153:     BBhead = BBtail = NULL;
        !           154:     while (getbbaux (NULLCP))
        !           155:        continue;
        !           156: #endif BPOP
        !           157: }
        !           158: 
        !           159: popassert () {
        !           160: #ifdef BPOP
        !           161:     register char **p;
        !           162:     register struct bboard *bb,
        !           163:                            *bp;
        !           164: 
        !           165:     if (BBtime == getbbtime ())
        !           166:        return;
        !           167: 
        !           168:     padvise (NULLCP, LOG_INFO, "list of BBoards has changed");
        !           169: 
        !           170:     for (bb = BBhead; bb; bb = bp) {
        !           171:        bp = bb -> bb_next;
        !           172: 
        !           173:        if (bb -> bb_name)
        !           174:            free (bb -> bb_name);
        !           175:        if (bb -> bb_file)
        !           176:            free (bb -> bb_file);
        !           177:        if (bb -> bb_archive)
        !           178:            free (bb -> bb_archive);
        !           179:        if (bb -> bb_info)
        !           180:            free (bb -> bb_info);
        !           181:        if (bb -> bb_map)
        !           182:            free (bb -> bb_map);
        !           183:        if (bb -> bb_passwd)
        !           184:            free (bb -> bb_passwd);
        !           185:        if (bb -> bb_date)
        !           186:            free (bb -> bb_date);
        !           187:        if (bb -> bb_addr)
        !           188:            free (bb -> bb_addr);
        !           189:        if (bb -> bb_request)
        !           190:            free (bb -> bb_request);
        !           191:        if (bb -> bb_relay)
        !           192:            free (bb -> bb_relay);
        !           193: 
        !           194:        for (p = bb -> bb_aka; *p; p++)
        !           195:            free (*p);
        !           196:        free ((char *) bb -> bb_aka);
        !           197: 
        !           198:        for (p = bb -> bb_leader; *p; p++)
        !           199:            free (*p);
        !           200:        free ((char *) bb -> bb_leader);
        !           201: 
        !           202:        for (p = bb -> bb_dist; *p; p++)
        !           203:            free (*p);
        !           204:        free ((char *) bb -> bb_dist);
        !           205: 
        !           206:        free ((char *) bb);
        !           207:     }
        !           208: 
        !           209:     BBhead = BBtail = NULL;
        !           210:     while (getbbaux (NULLCP))
        !           211:        continue;
        !           212: #endif BPOP
        !           213: }
        !           214: 
        !           215: /*  */
        !           216: 
        !           217: pop (in, out, priv, rhost)
        !           218: int    in,
        !           219:        out,
        !           220:        priv;
        !           221: char   *rhost;
        !           222: {
        !           223:     char    buffer[BUFSIZ],
        !           224:            *vec[NVEC + 1];
        !           225: #if    defined (DPOP) || defined (BPOP)
        !           226:     register struct passwd *pw;
        !           227: #endif defined (DPOP) || defined (BPOP)
        !           228:     register struct vector *v;
        !           229: 
        !           230:     m_foil (NULLCP);
        !           231:     mts_init (myname);
        !           232: 
        !           233:     rproto = priv;
        !           234:     hostname = rhost;
        !           235:     (void) sprintf (server, "%s %s server", myhost, priv ? "RPOP" : "POP");
        !           236: 
        !           237:     if ((input = fdopen (in, "r")) == NULL
        !           238:            || (output = fdopen (out, "w")) == NULL) {/* you lose big */
        !           239:        (void) respond (NOTOK, "%s loses on initialization", server);
        !           240:        return;
        !           241:     }
        !           242:     (void) signal (SIGPIPE, pipeser);
        !           243: 
        !           244: #ifdef DPOP
        !           245:     if ((pw = getpwnam (POPUID)) == NULL || !setpwinfo (pw, POPDB, 1)) {
        !           246:        (void) respond (NOTOK, "%s loses on DB initialization -- %s",
        !           247:                    server, pw ? getbberr () : "POP user-id unknown");
        !           248:        return;
        !           249:     }
        !           250:     pop_uid = pw -> pw_uid;
        !           251:     pop_gid = pw -> pw_gid;
        !           252: #endif DPOP
        !           253: #ifdef BPOP
        !           254:     if ((pw = getpwnam (popbbuser)) && pw -> pw_uid) {
        !           255:        guest_uid = pw -> pw_uid;
        !           256:        guest_gid = pw -> pw_gid;
        !           257:     }
        !           258:     else
        !           259:        guest_uid = guest_gid = 0;
        !           260: #endif BPOP
        !           261: 
        !           262:     (void) respond (OK, "%s ready (Comments to: PostMaster@%s)",
        !           263:            server, myhost);
        !           264: 
        !           265:     for (mystate = auth1; mystate != halt && mystate != error;)
        !           266:        switch (getline (buffer, sizeof buffer, input)) {
        !           267:            case OK: 
        !           268:                if ((v = getvector (buffer, vec)) == NULL)
        !           269:                    continue;
        !           270:                mystate = (v -> v_vec ? (v -> v_vec) (vec)
        !           271:                        : respond (OK, NULLCP)) == OK
        !           272:                    ? v -> v_win
        !           273:                    : v -> v_lose;
        !           274:                break;
        !           275: 
        !           276:            case NOTOK: 
        !           277:            case DONE: 
        !           278:                mystate = error;
        !           279:                (void) respond (NOTOK, "%s signing off", server);
        !           280:                break;
        !           281:        }
        !           282: }
        !           283: 
        !           284: /*  */
        !           285: 
        !           286: static int  user (vec)
        !           287: register char  **vec;
        !           288: {
        !           289:     make_lower (username, vec[1]);
        !           290: 
        !           291:     return respond (OK, "password required for %s", username);
        !           292: }
        !           293: 
        !           294: /*  */
        !           295: 
        !           296: static int  pass (vec)
        !           297: register char  **vec;
        !           298: {
        !           299:     int        guest = 0;
        !           300: #ifndef        DPOP
        !           301:     register struct passwd *pw;
        !           302: #else  DPOP
        !           303:     register struct bboard *pw;
        !           304: #endif DPOP
        !           305: 
        !           306: #ifndef        DPOP
        !           307: #ifdef BPOP
        !           308:     if (isguest ()) {
        !           309: #ifdef TRUSTED
        !           310:        static passwd gw;
        !           311: 
        !           312:        gw.pw_name = popbbuser;
        !           313:        gw.pw_uid = guest_uid;
        !           314:        pw = &gw;
        !           315: #endif TRUSTED
        !           316:        guest = 1;
        !           317:        goto anonymous;
        !           318:     }
        !           319: #endif BPOP
        !           320:     if ((pw = getpwnam (username)) == NULL
        !           321:            || *pw -> pw_passwd == NULL
        !           322:            || strcmp (crypt (vec[1], pw -> pw_passwd), pw -> pw_passwd)) {
        !           323: #ifdef TRUSTED
        !           324:        trusted (0, hostname, NULLCP, 0, pw ? pw -> pw_name : username,
        !           325:            pw && pw -> pw_uid == 0, "pop", "tcp", NULL);
        !           326: #endif TRUSTED
        !           327:        return respond (NOTOK, "login incorrect");
        !           328:     }
        !           329: #else  DPOP
        !           330: #ifdef BPOP
        !           331:     if (isguest ()) {
        !           332: #ifdef TRUSTED
        !           333:        static bboard gw;
        !           334: 
        !           335:        gw.bb_name = popbbuser;
        !           336:        pw = &gw;
        !           337: #endif TRUSTED
        !           338:        guest = 1;
        !           339:        goto anonymous;
        !           340:     }
        !           341: #endif BPOP
        !           342:     if (((pw = getbbnam (username)) == NULL
        !           343:                && (pw = getbbaka (username)) == NULL)
        !           344:            || *pw -> bb_passwd == NULL
        !           345:            || strcmp (crypt (vec[1], pw -> bb_passwd), pw -> bb_passwd)) {
        !           346: #ifdef TRUSTED
        !           347:        trusted (0, hostname, NULLCP, 0, pw ? pw -> bb_name : username,
        !           348:            0, "pop", "tcp", NULL);
        !           349: #endif TRUSTED
        !           350:        return respond (NOTOK, "login incorrect");
        !           351:     }
        !           352: #endif DPOP
        !           353: 
        !           354: #ifdef BPOP
        !           355: anonymous: ;
        !           356: #endif BPOP
        !           357: #ifdef TRUSTED
        !           358:     if (trusted (1, hostname, NULLCP, 0, myhost,
        !           359: #ifndef        DPOP
        !           360:                pw -> pw_name, pw -> pw_uid == 0,
        !           361: #else  DPOP
        !           362:                pw -> bb_name, 0,
        !           363: #endif DPOP
        !           364:                "pop", "tcp", NULL)
        !           365:            == 0)
        !           366:        return respond (NOTOK, "permission denied");
        !           367: #endif TRUSTED
        !           368:     return setup (pw, guest);
        !           369: }
        !           370: 
        !           371: /*  */
        !           372: 
        !           373: #ifdef BPOP
        !           374: static  isguest () {
        !           375:     int            i;
        !           376:     register char  *cp;
        !           377:     char    buffer[BUFSIZ];
        !           378:     register FILE  *fp;
        !           379: 
        !           380:     if (strcmp (username, popbbuser) || !guest_uid)
        !           381:        return FALSE;
        !           382:     if (popbblist == NULL || (fp = fopen (popbblist, "r")) == NULL)
        !           383:        return TRUE;
        !           384: 
        !           385:     i = FALSE;
        !           386:     if (hostname)
        !           387:        while (fgets (buffer, sizeof buffer, fp)) {
        !           388:            if (cp = index (buffer, '\n'))
        !           389:                *cp = NULL;
        !           390:            if (strcmp (buffer, hostname) == 0) {
        !           391:                i = TRUE;
        !           392:                break;
        !           393:            }
        !           394:        }
        !           395: 
        !           396:     (void) fclose (fp);
        !           397: 
        !           398:     return i;
        !           399: }
        !           400: #endif BPOP
        !           401: 
        !           402: /*  */
        !           403: 
        !           404: #ifdef RPOP
        !           405: static int rpop (vec)
        !           406: register char  **vec;
        !           407: {
        !           408: #ifndef        DPOP
        !           409:     register struct passwd *pw;
        !           410: #else  DPOP
        !           411:     register int hostok = 0;
        !           412:     register char  *bp,
        !           413:                   *cp;
        !           414:     char    buffer[BUFSIZ];
        !           415:     register struct bboard *pw;
        !           416: #endif DPOP
        !           417: 
        !           418: #ifndef        DPOP
        !           419:     if (!rproto || (pw = getpwnam (username)) == NULL) {
        !           420: #ifdef TRUSTED
        !           421:        trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp",
        !           422:            NULL);
        !           423: #endif TRUSTED
        !           424:        return respond (NOTOK, "login incorrect");
        !           425:     }
        !           426:     if (chdir (pw -> pw_dir) == NOTOK && chdir ("/") == NOTOK)
        !           427:        return respond (NOTOK, "no remote directory");
        !           428:     if (ruserok (hostname, pw -> pw_uid == 0, vec[1], username) == NOTOK) {
        !           429: #ifdef TRUSTED
        !           430:        trusted (0, hostname, vec[1], 0, pw -> pw_name,
        !           431:           pw -> pw_uid == 0, "rpop", "tcp", NULL);
        !           432: #endif TRUSTED
        !           433:        return respond (NOTOK, "permission denied");
        !           434:     }
        !           435: #else  DPOP
        !           436:     if (!rproto
        !           437:            || ((pw = getbbnam (username)) == NULL
        !           438:                && (pw = getbbaka (username)) == NULL)) {
        !           439: #ifdef TRUSTED
        !           440:        trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp",
        !           441:            NULL);
        !           442: #endif TRUSTED
        !           443:        return respond (NOTOK, "login incorrect");
        !           444:     }
        !           445: /*
        !           446:  * hacked by Dave Cohrs Tue Feb  4 14:12:15 CST 1986
        !           447:  *   to allow the hostname to be a list: user@host1,user@host2
        !           448:  *   NOTE: the separator must be a comma -- no spaces are allowed
        !           449:  */
        !           450:     (void) sprintf (buffer, "%s@%s", vec[1], hostname);
        !           451:     for (bp = pw -> bb_addr; bp; bp = cp) {
        !           452:        if ((cp = index (bp, ',')))
        !           453:            *cp = NULL;
        !           454:        hostok = strcmp (bp, buffer) == 0;
        !           455:        if (cp)
        !           456:            *cp++ = ',';
        !           457:        if (hostok)
        !           458:            break;
        !           459:     }
        !           460:     if (!hostok) {
        !           461: #ifdef TRUSTED
        !           462:        trusted (0, hostname, vec[1], 0, pw -> bb_name, 0, "rpop",
        !           463:            "tcp", NULL);
        !           464: #endif TRUSTED
        !           465:        return respond (NOTOK, "permission denied");
        !           466:     }
        !           467: #endif DPOP
        !           468: 
        !           469: #ifdef TRUSTED
        !           470:     if (trusted (1, hostname, vec[1], 0, username,
        !           471: #ifndef        DPOP
        !           472:                pw -> pw_uid == 0,
        !           473: #else  DPOP
        !           474:                0,
        !           475: #endif DPOP
        !           476:                "rpop", "tcp", NULL)
        !           477:            == 0)
        !           478:        return respond (NOTOK, "permission denied");
        !           479: #endif TRUSTED
        !           480:     return setup (pw, FALSE);
        !           481: }
        !           482: #endif RPOP
        !           483: 
        !           484: /*  */
        !           485: 
        !           486: static int setup (pw, guest)
        !           487: #ifndef        DPOP
        !           488: register struct passwd *pw;
        !           489: #else  DPOP
        !           490: register struct bboard *pw;
        !           491: #endif DPOP
        !           492: int    guest;
        !           493: {
        !           494: #ifdef BPOP
        !           495:     if (guest) {
        !           496:        (void) setgid (guest_gid);
        !           497:        (void) initgroups (popbbuser, guest_gid);
        !           498:        (void) setuid (guest_uid);
        !           499:     }
        !           500:     else {
        !           501: #endif BPOP
        !           502: #ifndef        DPOP
        !           503:        (void) setgid (pw -> pw_gid);
        !           504:        (void) initgroups (pw -> pw_name, pw -> pw_gid);
        !           505:        (void) setuid (pw -> pw_uid);
        !           506: #else  DPOP
        !           507:        (void) setgid (pop_gid);
        !           508:        (void) initgroups (POPUID, pop_gid);
        !           509:        (void) setuid (pop_uid);
        !           510: #endif DPOP
        !           511: #ifdef BPOP
        !           512:     }
        !           513: #endif BPOP
        !           514: 
        !           515: #ifndef        DPOP
        !           516:     (void) sprintf (maildrop, "%s/%s",
        !           517:            mmdfldir && *mmdfldir ? mmdfldir : pw -> pw_dir,
        !           518:            mmdflfil && *mmdflfil ? mmdflfil : pw -> pw_name);
        !           519: #else  DPOP
        !           520:     (void) strcpy (maildrop, pw -> bb_file);
        !           521: #endif DPOP
        !           522: 
        !           523:     if (setupaux (guest) == NOTOK)
        !           524:        return NOTOK;
        !           525: 
        !           526:     return respond (OK,
        !           527:            nmsgs ? "maildrop has %d message%s (%d octets)" : "maildrop empty",
        !           528:            nmsgs, nmsgs != 1 ? "s" : NULL, Msgs[0].m_size);
        !           529: }
        !           530: 
        !           531: /*  */
        !           532: 
        !           533: static int  setupaux (readonly)
        !           534: int    readonly;
        !           535: {
        !           536:     register int    i,
        !           537:                     msgp;
        !           538:     struct stat st;
        !           539: 
        !           540: #ifdef BPOP
        !           541:     xtnded = 0;
        !           542: #endif BPOP
        !           543:     if ((dp = readonly ? fopen (maildrop, "r") : lkfopen (maildrop, "r"))
        !           544:            == NULL)
        !           545:        switch (errno) {
        !           546:            case ENOENT: 
        !           547:                m_gMsgs (msgp = 0);
        !           548:                goto no_mail;
        !           549: 
        !           550:            default: 
        !           551:                nmsgs = dmsgs = 0;
        !           552:                return respond (NOTOK, "unable to %s maildrop: \"%s\"",
        !           553:                        readonly ? "read" : "lock", maildrop);
        !           554:        }
        !           555: 
        !           556:     if (fstat (fileno (dp), &st) != NOTOK) {
        !           557:        mode = (int) (st.st_mode & 0777), mtime = st.st_mtime;
        !           558:        msgp = read_map (maildrop, (long) st.st_size);
        !           559:     }
        !           560:     else {
        !           561:        mode = 0600, mtime = 0;
        !           562:        msgp = 0;
        !           563:     }
        !           564: 
        !           565:     if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
        !           566:        m_gMsgs (0);
        !           567: 
        !           568: no_mail: ;
        !           569:     dmsgs = 0;
        !           570:     nmsgs = msgp;
        !           571: 
        !           572:     Msgs[0].m_flags = readonly ? MREAD : MNULL;
        !           573:     Msgs[0].m_size = 0;
        !           574:     for (i = 1; i <= nmsgs; i++) {
        !           575:        if (Msgs[i].m_size == 0)
        !           576:            Msgs[i].m_size = mbx_size (i);
        !           577:        Msgs[0].m_size += Msgs[i].m_size;
        !           578:        Msgs[i].m_flags = MNULL;
        !           579:     }
        !           580: 
        !           581:     return OK;
        !           582: }
        !           583: 
        !           584: /*  */
        !           585: 
        !           586: static int  read_map (file, pos)
        !           587: char   *file;
        !           588: long   pos;
        !           589: {
        !           590:     register int    i,
        !           591:                     msgp;
        !           592:     register struct drop   *pp,
        !           593:                            *mp;
        !           594:     struct drop *rp;
        !           595: 
        !           596:     if (debug)
        !           597:        padvise (NULLCP, LOG_DEBUG, "read_map (%s, %ld)", file, pos);
        !           598: 
        !           599:     if ((i = map_read (file, pos, &rp, debug)) == 0)
        !           600:        return 0;
        !           601: 
        !           602:     m_gMsgs (i);
        !           603: 
        !           604:     msgp = 1;
        !           605:     for (pp = rp; i-- > 0; msgp++, pp++) {
        !           606:        mp = &Msgs[msgp].m_drop;
        !           607:        mp -> d_id = pp -> d_id;
        !           608:        mp -> d_size = pp -> d_size;
        !           609:        mp -> d_start = pp -> d_start;
        !           610:        mp -> d_stop = pp -> d_stop;
        !           611:     }
        !           612:     free ((char *) rp);
        !           613: 
        !           614:     return (msgp - 1);
        !           615: }
        !           616: 
        !           617: /*  */
        !           618: 
        !           619: static int  read_file (pos, msgp)
        !           620: register long  pos;
        !           621: register int   msgp;
        !           622: {
        !           623:     register int    i;
        !           624:     register struct drop   *pp,
        !           625:                            *mp;
        !           626:     struct drop *rp;
        !           627: 
        !           628:     if (debug)
        !           629:        padvise (NULLCP, LOG_DEBUG, "read_file (%ld, %d)",
        !           630:                pos, msgp);
        !           631: 
        !           632:     if ((i = mbx_read (dp, pos, &rp, debug)) <= 0)
        !           633:        return (msgp - 1);
        !           634: 
        !           635:     m_gMsgs ((msgp - 1) + i);
        !           636: 
        !           637:     for (pp = rp; i-- > 0; msgp++, pp++) {
        !           638:        mp = &Msgs[msgp].m_drop;
        !           639:        mp -> d_id = 0;
        !           640:        mp -> d_size = pp -> d_size;
        !           641:        mp -> d_start = pp -> d_start;
        !           642:        mp -> d_stop = pp -> d_stop;
        !           643:     }
        !           644:     free ((char *) rp);
        !           645: 
        !           646:     return (msgp - 1);
        !           647: }
        !           648: 
        !           649: /*  */
        !           650: 
        !           651: static m_gMsgs (n)
        !           652: int    n;
        !           653: {
        !           654:     if (debug)
        !           655:        padvise (NULLCP, LOG_DEBUG, "m_gMsgs (%d) 0x%x %d",
        !           656:                n, Msgs, nMsgs);
        !           657: 
        !           658:     if (Msgs == NULL) {
        !           659:        nMsgs = n + MAXFOLDER / 2;
        !           660:        Msgs = (struct Msg *) calloc ((unsigned) (nMsgs + 2), sizeof *Msgs);
        !           661:        if (Msgs == NULL)
        !           662:            padios (NULLCP, "unable to allocate Msgs structure");
        !           663:        return;
        !           664:     }
        !           665: 
        !           666:     if (nMsgs >= n)
        !           667:        return;
        !           668: 
        !           669:     nMsgs = n + MAXFOLDER / 2;
        !           670:     Msgs = (struct Msg *) realloc ((char *) Msgs,
        !           671:                                (unsigned) (nMsgs + 2) * sizeof *Msgs);
        !           672:     if (Msgs == NULL)
        !           673:        padios (NULLCP, "unable to reallocate Msgs structure");
        !           674: }
        !           675: 
        !           676: /*  */
        !           677: 
        !           678: static int  mbx_size (m)
        !           679: register int     m;
        !           680: {
        !           681:     register int    i;
        !           682:     register long   pos;
        !           683: 
        !           684:     (void) fseek (dp, Msgs[m].m_start, 0);
        !           685:     for (i = 0, pos = Msgs[m].m_stop - Msgs[m].m_start; pos > 0; i++, pos--)
        !           686:        if (fgetc (dp) == '\n')
        !           687:            i++;
        !           688: 
        !           689:     return i;
        !           690: }
        !           691: 
        !           692: /*  */
        !           693: 
        !           694: /* ARGSUSED */
        !           695: 
        !           696: static int  status (vec)
        !           697: char  **vec;
        !           698: {
        !           699:     return respond (OK, "%d %d", nmsgs - dmsgs, Msgs[0].m_size);
        !           700: }
        !           701: 
        !           702: 
        !           703: static int  list (vec)
        !           704: register char  **vec;
        !           705: {
        !           706:     register int    i;
        !           707: 
        !           708:     if (vec[1]) {
        !           709:        if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
        !           710:            return respond (NOTOK, "no such message: \"%s\"", vec[1]);
        !           711:        if (Msgs[i].m_flags & MDELE)
        !           712:            return respond (NOTOK, "message %d is deleted", i);
        !           713: 
        !           714: #ifndef        BPOP
        !           715:        return respond (OK, "%d %d", i, Msgs[i].m_size);
        !           716: #else  BPOP
        !           717:        return respond (OK, xtnded ? "%d %d %d" : "%d %d",
        !           718:                i, Msgs[i].m_size, Msgs[i].m_id);
        !           719: #endif BPOP
        !           720:     }
        !           721: 
        !           722:     (void) respond (OK, "%d message%s (%d octets)",
        !           723:            nmsgs - dmsgs, nmsgs - dmsgs != 1 ? "s" : NULL,
        !           724:            Msgs[0].m_size);
        !           725:     for (i = 1; i <= nmsgs; i++)
        !           726:        if (!(Msgs[i].m_flags & MDELE))
        !           727: #ifndef BPOP
        !           728:            multiline ("%d %d", i, Msgs[i].m_size);
        !           729: #else  BPOP
        !           730:            multiline (xtnded ? "%d %d %d" : "%d %d",
        !           731:                    i, Msgs[i].m_size, Msgs[i].m_id);
        !           732: #endif BPOP
        !           733:     multiend ();
        !           734: 
        !           735:     return OK;
        !           736: }
        !           737: 
        !           738: /*  */
        !           739: 
        !           740: static int  retrieve (vec)
        !           741: register char  **vec;
        !           742: {
        !           743:     register int    i;
        !           744:     register long   pos;
        !           745:     register char  *cp;
        !           746:     char    buffer[BUFSIZ];
        !           747: 
        !           748:     if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
        !           749:        return respond (NOTOK, "no such message: \"%s\"", vec[1]);
        !           750:     if (Msgs[i].m_flags & MDELE)
        !           751:        return respond (NOTOK, "message %d is deleted", i);
        !           752: 
        !           753:     (void) respond (OK, "%d octets", Msgs[i].m_size);
        !           754: 
        !           755:     for ((void) fseek (dp, pos = Msgs[i].m_start, 0);
        !           756:            fgets (buffer, sizeof buffer, dp) != NULL && pos < Msgs[i].m_stop;
        !           757:            pos += (long) (cp - buffer + 1)) {
        !           758:        if (*(cp = buffer + strlen (buffer) - 1) == '\n')
        !           759:            *cp = NULL;
        !           760:        multiline ("%s", buffer);
        !           761:     }
        !           762:     multiend ();
        !           763: 
        !           764:     return OK;
        !           765: }
        !           766: 
        !           767: /*  */
        !           768: 
        !           769: static int  delete (vec)
        !           770: register char   **vec;
        !           771: {
        !           772:     register int    i;
        !           773: 
        !           774:     if (Msgs[0].m_flags & MREAD)
        !           775:        return respond (NOTOK, "maildrop is read-only");
        !           776: 
        !           777:     if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
        !           778:        return respond (NOTOK, "no such message: \"%s\"", vec[1]);
        !           779:     if (Msgs[i].m_flags & MDELE)
        !           780:        return respond (NOTOK, "message %d is deleted", i);
        !           781: 
        !           782:     Msgs[i].m_flags |= MDELE;
        !           783:     Msgs[0].m_size -= Msgs[i].m_size;
        !           784:     dmsgs++;
        !           785: 
        !           786:     return respond (OK, "message %d deleted (%d octets)", i, Msgs[i].m_size);
        !           787: }
        !           788: 
        !           789: 
        !           790: static int  reset (vec)
        !           791: char   **vec;
        !           792: {
        !           793:     register int    i;
        !           794: 
        !           795:     for (i = 1; i <= nmsgs; i++)
        !           796:        if (Msgs[i].m_flags & MDELE) {
        !           797:            Msgs[i].m_flags &= ~MDELE;
        !           798:            Msgs[0].m_size += Msgs[i].m_size;
        !           799:            dmsgs--;
        !           800:        }
        !           801: 
        !           802:     return status (vec);
        !           803: }
        !           804: 
        !           805: /*  */
        !           806: 
        !           807: static int  top (vec)
        !           808: register char  **vec;
        !           809: {
        !           810:     register int    i,
        !           811:                     j,
        !           812:                     body,
        !           813:                     lines;
        !           814:     register long   pos;
        !           815:     register char  *cp;
        !           816:     char    buffer[BUFSIZ];
        !           817: 
        !           818:     if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
        !           819:        return respond (NOTOK, "no such message: \"%s\"", vec[1]);
        !           820:     if (Msgs[i].m_flags & MDELE)
        !           821:        return respond (NOTOK, "message %d is deleted", i);
        !           822:     if ((j = atoi (vec[2])) <= 0)
        !           823:        return respond (NOTOK, "bad number: \"%s\"", vec[2]);
        !           824: 
        !           825:     (void) respond (OK, vec[0]);
        !           826: 
        !           827:     body = lines = 0;
        !           828:     for ((void) fseek (dp, pos = Msgs[i].m_start, 0);
        !           829:            fgets (buffer, sizeof buffer, dp) != NULL && pos < Msgs[i].m_stop;
        !           830:            pos += (long) (cp - buffer + 1)) {
        !           831:        if (*(cp = buffer + strlen (buffer) - 1) == '\n')
        !           832:            *cp = NULL;
        !           833:        if (body) {
        !           834:            if (lines++ >= j)
        !           835:                break;
        !           836:        }
        !           837:        else
        !           838:            if (*buffer == NULL)
        !           839:                body++;
        !           840:        multiline ("%s", buffer);
        !           841:     }
        !           842:     multiend ();
        !           843: 
        !           844:     return OK;
        !           845: }
        !           846: 
        !           847: /*  */
        !           848: 
        !           849: #ifdef BPOP
        !           850: static int  xtnd (vec)
        !           851: register char    **vec;
        !           852: {
        !           853:     make_lower (vec[1], vec[1]);
        !           854: 
        !           855:     if (strcmp (vec[1], "bboards") == 0 || strcmp (vec[1], "archive") == 0)
        !           856:        return xtnd1 (vec);
        !           857:     if (strcmp (vec[1], "x-bboards") == 0)
        !           858:        return xtnd2 (vec);
        !           859: 
        !           860:     return respond (NOTOK, "unknown XTND command: \"%s\"", vec[1]);
        !           861: }
        !           862: 
        !           863: 
        !           864: static int  xtnd1 (vec)
        !           865: register char    **vec;
        !           866: {
        !           867:     register struct bboard *bb;
        !           868: 
        !           869:     if (vec[2]) {
        !           870:        make_lower (vec[2], vec[2]);
        !           871:        if ((bb = getbbaux (vec[2])) == NULL)
        !           872:            return respond (NOTOK, "unknown BBoard: \"%s\"", vec[2]);
        !           873: 
        !           874:        if (quitaux (NULLVP) == NOTOK)
        !           875:            return NOTOK;
        !           876:        (void) strcpy (maildrop,
        !           877:                strcmp (vec[1], "bboards") ? bb -> bb_archive : bb -> bb_file);
        !           878:        if (setupaux (TRUE) == NOTOK)
        !           879:            return NOTOK;
        !           880:        xtnded++;
        !           881:        (void) respond (OK, "%s", vec[1]);
        !           882:        multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
        !           883:     }
        !           884:     else {
        !           885:        if (strcmp (vec[1], "bboards"))
        !           886:            return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
        !           887: 
        !           888:        (void) respond (OK, "%s", vec[1]);
        !           889:        for (bb = BBhead; bb; bb = bb -> bb_next) {
        !           890:            getbbmax (bb);
        !           891:            if (!(bb -> bb_flags & BB_INVIS))
        !           892:                multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
        !           893:        }
        !           894:        while (bb = getbbaux (NULLCP))
        !           895:            if (!(bb -> bb_flags & BB_INVIS))
        !           896:                multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
        !           897:     }
        !           898:     multiend ();
        !           899: 
        !           900:     return OK;
        !           901: }
        !           902: 
        !           903: /*  */
        !           904: 
        !           905: static int  xtnd2 (vec)
        !           906: register char     **vec;
        !           907: {
        !           908:     register char  *cp,
        !           909:                   **ap;
        !           910:     char    buffer[BUFSIZ];
        !           911:     register struct bboard *bb;
        !           912: 
        !           913:     if (vec[2] == NULL)
        !           914:        return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
        !           915: 
        !           916:     make_lower (vec[2], vec[2]);
        !           917:     if ((bb = getbbaux (vec[2])) == NULL)
        !           918:        return respond (NOTOK, "unknown BBoard: \"%s\"", vec[2]);
        !           919: 
        !           920:     (void) respond (OK, "%s", vec[1]);
        !           921:     multiline ("%s", bb -> bb_name);
        !           922: 
        !           923:     cp = buffer;
        !           924:     for (ap = bb -> bb_aka; *ap; ap++) {
        !           925:        (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
        !           926:        cp += strlen (cp);
        !           927:     }
        !           928:     multiline ("%s", buffer);
        !           929: 
        !           930:     multiline ("%s", bb -> bb_file);
        !           931:     multiline ("%s", bb -> bb_archive);
        !           932:     multiline ("%s", bb -> bb_info);
        !           933:     multiline ("%s", bb -> bb_map);
        !           934:     multiline ("%s", bb -> bb_passwd);
        !           935: 
        !           936:     cp = buffer;
        !           937:     for (ap = bb -> bb_leader; *ap; ap++) {
        !           938:        (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
        !           939:        cp += strlen (cp);
        !           940:     }
        !           941:     multiline ("%s", buffer);
        !           942: 
        !           943:     multiline ("%s", bb -> bb_addr);
        !           944:     multiline ("%s", bb -> bb_request);
        !           945:     multiline ("%s", bb -> bb_relay);
        !           946: 
        !           947:     cp = buffer;
        !           948:     for (ap = bb -> bb_dist; *ap; ap++) {
        !           949:        (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
        !           950:        cp += strlen (cp);
        !           951:     }
        !           952:     multiline ("%s", buffer);
        !           953: 
        !           954:     getbbmax (bb);
        !           955:     multiline ("0%o %d", bb -> bb_flags, bb -> bb_maxima);
        !           956:     multiline ("%s", bb -> bb_date);
        !           957: 
        !           958:     multiend ();
        !           959: 
        !           960:     return OK;
        !           961: }
        !           962: 
        !           963: /*  */
        !           964: 
        !           965: static struct bboard *getbbaux (s)
        !           966: register char   *s;
        !           967: {
        !           968:     register struct bboard *bb;
        !           969:     struct stat st;
        !           970: 
        !           971:     if (BBhead == NULL)
        !           972:        if (setbbinfo (BBOARDS, BBDB, 1))
        !           973:            BBtime = getbbtime ();
        !           974:        else
        !           975:            return NULL;
        !           976: 
        !           977:     if (s != NULLCP)
        !           978:        for (bb = BBhead; bb; bb = bb -> bb_next)
        !           979:            if (strcmp (bb -> bb_name, s) == 0) {
        !           980:                if (debug)
        !           981:                    padvise (NULLCP, LOG_DEBUG, "getbbaux: \"%s\" from cache",
        !           982:                            bb -> bb_name);
        !           983:                getbbmax (bb);
        !           984:                return bb;
        !           985:            }
        !           986: 
        !           987:     while (bb = getbbent ()) {
        !           988:        if ((bb = getbbcpy (bb)) == NULL)
        !           989:            return NULL;
        !           990: 
        !           991:        if (access (bb -> bb_file, 04) == NOTOK && errno == EACCES)
        !           992:            bb -> bb_flags |= BB_INVIS;
        !           993:        bb -> bb_mtime = stat (bb -> bb_info, &st) != NOTOK ? st.st_mtime : 0L;
        !           994: 
        !           995:        if (BBtail != NULL)
        !           996:            BBtail -> bb_next = bb;
        !           997:        if (BBhead == NULL)
        !           998:            BBhead = bb;
        !           999:        BBtail = bb;
        !          1000: 
        !          1001:        if (s == NULL || strcmp (bb -> bb_name, s) == 0) {
        !          1002:            if (s && debug)
        !          1003:                padvise (NULLCP, LOG_DEBUG, "getbbaux: \"%s\" from scratch",
        !          1004:                        bb -> bb_name);
        !          1005:            return bb;
        !          1006:        }
        !          1007:     }
        !          1008: 
        !          1009:     return NULL;
        !          1010: }
        !          1011: 
        !          1012: /*  */
        !          1013: 
        !          1014: static  getbbmax (bb)
        !          1015: register struct bboard *bb;
        !          1016: {
        !          1017:     int     i;
        !          1018:     register char  *cp;
        !          1019:     char    buffer[BUFSIZ];
        !          1020:     struct stat st;
        !          1021:     register    FILE * fp;
        !          1022: 
        !          1023:     if (debug)
        !          1024:        padvise (NULLCP, LOG_DEBUG, "getbbmax: \"%s\", 0%o, %d, %s",
        !          1025:                bb -> bb_name, bb -> bb_flags, bb -> bb_maxima, bb -> bb_date);
        !          1026: 
        !          1027:     if (!(bb -> bb_flags & BB_INVIS)
        !          1028:            && access (bb -> bb_file, 04) == NOTOK && errno == EACCES)
        !          1029:        bb -> bb_flags |= BB_INVIS;
        !          1030: 
        !          1031:     if (stat (bb -> bb_info, &st) == NOTOK
        !          1032:            || bb -> bb_mtime == st.st_mtime
        !          1033:            || (fp = fopen (bb -> bb_info, "r")) == NULL)
        !          1034:        return;
        !          1035:     bb -> bb_mtime = st.st_mtime;
        !          1036: 
        !          1037:     if (fgets (buffer, sizeof buffer, fp) && (i = atoi (buffer)) > 0)
        !          1038:        bb -> bb_maxima = i;
        !          1039:     if (!feof (fp) && fgets (buffer, sizeof buffer, fp)) {
        !          1040:        if (bb -> bb_date)
        !          1041:            free (bb -> bb_date);
        !          1042:        if (cp = index (buffer, '\n'))
        !          1043:            *cp = NULL;
        !          1044:        bb -> bb_date = getcpy (buffer);
        !          1045:     }
        !          1046: 
        !          1047:     (void) fclose (fp);
        !          1048: 
        !          1049:     if (debug)
        !          1050:        padvise (NULLCP, LOG_DEBUG, "updated: \"%s\", 0%o, %d, %s",
        !          1051:                bb -> bb_name, bb -> bb_flags, bb -> bb_maxima, bb -> bb_date);
        !          1052: }
        !          1053: #endif BPOP
        !          1054: 
        !          1055: /*  */
        !          1056: 
        !          1057: static int  quit (vec)
        !          1058: char   **vec;
        !          1059: {
        !          1060:     int     d,
        !          1061:             n;
        !          1062: 
        !          1063:     d = dmsgs, n = nmsgs;
        !          1064: 
        !          1065:     if (quitaux (vec) == NOTOK)
        !          1066:        return NOTOK;
        !          1067: 
        !          1068: #ifdef BPOP
        !          1069:     if (xtnded)
        !          1070:        return respond (OK, "%s signing off", server);
        !          1071: #endif BPOP
        !          1072: 
        !          1073:     if (n == d)
        !          1074:        return respond (OK, "%s signing off (maildrop empty)", server);
        !          1075: 
        !          1076:     return respond (OK,
        !          1077:            n ? "%s signing off (%d message%s, %d octets left)"
        !          1078:            : "%s signing off (maildrop empty)",
        !          1079:            server, n - d, n - d != 1 ? "s" : NULL, Msgs[0].m_size);
        !          1080: }
        !          1081: 
        !          1082: 
        !          1083: static int  quitaux (vec)
        !          1084: char   **vec;
        !          1085: {
        !          1086:     int     i;
        !          1087: 
        !          1088:     if (dp == NULL)
        !          1089:        return OK;
        !          1090: 
        !          1091:     i = quitfile (vec);
        !          1092: 
        !          1093:     nmsgs = dmsgs = 0;
        !          1094:     (void) lkfclose (dp, maildrop);
        !          1095:     dp = NULL;
        !          1096: 
        !          1097:     return i;
        !          1098: }
        !          1099: 
        !          1100: /*  */
        !          1101: 
        !          1102: /* ARGSUSED */
        !          1103: 
        !          1104: static int  quitfile (vec)
        !          1105: char   **vec;
        !          1106: {
        !          1107:     register int    i,
        !          1108:                     md;
        !          1109:     char    tmpfil[BUFSIZ],
        !          1110:             map1[BUFSIZ],
        !          1111:             map2[BUFSIZ];
        !          1112:     struct stat st;
        !          1113: 
        !          1114:     if (dmsgs == 0 || (Msgs[0].m_flags & MREAD))
        !          1115:        return OK;
        !          1116: 
        !          1117:     if (fstat (fileno (dp), &st) == NOTOK)
        !          1118:        return respond (NOTOK, "unable to stat file");
        !          1119:     if (mtime != st.st_mtime)
        !          1120:        return respond (NOTOK, "new messages have arrived, no update");
        !          1121:     mode = (int) (st.st_mode & 0777);
        !          1122: 
        !          1123:     if (nmsgs == dmsgs) {
        !          1124:        i = truncate (maildrop, 0);
        !          1125:        (void) unlink (map_name (maildrop));/* XXX */
        !          1126:        if (i == NOTOK)
        !          1127:            return respond (NOTOK, "unable to zero %s", maildrop);
        !          1128:        return OK;
        !          1129:     }
        !          1130: 
        !          1131:     (void) strcpy (tmpfil, m_backup (maildrop));
        !          1132:     if ((md = mbx_open (tmpfil, st.st_uid, st.st_gid, mode)) == NOTOK)
        !          1133:        return respond (NOTOK, "unable to create temporary file");
        !          1134: 
        !          1135:     for (i = 1; i <= nmsgs; i++)
        !          1136:        if (!(Msgs[i].m_flags & MDELE)
        !          1137:            &&  mbx_write (tmpfil, md, dp, Msgs[i].m_id, Msgs[i].m_start,
        !          1138:                        Msgs[i].m_stop, TRUE, debug) == NOTOK) {
        !          1139:            (void) mbx_close (tmpfil, md);
        !          1140:            (void) unlink (tmpfil);
        !          1141:            return respond (NOTOK, "error writing temporary file");
        !          1142:        }
        !          1143:     (void) mbx_close (tmpfil, md);
        !          1144: 
        !          1145:     if ((i = rename (tmpfil, maildrop)) == OK) {
        !          1146:        (void) strcpy (map1, map_name (tmpfil));
        !          1147:        (void) strcpy (map2, map_name (maildrop));
        !          1148:        if (rename (map1, map2) == NOTOK) {
        !          1149:            (void) unlink (map1);
        !          1150:            (void) unlink (map2);
        !          1151:        }
        !          1152:     }
        !          1153: 
        !          1154:     if (i == NOTOK)
        !          1155:        return respond (NOTOK, "unable to rename maildrop");
        !          1156: 
        !          1157:     return OK;
        !          1158: }
        !          1159: 
        !          1160: /*  */
        !          1161: 
        !          1162: static struct vector   *getvector (bp, vec)
        !          1163: register char   *bp,
        !          1164:              **vec;
        !          1165: {
        !          1166:     register int    i;
        !          1167:     register struct vector *v;
        !          1168: 
        !          1169:     for (i = 0; i < NVEC; i++) {
        !          1170:        while (isspace (*bp))
        !          1171:            *bp++ = NULL;
        !          1172:        if (*bp == NULL) {
        !          1173:            vec[i] = NULL;
        !          1174:            break;
        !          1175:        }
        !          1176:        vec[i] = bp;
        !          1177:        while (!isspace (*bp))
        !          1178:            bp++;
        !          1179:     }
        !          1180:     i--;
        !          1181:     vec[NVEC] = NULL;
        !          1182: 
        !          1183:     if (*bp != NULL) {
        !          1184:        (void) respond (NOTOK, "too many arguments");
        !          1185:        return NULL;
        !          1186:     }
        !          1187:     if (*vec[0] == NULL) {
        !          1188:        (void) respond (NOTOK, "null command");
        !          1189:        return NULL;
        !          1190:     }
        !          1191:     make_lower (vec[0], vec[0]);
        !          1192: 
        !          1193:     for (v = vectors; v -> v_cmd; v++)
        !          1194:        if (strcmp (v -> v_cmd, vec[0]) == 0 && v -> v_valid == mystate) {
        !          1195:            if (i < v -> v_min || v -> v_max < i) {
        !          1196:                (void) respond (NOTOK, "too %s arguments to \"%s\"",
        !          1197:                        i < v -> v_min ? "few" : "many", vec[0]);
        !          1198:                return NULL;
        !          1199:            }
        !          1200:            else
        !          1201:                return v;
        !          1202:        }
        !          1203: 
        !          1204:     (void) respond (NOTOK, "unknown command: \"%s\"", vec[0]);
        !          1205:     return NULL;
        !          1206: }
        !          1207: 
        !          1208: /*  */
        !          1209: 
        !          1210: /* VARARGS2 */
        !          1211: 
        !          1212: static int  respond (code, fmt, a, b, c, d)
        !          1213: char   *fmt,
        !          1214:        *a,
        !          1215:        *b,
        !          1216:        *c,
        !          1217:        *d;
        !          1218: int     code;
        !          1219: {
        !          1220:     register char  *bp;
        !          1221:     char    buffer[BUFSIZ];
        !          1222: 
        !          1223:     bp = buffer;
        !          1224:     bp += strlen (sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR",
        !          1225:                fmt ? " " : NULL));
        !          1226:     if (fmt)
        !          1227:        bp += strlen (sprintf (bp, fmt, a, b, c, d));
        !          1228:     putline (buffer, output);
        !          1229: 
        !          1230:     return code;
        !          1231: }
        !          1232: 
        !          1233: 
        !          1234: /* VARARGS1 */
        !          1235: 
        !          1236: static  multiline (fmt, a, b, c, d)
        !          1237: char   *fmt,
        !          1238:        *a,
        !          1239:        *b,
        !          1240:        *c,
        !          1241:        *d;
        !          1242: {
        !          1243:     register char  *cp;
        !          1244:     char    buffer[BUFSIZ + TRMLEN];
        !          1245: 
        !          1246:     (void) strcpy (buffer, TRM);
        !          1247:     cp = sprintf (buffer + TRMLEN, fmt, a, b, c, d);
        !          1248:     if (strncmp (cp, TRM, TRMLEN) == 0)
        !          1249:        cp = buffer;
        !          1250: 
        !          1251:     putline (cp, output);
        !          1252: }
        !          1253: 
        !          1254: 
        !          1255: static  multiend () {
        !          1256:     putline (TRM, output);
        !          1257: }
        !          1258: 
        !          1259: /*  */
        !          1260: 
        !          1261: static int  getline (s, n, iop)
        !          1262: register char  *s;
        !          1263: register int   n;
        !          1264: register FILE  *iop;
        !          1265: {
        !          1266:     register int    c;
        !          1267:     register char  *p;
        !          1268: 
        !          1269:     p = s;
        !          1270:     while (--n > 0 && (c = fgetc (iop)) != EOF) {
        !          1271:        while (c == IAC) {
        !          1272:            (void) fgetc (iop);
        !          1273:            c = fgetc (iop);
        !          1274:        }
        !          1275:        if ((*p++ = c) == '\n')
        !          1276:            break;
        !          1277:     }
        !          1278:     if (ferror (iop))
        !          1279:        return NOTOK;
        !          1280:     if (c == EOF && p == s)
        !          1281:        return DONE;
        !          1282:     *p++ = NULL;
        !          1283:     if (debug)
        !          1284:        padvise (NULLCP, LOG_DEBUG, "<--- %s", s);
        !          1285: 
        !          1286:     return OK;
        !          1287: }
        !          1288: 
        !          1289: 
        !          1290: static  putline (s, iop)
        !          1291: register char   *s;
        !          1292: register FILE   *iop;
        !          1293: {
        !          1294:     (void) fprintf (iop, "%s\r\n", s);
        !          1295:     if (debug)
        !          1296:        padvise (NULLCP, LOG_DEBUG, "---> %s", s);
        !          1297: 
        !          1298:     (void) fflush (iop);
        !          1299: }
        !          1300: 
        !          1301: 
        !          1302: /* ARGSUSED */
        !          1303: 
        !          1304: static int pipeser (sig, code, sc)
        !          1305: int    sig;
        !          1306: long    code;
        !          1307: struct sigcontext *sc;
        !          1308: {
        !          1309:     padvise (NULLCP, LOG_WARNING, "lost connection");
        !          1310: 
        !          1311:     _exit (NOTOK);
        !          1312: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.