3 * popi.c -- POP initiator for MPOP
9 #include <h/fmt_scan.h>
10 #include <h/scansbr.h>
11 #include <zotnet/mts/mts.h>
15 # define RPOPminc(a) (a)
17 # define RPOPminc(a) 0
21 # define APOPminc(a) (a)
23 # define APOPminc(a) 0
27 # define BPOPminc(a) (a)
29 # define BPOPminc(a) 0
33 # define BULKminc(a) (a)
35 # define BULKminc(a) 0
38 static struct swit switches[] = {
40 { "apop", APOPminc (-4) },
42 { "noapop", APOPminc (-6) },
44 { "auto", BPOPminc(-4) },
46 { "noauto", BPOPminc(-6) },
48 { "bulk directory", BULKminc(-4) },
50 { "form formatfile", 0 },
52 { "format string", 5 },
56 { "mshproc program", 0 },
58 { "rpop", RPOPminc (-4) },
60 { "norpop", RPOPminc (-6) },
64 { "width columns", 0 },
72 static char *bulksw = NULL;
75 static char mailname[BUFSIZ];
76 static char *nfs = NULL;
77 static struct msgs *mp;
80 extern char response[];
85 int sc_width (void); /* from termsbr.c */
89 main (int argc, char **argv)
91 int autosw = 1, noisy = 1, rpop;
92 char *cp, *maildir, *folder = NULL, *form = NULL;
93 char *format = NULL, *host = NULL, *user = NULL;
94 char *pass = NULL, buf[BUFSIZ], **argp;
98 invo_name = r1bindex (argv[0], '/');
100 /* read user profile/context */
103 mts_init (invo_name);
104 arguments = getarguments (invo_name, argc, argv, 1);
107 if (pophost && *pophost)
109 if ((cp = getenv ("MHPOPDEBUG")) && *cp)
112 rpop = getuid() && !geteuid();
114 while (cp = *argp++) {
116 switch (smatch (++cp, switches)) {
118 ambigsw (cp, switches);
121 adios (NULL, "-%s unknown", cp);
124 snprintf (buf, sizeof(buf), "%s [+folder] [switches]",
126 print_help (buf, switches, 1);
129 print_version(invo_name);
140 if (!(bulksw = *argp++) || *bulksw == '-')
141 adios (NULL, "missing argument to %s", argp[-2]);
145 if (!(form = *argp++) || *form == '-')
146 adios (NULL, "missing argument to %s", argp[-2]);
150 if (!(format = *argp++) || *format == '-')
151 adios (NULL, "missing argument to %s", argp[-2]);
156 if (!(cp = *argp++) || *cp == '-')
157 adios (NULL, "missing argument to %s", argp[-2]);
162 if (!(host = *argp++) || *host == '-')
163 adios (NULL, "missing argument to %s", argp[-2]);
166 if (!(user = *argp++) || *user == '-')
167 adios (NULL, "missing argument to %s", argp[-2]);
182 if (!(mshproc = *argp++) || *mshproc == '-')
183 adios (NULL, "missing argument to %s", argp[-2]);
186 if (*cp == '+' || *cp == '@') {
188 adios (NULL, "only one folder at a time!");
190 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
193 adios (NULL, "usage: %s [+folder] [switches]", invo_name);
197 adios (NULL, "usage: %s -host \"host\"", invo_name);
205 user = getusername ();
207 pass = getusername ();
210 ruserpass (host, &user, &pass);
212 snprintf (mailname, sizeof(mailname), "PO box for %s@%s", user, host);
214 if (pop_init (host, user, pass, snoop, rpop) == NOTOK)
215 adios (NULL, "%s", response);
219 /* get new format string */
220 nfs = new_fs (form, format, FORMAT);
222 if (!context_find ("path"))
223 free (path ("./", TFOLDER));
225 folder = getfolder (0);
226 maildir = m_maildir (folder);
228 if (stat (maildir, &st) == NOTOK) {
230 adios (maildir, "error on folder");
231 cp = concat ("Create folder \"", maildir, "\"? ", NULL);
232 if (noisy && !getanswer (cp))
235 if (!makedir (maildir))
236 adios (NULL, "unable to create folder %s", maildir);
239 if (chdir (maildir) == NOTOK)
240 adios (maildir, "unable to change directory to");
242 if (!(mp = folder_read (folder)))
243 adios (NULL, "unable to read folder %s", folder);
254 context_replace (pfolder, folder); /* update current folder */
255 seq_setunseen (mp, 0); /* set the Unseen-Sequence */
257 context_save (); /* save the context file */
262 static struct swit popicmds[] = {
305 printf ("(%s) ", invo_name);
306 for (cp = buffer; (i = getchar ()) != '\n'; ) {
315 if (cp < buffer + sizeof buffer - 2)
319 if (buffer[0] == '\0')
321 if (buffer[0] == '?') {
322 printf ("commands:\n");
323 print_sw (ALL, popicmds, "");
324 printf ("type CTRL-D or use \"quit\" to leave %s\n", invo_name);
328 if (cp = strchr (buffer, ' '))
330 switch (i = smatch (buffer, popicmds)) {
332 ambigsw (buffer, popicmds);
335 printf ("%s unknown -- type \"?\" for help\n", buffer);
349 pop_command ("%s%s", popicmds[i].sw, cp ? cp : "");
350 printf ("%s\n", response);
356 if (pop_command ("%s%s", popicmds[i].sw, cp ? cp : "")
358 printf ("%s\n", response);
361 switch (pop_multiline ()) {
363 strcpy (response, ".");
366 printf ("%s\n", response);
370 printf ("%s\n", response);
380 advise (NULL, "missing argument to %s", buffer);
383 retr_action (NULL, OK);
384 pop_retr (atoi (++cp), retr_action);
385 retr_action (NULL, DONE);
386 printf ("%s\n", response);
398 for (dp = nfs, i = 0; *dp; dp++, i++)
399 if (*dp == '\\' || *dp == '"' || *dp == '\n')
402 if ((ep = malloc ((unsigned) i)) == NULL)
403 adios (NULL, "out of memory");
404 for (dp = nfs, fp = ep; *dp; dp++) {
406 *fp++ = '\\', *fp++ = 'n';
409 if (*dp == '"' || *dp == '\\')
415 pop_command ("xtnd scan %d \"%s\"", width, ep);
416 printf ("%s\n", response);
433 retr_action (char *rsp, int flag)
442 if (!(mp = folder_realloc (mp, mp->lowoff, msgnum = mp->hghmsg + 1)))
443 adios (NULL, "unable to allocate folder storage");
445 cp = getcpy (m_name (mp->hghmsg + 1));
446 if ((fp = fopen (cp, "w+")) == NULL)
447 adios (cp, "unable to write");
448 chmod (cp, m_gmprot ());
454 if (fstat (fileno (fp), &st) != NOTOK && st.st_size > 0) {
455 clear_msg_flags (mp, msgnum);
456 set_exists (mp, msgnum);
457 set_unseen (mp, msgnum);
458 mp->msgflags |= SEQMOD;
461 advise (cp, "write error on");
467 fclose (fp), fp = NULL;
468 free (cp), cp = NULL;
474 fprintf (fp, "%s\n", rsp);
483 char buf1[BUFSIZ], buf2[BUFSIZ], *vec[9];
485 if (pop_fd (buf1, sizeof(buf1), buf2, sizeof(buf2)) == NOTOK)
486 adios (NULL, "%s", response);
489 vec[vecp++] = r1bindex (mshproc, '/');
491 switch (child_id = fork ()) {
493 adios ("fork", "unable to");
496 vec[vecp++] = "-popread";
498 vec[vecp++] = "-popwrite";
500 vec[vecp++] = "-idname";
501 vec[vecp++] = mailname;
502 vec[vecp++] = mailname;
504 execvp (mshproc, vec);
505 fprintf (stderr, "unable to exec ");
510 pidXwait (child_id, mshproc);
518 #include <zotnet/mts/mts.h>
519 #include <mts/smtp/smtp.h>
522 dselect (struct direct *d)
526 if ((i = strlen (d->d_name)) < sizeof "smtp"
527 || strncmp (d->d_name, "smtp", sizeof "smtp" - 1))
529 return ((i -= (sizeof ".bulk" - 1)) > 0
530 && !strcmp (d->d_name + i, ".bulk"));
535 dcompar (struct direct *d1, struct direct *d2)
539 if (stat ((*d1)->d_name, &s1) == NOTOK)
541 if (stat ((*d2)->d_name, &s2) == NOTOK)
543 return ((int) (s1.st_mtime - s2.st_mtime));
552 struct direct **namelist;
554 if (chdir (bulksw) == NOTOK)
555 adios (bulksw, "unable to change directory to");
557 if ((n = scandir (".", &namelist, dselect, dcompar)) == NOTOK)
558 adios (bulksw, "unable to scan directory");
561 for (i = 0; i < n; i++) {
562 register struct direct *d = namelist[i];
565 if (rp_isbad (retval = sm_init (NULL, host, 1, 1, snoop)))
566 adios (NULL, "problem initializing server: %s",
572 switch (retval = sm_bulk (d->d_name)) {
574 if (rp_isbad (retval))
575 adios (NULL, "problem delivering msg %s: %s",
576 d->d_name, rp_string (retval));
581 advise (NULL, "msg %s: %s", d->d_name, rp_string (retval));
590 struct direct **newlist;
592 while ((l = scandir (".", &newlist, dselect, dcompar)) > OK) {
595 for (j = 0; j < l; j++) {
596 register struct direct *d = newlist[j];
598 for (i = 0; i < n; i++)
599 if (strcmp (d->d_name, namelist[i]->d_name) == 0)
602 switch (retval = sm_bulk (d->d_name)) {
604 if (rp_isbad (retval))
605 adios (NULL, "problem delivering msg %s: %s",
606 d->d_name, rp_string (retval));
611 advise (NULL, "msg %s: %s", d->d_name,
620 for (i = 0; i < n; i++)
621 free ((char *) namelist[i]);
622 free ((char *) namelist);
623 namelist = newlist, n = l;
631 if (sm == OK && rp_isbad (retval = sm_end (OK)))
632 adios (NULL, "problem finalizing server: %s", rp_string (retval));
634 for (i = 0; i < n; i++)
635 free ((char *) namelist[i]);
636 free ((char *) namelist);
638 free ((char *) namelist);