Mercurial > hg > Applications > mh
comparison uip/pgped.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bce86c4163a3 |
---|---|
1 /* pgped.c - PGP editor */ | |
2 #ifndef lint | |
3 static char ident[] = "@(#)$Id$"; | |
4 #endif /* lint */ | |
5 | |
6 #include "../h/mh.h" | |
7 #include "../h/mhn.h" | |
8 #include "../h/addrsbr.h" | |
9 #include "../h/aliasbr.h" | |
10 #include <stdio.h> | |
11 #include <ctype.h> | |
12 #include <signal.h> | |
13 #include <sys/stat.h> | |
14 #ifdef UNISTD | |
15 #include <unistd.h> | |
16 #endif /* UNISTD */ | |
17 #ifdef LOCALE | |
18 #include <locale.h> | |
19 #endif /* LOCALE */ | |
20 | |
21 struct addrlist { | |
22 char *address; | |
23 struct addrlist *next; | |
24 }; | |
25 | |
26 struct addrlist *add_addrlist(); | |
27 int exec_pgp5_for_keyid(); | |
28 char *get_micalg(); | |
29 static TYPESIG goodbye(); | |
30 | |
31 /* */ | |
32 | |
33 static struct swit switches[] = { | |
34 #define ALIASW 0 | |
35 {"alias aliasfile", 0}, | |
36 | |
37 #define MHNPROC 1 | |
38 {"mhnproc program", 0}, | |
39 | |
40 #define PGPPROC 2 | |
41 {"pgpproc program", -7}, | |
42 | |
43 #define SIGNSW 3 | |
44 {"sign", 0}, | |
45 #define NSIGNSW 4 | |
46 {"nosign", 0}, | |
47 | |
48 #define CRYPTSW 5 | |
49 {"encrypt", 0}, | |
50 #define NCRPTSW 6 | |
51 {"noencrypt", 0}, | |
52 | |
53 #define MIMESW 7 | |
54 {"mime", 0}, | |
55 #define NMIMESW 8 | |
56 {"nomime", 0}, | |
57 | |
58 #define HELPSW 9 | |
59 {"help", 4}, | |
60 | |
61 {NULL, 0} | |
62 }; | |
63 | |
64 /* */ | |
65 | |
66 static int signsw = 1; | |
67 static int encryptsw = 1; | |
68 static int mimesw = 1; | |
69 | |
70 static char *mhnproc = "mhn"; | |
71 static char *pgpproc = ""; /* "pgp"; */ | |
72 | |
73 static char prefix[] = "----- =_aaaaaaaaaa"; | |
74 | |
75 static char tmpfil1[BUFSIZ]; | |
76 static char tmpfil2[BUFSIZ]; | |
77 static char tmpfil3[BUFSIZ]; | |
78 static FILE *out1 = NULL; | |
79 static FILE *out2 = NULL; | |
80 | |
81 static struct addrlist *addrs = NULL; | |
82 static struct addrlist *from_addrs = NULL; | |
83 static struct addrlist *resent_addrs = NULL; | |
84 | |
85 char *addr_headers[] = { | |
86 "Reply-To", | |
87 "From", | |
88 "Sender", | |
89 "To", | |
90 "Cc", | |
91 "Bcc", | |
92 "Dcc", | |
93 | |
94 NULLCP | |
95 }; | |
96 | |
97 #define NOT_INSTALLED 127 | |
98 | |
99 /* */ | |
100 | |
101 main(argc, argv) | |
102 int argc; | |
103 char *argv[]; | |
104 { | |
105 int i, cnt, pid, tomhn, mimehdr, resent, compnum, state; | |
106 char *cp, *file = NULL, *keyid, buf[BUFSIZ], name[NAMESZ]; | |
107 char **ap, **argp, *arguments[MAXARGS]; | |
108 FILE *in; | |
109 struct addrlist *ip; | |
110 | |
111 #ifdef LOCALE | |
112 setlocale(LC_ALL, ""); | |
113 #endif /* LOCALE */ | |
114 #ifdef JAPAN | |
115 ml_init(); | |
116 #endif /* JAPAN */ | |
117 invo_name = r1bindex(argv[0], '/'); | |
118 if ((cp = m_find(invo_name)) != NULL) { | |
119 ap = brkstring(cp = getcpy(cp), " ", "\n"); | |
120 ap = copyip(ap, arguments); | |
121 } | |
122 else | |
123 ap = arguments; | |
124 (void) copyip(argv + 1, ap); | |
125 argp = arguments; | |
126 | |
127 /* */ | |
128 | |
129 while ((cp = *argp++)) { | |
130 if (*cp == '-') | |
131 switch (smatch(++cp, switches)) { | |
132 case AMBIGSW: | |
133 ambigsw(cp, switches); | |
134 done(1); | |
135 case UNKWNSW: | |
136 adios(NULLCP, "-%s unknown", cp); | |
137 case HELPSW: | |
138 (void) sprintf(buf, "%s [switches] file", invo_name); | |
139 help(buf, switches); | |
140 done(1); | |
141 | |
142 case ALIASW: | |
143 if (!(cp = *argp++) || *cp == '-') | |
144 adios(NULLCP, "missing argument to %s", argp[-2]); | |
145 if ((i = alias(cp)) != AK_OK) | |
146 adios(NULLCP, "aliasing error in %s - %s", cp, akerror(i)); | |
147 continue; | |
148 | |
149 case SIGNSW: | |
150 signsw++; | |
151 continue; | |
152 case NSIGNSW: | |
153 signsw = 0; | |
154 continue; | |
155 | |
156 case CRYPTSW: | |
157 encryptsw++; | |
158 continue; | |
159 case NCRPTSW: | |
160 encryptsw = 0; | |
161 continue; | |
162 | |
163 case MIMESW: | |
164 mimesw++; | |
165 continue; | |
166 case NMIMESW: | |
167 mimesw = 0; | |
168 continue; | |
169 | |
170 case MHNPROC: | |
171 if (!(mhnproc = *argp++) || *mhnproc == '-') | |
172 adios(NULLCP, "missing argument to %s", argp[-2]); | |
173 continue; | |
174 | |
175 case PGPPROC: | |
176 if (!(pgpproc = *argp++) || *pgpproc == '-') | |
177 adios(NULLCP, "missing argument to %s", argp[-2]); | |
178 continue; | |
179 } | |
180 else { | |
181 if (file) | |
182 adios(NULLCP, "only one file at a time!"); | |
183 else | |
184 file = cp; | |
185 } | |
186 } | |
187 /* for compatibility to "pgped.sh" */ | |
188 if (argc == 3 && strcmp(argv[1], "-sign") == 0 && *argv[2] != '-') | |
189 encryptsw = 0; | |
190 | |
191 /* */ | |
192 | |
193 if ((cp = m_find("Aliasfile"))) { /* allow Aliasfile: profile entry */ | |
194 char *dp = NULL; | |
195 | |
196 for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) | |
197 if ((i = alias(*ap)) != AK_OK) | |
198 adios (NULLCP, "aliasing error in %s - %s", *ap, akerror(i)); | |
199 if (dp) | |
200 free(dp); | |
201 } | |
202 (void) alias(AliasFile); | |
203 | |
204 if (!file || (!mimesw && !signsw && !encryptsw)) | |
205 adios(NULLCP, "usage: %s [switches] file", invo_name); | |
206 | |
207 /* */ | |
208 | |
209 if (mimesw) { | |
210 if ((in = fopen(file, "r")) == NULL) | |
211 adios(file, "unable to open"); | |
212 | |
213 tomhn = 1; | |
214 state = FLD; | |
215 while ((state = m_getfld(state, name, buf, sizeof(buf), in)) == FLD | |
216 || state == FLDPLUS || state == FLDEOF) { | |
217 if (uleq(name, VRSN_FIELD)) { | |
218 tomhn = 0; | |
219 break; | |
220 } | |
221 } | |
222 fclose(in); | |
223 | |
224 if (tomhn) { | |
225 if (!getenv("mhdraft")) | |
226 m_putenv("mhdraft", file); | |
227 switch (pid = fork()) { | |
228 case NOTOK: | |
229 adios("fork", "unable to"); | |
230 | |
231 case OK: | |
232 execlp(mhnproc, r1bindex(mhnproc, '/'), | |
233 "-nocache", "-noshow", "-nostore", file, NULLCP); | |
234 adios(mhnproc, "unable to exec"); | |
235 | |
236 default: | |
237 if (pidXwait(pid, r1bindex(mhnproc, '/'))) | |
238 done(1); | |
239 break; | |
240 } | |
241 } | |
242 if (!signsw && !encryptsw) | |
243 done(0); | |
244 } else | |
245 tomhn = 0; | |
246 | |
247 | |
248 /* */ | |
249 | |
250 if ((in = fopen(file, "r")) == NULL) | |
251 adios(file, "unable to open"); | |
252 tmpfil1[0] = tmpfil2[0] = tmpfil3[0] = '\0'; | |
253 | |
254 (void) signal(SIGHUP, goodbye); | |
255 (void) signal(SIGINT, goodbye); | |
256 (void) signal(SIGQUIT, goodbye); | |
257 (void) signal(SIGPIPE, goodbye); | |
258 (void) signal(SIGTERM, goodbye); | |
259 | |
260 (void) strcpy(tmpfil1, m_scratch("", m_maildir(invo_name))); | |
261 if ((out1 = fopen(tmpfil1, "w")) == NULL) { | |
262 (void) strcpy(tmpfil1, m_tmpfil(invo_name)); | |
263 if ((out1 = fopen(tmpfil1, "w")) == NULL) { | |
264 advise(tmpfil1, "unable to create"); | |
265 goodbye(); | |
266 } | |
267 } | |
268 (void) chmod(tmpfil1, 0600); | |
269 | |
270 (void) strcpy(tmpfil2, m_scratch("", m_maildir(invo_name))); | |
271 if ((out2 = fopen(tmpfil2, "w")) == NULL) { | |
272 (void) strcpy(tmpfil2, m_tmpfil(invo_name)); | |
273 if ((out2 = fopen(tmpfil2, "w")) == NULL) { | |
274 advise(tmpfil2, "unable to create"); | |
275 goodbye(); | |
276 } | |
277 } | |
278 (void) chmod(tmpfil2, 0600); | |
279 | |
280 /* */ | |
281 | |
282 mimehdr = resent = 0; | |
283 for (compnum = 1, state = FLD;;) { | |
284 switch (state = m_getfld(state, name, buf, sizeof(buf), in)) { | |
285 case FLD: | |
286 case FLDPLUS: | |
287 case FLDEOF: | |
288 compnum++; | |
289 cp = add(buf, NULLCP); | |
290 while (state == FLDPLUS) { | |
291 state = m_getfld(state, name, buf, sizeof(buf), in); | |
292 cp = add(buf, cp); | |
293 } | |
294 if (uleq(name, VRSN_FIELD)) | |
295 continue; | |
296 if (uprf(name, XXX_FIELD_PRF)) { | |
297 if (mimesw) { | |
298 char *pp; | |
299 pp = cp + strlen(cp); | |
300 if (*--pp == '\n') | |
301 *pp = '\0'; | |
302 if (*--pp == '\r') | |
303 *pp = '\0'; | |
304 fprintf(out2, "%s:%s\r\n", name, cp); | |
305 } else { | |
306 mimehdr = 1; | |
307 fprintf(out2, "%s:%s", name, cp); | |
308 } | |
309 } else { | |
310 char **h; | |
311 if (uprf(name, "Resent-")) { | |
312 for (h = addr_headers; *h; h++) | |
313 if (uleq(name+7, *h)) | |
314 break; | |
315 if (*h) | |
316 resent_addrs = add_addrlist(resent_addrs, cp); | |
317 if (uleq(name+7, "To")) /* Resent-To */ | |
318 resent = 1; | |
319 } else { | |
320 for (h = addr_headers; *h; h++) | |
321 if (uleq(name, *h)) | |
322 break; | |
323 if (*h) | |
324 addrs = add_addrlist(addrs, cp); | |
325 if (uleq(name, "From")) | |
326 from_addrs = add_addrlist(from_addrs, cp); | |
327 } | |
328 fprintf (out1, "%s:%s", name, cp); | |
329 } | |
330 free(cp); | |
331 continue; | |
332 | |
333 case BODY: | |
334 case BODYEOF: | |
335 (void) fseek(in, (long) (-strlen(buf)), 1); | |
336 break; | |
337 | |
338 case FILEEOF: | |
339 advise(NULLCP, "draft has empty body -- no directives!"); | |
340 goodbye(); | |
341 | |
342 case LENERR: | |
343 case FMTERR: | |
344 advise(NULLCP, "message format error in component #%d", compnum); | |
345 goodbye(); | |
346 | |
347 default: | |
348 advise(NULLCP, "getfld() returned %d", state); | |
349 goodbye(); | |
350 } | |
351 break; | |
352 } | |
353 if (mimesw) | |
354 fputs("\r\n", out2); | |
355 else if (mimehdr) | |
356 fputs("\n", out2); | |
357 | |
358 /* */ | |
359 | |
360 fprintf (out1, "%s: %s\n", VRSN_FIELD, VRSN_VALUE); | |
361 if (mimesw) { | |
362 int badprefix, len = strlen(prefix); | |
363 long pos; | |
364 char *pp; | |
365 | |
366 if ((pp = index(prefix, 'a')) == NULL) { | |
367 advise(NULLCP, "internal error"); | |
368 goodbye(); | |
369 } | |
370 pos = ftell(in); | |
371 badprefix = 0; | |
372 while (fgets(buf, sizeof(buf) - 2, in)) { | |
373 cp = buf + strlen(buf) - 1; | |
374 if (*cp-- == '\n' && *cp != '\r') { | |
375 *++cp = '\r'; | |
376 *++cp = '\n'; | |
377 *++cp = '\0'; | |
378 } | |
379 fputs(buf, out2); | |
380 if (badprefix || buf[0] != '-' || buf[1] != '-') | |
381 continue; | |
382 for (cp = buf + strlen(buf) - 1; cp >= buf; cp--) | |
383 if (!isspace(*cp)) | |
384 break; | |
385 *++cp = '\0'; | |
386 if (strncmp(buf + 2, prefix, len) == 0 | |
387 && isdigit(buf[2 + len])) | |
388 badprefix = 1; | |
389 } | |
390 while (badprefix) { | |
391 if (*pp < 'z') | |
392 (*pp)++; | |
393 else | |
394 if (*++pp == 0) { | |
395 advise(NULLCP, | |
396 "giving up trying to find a unique delimiter string" | |
397 ); | |
398 goodbye(); | |
399 } | |
400 else | |
401 (*pp)++; | |
402 fseek(in, pos, 0); | |
403 badprefix = 0; | |
404 while (fgets(buf, sizeof(buf) - 1, in)) { | |
405 if (buf[0] != '-' || buf[1] != '-') | |
406 continue; | |
407 for (cp = buf + strlen(buf) - 1; cp >= buf; cp--) | |
408 if (!isspace(*cp)) | |
409 break; | |
410 *++cp = '\0'; | |
411 if (strncmp(buf + 2, prefix, len) == 0 | |
412 && isdigit(buf[2 + len])) { | |
413 badprefix = 1; | |
414 break; | |
415 } | |
416 } | |
417 } | |
418 if (encryptsw) { | |
419 fprintf(out1, "%s: multipart/encrypted; ", TYPE_FIELD); | |
420 fprintf(out1, "protocol=\"application/pgp-encrypted\";\n"); | |
421 fprintf(out1, "\tboundary=\"%s%d\"\n\n", prefix, 0); | |
422 fprintf(out1, "--%s%d\n", prefix, 0); | |
423 fprintf(out1, "%s: application/pgp-encrypted\n", TYPE_FIELD); | |
424 fprintf(out1, "%s: 7bit\n\nVersion: 1\n\n", ENCODING_FIELD); | |
425 fprintf(out1, "--%s%d\n", prefix, 0); | |
426 fprintf(out1, "%s: application/octet-stream\n", TYPE_FIELD); | |
427 fprintf(out1, "%s: 7bit\n\n", ENCODING_FIELD); | |
428 } | |
429 } else { | |
430 while ((cnt = fread(buf, sizeof(char), sizeof(buf), in)) > 0) | |
431 fwrite(buf, sizeof(char), cnt, out2); | |
432 if (mimehdr) { | |
433 fprintf(out1, "%s: application/pgp; format=mime\n\n", TYPE_FIELD); | |
434 } else { | |
435 if (encryptsw) | |
436 fprintf(out1, "%s: application/pgp\n\n", TYPE_FIELD); | |
437 else | |
438 fprintf(out1, "%s: text/pgp\n\n", TYPE_FIELD); | |
439 } | |
440 } | |
441 fclose(in); | |
442 fclose(out2); | |
443 out2 = NULL; | |
444 | |
445 /* */ | |
446 | |
447 (void) strcpy(tmpfil3, m_scratch("", m_maildir(invo_name))); | |
448 if ((out2 = fopen(tmpfil3, "w")) == NULL) { | |
449 (void) strcpy(tmpfil3, m_tmpfil(invo_name)); | |
450 if ((out2 = fopen(tmpfil3, "w")) == NULL) { | |
451 advise(tmpfil3, "unable to create"); | |
452 goodbye(); | |
453 } | |
454 } | |
455 (void) chmod(tmpfil3, 0600); | |
456 fclose(out2); | |
457 unlink(tmpfil3); | |
458 | |
459 if (resent) | |
460 addrs = resent_addrs; | |
461 i = 0; | |
462 for (ip = addrs; ip; ip = ip->next) | |
463 i++; | |
464 if ((ap = (char **) malloc(sizeof(char *) * (i * 2 + 9))) == NULL) { | |
465 advise(NULLCP, "out of memory"); | |
466 goodbye(); | |
467 } | |
468 | |
469 /* */ | |
470 | |
471 if (! *pgpproc) { | |
472 /* for PGP5 */ | |
473 ap[i = 0] = pgpproc = encryptsw ? "pgpe" : "pgps"; | |
474 ap[++i] = encryptsw ? (signsw ? "-sat" : "-at") | |
475 : (mimesw ? "-ab" : "-at"); | |
476 ap[++i] = "+language=en"; | |
477 ap[++i] = "+armorlines=0"; | |
478 if (encryptsw) | |
479 for (ip = addrs; ip; ip = ip->next) { | |
480 ap[++i] = "-r"; | |
481 ap[++i] = ip->address; | |
482 } | |
483 if (signsw && from_addrs) { | |
484 ap[++i] = "-u"; | |
485 ap[++i] = from_addrs->address; | |
486 } | |
487 ap[++i] = tmpfil2; | |
488 ap[++i] = "-o"; | |
489 ap[++i] = tmpfil3; | |
490 ap[++i] = NULLCP; | |
491 | |
492 if (!mimesw || encryptsw) { | |
493 switch (pid = fork()) { | |
494 case NOTOK: | |
495 advise("fork", "unable to"); | |
496 goodbye(); | |
497 | |
498 case OK: | |
499 execvp(pgpproc, ap); | |
500 /* maybe PGP5 is not installed. */ | |
501 _exit(NOT_INSTALLED); | |
502 | |
503 default: | |
504 #if 0 | |
505 state = pidwait(pid, OK); | |
506 if (WIFEXITED(state) && WEXITSTATUS(state) == NOT_INSTALLED) | |
507 #else | |
508 if ((state = pidwait(pid, OK)) == (NOT_INSTALLED << 8)) | |
509 #endif | |
510 /* Let's try old PGP */ | |
511 pgpproc = "pgp"; | |
512 else if (pidstatus(state, stdout, pgpproc)) | |
513 goodbye(); | |
514 else | |
515 pgpproc = ""; | |
516 break; | |
517 } | |
518 } else if (exec_pgp5_for_keyid(pgpproc, ap, &keyid) == NOTOK) | |
519 /* Let's try old PGP */ | |
520 pgpproc = "pgp"; | |
521 else | |
522 pgpproc = ""; | |
523 } | |
524 if (*pgpproc) { | |
525 /* for PGP2 */ | |
526 ap[i = 0] = r1bindex(pgpproc, '/'); | |
527 ap[++i] = encryptsw ? (signsw ? "-esat" : "-eat") | |
528 : (mimesw ? "-sab" : "-sat"); | |
529 ap[++i] = "+language=en"; | |
530 ap[++i] = "+armorlines=0"; | |
531 ap[++i] = tmpfil2; | |
532 for (ip = addrs; ip; ip = ip->next) | |
533 ap[++i] = ip->address; | |
534 if (from_addrs && from_addrs->address) { | |
535 ap[++i] = "-u"; | |
536 ap[++i] = from_addrs->address; | |
537 } | |
538 ap[++i] = "-o"; | |
539 ap[++i] = tmpfil3; | |
540 ap[++i] = NULLCP; | |
541 | |
542 switch (pid = fork()) { | |
543 case NOTOK: | |
544 advise("fork", "unable to"); | |
545 goodbye(); | |
546 | |
547 case OK: | |
548 execvp(pgpproc, ap); | |
549 adios(pgpproc, "unable to exec"); | |
550 | |
551 default: | |
552 if (pidXwait(pid, r1bindex(pgpproc, '/'))) | |
553 goodbye(); | |
554 break; | |
555 } | |
556 } | |
557 | |
558 /* */ | |
559 | |
560 if (mimesw && !encryptsw) { | |
561 fprintf(out1, "%s: multipart/signed;\n", TYPE_FIELD); | |
562 fprintf(out1, "\tprotocol=\"application/pgp-signature\"; "); | |
563 fprintf(out1, "micalg=\"pgp-%s\";\n", | |
564 *pgpproc ? "md5" | |
565 : get_micalg(from_addrs ? from_addrs->address : NULLCP, | |
566 keyid)); | |
567 fprintf(out1, "\tboundary=\"%s%d\"\n\n", prefix, 0); | |
568 fprintf(out1, "--%s%d\n", prefix, 0); | |
569 if ((in = fopen(tmpfil2, "r")) == NULL) { | |
570 advise(tmpfil2, "unable to open"); | |
571 goodbye(); | |
572 } | |
573 while (fgets(buf, sizeof(buf) - 1, in)) { | |
574 cp = buf + strlen(buf) - 1; | |
575 if (*cp-- == '\n' && *cp == '\r') { | |
576 *cp++ = '\n'; | |
577 *cp = '\0'; | |
578 } | |
579 fputs(buf, out1); | |
580 } | |
581 fclose(in); | |
582 fprintf(out1, "\n--%s%d\n", prefix, 0); | |
583 fprintf(out1, "%s: application/pgp-signature\n", TYPE_FIELD); | |
584 fprintf(out1, "%s: 7bit\n\n", ENCODING_FIELD); | |
585 } | |
586 unlink(tmpfil2); | |
587 | |
588 if ((in = fopen(tmpfil3, "r")) == NULL) { | |
589 advise(tmpfil3, "unable to open"); | |
590 goodbye(); | |
591 } | |
592 while (fgets(buf, sizeof(buf) - 1, in)) | |
593 fputs(buf, out1); | |
594 fclose(in); | |
595 unlink(tmpfil3); | |
596 if (mimesw) | |
597 fprintf(out1, "\n--%s%d--\n", prefix, 0); | |
598 fclose(out1); | |
599 | |
600 if (!tomhn) { | |
601 sprintf(buf, "%s.orig", m_backup(file)); | |
602 if (rename(file, buf) == NOTOK) { | |
603 advise(buf, "unable to rename %s to", file); | |
604 goodbye(); | |
605 } | |
606 } | |
607 unlink(file); | |
608 if (rename(tmpfil1, file) == NOTOK) { | |
609 int in, out; | |
610 struct stat st; | |
611 if (stat(file, &st) != NOTOK) { | |
612 advise(file, "unable to rename %s to", tmpfil1); | |
613 goodbye(); | |
614 } | |
615 if ((in = open(tmpfil1, 0)) == NOTOK) { | |
616 advise(tmpfil1, "unable to open"); | |
617 goodbye(); | |
618 } | |
619 if ((out = creat(file, 0600)) == NOTOK) { | |
620 advise(file, "unable to create"); | |
621 (void) close(in); | |
622 goodbye(); | |
623 } | |
624 cpydata(in, out, tmpfil1, file); | |
625 (void) close(in); | |
626 (void) close(out); | |
627 unlink(tmpfil1); | |
628 } | |
629 | |
630 done(0); | |
631 } | |
632 | |
633 struct addrlist * | |
634 add_addrlist(addrp, str) | |
635 struct addrlist *addrp; | |
636 char *str; | |
637 { | |
638 char *cp; | |
639 struct addrlist *ap, **vp; | |
640 struct mailname *lp, *mp, *np, taddr; | |
641 | |
642 np = &taddr; | |
643 while ((cp = getname(str))) { | |
644 if (!(mp = getm(cp, NULLCP, 0, AD_HOST, NULLCP))) | |
645 continue; | |
646 np->m_next = mp; | |
647 np = mp; | |
648 } | |
649 np->m_next = NULL; | |
650 | |
651 np = &taddr; | |
652 for (lp = taddr.m_next; lp; lp = np->m_next) { | |
653 if (lp->m_nohost) { | |
654 char *pp; | |
655 pp = akvalue(lp->m_mbox); | |
656 while ((cp = getname(pp))) { | |
657 if (!(mp = getm(cp, NULLCP, 0, AD_HOST, NULLCP))) | |
658 continue; | |
659 np->m_next = mp; | |
660 np = mp; | |
661 } | |
662 np->m_next = lp->m_next; | |
663 mnfree(lp); | |
664 } else | |
665 np = lp; | |
666 } | |
667 | |
668 for (lp = taddr.m_next; lp; lp = np) { | |
669 switch (lp->m_type) { | |
670 case UUCPHOST: | |
671 cp = add(lp->m_mbox, add("!", add(lp->m_host, NULLCP))); | |
672 break; | |
673 case LOCALHOST: | |
674 cp = add(LocalName(), add("@", add(lp->m_mbox, NULLCP))); | |
675 break; | |
676 default: | |
677 cp = add(lp->m_host, add("@", add(lp->m_mbox, NULLCP))); | |
678 break; | |
679 } | |
680 vp = &addrp; | |
681 for (ap = addrp; ap; ap = ap->next) { | |
682 if (uleq(ap->address, cp)) | |
683 break; | |
684 vp = &(ap->next); | |
685 } | |
686 if (ap) | |
687 free(cp); | |
688 else { | |
689 if ((*vp = (struct addrlist *) malloc(sizeof(struct addrlist))) | |
690 == NULL) { | |
691 advise(NULLCP, "out of memory"); | |
692 goodbye(); | |
693 } | |
694 (*vp)->address = cp; | |
695 (*vp)->next = NULL; | |
696 } | |
697 np = lp->m_next; | |
698 mnfree(lp); | |
699 } | |
700 return addrp; | |
701 } | |
702 | |
703 int | |
704 exec_pgp5_for_keyid(prog, ap, keyid) | |
705 char *prog, *ap[], **keyid; | |
706 { | |
707 int cnt, state, pid, pdes[2]; | |
708 char *cp, *ep, *np, buf[BUFSIZ]; | |
709 | |
710 if (pipe(pdes) == NOTOK) { | |
711 advise(NULLCP, "unable to open pipe"); | |
712 goodbye(); | |
713 } | |
714 | |
715 switch (pid = fork()) { | |
716 case NOTOK: | |
717 close(pdes[0]); | |
718 close(pdes[1]); | |
719 advise("fork", "unable to"); | |
720 goodbye(); | |
721 | |
722 case OK: | |
723 if (pdes[1] != fileno(stdout)) | |
724 dup2(pdes[1], fileno(stdout)); | |
725 if (pdes[1] != fileno(stderr)) { | |
726 dup2(pdes[1], fileno(stderr)); | |
727 if (pdes[1] != fileno(stdout)) | |
728 close(pdes[1]); | |
729 } | |
730 close(pdes[0]); | |
731 execvp(prog, ap); | |
732 /* maybe PGP is not installed. */ | |
733 _exit(NOT_INSTALLED); | |
734 } | |
735 close(pdes[1]); | |
736 | |
737 cp = ep = buf; | |
738 *keyid = NULLCP; | |
739 while ((cnt = read(pdes[0], buf + (ep - cp), sizeof(buf) - (ep - cp) - 1)) | |
740 > 0) { | |
741 write(fileno(stdout), buf + (ep - cp), cnt); | |
742 | |
743 ep = buf + (ep - cp) + cnt; | |
744 cp = buf; | |
745 while (cp < ep) { | |
746 np = cp; | |
747 while (np < ep && *np != '\n') | |
748 np++; | |
749 if (np < ep || (cp == buf && np == buf + sizeof(buf) - 1)) { | |
750 char *xp, *yp; | |
751 *np = '\0'; | |
752 if (! *keyid) { | |
753 for (xp = cp; *xp; xp++) | |
754 if (strncmp(xp, "bits, Key ID ", 13) == 0) | |
755 break; | |
756 if (*xp && (yp = index(xp + 13, ','))) { | |
757 *yp = '\0'; | |
758 *keyid = add(xp + 13, NULLCP); | |
759 } | |
760 } | |
761 } else { | |
762 bcopy(cp, buf, ep - cp); | |
763 break; | |
764 } | |
765 cp = np + 1; | |
766 } | |
767 } | |
768 close(pdes[0]); | |
769 | |
770 #if 0 | |
771 state = pidwait(pid, OK); | |
772 if (WIFEXITED(state) && WEXITSTATUS(state) == NOT_INSTALLED) | |
773 #else | |
774 if ((state = pidwait(pid, OK)) == (NOT_INSTALLED << 8)) | |
775 #endif | |
776 return NOTOK; | |
777 | |
778 if (pidstatus(state, stdout, r1bindex(pgpproc, '/'))) | |
779 goodbye(); | |
780 | |
781 return OK; | |
782 } | |
783 | |
784 char * | |
785 get_micalg(userid, keyid) | |
786 char *userid, *keyid; | |
787 { | |
788 int pid, pdes[2]; | |
789 char *ap[5], buf[BUFSIZ], *hash = "md5"; /* default */ | |
790 FILE *in; | |
791 | |
792 if (pipe(pdes) == NOTOK) { | |
793 advise(NULLCP, "unable to open pipe"); | |
794 goodbye(); | |
795 } | |
796 | |
797 switch (pid = fork()) { | |
798 case NOTOK: | |
799 close(pdes[0]); | |
800 close(pdes[1]); | |
801 advise("fork", "unable to"); | |
802 goodbye(); | |
803 | |
804 case OK: | |
805 if (pdes[1] != fileno(stdout)) | |
806 dup2(pdes[1], fileno(stdout)); | |
807 if (pdes[1] != fileno(stderr)) { | |
808 dup2(pdes[1], fileno(stderr)); | |
809 if (pdes[1] != fileno(stdout)) | |
810 close(pdes[1]); | |
811 } | |
812 close(pdes[0]); | |
813 ap[0] = "pgpk"; | |
814 ap[1] = "-l"; | |
815 ap[2] = "+language=en"; | |
816 ap[3] = userid; /* might be NULLCP */ | |
817 ap[4] = NULLCP; | |
818 execvp("pgpk", ap); | |
819 adios("pgpk", "unable to exec"); | |
820 } | |
821 close(pdes[1]); | |
822 | |
823 in = fdopen(pdes[0], "r"); | |
824 while (fgets(buf, sizeof(buf), in)) { | |
825 if (strncmp(buf, "sec", 3) == 0 /* secret key */ | |
826 && strncmp(buf + 12, keyid, strlen(keyid)) == 0) { | |
827 if (strncmp(buf + 43, "DSS", 3) == 0) | |
828 hash = "sha1"; | |
829 else if (strncmp(buf + 43, "RSA", 3) == 0) | |
830 hash = "md5"; | |
831 } | |
832 } | |
833 fclose(in); | |
834 | |
835 if (pidXwait(pid, "pgpk")) | |
836 goodbye(); | |
837 | |
838 return hash; | |
839 } | |
840 | |
841 static TYPESIG goodbye() | |
842 { | |
843 if (out1) | |
844 fclose(out1); | |
845 if (out2) | |
846 fclose(out2); | |
847 if (tmpfil1[0]) | |
848 unlink(tmpfil1); | |
849 if (tmpfil2[0]) | |
850 unlink(tmpfil2); | |
851 if (tmpfil3[0]) | |
852 unlink(tmpfil3); | |
853 done(1); | |
854 /* NOT REACHED */ | |
855 } |