Mercurial > hg > Applications > mh
view uip/pgpshow.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
line wrap: on
line source
/* pgpshow.c - PGP viewer */ #ifndef lint static char ident[] = "@(#)$Id$"; #endif /* lint */ #include "../h/mh.h" #include <stdio.h> #include <errno.h> #include <signal.h> #include <sys/stat.h> #ifdef UNISTD #include <unistd.h> #endif /* UNISTD */ #ifdef LOCALE #include <locale.h> #endif /* LOCALE */ void pgp_show(); void pgp_store(); void pgp_mime(); int tee(); static TYPESIG goodbye(); /* */ static struct swit switches[] = { #define PGPPROC 0 {"pgpproc program", -7}, #define SHOWSW 1 {"show", 0}, #define NSHOWSW 2 {"noshow", 0}, #define STORESW 3 {"store", 0}, #define NSTORESW 4 {"nostore", 0}, #define MIMESW 5 {"mime", 0}, #define NMIMESW 6 {"nomime", 0}, #define HELPSW 7 {"help", 4}, {NULL, 0} }; /* */ static int showsw = 0; static int storesw = 0; static int mimesw = 0; static char *pgpproc = ""; /* "pgp"; */ static char *showprog = "show"; /* not showproc */ extern char *moreproc; static char tmpfil1[BUFSIZ]; static char tmpfil2[BUFSIZ]; static FILE *out = NULL; #define PGP_SIGN 1 #define PGP_ENCRYPT 2 #define PGP_VER2 (int)1 #define PGP_VER5 (int)2 #define PGP2_GOOD_SIGNATURE "Good signature from user" #define PGP5_GOOD_SIGNATURE "Good signature made" #define NOT_INSTALLED 127 /* */ main(argc, argv) int argc; char *argv[]; { int i, paramp = 0; char *cp, buf[BUFSIZ]; char **ap, **argp, *arguments[MAXARGS], *param[MAXARGS]; #ifdef LOCALE setlocale(LC_ALL, ""); #endif /* LOCALE */ #ifdef JAPAN ml_init(); #endif /* JAPAN */ invo_name = r1bindex(argv[0], '/'); 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; /* */ 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 [switches] file .. [parameters]", invo_name); help(buf, switches); done(1); case SHOWSW: showsw++; continue; case NSHOWSW: showsw = 0; continue; case STORESW: storesw++; continue; case NSTORESW: storesw = 0; continue; case MIMESW: mimesw++; continue; case NMIMESW: mimesw = 0; continue; case PGPPROC: if (!(pgpproc = *argp++) || *pgpproc == '-') adios(NULLCP, "missing argument to %s", argp[-2]); continue; } else param[paramp++] = cp; } param[paramp] = NULLCP; if ((!showsw && !storesw) || paramp < (mimesw ? 2 : 1)) adios(NULLCP, "usage: %s [switches] file .. [parameters]", invo_name); tmpfil1[0] = tmpfil2[0] = '\0'; /* */ if (mimesw) { int protocol = 0; char *micalg = NULLCP; for (i = 2; param[i]; i++) { if (uprf(param[i], "protocol=")) { if (uleq(param[i] + 9, "application/pgp-signature")) protocol = PGP_SIGN; else if (uleq(param[i] + 9, "application/pgp-encrypted")) protocol = PGP_ENCRYPT; else adios(NULLCP, "protocol \"%s\" is unsupported", param[i] + 9); } if (uprf(param[i], "micalg=")) { micalg = param[i] + 7; if (!uleq(micalg, "pgp-md5") && !uleq(micalg, "pgp-sha1")) adios(NULLCP, "micalg \"%s\" is unsupported", micalg); } } if (!protocol) adios(NULLCP, "protocol parameter is required"); pgp_mime(param[0], param[1], protocol, micalg, showsw); } else { int fmtmime = 0; for (i = 1; param[i]; i++) { if (uleq(param[i], "format=mime")) { fmtmime = 1; break; } } if (showsw) pgp_show(param[0], fmtmime); else pgp_store(param[0], fmtmime); } done(0); } void pgp_show(file, fmtmime) char *file; int fmtmime; { int pid, nopgp = 0; char *ap[5]; (void) signal(SIGHUP, goodbye); (void) signal(SIGINT, goodbye); (void) signal(SIGQUIT, goodbye); (void) signal(SIGPIPE, goodbye); (void) signal(SIGTERM, goodbye); (void) strcpy(tmpfil1, m_scratch("", m_maildir(invo_name))); if ((out = fopen(tmpfil1, "w")) == NULL) { (void) strcpy(tmpfil1, m_tmpfil(invo_name)); if ((out = fopen(tmpfil1, "w")) == NULL) { advise(tmpfil1, "unable to create"); goodbye(); } } (void) chmod(tmpfil1, 0600); fclose(out); out = NULL; unlink(tmpfil1); if (! *pgpproc) { /* for PGP5 */ ap[0] = pgpproc = "pgpv"; ap[1] = file; ap[2] = "-o"; ap[3] = tmpfil1; ap[4] = NULLCP; if (tee(ap, PGP_VER5) == NOTOK) /* Let's try old PGP */ pgpproc = "pgp"; else pgpproc = ""; } if (*pgpproc) { /* for PGP2 */ ap[0] = r1bindex(pgpproc, '/'); if (tee(ap, PGP_VER2) == NOTOK) { advise(pgpproc, "unable to exec"); nopgp = 1; } } if (fmtmime) { ap[0] = r1bindex(showprog, '/'); ap[1] = "-file"; ap[2] = nopgp ? file : tmpfil1; ap[3] = NULLCP; } else { ap[0] = r1bindex(moreproc, '/'); ap[1] = nopgp ? file : tmpfil1; ap[2] = NULLCP; } switch (pid = fork()) { case NOTOK: advise("fork", "unable to"); goodbye(); case OK: execvp(fmtmime ? showprog : moreproc, ap); adios(fmtmime ? showprog : moreproc, "unable to exec"); default: if (pidXwait(pid, fmtmime ? showprog : r1bindex(moreproc, '/'))) goodbye(); break; } unlink(tmpfil1); } void pgp_store(file, fmtmime) char *file; int fmtmime; { int pid, state; char *ap[5]; (void) signal(SIGHUP, goodbye); (void) signal(SIGINT, goodbye); (void) signal(SIGQUIT, goodbye); (void) signal(SIGPIPE, goodbye); (void) signal(SIGTERM, goodbye); (void) strcpy(tmpfil1, m_scratch("", m_maildir(invo_name))); if ((out = fopen(tmpfil1, "w")) == NULL) { (void) strcpy(tmpfil1, m_tmpfil(invo_name)); if ((out = fopen(tmpfil1, "w")) == NULL) { advise(tmpfil1, "unable to create"); goodbye(); } } (void) chmod(tmpfil1, 0600); cpydata(fileno(stdin), fileno(out), "stdin", tmpfil1); fclose(out); out = NULL; if (! *pgpproc) { /* for PGP5 */ ap[0] = "pgpv"; ap[1] = tmpfil1; ap[2] = "-o"; ap[3] = file; ap[4] = NULLCP; switch (pid = fork()) { case NOTOK: advise("fork", "unable to"); goodbye(); case OK: execvp("pgpv", ap); /* maybe PGP5 is not installed. */ _exit(NOT_INSTALLED); default: #if 0 state = pidwait(pid, OK); if (WIFEXITED(state) && WEXITSTATUS(state) == NOT_INSTALLED) #else if ((state = pidwait(pid, OK)) == (NOT_INSTALLED << 8)) #endif /* Let's try old PGP */ pgpproc = "pgp"; else if (pidstatus(state, stdout, "pgpv")) goodbye(); break; } } if (*pgpproc) { /* for PGP2 */ ap[0] = r1bindex(pgpproc, '/'); switch (pid = fork()) { case NOTOK: advise("fork", "unable to"); goodbye(); case OK: execvp(pgpproc, ap); adios(pgpproc, "unable to exec"); default: if (pidXwait(pid, r1bindex(pgpproc, '/'))) goodbye(); break; } } unlink(tmpfil1); if (fmtmime) { if (!m_find("path")) free(path("./", TFOLDER)); if (!(ap[0] = m_find(inbox))) ap[0] = defalt; if (*ap[0] != '+' && *ap[0] != '@') ap[0] = add(ap[0], add("+", NULLCP)); ap[1] = NULL; refile(ap, file); } } void pgp_mime(file1, file2, protocol, micalg, showsw) char *file1, *file2, *micalg; int protocol, showsw; { int pid; char *cp, *ap[6], buf[BUFSIZ]; FILE *in; (void) signal(SIGHUP, goodbye); (void) signal(SIGINT, goodbye); (void) signal(SIGQUIT, goodbye); (void) signal(SIGPIPE, goodbye); (void) signal(SIGTERM, goodbye); (void) strcpy(tmpfil1, m_scratch("", m_maildir(invo_name))); if ((out = fopen(tmpfil1, "w")) == NULL) { (void) strcpy(tmpfil1, m_tmpfil(invo_name)); if ((out = fopen(tmpfil1, "w")) == NULL) { advise(tmpfil1, "unable to create"); goodbye(); } } (void) chmod(tmpfil1, 0600); if (protocol == PGP_SIGN) { if ((in = fopen(file1, "r")) == NULL) { advise(file1, "unable to open"); goodbye(); } while (fgets(buf, sizeof(buf) - 2, in)) { cp = buf + strlen(buf) - 1; if (*cp-- == '\n' && *cp != '\r') { *++cp = '\r'; *++cp = '\n'; *++cp = '\0'; } fputs(buf, out); } fclose(in); fclose(out); out = NULL; ap[1] = "+batchmode=on"; ap[2] = file2; ap[3] = "-o"; ap[4] = tmpfil1; ap[5] = NULLCP; } else { fclose(out); out = NULL; unlink(tmpfil1); ap[1] = file2; ap[2] = "-o"; ap[3] = tmpfil1; ap[4] = NULLCP; } if (! *pgpproc) { /* for PGP5 */ ap[0] = pgpproc = "pgpv"; if (tee(ap, PGP_VER5) == NOTOK) { if (protocol == PGP_SIGN && !uleq(micalg, "pgp-md5")) { /* PGP2 only support PGP-MD5 */ advise(pgpproc, "unable to exec"); pgpproc = ""; } else /* Let's try old PGP */ pgpproc = "pgp"; } else pgpproc = ""; } if (*pgpproc) { /* for PGP2 */ ap[0] = r1bindex(pgpproc, '/'); if (protocol == PGP_SIGN) { ap[3] = tmpfil1; ap[4] = NULLCP; } if (tee(ap, PGP_VER2) == NOTOK) { advise(pgpproc, "unable to exec"); if (protocol != PGP_SIGN) goodbye(); } } ap[0] = r1bindex(showprog, '/'); ap[1] = "-file"; if (protocol == PGP_SIGN) ap[2] = file1; else { if ((in = fopen(tmpfil1, "r")) == NULL) { advise(tmpfil1, "unable to open"); goodbye(); } (void) strcpy(tmpfil2, m_scratch("", m_maildir(invo_name))); if ((out = fopen(tmpfil2, "w")) == NULL) { (void) strcpy(tmpfil2, m_tmpfil(invo_name)); if ((out = fopen(tmpfil2, "w")) == NULL) { advise(tmpfil2, "unable to create"); goodbye(); } } (void) chmod(tmpfil2, 0600); while (fgets(buf, sizeof(buf) - 1, in)) { cp = buf + strlen(buf) - 1; if (*cp-- == '\n' && *cp == '\r') { *cp++ = '\n'; *cp = '\0'; } fputs(buf, out); } fclose(in); fclose(out); out = NULL; ap[2] = tmpfil2; } ap[3] = NULLCP; unlink(tmpfil1); if (!showsw) { if (!m_find("path")) free(path("./", TFOLDER)); if (!(ap[0] = m_find(inbox))) ap[0] = defalt; if (*ap[0] != '+' && *ap[0] != '@') ap[0] = add(ap[0], add("+", NULLCP)); ap[1] = NULL; refile(ap, ap[2]); return; } switch (pid = fork()) { case NOTOK: advise("fork", "unable to"); goodbye(); case OK: execvp(showprog, ap); adios(showprog, "unable to exec"); default: if (pidXwait(pid, r1bindex(showprog, '/'))) goodbye(); break; } if (tmpfil2[0]) unlink(tmpfil2); } int tee(ap, pgpver) char *ap[]; int pgpver; { int cnt, state, pid, pdes[2]; char *cp, *ep, *np, buf[BUFSIZ]; if (pipe(pdes) == NOTOK) { advise(NULLCP, "unable to open pipe"); goodbye(); } switch (pid = fork()) { case NOTOK: close(pdes[0]); close(pdes[1]); advise("fork", "unable to"); goodbye(); case OK: if (pdes[1] != fileno(stdout)) dup2(pdes[1], fileno(stdout)); if (pdes[1] != fileno(stderr)) { dup2(pdes[1], fileno(stderr)); if (pdes[1] != fileno(stdout)) close(pdes[1]); } close(pdes[0]); execvp(pgpproc, ap); /* maybe PGP is not installed. */ _exit(NOT_INSTALLED); } close(pdes[1]); cp = ep = buf; while ((cnt = read(pdes[0], buf + (ep - cp), sizeof(buf) - (ep - cp) - 1)) > 0) { write(fileno(stdout), buf + (ep - cp), cnt); ep = buf + (ep - cp) + cnt; cp = buf; while (cp < ep) { np = cp; while (np < ep && *np != '\n') np++; if (np < ep || (cp == buf && np == buf + sizeof(buf) - 1)) { char *xp, *yp; *np = '\0'; if ((pgpver == PGP_VER5 && strncmp(cp, PGP5_GOOD_SIGNATURE, strlen(PGP5_GOOD_SIGNATURE)) == 0) || (pgpver == PGP_VER2 && strncmp(cp, PGP2_GOOD_SIGNATURE, strlen(PGP2_GOOD_SIGNATURE)) == 0)) { pgpver = -1; } if (pgpver < 0 && (xp = index(cp, '"')) && (yp = rindex(xp + 1, '"'))) { *yp = '\0'; m_putenv("PGP_SIGNATURE", xp + 1); pgpver = 0; } } else { bcopy(cp, buf, ep - cp); break; } cp = np + 1; } } close(pdes[0]); #if 0 state = pidwait(pid, OK); if (WIFEXITED(state) && WEXITSTATUS(state) == NOT_INSTALLED) #else if ((state = pidwait(pid, OK)) == (NOT_INSTALLED << 8)) #endif return NOTOK; if (pidstatus(state, stdout, r1bindex(pgpproc, '/'))) goodbye(); return OK; } static TYPESIG goodbye() { if (out) fclose(out); if (tmpfil1[0]) unlink(tmpfil1); if (tmpfil2[0]) unlink(tmpfil2); done(1); /* NOT REACHED */ }