Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / support / pop / RCS / popser.c,v
1 head    1.34;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.34
9 date    95.12.07.18.54.35;      author jromine; state Exp;
10 branches;
11 next    1.33;
12
13 1.33
14 date    94.04.21.18.26.16;      author jromine; state Exp;
15 branches;
16 next    1.32;
17
18 1.32
19 date    94.04.21.18.20.15;      author jromine; state Exp;
20 branches;
21 next    1.31;
22
23 1.31
24 date    93.08.25.17.23.14;      author jromine; state Exp;
25 branches;
26 next    1.30;
27
28 1.30
29 date    92.12.16.22.31.20;      author jromine; state Exp;
30 branches;
31 next    1.29;
32
33 1.29
34 date    92.12.15.00.20.22;      author jromine; state Exp;
35 branches;
36 next    1.28;
37
38 1.28
39 date    92.12.14.17.49.09;      author jromine; state Exp;
40 branches;
41 next    1.27;
42
43 1.27
44 date    92.10.28.18.42.42;      author jromine; state Exp;
45 branches;
46 next    1.26;
47
48 1.26
49 date    92.10.26.16.45.35;      author jromine; state Exp;
50 branches;
51 next    1.25;
52
53 1.25
54 date    92.10.20.22.47.28;      author jromine; state Exp;
55 branches;
56 next    1.24;
57
58 1.24
59 date    92.05.19.20.59.21;      author jromine; state Exp;
60 branches;
61 next    1.23;
62
63 1.23
64 date    92.02.11.17.40.59;      author jromine; state Exp;
65 branches;
66 next    1.22;
67
68 1.22
69 date    92.02.10.22.35.58;      author jromine; state Exp;
70 branches;
71 next    1.21;
72
73 1.21
74 date    92.02.04.21.59.41;      author jromine; state Exp;
75 branches;
76 next    1.20;
77
78 1.20
79 date    92.02.04.21.44.56;      author jromine; state Exp;
80 branches;
81 next    1.19;
82
83 1.19
84 date    92.02.04.21.39.42;      author jromine; state Exp;
85 branches;
86 next    1.18;
87
88 1.18
89 date    92.02.03.17.52.59;      author jromine; state Exp;
90 branches;
91 next    1.17;
92
93 1.17
94 date    92.01.31.22.06.03;      author jromine; state Exp;
95 branches;
96 next    1.16;
97
98 1.16
99 date    90.11.16.14.56.38;      author mh;      state Exp;
100 branches;
101 next    1.15;
102
103 1.15
104 date    90.11.16.14.38.00;      author mh;      state Exp;
105 branches;
106 next    1.14;
107
108 1.14
109 date    90.11.05.16.04.57;      author mh;      state Exp;
110 branches;
111 next    1.13;
112
113 1.13
114 date    90.04.09.09.45.18;      author sources; state Exp;
115 branches;
116 next    1.12;
117
118 1.12
119 date    90.04.05.16.07.32;      author sources; state Exp;
120 branches;
121 next    1.11;
122
123 1.11
124 date    90.04.05.16.07.03;      author sources; state Exp;
125 branches;
126 next    1.10;
127
128 1.10
129 date    90.04.05.15.34.40;      author sources; state Exp;
130 branches;
131 next    1.9;
132
133 1.9
134 date    90.04.05.14.54.01;      author sources; state Exp;
135 branches;
136 next    1.8;
137
138 1.8
139 date    90.03.20.11.15.44;      author sources; state Exp;
140 branches;
141 next    1.7;
142
143 1.7
144 date    90.02.23.14.49.38;      author sources; state Exp;
145 branches;
146 next    1.6;
147
148 1.6
149 date    90.02.06.13.13.55;      author sources; state Exp;
150 branches;
151 next    1.5;
152
153 1.5
154 date    90.02.05.15.04.53;      author sources; state Exp;
155 branches;
156 next    1.4;
157
158 1.4
159 date    90.02.05.14.16.51;      author sources; state Exp;
160 branches;
161 next    1.3;
162
163 1.3
164 date    90.02.05.14.08.18;      author sources; state Exp;
165 branches;
166 next    1.2;
167
168 1.2
169 date    90.02.05.13.58.53;      author sources; state Exp;
170 branches;
171 next    1.1;
172
173 1.1
174 date    90.02.05.13.58.34;      author sources; state Exp;
175 branches;
176 next    ;
177
178
179 desc
180 @@
181
182
183 1.34
184 log
185 @include prototype for truncate() - 64biyt
186 @
187 text
188 @/* popser.c - the POP service */
189 #ifndef lint
190 static char ident[]="@@(#)$Id: popser.c,v 1.33 1994/04/21 18:26:16 jromine Exp jromine $";
191 #endif
192
193 #include "../h/mh.h"
194 #include "../h/dropsbr.h"
195 #ifdef  MPOP
196 #ifdef  BPOP
197 #include "../h/formatsbr.h"
198 #include "../h/scansbr.h"
199 #endif
200 #endif /* MPOP */
201 #include "../zotnet/bboards.h"
202 #include <stdio.h>
203 #include "../zotnet/mts.h"
204 #include <ctype.h>
205 #include <errno.h>
206 #include <pwd.h>
207 #include <signal.h>
208 #include "syslog.h"
209 #include <sys/types.h>
210 #include <sys/stat.h>
211 #ifdef UNISTD
212 #include <unistd.h>
213 #endif
214 #ifdef KPOP
215 #include <krb.h>
216 #endif  /* KPOP */
217 #ifdef  SYS5
218 #include <fcntl.h>
219 #endif  /* SYS5 */
220 #ifdef  SHADOW
221 #include <shadow.h>
222 #endif  /* SHADOW */
223
224
225 #define TRUE    1
226 #define FALSE   0
227
228 #define NVEC    5
229
230 #ifndef POPSERVICE
231 #define POPSERVICE      "pop"
232 #endif
233
234 /* \f */
235
236 extern int  errno;
237
238 extern int  debug;
239 extern char myhost[];
240 extern char *myname;
241
242 #ifndef POP2
243 static enum state {
244     auth1, auth2, trans, update, halt, error
245 } mystate;
246 #else
247 static enum state {
248     auth1, auth2, trans, mbox, item, ack, update, halt, error
249 } mystate;
250 #endif
251
252
253 static int     user (), pass ();
254 #ifdef  BPOP
255 static          isguest(), getbbmax();
256 #ifndef MPOP
257 static  int     xtnd1(), xtnd2();
258 #else
259 static  int     xtnd1(), xtnd2(), xtnd3 ();
260 #endif /* MPOP */
261 #endif  /* BPOP */
262 #ifdef  RPOP
263 static int      rpop ();
264 #endif  /* RPOP */
265 #ifdef  APOP
266 static  int     apop ();
267 #endif
268 static int     status (), list (), retrieve (), delete (), reset ();
269 static int      top (), last ();
270 #ifdef  BPOP
271 static int      xtnd ();
272 #endif  /* BPOP */
273 static int     quit ();
274 #ifdef  POP2
275 static int      helo (), rdp2 (), acks (), ack2 (), fold (), nack ();
276 #endif  /* POP2 */
277
278 static struct vector {
279     char   *v_cmd;
280     int     v_min, v_max;
281     int     (*v_vec) ();
282     enum state v_valid;
283     enum state v_win, v_lose;
284 }               vectors[] = {
285     "user", 1, 1, user, auth1, auth2, auth1,
286     "pass", 1, 1, pass, auth2, trans, auth1,
287 #ifdef  RPOP
288     "rpop", 1, 1, rpop, auth2, trans, auth1,
289 #endif  /* RPOP */
290 #ifdef  APOP
291     "apop", 2, 2, apop, auth1, trans, auth1,
292 #endif
293     "quit", 0, 0, NULL, auth1, halt, halt,
294     "quit", 0, 0, NULL, auth2, halt, halt,
295
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,
302
303     "top",  2, 2, top,  trans, trans, trans,
304     "last", 0, 0, last, trans, trans, trans,
305 #ifdef  BPOP
306 #ifndef MPOP
307     "xtnd", 1, 2, xtnd, trans, trans, trans,
308 #else
309     "xtnd", 1, 3, xtnd, trans, trans, trans,
310 #endif /* MPOP */
311 #endif  /* BPOP */
312     "quit", 0, 0, quit, trans, halt, halt,
313
314 #ifdef  POP2
315     "helo", 2, 2, helo, auth1, mbox, auth1,
316
317     "fold", 1, 1, fold, mbox, mbox, mbox,
318     "quit", 0, 0, quit, mbox, halt, halt,
319     "read", 0, 1, rdp2, mbox, item, error,
320
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,
325
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,
330
331 #endif  /* POP2 */
332     NULL
333 };
334
335 static struct vector  *getvector ();
336
337 /* \f */
338
339 #ifdef  POP2
340 static int pop2 = NOTOK;        /* current pop2 msg, or NOTOK if pop3 */
341 #endif  /* POP2 */
342 #ifdef  DPOP
343 static int pop_uid;
344 static int pop_gid;
345 #endif  /* DPOP */
346
347 static int  rproto;
348 static char *hostname;
349 static char server[BUFSIZ];
350 static char timestamp[BUFSIZ];
351
352 static char username[BUFSIZ];
353
354 static char maildrop[BUFSIZ];
355 static int  mode;
356 static time_t mtime;
357 static FILE *dp;
358
359 static long lastseen;
360 static int  rmsgs;
361
362 #ifdef  BPOP
363 static int xtnded;
364
365 static int guest_uid;
366 static int guest_gid;
367
368 static struct bboard *BBhead = NULL;
369 static struct bboard *BBtail = NULL;
370
371 static long BBtime = 0L;
372
373 static struct bboard *getbbaux ();
374 #endif  /* BPOP */
375
376
377 struct Msg {                    /* Msgs[0] contains info for entire maildrop */
378     struct drop m_drop;
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
384
385     unsigned    m_flags;
386 #define MNULL   0x00
387 #define MDELE   0x01
388 #define MREAD   0x02
389 };
390
391 static int nMsgs = 0;
392 static struct Msg *Msgs = NULL;
393
394 static int  nmsgs;
395 static int  dmsgs;
396 #ifdef  MPOP
397 #ifdef  BPOP
398 static int   _sc_width = 0;
399 static char *nfs = NULL;
400 #endif
401 #endif /* MPOP */
402
403
404 #define TRM     "."
405 #define TRMLEN  (sizeof TRM - 1)
406 #define IAC     255
407
408 static TYPESIG    pipeser ();
409
410 FILE   *input;
411 FILE   *output;
412
413 #ifndef __STDC__
414 #ifdef  SYS5
415 struct passwd *getpwnam();
416 #endif
417 #endif
418
419 void    padvise (), padios ();
420 char   *crypt ();
421
422 #ifdef  POPUUMBOX
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();
427 #else
428 #define MBX_READ        mbx_read
429 #endif
430 extern  int     mbx_read ();
431
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();
435 /* \f */
436
437 popinit () {
438 #ifdef  BPOP
439     padvise (NULLCP, LOG_INFO, "initialize list of BBoards");
440
441     BBhead = BBtail = NULL;
442     while (getbbaux (NULLCP))
443         continue;
444 #endif  /* BPOP */
445 }
446
447 popassert () {
448 #ifdef  BPOP
449     register char **p;
450     register struct bboard *bb,
451                            *bp;
452
453     if (BBtime == getbbtime ())
454         return;
455
456     padvise (NULLCP, LOG_INFO, "list of BBoards has changed");
457
458     for (bb = BBhead; bb; bb = bp) {
459         bp = bb -> bb_next;
460
461         if (bb -> bb_name)
462             free (bb -> bb_name);
463         if (bb -> bb_file)
464             free (bb -> bb_file);
465         if (bb -> bb_archive)
466             free (bb -> bb_archive);
467         if (bb -> bb_info)
468             free (bb -> bb_info);
469         if (bb -> bb_map)
470             free (bb -> bb_map);
471         if (bb -> bb_passwd)
472             free (bb -> bb_passwd);
473         if (bb -> bb_date)
474             free (bb -> bb_date);
475         if (bb -> bb_addr)
476             free (bb -> bb_addr);
477         if (bb -> bb_request)
478             free (bb -> bb_request);
479         if (bb -> bb_relay)
480             free (bb -> bb_relay);
481
482         for (p = bb -> bb_aka; *p; p++)
483             free (*p);
484         free ((char *) bb -> bb_aka);
485
486         for (p = bb -> bb_leader; *p; p++)
487             free (*p);
488         free ((char *) bb -> bb_leader);
489
490         for (p = bb -> bb_dist; *p; p++)
491             free (*p);
492         free ((char *) bb -> bb_dist);
493
494         free ((char *) bb);
495     }
496
497     BBhead = BBtail = NULL;
498     while (getbbaux (NULLCP))
499         continue;
500 #endif  /* BPOP */
501 }
502
503 /* \f */
504
505 #ifdef KPOP
506 static char *kusername;
507
508 kpop (in, out, principal, rhost, auth)
509 int   in,
510       out;
511 char  *principal, *rhost;
512 int auth;
513 #else   /* KPOP */
514 pop (in, out, priv, rhost)
515 int     in,
516         out,
517         priv;
518 char   *rhost;
519 #endif  /* KPOP */
520 {
521     char    buffer[BUFSIZ],
522            *vec[NVEC + 1];
523 #if     defined (DPOP) || defined (BPOP)
524     register struct passwd *pw;
525 #endif  /* defined (DPOP) || defined (BPOP) */
526     register struct vector *v;
527
528     m_foil (NULLCP);
529     mts_init (myname);
530
531     hostname = rhost;
532 #ifdef KPOP
533     rproto = 1;
534     (void) sprintf (server, "%s KPOP server", myhost);
535 #else
536     rproto = priv;
537     (void) sprintf (server, "%s server", priv ? "RPOP" : "POP");
538 #endif  /* KPOP */
539
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);
543         return;
544     }
545     (void) signal (SIGPIPE, pipeser);
546 #ifdef KPOP
547     if (principal == NULLCP) {
548         char buf[512];
549         strcpy(buf,  "Authentication failed: ");
550         strcat(buf, krb_err_txt[auth]);
551         (void) respond (NOTOK, buf);
552         return;
553     }
554     kusername = principal;
555 #endif  /* KPOP */
556
557 #ifdef  DPOP
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");
561         return;
562     }
563     pop_uid = pw -> pw_uid;
564     pop_gid = pw -> pw_gid;
565 #endif  /* DPOP */
566 #ifdef  BPOP
567     if ((pw = getpwnam (popbbuser)) && pw -> pw_uid) {
568         guest_uid = pw -> pw_uid;
569         guest_gid = pw -> pw_gid;
570     }
571     else
572         guest_uid = guest_gid = 0;
573 #endif  /* BPOP */
574
575     {
576         long    clock;
577
578         (void) time (&clock);
579         (void) sprintf (timestamp, "<%d.%ld@@%s>", getpid (), clock, myhost);
580     }
581     (void) respond (OK, "%s ready %s", server, timestamp);
582
583     for (mystate = auth1; mystate != halt && mystate != error;)
584         switch (getline (buffer, sizeof buffer, input)) {
585             case OK: 
586                 if ((v = getvector (buffer, vec)) == NULL)
587                     continue;
588                 mystate = (v -> v_vec ? (v -> v_vec) (vec)
589                         : respond (OK, NULLCP)) == OK
590                     ? v -> v_win
591                     : v -> v_lose;
592                 break;
593
594             case NOTOK: 
595             case DONE: 
596                 mystate = error;
597                 (void) respond (NOTOK, "%s signing off", server);
598                 break;
599         }
600 }
601
602 /* \f */
603 #ifdef  POP2
604 static int  helo (vec)          /* sort of "user" and "pass" */
605 register char  **vec;
606 {
607     pop2 = 0;                           /* now we're talkin' pop2! */
608     make_lower (username, vec[1]);      /* helo user pass */
609     return pass (++vec);                /* user pass */
610 }
611 #endif
612
613 static int  user (vec)
614 register char  **vec;
615 {
616     make_lower (username, vec[1]);
617 #ifdef KPOP
618     if (!strcmp(username, kusername))
619       return respond (OK, "Kerberos authentication succeeded. Send username as password (%s)", username);
620     else {
621         respond (NOTOK, "Wrong username supplied (%s vs. %s)",
622                  kusername, username);
623         return (NOTOK);
624     }
625 #else
626     return respond (OK, "password required for %s", username);
627 #endif
628 }
629
630 /* \f */
631
632 static int  pass (vec)
633 register char  **vec;
634 {
635     int guest = 0;
636 #ifndef DPOP
637     register struct passwd *pw;
638 #ifdef  SHADOW
639     register struct spwd *shpw;
640 #endif  /* SHADOW */
641 #else   /* DPOP */
642     register struct bboard *pw;
643 #endif  /* DPOP */
644
645 #ifdef KPOP
646 #ifndef DPOP
647     if ((pw = getpwnam (username)) != NULL)
648       return setup(pw, FALSE);
649     else
650       return respond (NOTOK, "no local password entry");
651 #else
652     {
653       static struct bboard entry;
654       static char entry_file[BUFSIZ] = "/usr/spool/pop";
655       
656       pw = &entry;
657       pw->bb_name = username;
658       strcat(entry_file, username);
659       pw->bb_file = entry_file;
660       return setup(pw, FALSE);
661     }
662 #endif
663 #else   /* KPOP */
664
665 #ifndef DPOP
666 #ifdef  BPOP
667     if (isguest ()) {
668 #ifdef  TRUSTED
669         static passwd gw;
670
671         gw.pw_name = popbbuser;
672         gw.pw_uid = guest_uid;
673         pw = &gw;
674 #endif  /* TRUSTED */
675         guest = 1;
676         goto anonymous;
677     }
678 #endif  /* BPOP */
679     if ((pw = getpwnam (username)) == NULL
680 #ifndef SHADOW
681             || *pw -> pw_passwd == NULL
682             || strcmp (crypt (vec[1], pw -> pw_passwd), pw -> pw_passwd)) {
683 #else   /* SHADOW */
684             || (shpw = getspnam (username)) == NULL
685             || *shpw -> sp_pwdp == NULL
686             || strcmp (crypt (vec[1], shpw -> sp_pwdp), shpw -> sp_pwdp)) {
687 #endif  /* SHADOW */
688 #ifdef  TRUSTED
689         trusted (0, hostname, NULLCP, 0, pw ? pw -> pw_name : username,
690             pw && pw -> pw_uid == 0, POPSERVICE, "tcp", NULL);
691 #endif  /* TRUSTED */
692         return respond (NOTOK, "login incorrect");
693     }
694 #else   /* DPOP */
695 #ifdef  BPOP
696     if (isguest ()) {
697         static struct bboard gw;
698
699         gw.bb_name = popbbuser;
700         pw = &gw;
701         guest = 1;
702         goto anonymous;
703     }
704 #endif  /* BPOP */
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)) {
709 #ifdef  TRUSTED
710         trusted (0, hostname, NULLCP, 0, pw ? pw -> bb_name : username,
711             0, POPSERVICE, "tcp", NULL);
712 #endif  /* TRUSTED */
713         return respond (NOTOK, "login incorrect");
714     }
715 #endif  /* DPOP */
716
717 #ifdef  BPOP
718 anonymous: ;
719 #endif  /* BPOP */
720 #ifdef  TRUSTED
721     if (trusted (1, hostname, NULLCP, 0, myhost,
722 #ifndef DPOP
723                 pw -> pw_name, pw -> pw_uid == 0,
724 #else   /* DPOP */
725                 pw -> bb_name, 0,
726 #endif  /* DPOP */
727                 POPSERVICE, "tcp", NULL)
728             == 0)
729         return respond (NOTOK, "permission denied");
730 #endif  /* TRUSTED */
731     return setup (pw, guest);
732 #endif /* KPOP */
733 }
734
735 /* \f */
736
737 #ifdef  BPOP
738 static  isguest () {
739     int     i;
740     register char  *cp;
741     char    buffer[BUFSIZ];
742     register FILE  *fp;
743
744     if (strcmp (username, popbbuser) || !guest_uid)
745         return FALSE;
746     if (popbblist == NULL || (fp = fopen (popbblist, "r")) == NULL)
747         return TRUE;
748
749     i = FALSE;
750     if (hostname)
751         while (fgets (buffer, sizeof buffer, fp)) {
752             if (cp = index (buffer, '\n'))
753                 *cp = NULL;
754             if (strcmp (buffer, hostname) == 0) {
755                 i = TRUE;
756                 break;
757             }
758         }
759
760     (void) fclose (fp);
761
762     return i;
763 }
764 #endif  /* BPOP */
765
766 /* \f */
767
768 #ifdef  RPOP
769 static int rpop (vec)
770 register char  **vec;
771 {
772 #ifndef DPOP
773     register struct passwd *pw;
774 #else   /* DPOP */
775     register int hostok = 0;
776     register char  *bp,
777                    *cp;
778     char    buffer[BUFSIZ];
779     register struct bboard *pw;
780 #endif  /* DPOP */
781
782 #ifndef DPOP
783     if (!rproto || (pw = getpwnam (username)) == NULL) {
784 #ifdef  TRUSTED
785         trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp",
786             NULL);
787 #endif  /* TRUSTED */
788         return respond (NOTOK, "login incorrect");
789     }
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) {
793 #ifdef  TRUSTED
794         trusted (0, hostname, vec[1], 0, pw -> pw_name,
795            pw -> pw_uid == 0, "rpop", "tcp", NULL);
796 #endif  /* TRUSTED */
797         return respond (NOTOK, "permission denied");
798     }
799 #else   /* DPOP */
800     if (!rproto
801             || ((pw = getbbnam (username)) == NULL
802                 && (pw = getbbaka (username)) == NULL)) {
803 #ifdef  TRUSTED
804         trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp",
805             NULL);
806 #endif  /* TRUSTED */
807         return respond (NOTOK, "login incorrect");
808     }
809 /*
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
813  */
814     (void) sprintf (buffer, "%s@@%s", vec[1], hostname);
815     for (bp = pw -> bb_addr; bp; bp = cp) {
816         if ((cp = index (bp, ',')))
817             *cp = 0;
818         hostok = uleq (bp, buffer);
819         if (cp)
820             *cp++ = ',';
821         if (hostok)
822             break;
823     }
824     if (!hostok) {
825 #ifdef  TRUSTED
826         trusted (0, hostname, vec[1], 0, pw -> bb_name, 0, "rpop",
827             "tcp", NULL);
828 #endif  /* TRUSTED */
829         return respond (NOTOK, "permission denied");
830     }
831 #endif  /* DPOP */
832
833 #ifdef  TRUSTED
834     if (trusted (1, hostname, vec[1], 0, username,
835 #ifndef DPOP
836                 pw -> pw_uid == 0,
837 #else   /* DPOP */
838                 0,
839 #endif  /* DPOP */
840                 "rpop", "tcp", NULL)
841             == 0)
842         return respond (NOTOK, "permission denied");
843 #endif  /* TRUSTED */
844     return setup (pw, FALSE);
845 }
846 #endif  /* RPOP */
847
848 /* \f */
849
850 #ifdef  APOP
851 #include "popauth.h"
852 #include "../../uip/md5.c"
853 #include <ndbm.h>
854 #include <sys/file.h>
855 #ifdef  SYS5
856 #include <fcntl.h>
857 #endif
858
859
860 static int apop (vec)
861 register char  **vec;
862 {
863     register char *cp;
864     char    buffer[BUFSIZ];
865     register unsigned char *dp;
866     unsigned char *ep,
867                    digest[16];
868 #ifndef DPOP
869     register struct passwd *pw;
870 #else
871     register struct bboard *pw;
872 #endif
873     struct stat st;
874     datum   key,
875             value;
876     DBM    *db;
877     MD5_CTX mdContext;
878     struct authinfo auth;
879
880     (void) strcpy (username, vec[1]);
881
882 #ifndef DPOP
883     if ((pw = getpwnam (username)) == NULL
884             || *pw -> pw_passwd == NULL) {
885         return respond (NOTOK, "user invalid");
886     }
887 #else
888     if (((pw = getbbnam (username)) == NULL
889                 && (pw = getbbaka (username)) == NULL)
890             || *pw -> bb_passwd == NULL) {
891         return respond (NOTOK, "subscriber invalid");
892     }
893 #endif
894
895     if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL)
896         return respond (NOTOK, "POP authorization DB not available (%d)",
897                         errno);
898     if (fstat (dbm_pagfno (db), &st) != NOTOK
899             && (st.st_mode & 0777) != 0600) {
900         dbm_close (db);
901         return respond (NOTOK, "POP authorization DB has wrong mode (0%o)",
902                         st.st_mode & 0777);
903     }
904     if (flock (dbm_pagfno (db), LOCK_SH) == NOTOK) {
905         dbm_close (db);
906         return respond (NOTOK, "unable to lock POP authorization DB (%d)",
907                         errno);
908     }
909     key.dsize = strlen (key.dptr = vec[1]) + 1;
910     value = dbm_fetch (db, key);
911     if (value.dptr == NULL) {
912         dbm_close (db);
913         return respond (NOTOK, "not authorized");
914     }
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);
918
919     dbm_close (db);
920
921     MD5Init (&mdContext);
922     MD5Update (&mdContext, (unsigned char *) buffer,
923                (unsigned int) (strlen (timestamp) + auth.auth_secretlen));
924     MD5Final (digest, &mdContext);
925
926     cp = buffer;
927     for (ep = (dp = digest) + sizeof digest / sizeof digest[0];
928              dp < ep;
929              cp += 2)
930         (void) sprintf (cp, "%02x", *dp++ & 0xff);
931     *cp = NULL;
932
933     if (strcmp (vec[2], buffer))
934         return respond (NOTOK, "authentication failure");
935
936     return setup (pw, 0);
937 }
938 #endif
939
940 /* \f */
941
942 static int setup (pw, guest)
943 #ifndef DPOP
944 register struct passwd *pw;
945 #else   /* DPOP */
946 register struct bboard *pw;
947 #endif  /* DPOP */
948 int     guest;
949 {
950 #ifdef  BPOP
951     if (guest) {
952         (void) setgid (guest_gid);
953 #ifndef SYS5
954         (void) initgroups (popbbuser, guest_gid);
955 #endif  /* SYS5 */
956         (void) setuid (guest_uid);
957     }
958     else {
959 #endif  /* BPOP */
960 #ifndef DPOP
961         (void) setgid (pw -> pw_gid);
962 #ifndef SYS5
963         (void) initgroups (pw -> pw_name, pw -> pw_gid);
964 #endif  /* SYS5 */
965         (void) setuid (pw -> pw_uid);
966 #else   /* DPOP */
967         (void) setgid (pop_gid);
968 #ifndef SYS5
969         (void) initgroups (POPUID, pop_gid);
970 #endif  /* SYS5 */
971         (void) setuid (pop_uid);
972 #endif  /* DPOP */
973 #ifdef  BPOP
974     }
975 #endif  /* BPOP */
976
977 #ifndef DPOP
978     (void) sprintf (maildrop, "%s/%s",
979             mmdfldir && *mmdfldir ? mmdfldir : pw -> pw_dir,
980             mmdflfil && *mmdflfil ? mmdflfil : pw -> pw_name);
981 #else   /* DPOP */
982     (void) strcpy (maildrop, pw -> bb_file);
983 #endif  /* DPOP */
984
985     if (setupaux (guest) == NOTOK)
986         return NOTOK;
987
988 #ifdef  POP2
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);
993     }
994     else
995 #endif  /* POP2 */
996     return respond (OK,
997             nmsgs ? "maildrop has %d message%s (%d octets)" : "maildrop empty",
998             nmsgs, nmsgs != 1 ? "s" : "", Msgs[0].m_size);
999 }
1000
1001 /* \f */
1002
1003 static int  setupaux (readonly)
1004 int     readonly;
1005 {
1006     register int    i,
1007                     msgp;
1008     struct stat st;
1009
1010 #ifdef  BPOP
1011     xtnded = 0;
1012 #endif  /* BPOP */
1013     if ((dp = readonly ? fopen (maildrop, "r") : lkfopen (maildrop, "r"))
1014             == NULL)
1015         switch (errno) {
1016             case ENOENT: 
1017                 m_gMsgs (msgp = 0);
1018                 goto no_mail;
1019
1020             default: 
1021                 nmsgs = dmsgs = 0;
1022                 return respond (NOTOK, "unable to %s maildrop: \"%s\"",
1023                         readonly ? "read" : "lock", maildrop);
1024         }
1025
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);
1029     }
1030     else {
1031         mode = 0600, mtime = 0;
1032         msgp = 0;
1033     }
1034
1035     if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1)
1036         m_gMsgs (0);
1037
1038 no_mail: ;
1039     lastseen = Msgs[0].m_last;
1040 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: lastseen=%d",lastseen);
1041     dmsgs = rmsgs = 0;
1042     nmsgs = msgp;
1043
1044     Msgs[0].m_flags = readonly ? MREAD : MNULL;
1045     Msgs[0].m_size = 0;
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;
1051     }
1052
1053     return OK;
1054 }
1055
1056 /* \f */
1057
1058 static int  read_map (file, pos)
1059 char   *file;
1060 long    pos;
1061 {
1062     register int    i,
1063                     msgp;
1064     register struct drop   *pp,
1065                            *mp;
1066     struct drop *rp;
1067
1068     if (debug)
1069         padvise (NULLCP, LOG_DEBUG, "read_map (%s, %ld)", file, pos);
1070
1071     if ((i = map_read (file, pos, &rp, debug)) == 0)
1072         return 0;
1073
1074     m_gMsgs (i);
1075
1076     Msgs[0].m_last = rp -> d_start;
1077
1078     msgp = 1;
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;
1085     }
1086     free ((char *) rp);
1087
1088     if (Msgs[0].m_last > msgp) {
1089         if (debug)
1090             padvise (NULLCP, LOG_DEBUG, "lastseen adjusted from %d to %d",
1091                 Msgs[0].m_last, msgp);
1092         Msgs[0].m_last = msgp;
1093     }
1094
1095     return (msgp - 1);
1096 }
1097
1098 /* \f */
1099
1100 static int  read_file (pos, msgp)
1101 register long   pos;
1102 register int    msgp;
1103 {
1104     register int    i;
1105     register struct drop   *pp,
1106                            *mp;
1107     struct drop *rp;
1108
1109     if (debug)
1110         padvise (NULLCP, LOG_DEBUG, "read_file (%ld, %d)",
1111                 pos, msgp);
1112
1113     if ((i = MBX_READ (dp, pos, &rp, debug)) <= 0)
1114         return (msgp - 1);
1115
1116     m_gMsgs ((msgp - 1) + i);
1117
1118     for (pp = rp; i-- > 0; msgp++, pp++) {
1119         mp = &Msgs[msgp].m_drop;
1120         mp -> d_id = 0;
1121         mp -> d_size = pp -> d_size;
1122         mp -> d_start = pp -> d_start;
1123         mp -> d_stop = pp -> d_stop;
1124     }
1125     free ((char *) rp);
1126
1127     return (msgp - 1);
1128 }
1129
1130 /* \f */
1131
1132 static m_gMsgs (n)
1133 int     n;
1134 {
1135     if (debug)
1136         padvise (NULLCP, LOG_DEBUG, "m_gMsgs (%d) 0x%x %d",
1137                 n, Msgs, nMsgs);
1138
1139     if (Msgs == NULL) {
1140         nMsgs = n + MAXFOLDER / 2;
1141         Msgs = (struct Msg *) calloc ((unsigned) (nMsgs + 2), sizeof *Msgs);
1142         if (Msgs == NULL)
1143             padios (NULLCP, "unable to allocate Msgs structure");
1144         return;
1145     }
1146
1147     if (nMsgs >= n)
1148         return;
1149
1150     nMsgs = n + MAXFOLDER / 2;
1151     Msgs = (struct Msg *) realloc ((char *) Msgs,
1152                                 (unsigned) (nMsgs + 2) * sizeof *Msgs);
1153     if (Msgs == NULL)
1154         padios (NULLCP, "unable to reallocate Msgs structure");
1155 }
1156
1157 /* \f */
1158
1159 static int  pmbx_size (m)
1160 register int     m;
1161 {
1162     register int    i;
1163     register long   pos;
1164
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')
1168             i++;
1169
1170     return i;
1171 }
1172
1173 /* \f */
1174
1175 /* ARGSUSED */
1176
1177 static int  status (vec)
1178 char  **vec;
1179 {
1180     return respond (OK, "%d %d", nmsgs - dmsgs, Msgs[0].m_size);
1181 }
1182
1183
1184 #ifdef  POP2
1185 static int  rdp2 (vec)          /* always returns OK */
1186 char  **vec;
1187 {
1188     if (vec[1]) {
1189         if ((pop2 = atoi (vec[1])) <= 0)
1190             pop2 = 0;
1191     }
1192     else if (pop2 == 0)
1193         return NOTOK;           /* close 'em down */
1194
1195     if (pop2 <= 0 || pop2 > nmsgs) {
1196         pop2 = 0;
1197         return respond ('=', "0 no message"); 
1198     }
1199     if (Msgs[pop2].m_flags & MDELE) {
1200         pop2 = 0;
1201         return respond ('=', "0 message %d is deleted", pop2);
1202     }
1203
1204     return respond ('=', "%d (message %d)", Msgs[pop2].m_size, pop2);
1205 }
1206
1207 static int  ack2 (vec)
1208 char   **vec;
1209 {
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;
1213         dmsgs++;
1214     }
1215
1216     if (pop2) {         /* a current msg */
1217         rmsgs++;                        /* mark this one as read */
1218         if (++pop2 > nmsgs)
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;
1224     }
1225     return rdp2 (vec);          /* vec = { "acks", 0 } */
1226 }
1227
1228 static int  fold (vec)
1229 register char  **vec;
1230 {
1231     pop2 = 0;
1232
1233 #ifdef  notdef          
1234
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.
1237  * 16Nov90/JLR
1238  */
1239    
1240     if (quitaux (NULLVP) == NOTOK)
1241         return respond ('#', "0 unable to close folder");
1242     
1243     (void) sprintf (maildrop, vec[1]);
1244     if (setupaux (access (maildrop, 2) ? 1 : 0) == NOTOK)
1245         return respond ('#', "0 unable to read %s", maildrop);
1246
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);
1250     
1251 #endif
1252
1253     respond ('#', "0 unable to change folders");
1254     return NOTOK;
1255 }
1256 #endif  /* POP2 */
1257
1258 static int  list (vec)
1259 register char  **vec;
1260 {
1261     register int    i;
1262
1263     if (vec[1]) {
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);
1268
1269 #ifndef BPOP
1270         return respond (OK, "%d %d", i, Msgs[i].m_size);
1271 #else   /* BPOP */
1272 #ifdef  MPOP
1273         if (nfs && !xtnded) {
1274             char   *cp;
1275
1276             (void) fseek (dp, Msgs[i].m_start, 0);
1277
1278             switch (scan (dp, i, 0, nfs, 0, 0, 0,
1279                     0, NULLCP, (long) Msgs[i].m_size, 0)) {
1280                 case SCNMSG:
1281                 case SCNENC:
1282                 case SCNERR:
1283                     if (cp = index (scanl, '\n'))
1284                         *cp = NULL;
1285                     return respond (OK, "%d %d #%s",
1286                                     i, Msgs[i].m_size, scanl);
1287
1288                 case SCNEOF:
1289                     return respond (OK, "%d %d #%*d  empty",
1290                                     i, Msgs[i].m_size, DMAXFOLDER, i);
1291
1292                 default:
1293                     break;
1294             }
1295         }
1296 #endif /* MPOP */
1297         return respond (OK, xtnded ? "%d %d %d" : "%d %d",
1298                         i, Msgs[i].m_size, Msgs[i].m_id);
1299 #endif  /* BPOP */
1300     }
1301
1302     (void) respond (OK, "%d message%s (%d octets)",
1303             nmsgs - dmsgs, nmsgs - dmsgs != 1 ? "s" : "",
1304             Msgs[0].m_size);
1305     for (i = 1; i <= nmsgs; i++)
1306         if (!(Msgs[i].m_flags & MDELE)) {
1307 #ifndef BPOP
1308             multiline ("%d %d", i, Msgs[i].m_size);
1309 #else   /* BPOP */
1310 #ifdef  MPOP
1311             if (nfs && !xtnded) {
1312                 char   *cp;
1313
1314                 (void) fseek (dp, Msgs[i].m_start, 0);
1315
1316                 switch (scan (dp, i, 0, nfs, 0, 0, 0, 
1317                         0, NULLCP, (long) Msgs[i].m_size, 0)) {
1318                     case SCNMSG:
1319                     case SCNENC:
1320                     case SCNERR:
1321                         if (cp = index (scanl, '\n'))
1322                             *cp = NULL;
1323                         multiline ("%d %d #%s",
1324                                    i, Msgs[i].m_size, scanl);
1325                         continue;
1326
1327                     case SCNEOF:
1328                         multiline ("%d %d #%*d  empty",
1329                                    i, Msgs[i].m_size, DMAXFOLDER, i);
1330                         continue;
1331
1332                     default:
1333                         break;
1334                 }
1335             }
1336 #endif /* MPOP */
1337             multiline (xtnded ? "%d %d %d" : "%d %d",
1338                        i, Msgs[i].m_size, Msgs[i].m_id);
1339 #endif  /* BPOP */
1340         }
1341     multiend ();
1342
1343     return OK;
1344 }
1345
1346 /* \f */
1347
1348 static int  retrieve (vec)
1349 register char  **vec;
1350 {
1351     register int    i;
1352     register long   pos;
1353     register char  *cp;
1354     char    buffer[BUFSIZ];
1355
1356 #ifdef  POP2
1357   if (pop2 == 0)
1358     return NOTOK;
1359   else if (pop2 == NOTOK) {
1360 #endif
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);
1365
1366     (void) respond (OK, "%d octets", Msgs[i].m_size);
1367 #ifdef  POP2
1368   }
1369   else          /* if called by pop2, vec = { "retr", 0 } */
1370     i = pop2;
1371 #endif
1372
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')
1377             *cp = 0;
1378         multiline ("%s", buffer);
1379     }
1380 #ifdef  POP2
1381   if (pop2 == NOTOK) {          /* then multiend */
1382 #endif
1383     multiend ();
1384
1385     if (i > Msgs[0].m_last) {
1386         Msgs[0].m_last = i; 
1387         rmsgs++;
1388     }
1389 #ifdef  POP2
1390   }
1391 #endif
1392
1393     return OK;
1394 }
1395
1396 /* \f */
1397
1398 static int  delete (vec)
1399 register char   **vec;
1400 {
1401     register int    i;
1402
1403     if (Msgs[0].m_flags & MREAD)
1404         return respond (NOTOK, "maildrop is read-only");
1405
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);
1410
1411     Msgs[i].m_flags |= MDELE;
1412     Msgs[0].m_size -= Msgs[i].m_size;
1413     dmsgs++;
1414
1415     if (i > Msgs[0].m_last)
1416         Msgs[0].m_last = i;
1417
1418     return respond (OK, "message %d deleted (%d octets)", i, Msgs[i].m_size);
1419 }
1420
1421
1422 static int  reset (vec)
1423 char   **vec;
1424 {
1425     register int    i;
1426
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;
1431             dmsgs--;
1432         }
1433
1434     Msgs[0].m_last = lastseen;
1435
1436 #ifdef  MPOP
1437 #ifdef  BPOP
1438     if (nfs) {
1439         if (scanl)
1440             free (scanl), scanl = NULL;
1441         free (nfs), nfs = NULL;
1442     }
1443 #endif
1444 #endif /* MPOP */
1445
1446     return status (vec);
1447 }
1448
1449 /* \f */
1450
1451 static int  top (vec)
1452 register char  **vec;
1453 {
1454     register int    i,
1455                     j,
1456                     body,
1457                     lines;
1458     register long   pos;
1459     register char  *cp;
1460     char    buffer[BUFSIZ];
1461
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]);
1468
1469     (void) respond (OK, vec[0]);
1470
1471     body = lines = 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')
1476             *cp = 0;
1477         if (body) {
1478             if (lines++ >= j)
1479                 break;
1480         }
1481         else
1482             if (*buffer == 0)
1483                 body++;
1484         multiline ("%s", buffer);
1485     }
1486     multiend ();
1487
1488     return OK;
1489 }
1490
1491 /* \f */
1492
1493 /* ARGSUSED */
1494
1495 static int  last (vec)  
1496 char  **vec;
1497 {
1498     return respond (OK, "%d is the last msg seen", Msgs[0].m_last);
1499 }
1500
1501 /* \f */
1502
1503 #ifdef  BPOP
1504 static int  xtnd (vec)
1505 register char    **vec;
1506 {
1507     make_lower (vec[1], vec[1]);
1508
1509     if (strcmp (vec[1], "bboards") == 0 || strcmp (vec[1], "archive") == 0)
1510         return xtnd1 (vec);
1511     if (strcmp (vec[1], "x-bboards") == 0)
1512         return xtnd2 (vec);
1513 #ifdef  MPOP
1514     if (strcmp (vec[1], "scan") == 0)
1515         return xtnd3 (vec);
1516 #endif /* MPOP */
1517
1518     return respond (NOTOK, "unknown XTND command: \"%s\"", vec[1]);
1519 }
1520
1521
1522 static int  xtnd1 (vec)
1523 register char    **vec;
1524 {
1525     register struct bboard *bb;
1526
1527     if (vec[2]) {
1528         make_lower (vec[2], vec[2]);
1529         if ((bb = getbbaux (vec[2])) == NULL)
1530             return respond (NOTOK, "unknown BBoard: \"%s\"", vec[2]);
1531
1532         if (quitaux (NULLVP) == NOTOK)
1533             return NOTOK;
1534         (void) strcpy (maildrop,
1535                 strcmp (vec[1], "bboards") ? bb -> bb_archive : bb -> bb_file);
1536         if (setupaux (TRUE) == NOTOK)
1537             return NOTOK;
1538         xtnded++;
1539         (void) respond (OK, "%s", vec[1]);
1540         multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
1541     }
1542     else {
1543         if (strcmp (vec[1], "bboards"))
1544             return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
1545
1546         (void) respond (OK, "%s", vec[1]);
1547         for (bb = BBhead; bb; bb = bb -> bb_next) {
1548             getbbmax (bb);
1549             if (!(bb -> bb_flags & BB_INVIS))
1550                 multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
1551         }
1552         while (bb = getbbaux (NULLCP))
1553             if (!(bb -> bb_flags & BB_INVIS))
1554                 multiline ("%s %d", bb -> bb_name, bb -> bb_maxima);
1555     }
1556     multiend ();
1557
1558     return OK;
1559 }
1560
1561 /* \f */
1562
1563 static int  xtnd2 (vec)
1564 register char     **vec;
1565 {
1566     register char  *cp,
1567                   **ap;
1568     char    buffer[BUFSIZ];
1569     register struct bboard *bb;
1570
1571     if (vec[2] == NULL)
1572         return respond (NOTOK, "too few arguments to XTND \"%s\"", vec[1]);
1573
1574     make_lower (vec[2], vec[2]);
1575     if ((bb = getbbaux (vec[2])) == NULL)
1576         return respond (NOTOK, "unknown BBoard: \"%s\"", vec[2]);
1577
1578     (void) respond (OK, "%s", vec[1]);
1579     multiline ("%s", bb -> bb_name);
1580
1581     cp = buffer;
1582     for (ap = bb -> bb_aka; *ap; ap++) {
1583         (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
1584         cp += strlen (cp);
1585     }
1586     multiline ("%s", buffer);
1587
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);
1593
1594     cp = buffer;
1595     for (ap = bb -> bb_leader; *ap; ap++) {
1596         (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
1597         cp += strlen (cp);
1598     }
1599     multiline ("%s", buffer);
1600
1601     multiline ("%s", bb -> bb_addr);
1602     multiline ("%s", bb -> bb_request);
1603     multiline ("%s", bb -> bb_relay);
1604
1605     cp = buffer;
1606     for (ap = bb -> bb_dist; *ap; ap++) {
1607         (void) sprintf (cp, cp != buffer ? " %s" : "%s", *ap);
1608         cp += strlen (cp);
1609     }
1610     multiline ("%s", buffer);
1611
1612     getbbmax (bb);
1613     multiline ("0%o %d", bb -> bb_flags, bb -> bb_maxima);
1614     multiline ("%s", bb -> bb_date);
1615
1616     multiend ();
1617
1618     return OK;
1619 }
1620
1621 /* \f */
1622
1623 static struct bboard *getbbaux (s)
1624 register char   *s;
1625 {
1626     register struct bboard *bb;
1627     struct stat st;
1628
1629     if (BBhead == NULL)
1630         if (setbbinfo (BBOARDS, BBDB, 1))
1631             BBtime = getbbtime ();
1632         else
1633             return NULL;
1634
1635     if (s != NULLCP)
1636         for (bb = BBhead; bb; bb = bb -> bb_next)
1637             if (strcmp (bb -> bb_name, s) == 0) {
1638                 if (debug)
1639                     padvise (NULLCP, LOG_DEBUG, "getbbaux: \"%s\" from cache",
1640                             bb -> bb_name);
1641                 getbbmax (bb);
1642                 return bb;
1643             }
1644
1645     while (bb = getbbent ()) {
1646         if ((bb = getbbcpy (bb)) == NULL)
1647             return NULL;
1648
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;
1652
1653         if (BBtail != NULL)
1654             BBtail -> bb_next = bb;
1655         if (BBhead == NULL)
1656             BBhead = bb;
1657         BBtail = bb;
1658
1659         if (s == NULL || strcmp (bb -> bb_name, s) == 0) {
1660             if (s && debug)
1661                 padvise (NULLCP, LOG_DEBUG, "getbbaux: \"%s\" from scratch",
1662                         bb -> bb_name);
1663             return bb;
1664         }
1665     }
1666
1667     return NULL;
1668 }
1669
1670 /* \f */
1671
1672 static  getbbmax (bb)
1673 register struct bboard *bb;
1674 {
1675     int     i;
1676     register char  *cp;
1677     char    buffer[BUFSIZ];
1678     struct stat st;
1679     register    FILE * fp;
1680
1681     if (debug)
1682         padvise (NULLCP, LOG_DEBUG, "getbbmax: \"%s\", 0%o, %d, %s",
1683                 bb -> bb_name, bb -> bb_flags, bb -> bb_maxima, bb -> bb_date);
1684
1685     if (!(bb -> bb_flags & BB_INVIS)
1686             && access (bb -> bb_file, 04) == NOTOK && errno == EACCES)
1687         bb -> bb_flags |= BB_INVIS;
1688
1689     if (stat (bb -> bb_info, &st) == NOTOK
1690             || bb -> bb_mtime == st.st_mtime
1691             || (fp = fopen (bb -> bb_info, "r")) == NULL)
1692         return;
1693     bb -> bb_mtime = st.st_mtime;
1694
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)) {
1698         if (bb -> bb_date)
1699             free (bb -> bb_date);
1700         if (cp = index (buffer, '\n'))
1701             *cp = NULL;
1702         bb -> bb_date = getcpy (buffer);
1703     }
1704
1705     (void) fclose (fp);
1706
1707     if (debug)
1708         padvise (NULLCP, LOG_DEBUG, "updated: \"%s\", 0%o, %d, %s",
1709                 bb -> bb_name, bb -> bb_flags, bb -> bb_maxima, bb -> bb_date);
1710 }
1711
1712 /* \f */
1713
1714 #ifdef  MPOP
1715 static int xtnd3 (vec)
1716 register char **vec;
1717 {
1718     if (vec[2] == NULL)
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);
1723     if (scanl)
1724         (void) free (scanl), scanl = NULL;
1725
1726     return respond (OK, vec[1]);
1727 }
1728
1729 int     sc_width () { return _sc_width; }
1730 #endif /* MPOP */
1731 #endif  /* BPOP */
1732
1733 /* \f */
1734
1735 static int  quit (vec)
1736 char   **vec;
1737 {
1738     int     d,
1739             n;
1740
1741     d = dmsgs, n = nmsgs;
1742
1743     if (quitaux (vec) == NOTOK)
1744         return NOTOK;
1745
1746 #ifdef  BPOP
1747     if (xtnded)
1748         return respond (OK, "%s signing off", server);
1749 #endif  /* BPOP */
1750
1751     if (n == d)
1752         return respond (OK, "%s signing off (maildrop empty)", server);
1753
1754     return respond (OK,
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);
1758 }
1759
1760
1761 static int  quitaux (vec)
1762 char   **vec;
1763 {
1764     int     i;
1765
1766     if (dp == NULL)
1767         return OK;
1768
1769     i = quitfile (vec);
1770
1771     nmsgs = dmsgs = rmsgs = 0;
1772     (void) lkfclose (dp, maildrop);
1773     dp = NULL;
1774
1775     return i;
1776 }
1777
1778 /* \f */
1779
1780 /* ARGSUSED */
1781
1782 static int  quitfile (vec)
1783 char   **vec;
1784 {
1785     register int    i,
1786                     j,
1787                     tmpDR,
1788                     md;
1789     char    tmpfil[BUFSIZ],
1790             map1[BUFSIZ],
1791             map2[BUFSIZ];
1792     struct stat st;
1793
1794 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: dmsgs=%d rmsgs=%d readonly=%d",
1795                  dmsgs, rmsgs, Msgs[0].m_flags & MREAD);
1796
1797     if (dmsgs == 0 || (Msgs[0].m_flags & MREAD))
1798         return OK;
1799
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);
1805
1806     if (nmsgs == dmsgs) {
1807 #ifndef SYS5
1808         i = truncate (maildrop, 0);
1809 #else   /* SYS5 */
1810         i = open (maildrop, O_WRONLY | O_TRUNC);
1811         if (i != NOTOK) (void) close (i);
1812 #endif  /* SYS5 */
1813         (void) unlink (map_name (maildrop));/* XXX */
1814         if (i == NOTOK)
1815             return respond (NOTOK, "unable to zero %s", maildrop);
1816         return OK;
1817     }
1818
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);
1824           }
1825
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))
1830             j++;
1831         if (i == tmpDR)
1832             Msgs[0].m_last = j;
1833     }
1834 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: last=%d",Msgs[0].m_last);
1835
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)
1840                                 == NOTOK) {
1841             (void) mbx_close (tmpfil, md);
1842             (void) unlink (tmpfil);
1843             return respond (NOTOK, "error writing temporary file");
1844         }
1845     (void) mbx_close (tmpfil, md);
1846
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);
1853         }
1854     }
1855
1856     if (i == NOTOK)
1857         return respond (NOTOK, "unable to rename maildrop");
1858
1859     return OK;
1860 }
1861
1862 /* \f */
1863
1864 static struct vector   *getvector (bp, vec)
1865 register char   *bp,
1866               **vec;
1867 {
1868     register int    i;
1869     register struct vector *v;
1870
1871     for (i = 0; i < NVEC; i++) {
1872         while (isspace (*bp))
1873             *bp++ = 0;
1874         if (*bp == 0) {
1875             vec[i] = NULL;
1876             break;
1877         }
1878
1879         if (*bp == '"') {
1880             for (vec[i] = ++bp; *bp != '\0' && *bp != '"'; bp++)
1881                 if (*bp == '\\') {
1882                     switch (*++bp) {
1883                         case 'n':
1884                             (void) strcpy (bp, bp + 1);
1885                             *--bp = '\n';
1886                             break;
1887
1888                         case '\\':
1889                         case '"':
1890                             (void) strcpy (bp - 1, bp);
1891                             /* and fall... */
1892                         default:
1893                             bp--;
1894                             break;
1895                     }
1896                 }
1897             if (*bp == '"')
1898                 *bp++ = '\0';
1899             continue;
1900         }
1901         
1902         vec[i] = bp;
1903         while (!isspace (*bp))
1904             bp++;
1905     }
1906     i--;
1907     vec[NVEC] = NULL;
1908
1909     if (*bp != 0) {
1910         (void) respond (NOTOK, "too many arguments");
1911         return NULL;
1912     }
1913     if (*vec[0] == 0) {
1914         (void) respond (NOTOK, "null command");
1915         return NULL;
1916     }
1917     make_lower (vec[0], vec[0]);
1918
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]);
1924                 return NULL;
1925             }
1926             else
1927                 return v;
1928         }
1929
1930     (void) respond (NOTOK, "unknown command: \"%s\"", vec[0]);
1931     return NULL;
1932 }
1933
1934 /* \f */
1935
1936 /* VARARGS2 */
1937
1938 static int  respond (code, fmt, a, b, c, d)
1939 char   *fmt,
1940        *a,
1941        *b,
1942        *c,
1943        *d;
1944 int     code;
1945 {
1946     register char  *bp;
1947     char    buffer[BUFSIZ];
1948
1949     bp = buffer;
1950 #ifndef POP2
1951     (void) sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR", fmt ? " " : "");
1952     bp += strlen (bp);
1953 #else
1954     switch (code) {
1955         case OK:
1956         case NOTOK:
1957             (void) sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR",
1958                     fmt ? " " : "");
1959             bp += strlen (bp);
1960             break;
1961
1962         default:                /* only happens in pop2 */
1963             *bp++ = code;
1964             code = OK;
1965     }
1966 #endif
1967     if (fmt) {
1968         (void) sprintf (bp, fmt, a, b, c, d);
1969         bp += strlen (bp);
1970     }
1971     putline (buffer, output);
1972
1973     return code;
1974 }
1975
1976
1977 /* VARARGS1 */
1978
1979 static  multiline (fmt, a, b, c, d)
1980 char   *fmt,
1981        *a,
1982        *b,
1983        *c,
1984        *d;
1985 {
1986     register char  *cp;
1987     char    buffer[BUFSIZ + TRMLEN];
1988
1989     (void) strcpy (buffer, TRM);
1990     (void) sprintf (cp = (buffer + TRMLEN), fmt, a, b, c, d);
1991     if (strncmp (cp, TRM, TRMLEN) == 0)
1992         cp = buffer;
1993
1994     putline (cp, output);
1995 }
1996
1997
1998 static  multiend () {
1999     putline (TRM, output);
2000 }
2001
2002 /* \f */
2003
2004 static int  getline (s, n, iop)
2005 register char  *s;
2006 register int    n;
2007 register FILE  *iop;
2008 {
2009     register int    c;
2010     register char  *p;
2011
2012     p = s;
2013     while (--n > 0 && (c = fgetc (iop)) != EOF) {
2014         while (c == IAC) {
2015             (void) fgetc (iop);
2016             c = fgetc (iop);
2017         }
2018         if ((*p++ = c) == '\n')
2019             break;
2020     }
2021     if (ferror (iop))
2022         return NOTOK;
2023     if (c == EOF && p == s)
2024         return DONE;
2025     if (debug) {
2026         if (*--p == '\n')
2027             *p = 0;
2028         padvise (NULLCP, LOG_DEBUG, "<--- %s", s);
2029         if (*p == 0)
2030             *p = '\n';
2031         p++;
2032     }
2033     *p++ = 0;
2034
2035     return OK;
2036 }
2037
2038
2039 static  putline (s, iop)
2040 register char   *s;
2041 register FILE   *iop;
2042 {
2043     (void) fprintf (iop, "%s\r\n", s);
2044     if (debug)
2045         padvise (NULLCP, LOG_DEBUG, "---> %s", s);
2046
2047     (void) fflush (iop);
2048 }
2049
2050
2051 /* ARGSUSED */
2052
2053 static TYPESIG pipeser (sig, code, sc)
2054 int     sig;
2055 long    code;
2056 struct sigcontext *sc;
2057 {
2058     padvise (NULLCP, LOG_WARNING, "lost connection");
2059
2060     _exit (NOTOK);
2061 }
2062
2063 /* \f */
2064
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.
2070  *
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
2075  * 
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>.
2079  *
2080  * Here's what he says:
2081  * 
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:
2085  * 
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!
2089  * 
2090  * We have all mail sent to one machine and users are given two options:
2091  * 
2092  *   - MH on any machine.
2093  *   - any user agent on the postoffice machine.
2094  * 
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.
2099  * 
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.
2105  * 
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.
2110  * 
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
2115  */
2116 /* From:    Jim Reid <jim@@computer-science.strathclyde.ac.UK>
2117  * 
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.
2124  */
2125
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
2129  */
2130
2131 /* \f */
2132 #ifdef  POPUUMBOX
2133 /* from dropsbr.c - read from a mailbox - pop server version */
2134
2135 /* ALMOST IDENTICAL to mbx_read */
2136
2137 static  int     pmbx_read (fp, pos, drops, noisy)
2138 register FILE  *fp;
2139 register long   pos;
2140 struct drop **drops;
2141 int     noisy;
2142 {
2143     register int    len,
2144                     size;
2145     register char  *bp;
2146     char    buffer[BUFSIZ];
2147     register struct drop   *cp,
2148                            *dp,
2149                            *ep,
2150                            *pp;
2151
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);
2157
2158     /* get drop storage */
2159     pp = (struct drop  *) calloc ((unsigned) (len = MAXFOLDER), sizeof *dp);
2160
2161     if (debug)
2162         padvise (NULLCP, LOG_DEBUG, "pmbx_read (%d, %ld, %d, %d)",
2163                 fp, pos,drops,noisy);
2164
2165     if (pp == NULL) {
2166         if (noisy)
2167             admonish (NULLCP, "unable to allocate drop storage");
2168         return NOTOK;
2169     }
2170
2171     /* rewind drop file */
2172     (void) fseek (fp, pos, 0);
2173
2174     if (debug)
2175         padvise (NULLCP, LOG_DEBUG, "rewind maildrop");
2176
2177     /* read a buffer */
2178     for (ep = (dp = pp) + len - 1; fgets (buffer, sizeof buffer, fp);) {
2179         size = 0;
2180
2181         /* if beginning of msg then mark it */
2182
2183         if (p_ishead(buffer)) /*(strcmp (buffer, mmdlm1) == 0)*/ {
2184             /* (don't) inc pos to msg start, mark it */
2185             /*pos += ld1;*/
2186             dp -> d_start = pos;
2187             pos += strlen(buffer);  /* inc pos after marking head */
2188         }
2189         else {
2190             /* didn't find it; mark it anyway */
2191             dp -> d_start = pos, pos += (long) strlen (buffer);
2192
2193             /* count newlines and inc size if any found */
2194             for (bp = buffer; *bp; bp++, size++)
2195                 if (*bp == '\n')
2196                     size++;
2197         }
2198
2199         /* read more lines... */
2200         while (fgets (buffer, sizeof buffer, fp) != NULL)
2201
2202             /* found end? */
2203             if (p_ishead(buffer)) /*(strcmp (buffer, mmdlm2) == 0)*/ {
2204
2205                 /* out of loop */
2206                 (void) fseek (fp, pos, 0);
2207                 break;
2208
2209             }
2210             else {
2211                 /* add buffer size to pos */
2212                 pos += (long) strlen (buffer);
2213
2214                 /* count newlines.... */
2215                 for (bp = buffer; *bp; bp++, size++)
2216                     if (*bp == '\n')
2217                         size++;
2218             }
2219
2220         if (dp -> d_start != pos) {
2221             /* do this if pos was actually incremented; got some text */
2222             dp -> d_id = 0;
2223             dp -> d_size = size;  /* save the stuff we got */
2224             dp -> d_stop = pos;
2225             dp++;
2226         }
2227
2228         /* (don't) advance pos */
2229         /* pos += ld2; */
2230
2231         /* need more storage.... */
2232         if (dp >= ep) {
2233             register int    curlen = dp - pp;
2234
2235             cp = (struct drop  *) realloc ((char *) pp,
2236                                     (unsigned) (len += MAXFOLDER) * sizeof *pp);
2237             if (cp == NULL) {
2238                 if (noisy)
2239                     admonish (NULLCP, "unable to allocate drop storage");
2240                 free ((char *) pp);
2241                 return 0;
2242             }
2243             dp = cp + curlen, ep = (pp = cp) + len - 1;
2244         }
2245     }
2246
2247     /* return unused stuff */
2248     if (dp == pp)
2249         free ((char *) pp);
2250     else
2251         *drops = pp;
2252     return (dp - pp);
2253 }
2254
2255 /*
2256  * The remainder of this file adapted from:
2257  *
2258  *      head.c  5.2 (Berkeley) 6/21/85
2259  */
2260
2261 struct p_hdline {
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 */
2265 };
2266
2267 /*
2268  *
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.
2272  */
2273
2274 #define NOSTR           ((char *) 0)    /* Null string pointer */
2275 static  char *p_copyin();
2276 static  char *p_copy();
2277
2278
2279 static  p_ishead(buffer)
2280 char buffer[];
2281 {
2282 register char *cp;
2283 struct p_hdline hl;
2284 char linebuf[BUFSIZ];
2285 char parbuf[BUFSIZ];
2286
2287         strcpy(linebuf,buffer);
2288         cp = linebuf;
2289
2290         if (linebuf[0]=='F')
2291                   padvise (NULLCP, LOG_DEBUG, "ishead: '%s'",linebuf);
2292
2293         if (strncmp("From ", cp, 5) != 0)
2294                 return(0);
2295
2296         padvise (NULLCP, LOG_DEBUG, "Fromline...");
2297
2298         /* get full header */
2299         p_parse(cp, &hl, parbuf);
2300
2301         if (hl.l_from == NOSTR || hl.l_date ==  NOSTR) {
2302                   padvise (NULLCP, LOG_DEBUG, "Fromline...NODATE");
2303                 return(0);
2304                 }
2305
2306         if (!p_isdate(hl.l_date)) {
2307                   padvise (NULLCP, LOG_DEBUG, "Fromline...BADDATE %s",
2308                         hl.l_date);
2309                 return(0);
2310                 }
2311
2312         /* I guess we got it! */
2313         padvise (NULLCP, LOG_DEBUG, "got a head.. ");
2314
2315         return(1);
2316 }
2317
2318 /*
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.
2323  */
2324
2325 static  p_parse(line, hl, pbuf)
2326         char line[], pbuf[];
2327         struct p_hdline *hl;
2328 {
2329         register char *cp, *dp;
2330         char *sp;
2331         char word[BUFSIZ];
2332         char * p_nextword();
2333
2334         hl->l_from = NOSTR;
2335         hl->l_tty = NOSTR;
2336         hl->l_date = NOSTR;
2337         cp = line;
2338         sp = pbuf;
2339
2340         /*
2341          * Skip the first "word" of the line, which should be "From"
2342          * anyway.
2343          */
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);
2348
2349         /* UNLIKELY */
2350         if (strncmp(dp, "tty", 3) == 0) {
2351                 cp = p_nextword(dp, word);
2352                 hl->l_tty = p_copyin(word, &sp);
2353                 if (cp != NOSTR)
2354                         hl->l_date = p_copyin(cp, &sp);
2355         }
2356
2357         /* USUAL */
2358         else
2359                 if (dp != NOSTR)
2360                         hl->l_date = p_copyin(dp, &sp);
2361 }
2362
2363 /*
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.
2368  */
2369
2370 static  char *
2371 p_copyin(src, space)
2372         char src[];
2373         char **space;
2374 {
2375         register char *cp, *top;
2376         register int s;
2377
2378         s = strlen(src);
2379         cp = *space;
2380         top = cp;
2381         strcpy(cp, src);
2382         cp += s + 1;
2383         *space = cp;
2384         return(top);
2385 }
2386
2387 /*
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.
2391  */
2392
2393 static  char *
2394 p_nextword(wp, wbuf)
2395         char wp[], wbuf[];
2396 {
2397         register char *cp, *cp2;
2398
2399         if ((cp = wp) == NOSTR) {
2400                 p_copy("", wbuf);
2401                 return(NOSTR);
2402         }
2403         cp2 = wbuf;
2404         while (!any(*cp, " \t") && *cp != '\0')
2405                 if (*cp == '"') {
2406                         *cp2++ = *cp++;
2407                         while (*cp != '\0' && *cp != '"')
2408                                 *cp2++ = *cp++;
2409                         if (*cp == '"')
2410                                 *cp2++ = *cp++;
2411                 } else
2412                         *cp2++ = *cp++;
2413         *cp2 = '\0';
2414         while (any(*cp, " \t"))
2415                 cp++;
2416         if (*cp == '\0')
2417                 return(NOSTR);
2418         return(cp);
2419 }
2420
2421 /*
2422  * Copy str1 to str2, return pointer to null in str2.
2423  */
2424
2425 static  char *
2426 p_copy(str1, str2)
2427         char *str1, *str2;
2428 {
2429         register char *s1, *s2;
2430
2431         s1 = str1;
2432         s2 = str2;
2433         while (*s1)
2434                 *s2++ = *s1++;
2435         *s2 = 0;
2436         return(s2);
2437 }
2438
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 */
2446
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 */
2450
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 */
2454
2455 static  p_isdate(date)
2456         char date[];
2457 {
2458         register char *cp;
2459
2460         cp = date;
2461         if (p_cmatch(cp, p_ctypes))
2462                 return(1);
2463
2464         return(p_cmatch(cp, p_tmztyp));
2465 }
2466
2467 /*
2468  * Match the given string against the given template.
2469  * Return 1 if they match, 0 if they don't
2470  */
2471
2472 static  p_cmatch(str, temp)
2473         char str[], temp[];
2474 {
2475         register char *cp, *tp;
2476         register int c;
2477
2478         cp = str;
2479         tp = temp;
2480         while (*cp != '\0' && *tp != 0) {
2481                 c = *cp++;
2482                 switch (*tp++) {
2483                 case L:
2484                         if (c < 'a' || c > 'z')
2485                                 return(0);
2486                         break;
2487
2488                 case U:
2489                         if (c < 'A' || c > 'Z')
2490                                 return(0);
2491                         break;
2492
2493                 case S:
2494                         if (c != ' ')
2495                                 return(0);
2496                         break;
2497
2498                 case D:
2499                         if (!isdigit(c))
2500                                 return(0);
2501                         break;
2502
2503                 case O:
2504                         if (c != ' ' && !isdigit(c))
2505                                 return(0);
2506                         break;
2507
2508                 case C:
2509                         if (c != ':')
2510                                 return(0);
2511                         break;
2512
2513                 case N:
2514                         if (c != '\n')
2515                                 return(0);
2516                         break;
2517                 }
2518         }
2519         if ((*cp != '\0' && *cp != '\n') || *tp != 0)
2520                 return(0);
2521         return(1);
2522 }
2523
2524 static  any(ch, str)
2525         char *str;
2526 {
2527         register char *f;
2528         register c;
2529
2530         f = str;
2531         c = ch;
2532         while (*f)
2533                 if (c == *f++)
2534                         return(1);
2535         return(0);
2536 }
2537 #endif
2538 @
2539
2540
2541 1.33
2542 log
2543 @typo
2544 @
2545 text
2546 @d3 1
2547 a3 1
2548 static char ident[]="@@(#)$Id: popser.c,v 1.32 1994/04/21 18:20:15 jromine Exp jromine $";
2549 d24 3
2550 @
2551
2552
2553 1.32
2554 log
2555 @update for scansbr.c
2556 @
2557 text
2558 @d3 1
2559 a3 1
2560 static char ident[]="@@(#)$Id: popser.c,v 1.31 1993/08/25 17:23:14 jromine Exp jromine $";
2561 d1126 2
2562 a1127 2
2563                 switch (scan (dp, i, 0, nfs, 0, 0, NULLCP,
2564                               (long) Msgs[i].m_size, 0)) {
2565 @
2566
2567
2568 1.31
2569 log
2570 @off_t fixes for BSD44
2571 @
2572 text
2573 @d3 1
2574 a3 1
2575 static char ident[]="@@(#)$Id: popser.c,v 1.30 1992/12/16 22:31:20 jromine Exp jromine $";
2576 d1088 2
2577 a1089 2
2578             switch (scan (dp, i, 0, nfs, 0, 0, NULLCP,
2579                           (long) Msgs[i].m_size, 0)) {
2580 @
2581
2582
2583 1.30
2584 log
2585 @TYPESIG fixups
2586 @
2587 text
2588 @d3 1
2589 a3 1
2590 static char ident[]="@@(#)$Id: popser.c,v 1.29 1992/12/15 00:20:22 jromine Exp jromine $";
2591 a229 1
2592 long    lseek ();
2593 @
2594
2595
2596 1.29
2597 log
2598 @endif sugar
2599 @
2600 text
2601 @d3 1
2602 a3 1
2603 static char ident[]="@@(#)$Id: popser.c,v 1.28 1992/12/14 17:49:09 jromine Exp jromine $";
2604 d218 1
2605 a218 1
2606 static int    pipeser ();
2607 d1864 1
2608 a1864 1
2609 static int pipeser (sig, code, sc)
2610 @
2611
2612
2613 1.28
2614 log
2615 @fix decls
2616 @
2617 text
2618 @d3 1
2619 a3 1
2620 static char ident[]="@@(#)$Id: popser.c,v 1.27 1992/10/28 18:42:42 jromine Exp jromine $";
2621 d29 1
2622 a29 1
2623 #endif  SYS5
2624 d32 1
2625 a32 1
2626 #endif  SHADOW
2627 d71 1
2628 a71 1
2629 #endif  BPOP
2630 d74 1
2631 a74 1
2632 #endif  RPOP
2633 d82 1
2634 a82 1
2635 #endif  BPOP
2636 d86 1
2637 a86 1
2638 #endif  POP2
2639 d99 1
2640 a99 1
2641 #endif  RPOP
2642 d121 1
2643 a121 1
2644 #endif  BPOP
2645 d141 1
2646 a141 1
2647 #endif  POP2
2648 d151 1
2649 a151 1
2650 #endif  POP2
2651 d155 1
2652 a155 1
2653 #endif  DPOP
2654 d184 1
2655 a184 1
2656 #endif  BPOP
2657 d255 1
2658 a255 1
2659 #endif  BPOP
2660 d311 1
2661 a311 1
2662 #endif  BPOP
2663 d336 1
2664 a336 1
2665 #endif  defined (DPOP) || defined (BPOP)
2666 d376 1
2667 a376 1
2668 #endif  DPOP
2669 d384 1
2670 a384 1
2671 #endif  BPOP
2672 d451 2
2673 a452 2
2674 #endif  SHADOW
2675 #else   DPOP
2676 d454 1
2677 a454 1
2678 #endif  DPOP
2679 d485 1
2680 a485 1
2681 #endif  TRUSTED
2682 d489 1
2683 a489 1
2684 #endif  BPOP
2685 d494 1
2686 a494 1
2687 #else   SHADOW
2688 d498 1
2689 a498 1
2690 #endif  SHADOW
2691 d502 1
2692 a502 1
2693 #endif  TRUSTED
2694 d505 1
2695 a505 1
2696 #else   DPOP
2697 d515 1
2698 a515 1
2699 #endif  BPOP
2700 d523 1
2701 a523 1
2702 #endif  TRUSTED
2703 d526 1
2704 a526 1
2705 #endif  DPOP
2706 d530 1
2707 a530 1
2708 #endif  BPOP
2709 d535 1
2710 a535 1
2711 #else   DPOP
2712 d537 1
2713 a537 1
2714 #endif  DPOP
2715 d541 1
2716 a541 1
2717 #endif  TRUSTED
2718 d575 1
2719 a575 1
2720 #endif  BPOP
2721 d585 1
2722 a585 1
2723 #else   DPOP
2724 d591 1
2725 a591 1
2726 #endif  DPOP
2727 d598 1
2728 a598 1
2729 #endif  TRUSTED
2730 d607 1
2731 a607 1
2732 #endif  TRUSTED
2733 d610 1
2734 a610 1
2735 #else   DPOP
2736 d617 1
2737 a617 1
2738 #endif  TRUSTED
2739 d639 1
2740 a639 1
2741 #endif  TRUSTED
2742 d642 1
2743 a642 1
2744 #endif  DPOP
2745 d648 1
2746 a648 1
2747 #else   DPOP
2748 d650 1
2749 a650 1
2750 #endif  DPOP
2751 d654 1
2752 a654 1
2753 #endif  TRUSTED
2754 d657 1
2755 a657 1
2756 #endif  RPOP
2757 d756 1
2758 a756 1
2759 #else   DPOP
2760 d758 1
2761 a758 1
2762 #endif  DPOP
2763 d766 1
2764 a766 1
2765 #endif  SYS5
2766 d770 1
2767 a770 1
2768 #endif  BPOP
2769 d775 1
2770 a775 1
2771 #endif  SYS5
2772 d777 1
2773 a777 1
2774 #else   DPOP
2775 d781 1
2776 a781 1
2777 #endif  SYS5
2778 d783 1
2779 a783 1
2780 #endif  DPOP
2781 d786 1
2782 a786 1
2783 #endif  BPOP
2784 d792 1
2785 a792 1
2786 #else   DPOP
2787 d794 1
2788 a794 1
2789 #endif  DPOP
2790 d806 1
2791 a806 1
2792 #endif  POP2
2793 d823 1
2794 a823 1
2795 #endif  BPOP
2796 d1067 1
2797 a1067 1
2798 #endif  POP2
2799 d1082 1
2800 a1082 1
2801 #else   BPOP
2802 d1110 1
2803 a1110 1
2804 #endif  BPOP
2805 d1120 1
2806 a1120 1
2807 #else   BPOP
2808 d1150 1
2809 a1150 1
2810 #endif  BPOP
2811 d1542 1
2812 a1542 1
2813 #endif  BPOP
2814 d1560 1
2815 a1560 1
2816 #endif  BPOP
2817 d1620 1
2818 a1620 1
2819 #else   SYS5
2820 d1623 1
2821 a1623 1
2822 #endif  SYS5
2823 @
2824
2825
2826 1.27
2827 log
2828 @add some MPOP #ifdefs
2829 @
2830 text
2831 @d3 1
2832 a3 1
2833 static char ident[]="@@(#)$Id: popser.c,v 1.16 1990/11/16 14:56:38 mh Exp jromine $";
2834 d81 1
2835 a81 1
2836 int     xtnd ();
2837 d183 1
2838 a183 1
2839 struct bboard *getbbaux ();
2840 @
2841
2842
2843 1.26
2844 log
2845 @APOP changes from MTR
2846 @
2847 text
2848 @d3 1
2849 a3 1
2850 static char ident[]="@@(#)$Id: popser.c,v 1.25 1992/10/20 22:47:28 jromine Exp jromine $";
2851 d8 1
2852 d13 1
2853 d66 3
2854 d70 1
2855 d116 3
2856 d120 1
2857 d206 1
2858 d211 1
2859 d1083 1
2860 d1107 1
2861 d1121 1
2862 d1147 1
2863 d1247 1
2864 d1255 1
2865 d1324 1
2866 d1327 1
2867 d1525 1
2868 d1541 1
2869 @
2870
2871
2872 1.25
2873 log
2874 @change location of md5.c
2875 @
2876 text
2877 @d3 1
2878 a3 1
2879 static char ident[]="@@(#)$Id: popser.c,v 1.24 1992/05/19 20:59:21 jromine Exp jromine $";
2880 d665 2
2881 a666 1
2882     unsigned char *ep;
2883 d723 1
2884 a723 1
2885     MD5Final (&mdContext);
2886 d726 1
2887 a726 2
2888     for (ep = (dp = mdContext.digest)
2889                         + sizeof mdContext.digest / sizeof mdContext.digest[0];
2890 @
2891
2892
2893 1.24
2894 log
2895 @NULL->0
2896 @
2897 text
2898 @d3 1
2899 a3 1
2900 static char ident[]="@@(#)$Id: popser.c,v 1.23 1992/02/11 17:40:59 jromine Exp jromine $";
2901 d651 1
2902 a651 1
2903 #include "md5.c"
2904 @
2905
2906
2907 1.23
2908 log
2909 @cleanup KPOP ifdefs
2910 @
2911 text
2912 @d3 1
2913 a3 1
2914 static char ident[]="@@(#)$Id: popser.c,v 1.22 1992/02/10 22:35:58 jromine Exp jromine $";
2915 d1669 1
2916 a1669 1
2917             for (vec[i] = ++bp; *bp != NULL && *bp != '"'; bp++)
2918 d1687 1
2919 a1687 1
2920                 *bp++ = NULL;
2921 @
2922
2923
2924 1.22
2925 log
2926 @allow "top msg 0"
2927 @
2928 text
2929 @d3 1
2930 a3 1
2931 static char ident[]="@@(#)$Id: popser.c,v 1.21 1992/02/04 21:59:41 jromine Exp jromine $";
2932 d24 1
2933 a24 1
2934 #endif
2935 d312 1
2936 a312 1
2937 #else
2938 d318 1
2939 a318 1
2940 #endif
2941 d337 1
2942 a337 1
2943 #endif
2944 d354 1
2945 a354 1
2946 #endif
2947 a418 4
2948 #else
2949     return respond (OK, "password required for %s", username);
2950 #endif
2951 #ifdef KPOP
2952 d424 2
2953 d462 1
2954 a462 1
2955 #else
2956 @
2957
2958
2959 1.21
2960 log
2961 @contributed patch
2962 @
2963 text
2964 @d3 1
2965 a3 1
2966 static char ident[]="@@(#)$Id: popser.c,v 1.20 1992/02/04 21:44:56 jromine Exp jromine $";
2967 d1261 1
2968 a1261 1
2969     if ((j = atoi (vec[2])) <= 0)
2970 @
2971
2972
2973 1.20
2974 log
2975 @contributed patch
2976 @
2977 text
2978 @d3 1
2979 a3 1
2980 static char ident[]="@@(#)$Id: popser.c,v 1.19 1992/02/04 21:39:42 jromine Exp jromine $";
2981 d719 2
2982 d734 1
2983 a734 2
2984     if (strcmp (vec[2], buffer)) {
2985         dbm_close (db);
2986 a735 1
2987     }
2988 @
2989
2990
2991 1.19
2992 log
2993 @contributed patch
2994 @
2995 text
2996 @d3 1
2997 a3 1
2998 static char ident[]="@@(#)$Id: popser.c,v 1.18 1992/02/03 17:52:59 jromine Exp jromine $";
2999 d95 1
3000 a95 1
3001     "apop", 3, 3, apop, auth1, trans, auth1,
3002 d150 1
3003 d336 1
3004 a336 1
3005     (void) sprintf (server, "%s %s server", myhost, priv ? "RPOP" : "POP");
3006 d374 2
3007 a375 2
3008     (void) respond (OK, "%s ready (Comments to: PostMaster@@%s)",
3009             server, myhost);
3010 d377 5
3011 d652 1
3012 a660 7
3013 struct authinfo {
3014     long    auth_clock;
3015     char    auth_secret[16];
3016     int     auth_secretlen;
3017 };
3018
3019
3020 a663 1
3021     long    clock;
3022 d665 1
3023 a665 2
3024     char   *ap,
3025             buffer[BUFSIZ];
3026 d695 1
3027 a695 1
3028     if ((db = dbm_open (APOP, O_RDWR, 0)) == NULL)
3029 d704 1
3030 a704 1
3031     if (flock (dbm_pagfno (db), LOCK_EX) == NOTOK) {
3032 d716 2
3033 a718 14
3034     if (sscanf (vec[2], "%ld", &clock) != 1) {
3035         dbm_close (db);
3036         return respond (NOTOK, "invalid timestamp");
3037     }
3038     if (clock < auth.auth_clock) {
3039         dbm_close (db);
3040         return respond (NOTOK, "timestamp smaller than %ld",
3041                         auth.auth_clock);
3042     }
3043
3044     (void) sprintf (cp = buffer, "%s %s ", vec[1], vec[2]);
3045     cp += strlen (cp);
3046     (void) bcopy (auth.auth_secret, ap = cp, auth.auth_secretlen);
3047
3048 d721 1
3049 a721 1
3050                (unsigned int) ((cp - buffer) + auth.auth_secretlen));
3051 d724 1
3052 d732 1
3053 a732 1
3054     if (strcmp (vec[3], ap)) {
3055 a735 5
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?!?");
3060     dbm_close (db);
3061 @
3062
3063
3064 1.18
3065 log
3066 @getpw
3067 STDC
3068 SYS5
3069 @
3070 text
3071 @d3 1
3072 a3 1
3073 static char ident[]="@@(#)$Id: popser.c,v 1.17 1992/01/31 22:06:03 jromine Exp jromine $";
3074 d8 4
3075 d36 1
3076 a36 1
3077 #define NVEC    4
3078 d64 1
3079 a64 1
3080 static  int     xtnd1(), xtnd2();
3081 d69 3
3082 d94 3
3083 d110 1
3084 a110 1
3085     "xtnd", 1, 2, xtnd, trans, trans, trans,
3086 d195 4
3087 d227 1
3088 a228 1
3089 #endif
3090 d645 116
3091 d1091 23
3092 d1115 1
3093 a1115 1
3094                 i, Msgs[i].m_size, Msgs[i].m_id);
3095 d1123 1
3096 a1123 1
3097         if (!(Msgs[i].m_flags & MDELE))
3098 d1127 25
3099 d1153 1
3100 a1153 1
3101                     i, Msgs[i].m_size, Msgs[i].m_id);
3102 d1155 1
3103 d1251 8
3104 d1306 2
3105 d1326 2
3106 d1522 18
3107 d1603 4
3108 a1606 1
3109     if ((dmsgs == 0 && rmsgs == 0) || (Msgs[0].m_flags & MREAD))
3110 a1608 1
3111 if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: rmsgs=%d",rmsgs);
3112 d1687 24
3113 d1834 8
3114 a1842 2
3115     if (debug)
3116         padvise (NULLCP, LOG_DEBUG, "<--- %s", s);
3117 a1953 2
3118     long    ld1,
3119             ld2;
3120 d1961 6
3121 a1978 4
3122
3123     /* get sizes of msg delimiters */
3124     ld1 = (long) strlen (mmdlm1);
3125     ld2 = (long) strlen (mmdlm2);
3126 @
3127
3128
3129 1.17
3130 log
3131 @kerberos
3132 @
3133 text
3134 @d3 1
3135 a3 1
3136 static char ident[]="@@(#)$Id: popser.c,v 1.16 1990/11/16 14:56:38 mh Exp jromine $";
3137 d196 5
3138 @
3139
3140
3141 1.16
3142 log
3143 @jlr
3144 @
3145 text
3146 @d3 1
3147 a3 1
3148 static char ident[]="@@(#)$Id: popser.c,v 1.15 90/11/16 14:38:00 mh Exp Locker: mh $";
3149 d18 3
3150 d284 9
3151 d298 1
3152 d310 5
3153 a315 1
3154     hostname = rhost;
3155 d317 1
3156 d325 10
3157 d391 4
3158 a394 1
3159
3160 d396 8
3161 d421 20
3162 d508 1
3163 d593 1
3164 a593 1
3165             *cp = NULL;
3166 d1008 1
3167 a1008 1
3168             *cp = NULL;
3169 d1097 1
3170 a1097 1
3171             *cp = NULL;
3172 d1103 1
3173 a1103 1
3174             if (*buffer == NULL)
3175 d1466 2
3176 a1467 2
3177             *bp++ = NULL;
3178         if (*bp == NULL) {
3179 d1478 1
3180 a1478 1
3181     if (*bp != NULL) {
3182 d1482 1
3183 a1482 1
3184     if (*vec[0] == NULL) {
3185 d1594 1
3186 a1594 1
3187     *p++ = NULL;
3188 @
3189
3190
3191 1.15
3192 log
3193 @make popser speak POP2 as well as POP3 -- a major win!
3194
3195 jlr
3196 @
3197 text
3198 @d3 1
3199 a3 1
3200 static char ident[]="@@(#)$Id: popser.c,v 1.14 90/11/05 16:04:57 mh Exp Locker: mh $";
3201 a4 2
3202
3203 #define POP2
3204 @
3205
3206
3207 1.14
3208 log
3209 @see comments in code
3210 @
3211 text
3212 @d3 1
3213 a3 1
3214 static char ident[]="@@(#)$Id: popser.c,v 1.13 90/04/09 09:45:18 sources Exp Locker: mh $";
3215 d6 2
3216 d45 1
3217 d49 5
3218 d70 3
3219 a100 1
3220
3221 d103 18
3222 d128 3
3223 d351 9
3224 d614 8
3225 d624 1
3226 a624 1
3227             nmsgs, nmsgs != 1 ? "s" : NULL, Msgs[0].m_size);
3228 d810 74
3229 d904 1
3230 a904 1
3231             nmsgs - dmsgs, nmsgs - dmsgs != 1 ? "s" : NULL,
3232 d929 5
3233 d940 5
3234 d953 3
3235 d962 3
3236 d1294 1
3237 a1294 1
3238             server, n - d, n - d != 1 ? "s" : NULL, Msgs[0].m_size);
3239 d1461 21
3240 a1481 4
3241     bp += strlen (sprintf (bp, "%s%s", code == OK ? "+OK" : "-ERR",
3242                 fmt ? " " : NULL));
3243     if (fmt)
3244         bp += strlen (sprintf (bp, fmt, a, b, c, d));
3245 @
3246
3247
3248 1.13
3249 log
3250 @POPSERVICE define
3251 @
3252 text
3253 @d3 1
3254 a3 1
3255 static char ident[]="@@(#)$Id: popser.c,v 1.12 90/04/05 16:07:32 sources Exp Locker: sources $";
3256 d169 2
3257 d174 4
3258 d691 1
3259 a691 1
3260     if ((i = pmbx_read (dp, pos, &rp, debug)) <= 0)
3261 d1466 9
3262 d1476 5
3263 d1482 1
3264 d1887 1
3265 @
3266
3267
3268 1.12
3269 log
3270 @Id
3271 @
3272 text
3273 @d3 1
3274 a3 1
3275 static char ident[]="@@(#)$Id:$";
3276 d31 4
3277 d363 1
3278 a363 1
3279             pw && pw -> pw_uid == 0, "pop", "tcp", NULL);
3280 d384 1
3281 a384 1
3282             0, "pop", "tcp", NULL);
3283 d400 1
3284 a400 1
3285                 "pop", "tcp", NULL)
3286 @
3287
3288
3289 1.11
3290 log
3291 @*** empty log message ***
3292 @
3293 text
3294 @d2 3
3295 @
3296
3297
3298 1.10
3299 log
3300 @add ID
3301 @
3302 text
3303 @a1 3
3304 #ifndef lint
3305 static char ident[] = "@@(#)$Id:$";
3306 #endif  lint
3307 d42 4
3308 d162 4
3309 d1459 1
3310 a1459 1
3311 int     pmbx_read (fp, pos, drops, noisy)
3312 d1597 2
3313 d1600 2
3314 a1601 1
3315 p_ishead(buffer)
3316 a1608 3
3317 char * p_copyin();
3318 char * p_copy();
3319
3320 d1647 1
3321 a1647 1
3322 p_parse(line, hl, pbuf)
3323 d1692 1
3324 a1692 1
3325 char *
3326 d1715 1
3327 a1715 1
3328 char *
3329 d1747 1
3330 a1747 1
3331 char *
3332 d1769 3
3333 a1771 2
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};
3336 d1773 3
3337 a1775 2
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};
3340 d1777 1
3341 a1777 1
3342 p_isdate(date)
3343 d1794 1
3344 a1794 1
3345 p_cmatch(str, temp)
3346 d1846 1
3347 a1846 1
3348 any(ch, str)
3349 a1858 1
3350
3351 @
3352
3353
3354 1.9
3355 log
3356 @add ID
3357 @
3358 text
3359 @d3 1
3360 a3 1
3361 static char ident[] = "@@(#)$Id:";
3362 @
3363
3364
3365 1.8
3366 log
3367 @contrib'd fixes to make popd read UUCP as well as MMDF maildrops.
3368 @
3369 text
3370 @d2 3
3371 @
3372
3373
3374 1.7
3375 log
3376 @make mbx_size be pmbx_size for ANSI C
3377 @
3378 text
3379 @d670 1
3380 a670 1
3381     if ((i = mbx_read (dp, pos, &rp, debug)) <= 0)
3382 d1197 4
3383 a1200 1
3384         return respond (NOTOK, "unable to create temporary file");
3385 d1391 459
3386 @
3387
3388
3389 1.6
3390 log
3391 @ANSI Compilance
3392 @
3393 text
3394 @d158 1
3395 a158 1
3396 static int      setup(), setupaux(), read_map(), read_file(), mbx_size();
3397 d605 1
3398 a605 1
3399             Msgs[i].m_size = mbx_size (i);
3400 d716 1
3401 a716 1
3402 static int  mbx_size (m)
3403 @
3404
3405
3406 1.5
3407 log
3408 @SHADOW
3409 @
3410 text
3411 @d41 1
3412 a41 1
3413 int     user (), pass ();
3414 d43 1
3415 a43 1
3416 int     rpop ();
3417 d45 2
3418 a46 2
3419 int     status (), list (), retrieve (), delete (), reset ();
3420 int     top (), last ();
3421 d50 1
3422 a50 1
3423 int     quit ();
3424 d85 1
3425 a85 1
3426 struct vector  *getvector ();
3427 d148 1
3428 a148 1
3429 int    pipeser ();
3430 d158 3
3431 @
3432
3433
3434 1.4
3435 log
3436 @*** empty log message ***
3437 @
3438 text
3439 @d18 3
3440 d313 3
3441 d335 1
3442 d338 5
3443 @
3444
3445
3446 1.3
3447 log
3448 @*** empty log message ***
3449 @
3450 text
3451 @d1307 1
3452 a1307 1
3453     cp = sprintf (buffer + TRMLEN, fmt, a, b, c, d);
3454 @
3455
3456
3457 1.2
3458 log
3459 @SYS5 fix
3460 @
3461 text
3462 @d12 1
3463 a12 1
3464 #include <syslog.h>
3465 @
3466
3467
3468 1.1
3469 log
3470 @Initial revision
3471 @
3472 text
3473 @d15 3
3474 d503 1
3475 d505 1
3476 d512 1
3477 d514 1
3478 d518 1
3479 d520 1
3480 d1168 1
3481 d1170 4
3482 @