9 date 95.12.07.18.54.35; author jromine; state Exp;
14 date 94.04.21.18.26.16; author jromine; state Exp;
19 date 94.04.21.18.20.15; author jromine; state Exp;
24 date 93.08.25.17.23.14; author jromine; state Exp;
29 date 92.12.16.22.31.20; author jromine; state Exp;
34 date 92.12.15.00.20.22; author jromine; state Exp;
39 date 92.12.14.17.49.09; author jromine; state Exp;
44 date 92.10.28.18.42.42; author jromine; state Exp;
49 date 92.10.26.16.45.35; author jromine; state Exp;
54 date 92.10.20.22.47.28; author jromine; state Exp;
59 date 92.05.19.20.59.21; author jromine; state Exp;
64 date 92.02.11.17.40.59; author jromine; state Exp;
69 date 92.02.10.22.35.58; author jromine; state Exp;
74 date 92.02.04.21.59.41; author jromine; state Exp;
79 date 92.02.04.21.44.56; author jromine; state Exp;
84 date 92.02.04.21.39.42; author jromine; state Exp;
89 date 92.02.03.17.52.59; author jromine; state Exp;
94 date 92.01.31.22.06.03; author jromine; state Exp;
99 date 90.11.16.14.56.38; author mh; state Exp;
104 date 90.11.16.14.38.00; author mh; state Exp;
109 date 90.11.05.16.04.57; author mh; state Exp;
114 date 90.04.09.09.45.18; author sources; state Exp;
119 date 90.04.05.16.07.32; author sources; state Exp;
124 date 90.04.05.16.07.03; author sources; state Exp;
129 date 90.04.05.15.34.40; author sources; state Exp;
134 date 90.04.05.14.54.01; author sources; state Exp;
139 date 90.03.20.11.15.44; author sources; state Exp;
144 date 90.02.23.14.49.38; author sources; state Exp;
149 date 90.02.06.13.13.55; author sources; state Exp;
154 date 90.02.05.15.04.53; author sources; state Exp;
159 date 90.02.05.14.16.51; author sources; state Exp;
164 date 90.02.05.14.08.18; author sources; state Exp;
169 date 90.02.05.13.58.53; author sources; state Exp;
174 date 90.02.05.13.58.34; author sources; state Exp;
185 @include prototype for truncate() - 64biyt
188 @/* popser.c - the POP service */
190 static char ident[]="@@(#)$Id: popser.c,v 1.33 1994/04/21 18:26:16 jromine Exp jromine $";
194 #include "../h/dropsbr.h"
197 #include "../h/formatsbr.h"
198 #include "../h/scansbr.h"
201 #include "../zotnet/bboards.h"
203 #include "../zotnet/mts.h"
209 #include <sys/types.h>
210 #include <sys/stat.h>
231 #define POPSERVICE "pop"
239 extern char myhost[];
244 auth1, auth2, trans, update, halt, error
248 auth1, auth2, trans, mbox, item, ack, update, halt, error
253 static int user (), pass ();
255 static isguest(), getbbmax();
257 static int xtnd1(), xtnd2();
259 static int xtnd1(), xtnd2(), xtnd3 ();
268 static int status (), list (), retrieve (), delete (), reset ();
269 static int top (), last ();
275 static int helo (), rdp2 (), acks (), ack2 (), fold (), nack ();
278 static struct vector {
283 enum state v_win, v_lose;
285 "user", 1, 1, user, auth1, auth2, auth1,
286 "pass", 1, 1, pass, auth2, trans, auth1,
288 "rpop", 1, 1, rpop, auth2, trans, auth1,
291 "apop", 2, 2, apop, auth1, trans, auth1,
293 "quit", 0, 0, NULL, auth1, halt, halt,
294 "quit", 0, 0, NULL, auth2, halt, halt,
296 "stat", 0, 0, status, trans, trans, trans,
297 "list", 0, 1, list, trans, trans, trans,
298 "retr", 1, 1, retrieve, trans, trans, trans,
299 "dele", 1, 1, delete, trans, trans, trans,
300 "noop", 0, 0, NULL, trans, trans, trans,
301 "rset", 0, 0, reset, trans, trans, trans,
303 "top", 2, 2, top, trans, trans, trans,
304 "last", 0, 0, last, trans, trans, trans,
307 "xtnd", 1, 2, xtnd, trans, trans, trans,
309 "xtnd", 1, 3, xtnd, trans, trans, trans,
312 "quit", 0, 0, quit, trans, halt, halt,
315 "helo", 2, 2, helo, auth1, mbox, auth1,
317 "fold", 1, 1, fold, mbox, mbox, mbox,
318 "quit", 0, 0, quit, mbox, halt, halt,
319 "read", 0, 1, rdp2, mbox, item, error,
321 "fold", 1, 1, fold, item, mbox, mbox,
322 "read", 0, 1, rdp2, item, item, error,
323 "quit", 0, 0, quit, item, halt, halt,
324 "retr", 0, 0, retrieve, item, ack, error,
326 "acks", 0, 0, ack2, ack, item, error,
327 "ackd", 0, 0, ack2, ack, item, error,
328 "nack", 0, 0, rdp2, ack, item, error,
329 "quit", 0, 0, NULL, ack, halt, halt,
335 static struct vector *getvector ();
340 static int pop2 = NOTOK; /* current pop2 msg, or NOTOK if pop3 */
348 static char *hostname;
349 static char server[BUFSIZ];
350 static char timestamp[BUFSIZ];
352 static char username[BUFSIZ];
354 static char maildrop[BUFSIZ];
359 static long lastseen;
365 static int guest_uid;
366 static int guest_gid;
368 static struct bboard *BBhead = NULL;
369 static struct bboard *BBtail = NULL;
371 static long BBtime = 0L;
373 static struct bboard *getbbaux ();
377 struct Msg { /* Msgs[0] contains info for entire maildrop */
379 #define m_id m_drop.d_id
380 #define m_size m_drop.d_size
381 #define m_last m_drop.d_start /* Msgs[i = 0] */
382 #define m_start m_drop.d_start /* Msgs[i > 0] */
383 #define m_stop m_drop.d_stop
391 static int nMsgs = 0;
392 static struct Msg *Msgs = NULL;
398 static int _sc_width = 0;
399 static char *nfs = NULL;
405 #define TRMLEN (sizeof TRM - 1)
408 static TYPESIG pipeser ();
415 struct passwd *getpwnam();
419 void padvise (), padios ();
423 #define MBX_READ pmbx_read
424 static int pmbx_read ();
425 static char *p_copy(), *p_copyin(), *p_nextword();
426 static p_cmatch(), p_isdate(), p_ishead(), p_parse(), any();
428 #define MBX_READ mbx_read
430 extern int mbx_read ();
432 static int setup(), setupaux(), read_map(), read_file(), pmbx_size();
433 static int quitaux(), quitfile(), respond(), getline();
434 static m_gMsgs(), multiline(), multiend(), putline();
439 padvise (NULLCP, LOG_INFO, "initialize list of BBoards");
441 BBhead = BBtail = NULL;
442 while (getbbaux (NULLCP))
450 register struct bboard *bb,
453 if (BBtime == getbbtime ())
456 padvise (NULLCP, LOG_INFO, "list of BBoards has changed");
458 for (bb = BBhead; bb; bb = bp) {
462 free (bb -> bb_name);
464 free (bb -> bb_file);
465 if (bb -> bb_archive)
466 free (bb -> bb_archive);
468 free (bb -> bb_info);
472 free (bb -> bb_passwd);
474 free (bb -> bb_date);
476 free (bb -> bb_addr);
477 if (bb -> bb_request)
478 free (bb -> bb_request);
480 free (bb -> bb_relay);
482 for (p = bb -> bb_aka; *p; p++)
484 free ((char *) bb -> bb_aka);
486 for (p = bb -> bb_leader; *p; p++)
488 free ((char *) bb -> bb_leader);
490 for (p = bb -> bb_dist; *p; p++)
492 free ((char *) bb -> bb_dist);
497 BBhead = BBtail = NULL;
498 while (getbbaux (NULLCP))
506 static char *kusername;
508 kpop (in, out, principal, rhost, auth)
511 char *principal, *rhost;
514 pop (in, out, priv, rhost)
523 #if defined (DPOP) || defined (BPOP)
524 register struct passwd *pw;
525 #endif /* defined (DPOP) || defined (BPOP) */
526 register struct vector *v;
534 (void) sprintf (server, "%s KPOP server", myhost);
537 (void) sprintf (server, "%s server", priv ? "RPOP" : "POP");
540 if ((input = fdopen (in, "r")) == NULL
541 || (output = fdopen (out, "w")) == NULL) {/* you lose big */
542 (void) respond (NOTOK, "%s loses on initialization", server);
545 (void) signal (SIGPIPE, pipeser);
547 if (principal == NULLCP) {
549 strcpy(buf, "Authentication failed: ");
550 strcat(buf, krb_err_txt[auth]);
551 (void) respond (NOTOK, buf);
554 kusername = principal;
558 if ((pw = getpwnam (POPUID)) == NULL || !setpwinfo (pw, POPDB, 1)) {
559 (void) respond (NOTOK, "%s loses on DB initialization -- %s",
560 server, pw ? getbberr () : "POP user-id unknown");
563 pop_uid = pw -> pw_uid;
564 pop_gid = pw -> pw_gid;
567 if ((pw = getpwnam (popbbuser)) && pw -> pw_uid) {
568 guest_uid = pw -> pw_uid;
569 guest_gid = pw -> pw_gid;
572 guest_uid = guest_gid = 0;
578 (void) time (&clock);
579 (void) sprintf (timestamp, "<%d.%ld@@%s>", getpid (), clock, myhost);
581 (void) respond (OK, "%s ready %s", server, timestamp);
583 for (mystate = auth1; mystate != halt && mystate != error;)
584 switch (getline (buffer, sizeof buffer, input)) {
586 if ((v = getvector (buffer, vec)) == NULL)
588 mystate = (v -> v_vec ? (v -> v_vec) (vec)
589 : respond (OK, NULLCP)) == OK
597 (void) respond (NOTOK, "%s signing off", server);
604 static int helo (vec) /* sort of "user" and "pass" */
607 pop2 = 0; /* now we're talkin' pop2! */
608 make_lower (username, vec[1]); /* helo user pass */
609 return pass (++vec); /* user pass */
613 static int user (vec)
616 make_lower (username, vec[1]);
618 if (!strcmp(username, kusername))
619 return respond (OK, "Kerberos authentication succeeded. Send username as password (%s)", username);
621 respond (NOTOK, "Wrong username supplied (%s vs. %s)",
622 kusername, username);
626 return respond (OK, "password required for %s", username);
632 static int pass (vec)
637 register struct passwd *pw;
639 register struct spwd *shpw;
642 register struct bboard *pw;
647 if ((pw = getpwnam (username)) != NULL)
648 return setup(pw, FALSE);
650 return respond (NOTOK, "no local password entry");
653 static struct bboard entry;
654 static char entry_file[BUFSIZ] = "/usr/spool/pop";
657 pw->bb_name = username;
658 strcat(entry_file, username);
659 pw->bb_file = entry_file;
660 return setup(pw, FALSE);
671 gw.pw_name = popbbuser;
672 gw.pw_uid = guest_uid;
679 if ((pw = getpwnam (username)) == NULL
681 || *pw -> pw_passwd == NULL
682 || strcmp (crypt (vec[1], pw -> pw_passwd), pw -> pw_passwd)) {
684 || (shpw = getspnam (username)) == NULL
685 || *shpw -> sp_pwdp == NULL
686 || strcmp (crypt (vec[1], shpw -> sp_pwdp), shpw -> sp_pwdp)) {
689 trusted (0, hostname, NULLCP, 0, pw ? pw -> pw_name : username,
690 pw && pw -> pw_uid == 0, POPSERVICE, "tcp", NULL);
692 return respond (NOTOK, "login incorrect");
697 static struct bboard gw;
699 gw.bb_name = popbbuser;
705 if (((pw = getbbnam (username)) == NULL
706 && (pw = getbbaka (username)) == NULL)
707 || *pw -> bb_passwd == NULL
708 || strcmp (crypt (vec[1], pw -> bb_passwd), pw -> bb_passwd)) {
710 trusted (0, hostname, NULLCP, 0, pw ? pw -> bb_name : username,
711 0, POPSERVICE, "tcp", NULL);
713 return respond (NOTOK, "login incorrect");
721 if (trusted (1, hostname, NULLCP, 0, myhost,
723 pw -> pw_name, pw -> pw_uid == 0,
727 POPSERVICE, "tcp", NULL)
729 return respond (NOTOK, "permission denied");
731 return setup (pw, guest);
744 if (strcmp (username, popbbuser) || !guest_uid)
746 if (popbblist == NULL || (fp = fopen (popbblist, "r")) == NULL)
751 while (fgets (buffer, sizeof buffer, fp)) {
752 if (cp = index (buffer, '\n'))
754 if (strcmp (buffer, hostname) == 0) {
769 static int rpop (vec)
773 register struct passwd *pw;
775 register int hostok = 0;
779 register struct bboard *pw;
783 if (!rproto || (pw = getpwnam (username)) == NULL) {
785 trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp",
788 return respond (NOTOK, "login incorrect");
790 if (chdir (pw -> pw_dir) == NOTOK && chdir ("/") == NOTOK)
791 return respond (NOTOK, "no remote directory");
792 if (ruserok (hostname, pw -> pw_uid == 0, vec[1], username) == NOTOK) {
794 trusted (0, hostname, vec[1], 0, pw -> pw_name,
795 pw -> pw_uid == 0, "rpop", "tcp", NULL);
797 return respond (NOTOK, "permission denied");
801 || ((pw = getbbnam (username)) == NULL
802 && (pw = getbbaka (username)) == NULL)) {
804 trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp",
807 return respond (NOTOK, "login incorrect");
810 * hacked by Dave Cohrs Tue Feb 4 14:12:15 CST 1986
811 * to allow the hostname to be a list: user@@host1,user@@host2
812 * NOTE: the separator must be a comma -- no spaces are allowed
814 (void) sprintf (buffer, "%s@@%s", vec[1], hostname);
815 for (bp = pw -> bb_addr; bp; bp = cp) {
816 if ((cp = index (bp, ',')))
818 hostok = uleq (bp, buffer);
826 trusted (0, hostname, vec[1], 0, pw -> bb_name, 0, "rpop",
829 return respond (NOTOK, "permission denied");
834 if (trusted (1, hostname, vec[1], 0, username,
842 return respond (NOTOK, "permission denied");
844 return setup (pw, FALSE);
852 #include "../../uip/md5.c"
854 #include <sys/file.h>
860 static int apop (vec)
865 register unsigned char *dp;
869 register struct passwd *pw;
871 register struct bboard *pw;
878 struct authinfo auth;
880 (void) strcpy (username, vec[1]);
883 if ((pw = getpwnam (username)) == NULL
884 || *pw -> pw_passwd == NULL) {
885 return respond (NOTOK, "user invalid");
888 if (((pw = getbbnam (username)) == NULL
889 && (pw = getbbaka (username)) == NULL)
890 || *pw -> bb_passwd == NULL) {
891 return respond (NOTOK, "subscriber invalid");
895 if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL)
896 return respond (NOTOK, "POP authorization DB not available (%d)",
898 if (fstat (dbm_pagfno (db), &st) != NOTOK
899 && (st.st_mode & 0777) != 0600) {
901 return respond (NOTOK, "POP authorization DB has wrong mode (0%o)",
904 if (flock (dbm_pagfno (db), LOCK_SH) == NOTOK) {
906 return respond (NOTOK, "unable to lock POP authorization DB (%d)",
909 key.dsize = strlen (key.dptr = vec[1]) + 1;
910 value = dbm_fetch (db, key);
911 if (value.dptr == NULL) {
913 return respond (NOTOK, "not authorized");
915 bcopy (value.dptr, (char *) &auth, sizeof auth);
916 (void) sprintf (cp = buffer, "%s%*.*s", timestamp, auth.auth_secretlen,
917 auth.auth_secretlen, auth.auth_secret);
921 MD5Init (&mdContext);
922 MD5Update (&mdContext, (unsigned char *) buffer,
923 (unsigned int) (strlen (timestamp) + auth.auth_secretlen));
924 MD5Final (digest, &mdContext);
927 for (ep = (dp = digest) + sizeof digest / sizeof digest[0];
930 (void) sprintf (cp, "%02x", *dp++ & 0xff);
933 if (strcmp (vec[2], buffer))
934 return respond (NOTOK, "authentication failure");
936 return setup (pw, 0);
942 static int setup (pw, guest)
944 register struct passwd *pw;
946 register struct bboard *pw;
952 (void) setgid (guest_gid);
954 (void) initgroups (popbbuser, guest_gid);
956 (void) setuid (guest_uid);
961 (void) setgid (pw -> pw_gid);
963 (void) initgroups (pw -> pw_name, pw -> pw_gid);
965 (void) setuid (pw -> pw_uid);
967 (void) setgid (pop_gid);
969 (void) initgroups (POPUID, pop_gid);
971 (void) setuid (pop_uid);
978 (void) sprintf (maildrop, "%s/%s",
979 mmdfldir && *mmdfldir ? mmdfldir : pw -> pw_dir,
980 mmdflfil && *mmdflfil ? mmdflfil : pw -> pw_name);
982 (void) strcpy (maildrop, pw -> bb_file);
985 if (setupaux (guest) == NOTOK)
989 if (pop2 != NOTOK) { /* in response to pop2 "helo" */
990 pop2 = nmsgs > 0 ? 1 : 0;
991 return respond ('#', "%d message%s (%d octets)",
992 nmsgs, nmsgs != 1 ? "s" : "", Msgs[0].m_size);
997 nmsgs ? "maildrop has %d message%s (%d octets)" : "maildrop empty",
998 nmsgs, nmsgs != 1 ? "s" : "", Msgs[0].m_size);
1003 static int setupaux (readonly)
1013 if ((dp = readonly ? fopen (maildrop, "r") : lkfopen (maildrop, "r"))
1022 return respond (NOTOK, "unable to %s maildrop: \"%s\"",
1023 readonly ? "read" : "lock", maildrop);
1026 if (fstat (fileno (dp), &st) != NOTOK) {
1027 mode = (int) (st.st_mode & 0777), mtime = st.st_mtime;
1028 msgp = read_map (maildrop, (long) st.st_size);
1031 mode = 0600, mtime = 0;
1035 if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
1039 lastseen = Msgs[0].m_last;
1040 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: lastseen=%d",lastseen);
1044 Msgs[0].m_flags = readonly ? MREAD : MNULL;
1046 for (i = 1; i <= nmsgs; i++) {
1047 if (Msgs[i].m_size == 0)
1048 Msgs[i].m_size = pmbx_size (i);
1049 Msgs[0].m_size += Msgs[i].m_size;
1050 Msgs[i].m_flags = MNULL;
1058 static int read_map (file, pos)
1064 register struct drop *pp,
1069 padvise (NULLCP, LOG_DEBUG, "read_map (%s, %ld)", file, pos);
1071 if ((i = map_read (file, pos, &rp, debug)) == 0)
1076 Msgs[0].m_last = rp -> d_start;
1079 for (pp = rp + 1; i-- > 0; msgp++, pp++) {
1080 mp = &Msgs[msgp].m_drop;
1081 mp -> d_id = pp -> d_id;
1082 mp -> d_size = pp -> d_size;
1083 mp -> d_start = pp -> d_start;
1084 mp -> d_stop = pp -> d_stop;
1088 if (Msgs[0].m_last > msgp) {
1090 padvise (NULLCP, LOG_DEBUG, "lastseen adjusted from %d to %d",
1091 Msgs[0].m_last, msgp);
1092 Msgs[0].m_last = msgp;
1100 static int read_file (pos, msgp)
1105 register struct drop *pp,
1110 padvise (NULLCP, LOG_DEBUG, "read_file (%ld, %d)",
1113 if ((i = MBX_READ (dp, pos, &rp, debug)) <= 0)
1116 m_gMsgs ((msgp - 1) + i);
1118 for (pp = rp; i-- > 0; msgp++, pp++) {
1119 mp = &Msgs[msgp].m_drop;
1121 mp -> d_size = pp -> d_size;
1122 mp -> d_start = pp -> d_start;
1123 mp -> d_stop = pp -> d_stop;
1136 padvise (NULLCP, LOG_DEBUG, "m_gMsgs (%d) 0x%x %d",
1140 nMsgs = n + MAXFOLDER / 2;
1141 Msgs = (struct Msg *) calloc ((unsigned) (nMsgs + 2), sizeof *Msgs);
1143 padios (NULLCP, "unable to allocate Msgs structure");
1150 nMsgs = n + MAXFOLDER / 2;
1151 Msgs = (struct Msg *) realloc ((char *) Msgs,
1152 (unsigned) (nMsgs + 2) * sizeof *Msgs);
1154 padios (NULLCP, "unable to reallocate Msgs structure");
1159 static int pmbx_size (m)
1165 (void) fseek (dp, Msgs[m].m_start, 0);
1166 for (i = 0, pos = Msgs[m].m_stop - Msgs[m].m_start; pos > 0; i++, pos--)
1167 if (fgetc (dp) == '\n')
1177 static int status (vec)
1180 return respond (OK, "%d %d", nmsgs - dmsgs, Msgs[0].m_size);
1185 static int rdp2 (vec) /* always returns OK */
1189 if ((pop2 = atoi (vec[1])) <= 0)
1193 return NOTOK; /* close 'em down */
1195 if (pop2 <= 0 || pop2 > nmsgs) {
1197 return respond ('=', "0 no message");
1199 if (Msgs[pop2].m_flags & MDELE) {
1201 return respond ('=', "0 message %d is deleted", pop2);
1204 return respond ('=', "%d (message %d)", Msgs[pop2].m_size, pop2);
1207 static int ack2 (vec)
1210 if (strcmp (vec[0], "ackd") == 0) {
1211 Msgs[pop2].m_flags |= MDELE; /* ignored later if MREAD */
1212 Msgs[0].m_size -= Msgs[pop2].m_size;
1216 if (pop2) { /* a current msg */
1217 rmsgs++; /* mark this one as read */
1219 pop2 = -1; /* let rdp2 reset */
1220 else if (Msgs[pop2].m_flags & MDELE)
1221 pop2 = -1; /* let rdp2 reset */
1222 if (pop2 > Msgs[0].m_last)
1223 Msgs[0].m_last = pop2;
1225 return rdp2 (vec); /* vec = { "acks", 0 } */
1228 static int fold (vec)
1229 register char **vec;
1235 /* This might work, or it might be a huge security hole. For my purpose,
1236 * it doesn't need to work, so I'm not going to make sure it's OK.
1240 if (quitaux (NULLVP) == NOTOK)
1241 return respond ('#', "0 unable to close folder");
1243 (void) sprintf (maildrop, vec[1]);
1244 if (setupaux (access (maildrop, 2) ? 1 : 0) == NOTOK)
1245 return respond ('#', "0 unable to read %s", maildrop);
1247 pop2 = nmsgs > 0 ? 1 : 0;
1248 return respond ('#', "%d message%s in %s (%d octets)",
1249 nmsgs, nmsgs != 1 ? "s" : "", maildrop, Msgs[0].m_size);
1253 respond ('#', "0 unable to change folders");
1258 static int list (vec)
1259 register char **vec;
1264 if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
1265 return respond (NOTOK, "no such message: \"%s\"", vec[1]);
1266 if (Msgs[i].m_flags & MDELE)
1267 return respond (NOTOK, "message %d is deleted", i);
1270 return respond (OK, "%d %d", i, Msgs[i].m_size);
1273 if (nfs && !xtnded) {
1276 (void) fseek (dp, Msgs[i].m_start, 0);
1278 switch (scan (dp, i, 0, nfs, 0, 0, 0,
1279 0, NULLCP, (long) Msgs[i].m_size, 0)) {
1283 if (cp = index (scanl, '\n'))
1285 return respond (OK, "%d %d #%s",
1286 i, Msgs[i].m_size, scanl);
1289 return respond (OK, "%d %d #%*d empty",
1290 i, Msgs[i].m_size, DMAXFOLDER, i);
1297 return respond (OK, xtnded ? "%d %d %d" : "%d %d",
1298 i, Msgs[i].m_size, Msgs[i].m_id);
1302 (void) respond (OK, "%d message%s (%d octets)",
1303 nmsgs - dmsgs, nmsgs - dmsgs != 1 ? "s" : "",
1305 for (i = 1; i <= nmsgs; i++)
1306 if (!(Msgs[i].m_flags & MDELE)) {
1308 multiline ("%d %d", i, Msgs[i].m_size);
1311 if (nfs && !xtnded) {
1314 (void) fseek (dp, Msgs[i].m_start, 0);
1316 switch (scan (dp, i, 0, nfs, 0, 0, 0,
1317 0, NULLCP, (long) Msgs[i].m_size, 0)) {
1321 if (cp = index (scanl, '\n'))
1323 multiline ("%d %d #%s",
1324 i, Msgs[i].m_size, scanl);
1328 multiline ("%d %d #%*d empty",
1329 i, Msgs[i].m_size, DMAXFOLDER, i);
1337 multiline (xtnded ? "%d %d %d" : "%d %d",
1338 i, Msgs[i].m_size, Msgs[i].m_id);
1348 static int retrieve (vec)
1349 register char **vec;
1354 char buffer[BUFSIZ];
1359 else if (pop2 == NOTOK) {
1361 if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
1362 return respond (NOTOK, "no such message: \"%s\"", vec[1]);
1363 if (Msgs[i].m_flags & MDELE)
1364 return respond (NOTOK, "message %d is deleted", i);
1366 (void) respond (OK, "%d octets", Msgs[i].m_size);
1369 else /* if called by pop2, vec = { "retr", 0 } */
1373 for ((void) fseek (dp, pos = Msgs[i].m_start, 0);
1374 fgets (buffer, sizeof buffer, dp) != NULL && pos < Msgs[i].m_stop;
1375 pos += (long) (cp - buffer + 1)) {
1376 if (*(cp = buffer + strlen (buffer) - 1) == '\n')
1378 multiline ("%s", buffer);
1381 if (pop2 == NOTOK) { /* then multiend */
1385 if (i > Msgs[0].m_last) {
1398 static int delete (vec)
1399 register char **vec;
1403 if (Msgs[0].m_flags & MREAD)
1404 return respond (NOTOK, "maildrop is read-only");
1406 if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
1407 return respond (NOTOK, "no such message: \"%s\"", vec[1]);
1408 if (Msgs[i].m_flags & MDELE)
1409 return respond (NOTOK, "message %d is deleted", i);
1411 Msgs[i].m_flags |= MDELE;
1412 Msgs[0].m_size -= Msgs[i].m_size;
1415 if (i > Msgs[0].m_last)
1418 return respond (OK, "message %d deleted (%d octets)", i, Msgs[i].m_size);
1422 static int reset (vec)
1427 for (i = 1; i <= nmsgs; i++)
1428 if (Msgs[i].m_flags & MDELE) {
1429 Msgs[i].m_flags &= ~MDELE;
1430 Msgs[0].m_size += Msgs[i].m_size;
1434 Msgs[0].m_last = lastseen;
1440 free (scanl), scanl = NULL;
1441 free (nfs), nfs = NULL;
1446 return status (vec);
1451 static int top (vec)
1452 register char **vec;
1460 char buffer[BUFSIZ];
1462 if ((i = atoi (vec[1])) <= 0 || i > nmsgs)
1463 return respond (NOTOK, "no such message: \"%s\"", vec[1]);
1464 if (Msgs[i].m_flags & MDELE)
1465 return respond (NOTOK, "message %d is deleted", i);
1466 if ((j = atoi (vec[2])) < 0)
1467 return respond (NOTOK, "bad number: \"%s\"", vec[2]);
1469 (void) respond (OK, vec[0]);
1472 for ((void) fseek (dp, pos = Msgs[i].m_start, 0);
1473 fgets (buffer, sizeof buffer, dp) != NULL && pos < Msgs[i].m_stop;
1474 pos += (long) (cp - buffer + 1)) {
1475 if (*(cp = buffer + strlen (buffer) - 1) == '\n')
1484 multiline ("%s", buffer);
1495 static int last (vec)
1498 return respond (OK, "%d is the last msg seen", Msgs[0].m_last);
1504 static int xtnd (vec)
1505 register char **vec;
1507 make_lower (vec[1], vec[1]);
1509 if (strcmp (vec[1], "bboards") == 0 || strcmp (vec[1], "archive") == 0)
1511 if (strcmp (vec[1], "x-bboards") == 0)
1514 if (strcmp (vec[1], "scan") == 0)
1518 return respond (NOTOK, "unknown XTND command: \"%s\"", vec[1]);
1522 static int xtnd1 (vec)
1523 register char **vec;
1525 register struct bboard *bb;
1528 make_lower (vec[2], vec[2]);
1529 if ((bb = getbbaux (vec[2])) == NULL)
1530 return respond (NOTOK, "unknown BBoard: \"%s\"", vec[2]);
1532 if (quitaux (NULLVP) == NOTOK)
1534 (void) strcpy (maildrop,
1535 strcmp (vec[1], "bboards") ? bb -> bb_archive : bb -> bb_file);
1536 if (setupaux (TRUE) == NOTOK)
1539 (void) respond (OK, "%s", vec[1]);
1540 multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
1543 if (strcmp (vec[1], "bboards"))
1544 return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
1546 (void) respond (OK, "%s", vec[1]);
1547 for (bb = BBhead; bb; bb = bb -> bb_next) {
1549 if (!(bb -> bb_flags & BB_INVIS))
1550 multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
1552 while (bb = getbbaux (NULLCP))
1553 if (!(bb -> bb_flags & BB_INVIS))
1554 multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
1563 static int xtnd2 (vec)
1564 register char **vec;
1568 char buffer[BUFSIZ];
1569 register struct bboard *bb;
1572 return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
1574 make_lower (vec[2], vec[2]);
1575 if ((bb = getbbaux (vec[2])) == NULL)
1576 return respond (NOTOK, "unknown BBoard: \"%s\"", vec[2]);
1578 (void) respond (OK, "%s", vec[1]);
1579 multiline ("%s", bb -> bb_name);
1582 for (ap = bb -> bb_aka; *ap; ap++) {
1583 (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
1586 multiline ("%s", buffer);
1588 multiline ("%s", bb -> bb_file);
1589 multiline ("%s", bb -> bb_archive);
1590 multiline ("%s", bb -> bb_info);
1591 multiline ("%s", bb -> bb_map);
1592 multiline ("%s", bb -> bb_passwd);
1595 for (ap = bb -> bb_leader; *ap; ap++) {
1596 (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
1599 multiline ("%s", buffer);
1601 multiline ("%s", bb -> bb_addr);
1602 multiline ("%s", bb -> bb_request);
1603 multiline ("%s", bb -> bb_relay);
1606 for (ap = bb -> bb_dist; *ap; ap++) {
1607 (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
1610 multiline ("%s", buffer);
1613 multiline ("0%o %d", bb -> bb_flags, bb -> bb_maxima);
1614 multiline ("%s", bb -> bb_date);
1623 static struct bboard *getbbaux (s)
1626 register struct bboard *bb;
1630 if (setbbinfo (BBOARDS, BBDB, 1))
1631 BBtime = getbbtime ();
1636 for (bb = BBhead; bb; bb = bb -> bb_next)
1637 if (strcmp (bb -> bb_name, s) == 0) {
1639 padvise (NULLCP, LOG_DEBUG, "getbbaux: \"%s\" from cache",
1645 while (bb = getbbent ()) {
1646 if ((bb = getbbcpy (bb)) == NULL)
1649 if (access (bb -> bb_file, 04) == NOTOK && errno == EACCES)
1650 bb -> bb_flags |= BB_INVIS;
1651 bb -> bb_mtime = stat (bb -> bb_info, &st) != NOTOK ? st.st_mtime : 0L;
1654 BBtail -> bb_next = bb;
1659 if (s == NULL || strcmp (bb -> bb_name, s) == 0) {
1661 padvise (NULLCP, LOG_DEBUG, "getbbaux: \"%s\" from scratch",
1672 static getbbmax (bb)
1673 register struct bboard *bb;
1677 char buffer[BUFSIZ];
1682 padvise (NULLCP, LOG_DEBUG, "getbbmax: \"%s\", 0%o, %d, %s",
1683 bb -> bb_name, bb -> bb_flags, bb -> bb_maxima, bb -> bb_date);
1685 if (!(bb -> bb_flags & BB_INVIS)
1686 && access (bb -> bb_file, 04) == NOTOK && errno == EACCES)
1687 bb -> bb_flags |= BB_INVIS;
1689 if (stat (bb -> bb_info, &st) == NOTOK
1690 || bb -> bb_mtime == st.st_mtime
1691 || (fp = fopen (bb -> bb_info, "r")) == NULL)
1693 bb -> bb_mtime = st.st_mtime;
1695 if (fgets (buffer, sizeof buffer, fp) && (i = atoi (buffer)) > 0)
1696 bb -> bb_maxima = i;
1697 if (!feof (fp) && fgets (buffer, sizeof buffer, fp)) {
1699 free (bb -> bb_date);
1700 if (cp = index (buffer, '\n'))
1702 bb -> bb_date = getcpy (buffer);
1708 padvise (NULLCP, LOG_DEBUG, "updated: \"%s\", 0%o, %d, %s",
1709 bb -> bb_name, bb -> bb_flags, bb -> bb_maxima, bb -> bb_date);
1715 static int xtnd3 (vec)
1716 register char **vec;
1719 return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
1720 if ((_sc_width = atoi (vec[2])) < WIDTH / 2)
1721 _sc_width = WIDTH / 2;
1722 nfs = new_fs (NULLCP, vec[3], FORMAT);
1724 (void) free (scanl), scanl = NULL;
1726 return respond (OK, vec[1]);
1729 int sc_width () { return _sc_width; }
1735 static int quit (vec)
1741 d = dmsgs, n = nmsgs;
1743 if (quitaux (vec) == NOTOK)
1748 return respond (OK, "%s signing off", server);
1752 return respond (OK, "%s signing off (maildrop empty)", server);
1755 n ? "%s signing off (%d message%s, %d octets left)"
1756 : "%s signing off (maildrop empty)",
1757 server, n - d, n - d != 1 ? "s" : "", Msgs[0].m_size);
1761 static int quitaux (vec)
1771 nmsgs = dmsgs = rmsgs = 0;
1772 (void) lkfclose (dp, maildrop);
1782 static int quitfile (vec)
1789 char tmpfil[BUFSIZ],
1794 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: dmsgs=%d rmsgs=%d readonly=%d",
1795 dmsgs, rmsgs, Msgs[0].m_flags & MREAD);
1797 if (dmsgs == 0 || (Msgs[0].m_flags & MREAD))
1800 if (fstat (fileno (dp), &st) == NOTOK)
1801 return respond (NOTOK, "unable to stat file");
1802 if (mtime != st.st_mtime)
1803 return respond (NOTOK, "new messages have arrived, no update");
1804 mode = (int) (st.st_mode & 0777);
1806 if (nmsgs == dmsgs) {
1808 i = truncate (maildrop, 0);
1810 i = open (maildrop, O_WRONLY | O_TRUNC);
1811 if (i != NOTOK) (void) close (i);
1813 (void) unlink (map_name (maildrop));/* XXX */
1815 return respond (NOTOK, "unable to zero %s", maildrop);
1819 (void) strcpy (tmpfil, m_backup (maildrop));
1820 if ((md = mbx_open (tmpfil, st.st_uid, st.st_gid, mode)) == NOTOK)
1821 { char msgbuf0[256];
1822 sprintf(msgbuf0,"unable to create temporary file (%s)",tmpfil);
1823 return respond (NOTOK, msgbuf0);
1826 j = 0, tmpDR = Msgs[0].m_last;
1827 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: last=%d",Msgs[0].m_last);
1828 for (i = 1; i <= nmsgs; i++) {
1829 if (!(Msgs[i].m_flags & MDELE))
1834 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: last=%d",Msgs[0].m_last);
1836 for (i = 1; i <= nmsgs; i++)
1837 if (!(Msgs[i].m_flags & MDELE)
1838 && mbx_write (tmpfil, md, dp, Msgs[i].m_id, Msgs[0].m_last,
1839 Msgs[i].m_start, Msgs[i].m_stop, TRUE, debug)
1841 (void) mbx_close (tmpfil, md);
1842 (void) unlink (tmpfil);
1843 return respond (NOTOK, "error writing temporary file");
1845 (void) mbx_close (tmpfil, md);
1847 if ((i = rename (tmpfil, maildrop)) == OK) {
1848 (void) strcpy (map1, map_name (tmpfil));
1849 (void) strcpy (map2, map_name (maildrop));
1850 if (rename (map1, map2) == NOTOK) {
1851 (void) unlink (map1);
1852 (void) unlink (map2);
1857 return respond (NOTOK, "unable to rename maildrop");
1864 static struct vector *getvector (bp, vec)
1869 register struct vector *v;
1871 for (i = 0; i < NVEC; i++) {
1872 while (isspace (*bp))
1880 for (vec[i] = ++bp; *bp != '\0' && *bp != '"'; bp++)
1884 (void) strcpy (bp, bp + 1);
1890 (void) strcpy (bp - 1, bp);
1903 while (!isspace (*bp))
1910 (void) respond (NOTOK, "too many arguments");
1914 (void) respond (NOTOK, "null command");
1917 make_lower (vec[0], vec[0]);
1919 for (v = vectors; v -> v_cmd; v++)
1920 if (strcmp (v -> v_cmd, vec[0]) == 0 && v -> v_valid == mystate) {
1921 if (i < v -> v_min || v -> v_max < i) {
1922 (void) respond (NOTOK, "too %s arguments to \"%s\"",
1923 i < v -> v_min ? "few" : "many", vec[0]);
1930 (void) respond (NOTOK, "unknown command: \"%s\"", vec[0]);
1938 static int respond (code, fmt, a, b, c, d)
1947 char buffer[BUFSIZ];
1951 (void) sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR", fmt ? " " : "");
1957 (void) sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR",
1962 default: /* only happens in pop2 */
1968 (void) sprintf (bp, fmt, a, b, c, d);
1971 putline (buffer, output);
1979 static multiline (fmt, a, b, c, d)
1987 char buffer[BUFSIZ + TRMLEN];
1989 (void) strcpy (buffer, TRM);
1990 (void) sprintf (cp = (buffer + TRMLEN), fmt, a, b, c, d);
1991 if (strncmp (cp, TRM, TRMLEN) == 0)
1994 putline (cp, output);
1998 static multiend () {
1999 putline (TRM, output);
2004 static int getline (s, n, iop)
2013 while (--n > 0 && (c = fgetc (iop)) != EOF) {
2018 if ((*p++ = c) == '\n')
2023 if (c == EOF && p == s)
2028 padvise (NULLCP, LOG_DEBUG, "<--- %s", s);
2039 static putline (s, iop)
2043 (void) fprintf (iop, "%s\r\n", s);
2045 padvise (NULLCP, LOG_DEBUG, "---> %s", s);
2047 (void) fflush (iop);
2053 static TYPESIG pipeser (sig, code, sc)
2056 struct sigcontext *sc;
2058 padvise (NULLCP, LOG_WARNING, "lost connection");
2065 /* Some people don't want to use the POP delivery agent with Sendmail
2066 * if they're going to run POP. Sendmail writes maildrops in the old
2067 * UUCP format, and popd doesn't know how to read them. These people
2068 * really should do what the MH manual says -- run the pop delivery
2069 * agent and be done with it. Some things never die.
2071 * A real fix would be to make uip/dropsbr.c should use the same methods
2072 * as sbr/m_getfld.c to determine the format of maildrops and read &
2073 * write them. Unfortunately, it'll take a lot of work to bring it into
2074 * the fold. 20Mar90/JLR
2076 * I really really hate to add this, but this lets stuff popd read
2077 * UUCP style maildrops as well as MMDF (ctrl/A) style maildrops. It was
2078 * contributed by Steve Dempsey <steved@@longs.LANCE.ColoState.Edu>.
2080 * Here's what he says:
2082 * Ideally, one should be able to do it with the mmdelim strings, but
2083 * the MH parser is not intelligent enough to do this. You have at
2084 * least a couple of choices:
2086 * - use aliases to deliver mail to POP users (user: user@@pop) and
2087 * install the POP delivery agent - should work well with sendmail.
2088 * - fix the POP server!
2090 * We have all mail sent to one machine and users are given two options:
2092 * - MH on any machine.
2093 * - any user agent on the postoffice machine.
2095 * Most of our workstations run xmh and users find that to be sufficient.
2096 * New users are only taught to use MH, and a very few old timers stay
2097 * with BSD mail. In any case, several agents are available at the cost
2098 * of a telnet/rlogin if a user does not like MH.
2100 * I have made the changes to the POP server (MH-6.6/support/pop/popser.c)
2101 * to look for the `\n\nFrom ' delimiter instead of the ^A's, using some
2102 * code from the BSD agent. Context diff is included below. When this
2103 * is installed, you just go back to the normal localmail and get rid of
2104 * slocal completely.
2106 * I have not tried this modification with anything but the MH client,
2107 * but it should work. Nothing in the POP protocol changes; the server
2108 * just has different criteria for delimiting messages in the mailbox.
2109 * If you decide to use this, I'd like to know what happens.
2111 * Steve Dempsey, Center for Computer Assisted Engineering
2112 * Colorado State University, Fort Collins, CO 80523 +1 303 491 0630
2113 * INET: steved@@longs.LANCE.ColoState.Edu, dempsey@@handel.CS.ColoState.Edu
2114 * boulder!ccncsu!longs.LANCE.ColoState.Edu!steved, ...!ncar!handel!dempsey
2116 /* From: Jim Reid <jim@@computer-science.strathclyde.ac.UK>
2118 * MH-6.7 does not support MMDF-style mailboxes with POP as claimed. It
2119 * appears that when code was added to popser.c to support UNIX-style
2120 * mailboxes, the old behaviour was lost. i.e. The new popd worked with
2121 * UNIX-style mailboxes, but not MMDF ones. Users would get "format error"
2122 * error messages if they tried to inc a remote MMDF-style mailbox because
2123 * the pop daemon didn't want to know or like the MMDF message delimiters.
2126 /* So... Now there's an incredible hack in mhconfig.c to define POPUUMBOX
2127 * in support/pop/Makefile if we're using Sendmail. This causes this
2128 * UUCP-mbox reading code to be used here. Ugh. 05Nov90/JLR
2133 /* from dropsbr.c - read from a mailbox - pop server version */
2135 /* ALMOST IDENTICAL to mbx_read */
2137 static int pmbx_read (fp, pos, drops, noisy)
2140 struct drop **drops;
2146 char buffer[BUFSIZ];
2147 register struct drop *cp,
2152 /* MTR: tsk, tsk, tsk... */
2153 (void) fseek (fp, pos, 0);
2154 if (fgets (buffer, sizeof buffer, fp)
2155 && strcmp (buffer, mmdlm1) == 0)
2156 return mbx_read (fp, pos, drops, noisy);
2158 /* get drop storage */
2159 pp = (struct drop *) calloc ((unsigned) (len = MAXFOLDER), sizeof *dp);
2162 padvise (NULLCP, LOG_DEBUG, "pmbx_read (%d, %ld, %d, %d)",
2163 fp, pos,drops,noisy);
2167 admonish (NULLCP, "unable to allocate drop storage");
2171 /* rewind drop file */
2172 (void) fseek (fp, pos, 0);
2175 padvise (NULLCP, LOG_DEBUG, "rewind maildrop");
2178 for (ep = (dp = pp) + len - 1; fgets (buffer, sizeof buffer, fp);) {
2181 /* if beginning of msg then mark it */
2183 if (p_ishead(buffer)) /*(strcmp (buffer, mmdlm1) == 0)*/ {
2184 /* (don't) inc pos to msg start, mark it */
2186 dp -> d_start = pos;
2187 pos += strlen(buffer); /* inc pos after marking head */
2190 /* didn't find it; mark it anyway */
2191 dp -> d_start = pos, pos += (long) strlen (buffer);
2193 /* count newlines and inc size if any found */
2194 for (bp = buffer; *bp; bp++, size++)
2199 /* read more lines... */
2200 while (fgets (buffer, sizeof buffer, fp) != NULL)
2203 if (p_ishead(buffer)) /*(strcmp (buffer, mmdlm2) == 0)*/ {
2206 (void) fseek (fp, pos, 0);
2211 /* add buffer size to pos */
2212 pos += (long) strlen (buffer);
2214 /* count newlines.... */
2215 for (bp = buffer; *bp; bp++, size++)
2220 if (dp -> d_start != pos) {
2221 /* do this if pos was actually incremented; got some text */
2223 dp -> d_size = size; /* save the stuff we got */
2228 /* (don't) advance pos */
2231 /* need more storage.... */
2233 register int curlen = dp - pp;
2235 cp = (struct drop *) realloc ((char *) pp,
2236 (unsigned) (len += MAXFOLDER) * sizeof *pp);
2239 admonish (NULLCP, "unable to allocate drop storage");
2243 dp = cp + curlen, ep = (pp = cp) + len - 1;
2247 /* return unused stuff */
2256 * The remainder of this file adapted from:
2258 * head.c 5.2 (Berkeley) 6/21/85
2262 char *l_from; /* The name of the sender */
2263 char *l_tty; /* His tty string (if any) */
2264 char *l_date; /* The entire date string */
2269 * See if position in a file is a mail header.
2270 * Return true if yes. Note the extreme pains to
2271 * accomodate all funny formats.
2274 #define NOSTR ((char *) 0) /* Null string pointer */
2275 static char *p_copyin();
2276 static char *p_copy();
2279 static p_ishead(buffer)
2284 char linebuf[BUFSIZ];
2285 char parbuf[BUFSIZ];
2287 strcpy(linebuf,buffer);
2290 if (linebuf[0]=='F')
2291 padvise (NULLCP, LOG_DEBUG, "ishead: '%s'",linebuf);
2293 if (strncmp("From ", cp, 5) != 0)
2296 padvise (NULLCP, LOG_DEBUG, "Fromline...");
2298 /* get full header */
2299 p_parse(cp, &hl, parbuf);
2301 if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
2302 padvise (NULLCP, LOG_DEBUG, "Fromline...NODATE");
2306 if (!p_isdate(hl.l_date)) {
2307 padvise (NULLCP, LOG_DEBUG, "Fromline...BADDATE %s",
2312 /* I guess we got it! */
2313 padvise (NULLCP, LOG_DEBUG, "got a head.. ");
2319 * Split a headline into its useful components.
2320 * Copy the line into dynamic string space, then set
2321 * pointers into the copied line in the passed headline
2322 * structure. Actually, it scans.
2325 static p_parse(line, hl, pbuf)
2326 char line[], pbuf[];
2327 struct p_hdline *hl;
2329 register char *cp, *dp;
2332 char * p_nextword();
2341 * Skip the first "word" of the line, which should be "From"
2344 cp = p_nextword(cp, word);
2345 dp = p_nextword(cp, word);
2346 if (!(strcmp(word, "")==0))
2347 hl->l_from = p_copyin(word, &sp);
2350 if (strncmp(dp, "tty", 3) == 0) {
2351 cp = p_nextword(dp, word);
2352 hl->l_tty = p_copyin(word, &sp);
2354 hl->l_date = p_copyin(cp, &sp);
2360 hl->l_date = p_copyin(dp, &sp);
2364 * Copy the string on the left into the string on the right
2365 * and bump the right (reference) string pointer by the length.
2366 * Thus, dynamically allocate space in the right string, copying
2367 * the left string into it.
2371 p_copyin(src, space)
2375 register char *cp, *top;
2388 * Collect a liberal (space, tab delimited) word into the word buffer
2389 * passed. Also, return a pointer to the next word following that,
2390 * or (empty) if none follow.
2394 p_nextword(wp, wbuf)
2397 register char *cp, *cp2;
2399 if ((cp = wp) == NOSTR) {
2404 while (!any(*cp, " \t") && *cp != '\0')
2407 while (*cp != '\0' && *cp != '"')
2414 while (any(*cp, " \t"))
2422 * Copy str1 to str2, return pointer to null in str2.
2429 register char *s1, *s2;
2439 #define L 1 /* A lower case char */
2440 #define S 2 /* A space */
2441 #define D 3 /* A digit */
2442 #define O 4 /* An optional digit or space */
2443 #define C 5 /* A colon */
2444 #define N 6 /* A new line */
2445 #define U 7 /* An upper case char */
2447 static char p_ctypes[] =
2448 {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
2449 /* T h u S e p 2 9 1 5 : 2 0 : 1 9 1 9 8 8 */
2451 static char p_tmztyp[] =
2452 {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
2453 /* T h u S e p 2 9 1 5 : 2 0 : 1 9 M S T 1 9 8 8 */
2455 static p_isdate(date)
2461 if (p_cmatch(cp, p_ctypes))
2464 return(p_cmatch(cp, p_tmztyp));
2468 * Match the given string against the given template.
2469 * Return 1 if they match, 0 if they don't
2472 static p_cmatch(str, temp)
2475 register char *cp, *tp;
2480 while (*cp != '\0' && *tp != 0) {
2484 if (c < 'a' || c > 'z')
2489 if (c < 'A' || c > 'Z')
2504 if (c != ' ' && !isdigit(c))
2519 if ((*cp != '\0' && *cp != '\n') || *tp != 0)
2548 static char ident[]="@@(#)$Id: popser.c,v 1.32 1994/04/21 18:20:15 jromine Exp jromine $";
2555 @update for scansbr.c
2560 static char ident[]="@@(#)$Id: popser.c,v 1.31 1993/08/25 17:23:14 jromine Exp jromine $";
2563 switch (scan (dp, i, 0, nfs, 0, 0, NULLCP,
2564 (long) Msgs[i].m_size, 0)) {
2570 @off_t fixes for BSD44
2575 static char ident[]="@@(#)$Id: popser.c,v 1.30 1992/12/16 22:31:20 jromine Exp jromine $";
2578 switch (scan (dp, i, 0, nfs, 0, 0, NULLCP,
2579 (long) Msgs[i].m_size, 0)) {
2590 static char ident[]="@@(#)$Id: popser.c,v 1.29 1992/12/15 00:20:22 jromine Exp jromine $";
2603 static char ident[]="@@(#)$Id: popser.c,v 1.28 1992/12/14 17:49:09 jromine Exp jromine $";
2606 static int pipeser ();
2609 static int pipeser (sig, code, sc)
2620 static char ident[]="@@(#)$Id: popser.c,v 1.27 1992/10/28 18:42:42 jromine Exp jromine $";
2665 #endif defined (DPOP) || defined (BPOP)
2828 @add some MPOP #ifdefs
2833 static char ident[]="@@(#)$Id: popser.c,v 1.16 1990/11/16 14:56:38 mh Exp jromine $";
2839 struct bboard *getbbaux ();
2845 @APOP changes from MTR
2850 static char ident[]="@@(#)$Id: popser.c,v 1.25 1992/10/20 22:47:28 jromine Exp jromine $";
2874 @change location of md5.c
2879 static char ident[]="@@(#)$Id: popser.c,v 1.24 1992/05/19 20:59:21 jromine Exp jromine $";
2885 MD5Final (&mdContext);
2888 for (ep = (dp = mdContext.digest)
2889 + sizeof mdContext.digest / sizeof mdContext.digest[0];
2900 static char ident[]="@@(#)$Id: popser.c,v 1.23 1992/02/11 17:40:59 jromine Exp jromine $";
2909 @cleanup KPOP ifdefs
2914 static char ident[]="@@(#)$Id: popser.c,v 1.22 1992/02/10 22:35:58 jromine Exp jromine $";
2917 for (vec[i] = ++bp; *bp != NULL && *bp != '"'; bp++)
2931 static char ident[]="@@(#)$Id: popser.c,v 1.21 1992/02/04 21:59:41 jromine Exp jromine $";
2949 return respond (OK, "password required for %s", username);
2966 static char ident[]="@@(#)$Id: popser.c,v 1.20 1992/02/04 21:44:56 jromine Exp jromine $";
2969 if ((j = atoi (vec[2])) <= 0)
2980 static char ident[]="@@(#)$Id: popser.c,v 1.19 1992/02/04 21:39:42 jromine Exp jromine $";
2984 if (strcmp (vec[2], buffer)) {
2998 static char ident[]="@@(#)$Id: popser.c,v 1.18 1992/02/03 17:52:59 jromine Exp jromine $";
3001 "apop", 3, 3, apop, auth1, trans, auth1,
3005 (void) sprintf (server, "%s %s server", myhost, priv ? "RPOP" : "POP");
3008 (void) respond (OK, "%s ready (Comments to: PostMaster@@%s)",
3015 char auth_secret[16];
3028 if ((db = dbm_open (APOP, O_RDWR, 0)) == NULL)
3031 if (flock (dbm_pagfno (db), LOCK_EX) == NOTOK) {
3034 if (sscanf (vec[2], "%ld", &clock) != 1) {
3036 return respond (NOTOK, "invalid timestamp");
3038 if (clock < auth.auth_clock) {
3040 return respond (NOTOK, "timestamp smaller than %ld",
3044 (void) sprintf (cp = buffer, "%s %s ", vec[1], vec[2]);
3046 (void) bcopy (auth.auth_secret, ap = cp, auth.auth_secretlen);
3050 (unsigned int) ((cp - buffer) + auth.auth_secretlen));
3054 if (strcmp (vec[3], ap)) {
3056 auth.auth_clock = clock;
3057 value.dptr = (char *) &auth, value.dsize = sizeof auth;
3058 if (dbm_store (db, key, value, DBM_REPLACE))
3059 padvise (NULLCP, LOG_INFO, "POP authorization DB may be corrupt?!?");
3073 static char ident[]="@@(#)$Id: popser.c,v 1.17 1992/01/31 22:06:03 jromine Exp jromine $";
3080 static int xtnd1(), xtnd2();
3085 "xtnd", 1, 2, xtnd, trans, trans, trans,
3094 i, Msgs[i].m_size, Msgs[i].m_id);
3097 if (!(Msgs[i].m_flags & MDELE))
3101 i, Msgs[i].m_size, Msgs[i].m_id);
3109 if ((dmsgs == 0 && rmsgs == 0) || (Msgs[0].m_flags & MREAD))
3111 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: rmsgs=%d",rmsgs);
3116 padvise (NULLCP, LOG_DEBUG, "<--- %s", s);
3123 /* get sizes of msg delimiters */
3124 ld1 = (long) strlen (mmdlm1);
3125 ld2 = (long) strlen (mmdlm2);
3136 static char ident[]="@@(#)$Id: popser.c,v 1.16 1990/11/16 14:56:38 mh Exp jromine $";
3148 static char ident[]="@@(#)$Id: popser.c,v 1.15 90/11/16 14:38:00 mh Exp Locker: mh $";
3174 if (*buffer == NULL)
3184 if (*vec[0] == NULL) {
3193 @make popser speak POP2 as well as POP3 -- a major win!
3200 static char ident[]="@@(#)$Id: popser.c,v 1.14 90/11/05 16:04:57 mh Exp Locker: mh $";
3209 @see comments in code
3214 static char ident[]="@@(#)$Id: popser.c,v 1.13 90/04/09 09:45:18 sources Exp Locker: mh $";
3227 nmsgs, nmsgs != 1 ? "s" : NULL, Msgs[0].m_size);
3231 nmsgs - dmsgs, nmsgs - dmsgs != 1 ? "s" : NULL,
3238 server, n - d, n - d != 1 ? "s" : NULL, Msgs[0].m_size);
3241 bp += strlen (sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR",
3244 bp += strlen (sprintf (bp, fmt, a, b, c, d));
3255 static char ident[]="@@(#)$Id: popser.c,v 1.12 90/04/05 16:07:32 sources Exp Locker: sources $";
3260 if ((i = pmbx_read (dp, pos, &rp, debug)) <= 0)
3275 static char ident[]="@@(#)$Id:$";
3279 pw && pw -> pw_uid == 0, "pop", "tcp", NULL);
3282 0, "pop", "tcp", NULL);
3291 @*** empty log message ***
3305 static char ident[] = "@@(#)$Id:$";
3311 int pmbx_read (fp, pos, drops, noisy)
3322 p_parse(line, hl, pbuf)
3334 /*example T h u S e p 2 9 1 5 : 2 0 : 1 9 1 9 8 8 */
3335 char p_ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
3338 /* example T h u S e p 2 9 1 5 : 2 0 : 1 9 M S T 1 9 8 8 */
3339 char p_tmztyp[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
3361 static char ident[] = "@@(#)$Id:";
3367 @contrib'd fixes to make popd read UUCP as well as MMDF maildrops.
3376 @make mbx_size be pmbx_size for ANSI C
3381 if ((i = mbx_read (dp, pos, &rp, debug)) <= 0)
3384 return respond (NOTOK, "unable to create temporary file");
3396 static int setup(), setupaux(), read_map(), read_file(), mbx_size();
3399 Msgs[i].m_size = mbx_size (i);
3402 static int mbx_size (m)
3413 int user (), pass ();
3419 int status (), list (), retrieve (), delete (), reset ();
3420 int top (), last ();
3426 struct vector *getvector ();
3436 @*** empty log message ***
3448 @*** empty log message ***
3453 cp = sprintf (buffer + TRMLEN, fmt, a, b, c, d);