Mercurial > hg > Applications > mh
view uip/popi.c @ 4:6bc439d68ff9 utf-8-support
*** empty log message ***
author | kono |
---|---|
date | Wed, 20 Apr 2005 14:39:40 +0900 |
parents | bce86c4163a3 |
children | a6481689f99c |
line wrap: on
line source
/* popi.c - POP initiator - for MPOP */ #ifndef lint static char ident[] = "@(#)$Id$"; #endif lint #include "../h/mh.h" #include "../h/formatsbr.h" #include "../h/scansbr.h" #include <errno.h> #include <stdio.h> #include <sys/types.h> #ifdef SMTP #include "../h/local.h" #else /* SMTP */ #include <sys/stat.h> #endif /* SMTP */ #include "../zotnet/mts.h" #ifdef SYS5DIR #include <stdlib.h> #endif /* */ #ifndef RPOP #define RPOPminc(a) (a) #else #define RPOPminc(a) 0 #endif #ifndef APOP #define APOPminc(a) (a) #else #define APOPminc(a) 0 #endif #if !defined(BPOP) || defined(NNTP) #define BPOPminc(a) (a) #else #define BPOPminc(a) 0 #endif #ifndef SMTP #define BULKminc(a) (a) #else #define BULKminc(a) 0 #endif static struct swit switches[] = { #define APOPSW 0 "apop", APOPminc (-4), #define NAPOPSW 1 "noapop", APOPminc (-6), #define AUTOSW 2 "auto", BPOPminc(-4), #define NAUTOSW 3 "noauto", BPOPminc(-6), #define BULKSW 4 "bulk directory", BULKminc(-4), #define FORMSW 5 "form formatfile", 0, #define FMTSW 6 "format string", 5, #define HOSTSW 7 "host host", 0, #define PROGSW 8 "mshproc program", 0, #define RPOPSW 9 "rpop", RPOPminc (-4), #define NRPOPSW 10 "norpop", RPOPminc (-6), #define USERSW 11 "user user", 0, #define WIDSW 12 "width columns", 0, #define HELPSW 13 "help", 4, NULL, 0 }; /* */ static char *bulksw = NULLCP; static int snoop = 0; static int width = 0; static char mailname[BUFSIZ]; static char *nfs = NULL; static struct msgs *mp; extern int errno; extern char response[]; static popi(), retr_action(); #if defined(BPOP) && !defined(NNTP) static msh(); #endif #ifdef SMTP static do_bulk(); #endif /* */ /* ARGSUSED */ main (argc, argv) int argc; char *argv[]; { int autosw = 1, noisy = 1, rpop; char *cp, *maildir, *folder = NULL, *form = NULL, *format = NULL, *host = NULL, *user = NULL, *pass = NULL, buf[100], **ap, **argp, *arguments[MAXARGS]; struct stat st; invo_name = r1bindex (argv[0], '/'); mts_init (invo_name); if (pophost && *pophost) host = pophost; if ((cp = getenv ("MHPOPDEBUG")) && *cp) snoop++; if ((cp = m_find (invo_name)) != NULL) { ap = brkstring (cp = getcpy (cp), " ", "\n"); ap = copyip (ap, arguments); } else ap = arguments; (void) copyip (argv + 1, ap); argp = arguments; rpop = getuid () && !geteuid (); /* */ while (cp = *argp++) { if (*cp == '-') switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULLCP, "-%s unknown", cp); case HELPSW: (void) sprintf (buf, "%s [+folder] [switches]", invo_name); help (buf, switches); done (1); case AUTOSW: autosw = 1; continue; case NAUTOSW: autosw = 0; continue; case BULKSW: if (!(bulksw = *argp++) || *bulksw == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULLCP, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULLCP, "missing argument to %s", argp[-2]); form = NULL; continue; case WIDSW: if (!(cp = *argp++) || *cp == '-') adios (NULLCP, "missing argument to %s", argp[-2]); width = atoi (cp); continue; case HOSTSW: if (!(host = *argp++) || *host == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case USERSW: if (!(user = *argp++) || *user == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case APOPSW: rpop = -1; continue; case RPOPSW: rpop = 1; continue; case NAPOPSW: case NRPOPSW: rpop = 0; continue; case PROGSW: if (!(mshproc = *argp++) || *mshproc == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; } if (*cp == '+' || *cp == '@') { if (folder) adios (NULLCP, "only one folder at a time!"); else folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); } else adios (NULLCP, "usage: %s [+folder] [switches]", invo_name); } /* */ if (!host) adios (NULLCP, "usage: %s -host \"host\"", invo_name); #ifdef SMTP if (bulksw) do_bulk (host); #endif if (user == NULL) user = getusr (); if (rpop > 0) pass = getusr (); else { (void) setuid (getuid ()); ruserpass (host, &user, &pass); } (void) sprintf (mailname, "PO box for %s@%s", user, host); if (pop_init (host, user, pass, snoop, rpop) == NOTOK) adios (NULLCP, "%s", response); if (rpop > 0) (void) setuid (getuid ()); nfs = new_fs (form, format, FORMAT); if (!m_find ("path")) free (path ("./", TFOLDER)); if (!folder && !(folder = m_find (inbox))) folder = defalt; maildir = m_maildir (folder); if (stat (maildir, &st) == NOTOK) { if (errno != ENOENT) adios (maildir, "error on folder"); cp = concat ("Create folder \"", maildir, "\"? ", NULLCP); if (noisy && !getanswer (cp)) done (1); free (cp); if (!makedir (maildir)) adios (NULLCP, "unable to create folder %s", maildir); } if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); if (!(mp = m_gmsg (folder))) adios (NULLCP, "unable to read folder %s", folder); #if defined(BPOP) && !defined(NNTP) if (autosw) msh (); else #endif popi (); (void) pop_quit (); m_replace (pfolder, folder); m_setvis (mp, 0); m_sync (mp); m_update (); done (0); /* NOTREACHED */ } /* */ static struct swit popicmds[] = { #define DELECMD 0 "dele", 0, #define LASTCMD 1 "last", 0, #define LISTCMD 2 "list", 0, #define NOOPCMD 3 "noop", 0, #define QUITCMD 4 "quit", 0, #define RETRCMD 5 "retr", 0, #define RSETCMD 6 "rset", 0, #define SCANCMD 7 "scan", 0, #define STATCMD 8 "stat", 0, #define TOPCMD 9 "top", 0, #if defined(BPOP) && !defined(NNTP) #define MSHCMD 10 "msh", 0, #endif NULL, 0 }; /* */ static popi () { int eof; eof = 0; for (;;) { int i; register char *cp; char buffer[BUFSIZ]; if (eof) return; printf ("(%s) ", invo_name); for (cp = buffer; (i = getchar ()) != '\n'; ) { if (i == EOF) { (void) putchar ('\n'); if (cp == buffer) return; eof = 1; break; } if (cp < buffer + sizeof buffer - 2) *cp++ = i; } *cp = '\0'; if (buffer[0] == '\0') continue; if (buffer[0] == '?') { printf ("commands:\n"); printsw (ALL, popicmds, ""); printf ("type CTRL-D or use \"quit\" to leave %s\n", invo_name); continue; } if (cp = index (buffer, ' ')) *cp = '\0'; switch (i = smatch (buffer, popicmds)) { case AMBIGSW: ambigsw (buffer, popicmds); continue; case UNKWNSW: printf ("%s unknown -- type \"?\" for help\n", buffer); continue; case QUITCMD: return; case STATCMD: case DELECMD: case NOOPCMD: case LASTCMD: case RSETCMD: case TOPCMD: if (cp) *cp = ' '; (void) pop_command ("%s%s", popicmds[i].sw, cp ? cp : ""); printf ("%s\n", response); break; case LISTCMD: if (cp) *cp = ' '; if (pop_command ("%s%s", popicmds[i].sw, cp ? cp : "") == OK) { printf ("%s\n", response); if (!cp) for (;;) { switch (pop_multiline ()) { case DONE: (void) strcpy (response, "."); /* and fall... */ case NOTOK: printf ("%s\n", response); break; case OK: printf ("%s\n", response); continue; } break; } } break; case RETRCMD: if (!cp) { advise (NULLCP, "missing argument to %s", buffer); break; } retr_action (NULLCP, OK); (void) pop_retr (atoi (++cp), retr_action); retr_action (NULLCP, DONE); printf ("%s\n", response); break; case SCANCMD: { char *dp, *ep, *fp; if (width == 0) width = sc_width (); for (dp = nfs, i = 0; *dp; dp++, i++) if (*dp == '\\' || *dp == '"' || *dp == '\n') i++; i++; if ((ep = malloc ((unsigned) i)) == NULL) adios (NULLCP, "out of memory"); for (dp = nfs, fp = ep; *dp; dp++) { if (*dp == '\n') { *fp++ = '\\', *fp++ = 'n'; continue; } if (*dp == '"' || *dp == '\\') *fp++ = '\\'; *fp++ = *dp; } *fp = '\0'; (void) pop_command ("xtnd scan %d \"%s\"", width, ep); printf ("%s\n", response); free (ep); } break; #if defined(BPOP) && !defined(NNTP) case MSHCMD: msh (); break; #endif } } } /* */ static int retr_action (rsp, flag) char *rsp; int flag; { static FILE *fp; if (rsp == NULL) { static int msgnum; static char *cp; if (flag == OK) { if ((mp = m_remsg (mp, 0, msgnum = mp -> hghmsg + 1)) == NULL) adios (NULLCP, "unable to allocate folder storage"); cp = getcpy (m_name (mp -> hghmsg + 1)); if ((fp = fopen (cp, "w+")) == NULL) adios (cp, "unable to write"); (void) chmod (cp, m_gmprot ()); } else { struct stat st; (void) fflush (fp); if (fstat (fileno (fp), &st) != NOTOK && st.st_size > 0) { mp -> msgstats[msgnum] = EXISTS | UNSEEN; mp -> msgflags |= SEQMOD; if (ferror (fp)) advise (cp, "write error on"); mp -> hghmsg = msgnum; } else (void) unlink (cp); (void) fclose (fp), fp = NULL; free (cp), cp = NULL; } return; } fprintf (fp, "%s\n", rsp); } /* */ #if defined(BPOP) && !defined(NNTP) static msh () { int child_id, vecp; char buf1[BUFSIZ], buf2[BUFSIZ], *vec[9]; if (pop_fd (buf1, buf2) == NOTOK) adios (NULLCP, "%s", response); vecp = 0; vec[vecp++] = r1bindex (mshproc, '/'); switch (child_id = fork ()) { case NOTOK: adios ("fork", "unable to"); case OK: vec[vecp++] = "-popread"; vec[vecp++] = buf1; vec[vecp++] = "-popwrite"; vec[vecp++] = buf2; vec[vecp++] = "-idname"; vec[vecp++] = mailname; vec[vecp++] = mailname; vec[vecp] = NULL; (void) execvp (mshproc, vec); fprintf (stderr, "unable to exec "); perror (mshproc); _exit (-1); default: (void) pidXwait (child_id, mshproc); break; } } #endif /* */ #ifdef SMTP #include "../zotnet/mts.h" #include "../mts/sendmail/smail.h" static int dselect (d) #ifdef SYS5DIR register struct dirent *d; #else register struct direct *d; #endif { int i; if ((i = strlen (d -> d_name)) < sizeof "smtp" || strncmp (d -> d_name, "smtp", sizeof "smtp" - 1)) return 0; return ((i -= (sizeof ".bulk" - 1)) > 0 && !strcmp (d -> d_name + i, ".bulk")); } static int dcompar (d1, d2) #ifdef SYS5DIR struct dirent **d1, **d2; #else struct direct **d1, **d2; #endif { struct stat s1, s2; if (stat ((*d1) -> d_name, &s1) == NOTOK) return 1; if (stat ((*d2) -> d_name, &s2) == NOTOK) return -1; return ((int) (s1.st_mtime - s2.st_mtime)); } static do_bulk (host) char *host; { register int i; int n, retval, sm; #ifdef SYS5DIR struct dirent **namelist; #else struct direct **namelist; #endif if (chdir (bulksw) == NOTOK) adios (bulksw, "unable to change directory to"); if ((n = scandir (".", &namelist, dselect, dcompar)) == NOTOK) adios (bulksw, "unable to scan directory"); sm = NOTOK; for (i = 0; i < n; i++) { #ifdef SYS5DIR register struct dirent *d = namelist[i]; #else register struct direct *d = namelist[i]; #endif if (sm == NOTOK) { if (rp_isbad (retval = sm_init (NULLCP, host, 1, 1, snoop))) adios (NULLCP, "problem initializing server: %s", rp_string (retval)); else sm = OK; } switch (retval = sm_bulk (d -> d_name)) { default: if (rp_isbad (retval)) adios (NULLCP, "problem delivering msg %s: %s", d -> d_name, rp_string (retval)); /* else fall... */ case RP_OK: case RP_NO: case RP_NDEL: advise (NULLCP, "msg %s: %s", d -> d_name, rp_string (retval)); break; } } if (sm == OK) { register int j; int l, m; #ifdef SYS5DIR struct dirent **newlist; #else struct direct **newlist; #endif while ((l = scandir (".", &newlist, dselect, dcompar)) > OK) { m = 0; for (j = 0; j < l; j++) { #ifdef SYS5DIR register struct dirent *d = newlist[j]; #else register struct direct *d = newlist[j]; #endif for (i = 0; i < n; i++) if (strcmp (d -> d_name, namelist[i] -> d_name) == 0) break; if (i >= n) { switch (retval = sm_bulk (d -> d_name)) { default: if (rp_isbad (retval)) adios (NULLCP, "problem delivering msg %s: %s", d -> d_name, rp_string (retval)); /* else fall... */ case RP_OK: case RP_NO: case RP_NDEL: advise (NULLCP, "msg %s: %s", d -> d_name, rp_string (retval)); break; } m = 1; } } for (i = 0; i < n; i++) free ((char *) namelist[i]); free ((char *) namelist); namelist = newlist, n = l; if (!m) break; newlist = NULL; } } if (sm == OK && rp_isbad (retval = sm_end (OK))) adios (NULLCP, "problem finalizing server: %s", rp_string (retval)); for (i = 0; i < n; i++) free ((char *) namelist[i]); free ((char *) namelist); free ((char *) namelist); done (0); } #endif #if defined(SYS5DIR) && !defined(BSD42) && !defined(hpux) && !defined(sgi) && !defined(linux) /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91"; #endif /* LIBC_SCCS and not lint */ /* * Scan the directory dirname calling select to make a list of selected * directory entries then sort using qsort and compare routine dcomp. * Returns the number of entries and a pointer to a list of pointers to * struct dirent (through namelist). Returns -1 if there were any errors. */ /* * This code modified by Ted Nolan to take Solaris dirent structures * and mollify gcc -traditional. In general, everything from BSD that * didn't work is "ifdef notdef" ed out * * 3 Feb 94 */ #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> /* #include <stdlib.h> */ #include <string.h> /* * The DIRSIZ macro gives the minimum record length which will hold * the directory entry. This requires the amount of space in struct dirent * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. */ #undef DIRSIZ #ifdef notdef #define DIRSIZ(dp) \ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) #else #define DIRSIZ(dp) \ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + ((strlen(dp->d_name)+1 + 3) &~ 3)) #endif int scandir(dirname, namelist, select, dcomp) #ifdef notdef const char *dirname; #else char *dirname; #endif struct dirent ***namelist; #ifdef notdef int (*select) __P((struct dirent *)); int (*dcomp) __P((const void *, const void *)); #else int (*select)(); int (*dcomp)(); #endif { register struct dirent *d, *p, **names; register size_t nitems; struct stat stb; long arraysz; DIR *dirp; if ((dirp = opendir(dirname)) == NULL) return(-1); if (stat(dirname, &stb) < 0) return(-1); /* * estimate the array size by taking the size of the directory file * and dividing it by a multiple of the minimum size entry. */ arraysz = (stb.st_size / 24); names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); if (names == NULL) return(-1); nitems = 0; while ((d = readdir(dirp)) != NULL) { if (select != NULL && !(*select)(d)) continue; /* just selected names */ /* * Make a minimum size copy of the data */ p = (struct dirent *)malloc(DIRSIZ(d)); if (p == NULL) return(-1); p->d_ino = d->d_ino; p->d_reclen = d->d_reclen; #ifdef notdef p->d_namlen = d->d_namlen; bcopy(d->d_name, p->d_name, p->d_namlen + 1); #else bcopy(d->d_name, p->d_name, strlen(p->d_name) + 1); #endif /* * Check to make sure the array has space left and * realloc the maximum size. */ if (++nitems >= arraysz) { if (stat(dirname, &stb) < 0) return(-1); /* just might have grown */ arraysz = stb.st_size / 12; names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *)); if (names == NULL) return(-1); } names[nitems-1] = p; } closedir(dirp); if (nitems && dcomp != NULL) qsort(names, nitems, sizeof(struct dirent *), dcomp); *namelist = names; return(nitems); } /* * Alphabetic order comparison routine for those who want it. */ int alphasort(d1, d2) #ifdef notdef const void *d1; const void *d2; #else char *d1; char *d2; #endif /* notdef */ { return(strcmp((*(struct dirent **)d1)->d_name, (*(struct dirent **)d2)->d_name)); } #endif