3 * popi.c -- POP initiator for MPOP
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
13 #include <h/fmt_scan.h>
14 #include <h/scansbr.h>
20 # define RPOPminc(a) (a)
22 # define RPOPminc(a) 0
26 # define APOPminc(a) (a)
28 # define APOPminc(a) 0
32 # define BPOPminc(a) (a)
34 # define BPOPminc(a) 0
38 # define BULKminc(a) (a)
40 # define BULKminc(a) 0
43 static struct swit switches[] = {
45 { "apop", APOPminc (-4) },
47 { "noapop", APOPminc (-6) },
49 { "auto", BPOPminc(-4) },
51 { "noauto", BPOPminc(-6) },
53 { "bulk directory", BULKminc(-4) },
55 { "form formatfile", 0 },
57 { "format string", 5 },
61 { "mshproc program", 0 },
63 { "rpop", RPOPminc (-4) },
65 { "norpop", RPOPminc (-6) },
69 { "width columns", 0 },
77 static char *bulksw = NULL;
80 static char mailname[BUFSIZ];
81 static char *nfs = NULL;
82 static struct msgs *mp;
84 extern char response[];
89 int sc_width (void); /* from termsbr.c */
93 main (int argc, char **argv)
95 int autosw = 1, noisy = 1, rpop;
96 char *cp, *maildir, *folder = NULL, *form = NULL;
97 char *format = NULL, *host = NULL, *user = NULL;
98 char *pass = NULL, buf[BUFSIZ], **argp;
102 invo_name = r1bindex (argv[0], '/');
104 /* read user profile/context */
107 mts_init (invo_name);
108 arguments = getarguments (invo_name, argc, argv, 1);
111 if (pophost && *pophost)
113 if ((cp = getenv ("MHPOPDEBUG")) && *cp)
116 rpop = getuid() && !geteuid();
118 while (cp = *argp++) {
120 switch (smatch (++cp, switches)) {
122 ambigsw (cp, switches);
125 adios (NULL, "-%s unknown", cp);
128 snprintf (buf, sizeof(buf), "%s [+folder] [switches]",
130 print_help (buf, switches, 1);
133 print_version(invo_name);
144 if (!(bulksw = *argp++) || *bulksw == '-')
145 adios (NULL, "missing argument to %s", argp[-2]);
149 if (!(form = *argp++) || *form == '-')
150 adios (NULL, "missing argument to %s", argp[-2]);
154 if (!(format = *argp++) || *format == '-')
155 adios (NULL, "missing argument to %s", argp[-2]);
160 if (!(cp = *argp++) || *cp == '-')
161 adios (NULL, "missing argument to %s", argp[-2]);
166 if (!(host = *argp++) || *host == '-')
167 adios (NULL, "missing argument to %s", argp[-2]);
170 if (!(user = *argp++) || *user == '-')
171 adios (NULL, "missing argument to %s", argp[-2]);
186 if (!(mshproc = *argp++) || *mshproc == '-')
187 adios (NULL, "missing argument to %s", argp[-2]);
190 if (*cp == '+' || *cp == '@') {
192 adios (NULL, "only one folder at a time!");
194 folder = pluspath (cp);
197 adios (NULL, "usage: %s [+folder] [switches]", invo_name);
201 adios (NULL, "usage: %s -host \"host\"", invo_name);
209 user = getusername ();
211 pass = getusername ();
214 ruserpass (host, &user, &pass);
216 snprintf (mailname, sizeof(mailname), "PO box for %s@%s", user, host);
218 if (pop_init (host, user, pass, NULL, snoop, rpop) == NOTOK)
219 adios (NULL, "%s", response);
223 /* get new format string */
224 nfs = new_fs (form, format, FORMAT);
226 if (!context_find ("path"))
227 free (path ("./", TFOLDER));
229 folder = getfolder (0);
230 maildir = m_maildir (folder);
232 create_folder(maildir, 0, done);
234 if (chdir (maildir) == NOTOK)
235 adios (maildir, "unable to change directory to");
237 if (!(mp = folder_read (folder)))
238 adios (NULL, "unable to read folder %s", folder);
249 context_replace (pfolder, folder); /* update current folder */
250 seq_setunseen (mp, 0); /* set the Unseen-Sequence */
252 context_save (); /* save the context file */
257 static struct swit popicmds[] = {
300 printf ("(%s) ", invo_name);
301 for (cp = buffer; (i = getchar ()) != '\n'; ) {
310 if (cp < buffer + sizeof buffer - 2)
314 if (buffer[0] == '\0')
316 if (buffer[0] == '?') {
317 printf ("commands:\n");
318 print_sw (ALL, popicmds, "");
319 printf ("type CTRL-D or use \"quit\" to leave %s\n", invo_name);
323 if (cp = strchr (buffer, ' '))
325 switch (i = smatch (buffer, popicmds)) {
327 ambigsw (buffer, popicmds);
330 printf ("%s unknown -- type \"?\" for help\n", buffer);
344 pop_command ("%s%s", popicmds[i].sw, cp ? cp : "");
345 printf ("%s\n", response);
351 if (pop_command ("%s%s", popicmds[i].sw, cp ? cp : "")
353 printf ("%s\n", response);
356 switch (pop_multiline ()) {
358 strcpy (response, ".");
361 printf ("%s\n", response);
365 printf ("%s\n", response);
375 advise (NULL, "missing argument to %s", buffer);
378 retr_action (NULL, OK);
379 pop_retr (atoi (++cp), retr_action);
380 retr_action (NULL, DONE);
381 printf ("%s\n", response);
393 for (dp = nfs, i = 0; *dp; dp++, i++)
394 if (*dp == '\\' || *dp == '"' || *dp == '\n')
397 ep = mh_xmalloc ((unsigned) i);
398 for (dp = nfs, fp = ep; *dp; dp++) {
400 *fp++ = '\\', *fp++ = 'n';
403 if (*dp == '"' || *dp == '\\')
409 pop_command ("xtnd scan %d \"%s\"", width, ep);
410 printf ("%s\n", response);
427 retr_action (char *rsp, int flag)
436 if (!(mp = folder_realloc (mp, mp->lowoff, msgnum = mp->hghmsg + 1)))
437 adios (NULL, "unable to allocate folder storage");
439 cp = getcpy (m_name (mp->hghmsg + 1));
440 if ((fp = fopen (cp, "w+")) == NULL)
441 adios (cp, "unable to write");
442 chmod (cp, m_gmprot ());
448 if (fstat (fileno (fp), &st) != NOTOK && st.st_size > 0) {
449 clear_msg_flags (mp, msgnum);
450 set_exists (mp, msgnum);
451 set_unseen (mp, msgnum);
452 mp->msgflags |= SEQMOD;
455 advise (cp, "write error on");
461 fclose (fp), fp = NULL;
462 free (cp), cp = NULL;
468 fprintf (fp, "%s\n", rsp);
477 char buf1[BUFSIZ], buf2[BUFSIZ], *vec[9];
479 if (pop_fd (buf1, sizeof(buf1), buf2, sizeof(buf2)) == NOTOK)
480 adios (NULL, "%s", response);
483 vec[vecp++] = r1bindex (mshproc, '/');
485 switch (child_id = fork ()) {
487 adios ("fork", "unable to");
490 vec[vecp++] = "-popread";
492 vec[vecp++] = "-popwrite";
494 vec[vecp++] = "-idname";
495 vec[vecp++] = mailname;
496 vec[vecp++] = mailname;
498 execvp (mshproc, vec);
499 fprintf (stderr, "unable to exec ");
504 pidXwait (child_id, mshproc);
513 #include <mts/smtp/smtp.h>
516 dselect (struct direct *d)
520 if ((i = strlen (d->d_name)) < sizeof "smtp"
521 || strncmp (d->d_name, "smtp", sizeof "smtp" - 1))
523 return ((i -= (sizeof ".bulk" - 1)) > 0
524 && !strcmp (d->d_name + i, ".bulk"));
529 dcompar (struct direct *d1, struct direct *d2)
533 if (stat ((*d1)->d_name, &s1) == NOTOK)
535 if (stat ((*d2)->d_name, &s2) == NOTOK)
537 return ((int) (s1.st_mtime - s2.st_mtime));
546 struct direct **namelist;
548 if (chdir (bulksw) == NOTOK)
549 adios (bulksw, "unable to change directory to");
551 if ((n = scandir (".", &namelist, dselect, dcompar)) == NOTOK)
552 adios (bulksw, "unable to scan directory");
555 for (i = 0; i < n; i++) {
556 register struct direct *d = namelist[i];
559 if (rp_isbad (retval = sm_init (NULL, host, 1, 1, snoop)))
560 adios (NULL, "problem initializing server: %s",
566 switch (retval = sm_bulk (d->d_name)) {
568 if (rp_isbad (retval))
569 adios (NULL, "problem delivering msg %s: %s",
570 d->d_name, rp_string (retval));
575 advise (NULL, "msg %s: %s", d->d_name, rp_string (retval));
584 struct direct **newlist;
586 while ((l = scandir (".", &newlist, dselect, dcompar)) > OK) {
589 for (j = 0; j < l; j++) {
590 register struct direct *d = newlist[j];
592 for (i = 0; i < n; i++)
593 if (strcmp (d->d_name, namelist[i]->d_name) == 0)
596 switch (retval = sm_bulk (d->d_name)) {
598 if (rp_isbad (retval))
599 adios (NULL, "problem delivering msg %s: %s",
600 d->d_name, rp_string (retval));
605 advise (NULL, "msg %s: %s", d->d_name,
614 for (i = 0; i < n; i++)
615 free ((char *) namelist[i]);
616 free ((char *) namelist);
617 namelist = newlist, n = l;
625 if (sm == OK && rp_isbad (retval = sm_end (OK)))
626 adios (NULL, "problem finalizing server: %s", rp_string (retval));
628 for (i = 0; i < n; i++)
629 free ((char *) namelist[i]);
630 free ((char *) namelist);
632 free ((char *) namelist);