reformime.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:17k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 2000 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. #if HAVE_CONFIG_H
  6. #include "config.h"
  7. #endif
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <time.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #if HAVE_STRINGS_H
  14. #include <strings.h>
  15. #endif
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. #include <pwd.h>
  19. #include <fcntl.h>
  20. #include <signal.h>
  21. #include "rfc2045.h"
  22. #include "rfc2045charset.h"
  23. #if HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #if HAVE_SYS_WAIT_H
  27. #include <sys/wait.h>
  28. #endif
  29. #include "numlib/numlib.h"
  30. #if     HAS_GETHOSTNAME
  31. #else
  32. int gethostname(const char *, size_t);
  33. #endif
  34. static const char rcsid[]="$Id: reformime.c,v 1.23 2000/05/23 17:55:02 mrsam Exp $";
  35. void rfc2045_error(const char *errmsg)
  36. {
  37. fprintf(stderr, "reformime: %sn", errmsg);
  38. exit(1);
  39. }
  40. static void do_print_structure(struct rfc2045 *p, struct rfc2045id *id, void *ptr)
  41. {
  42. p=p;
  43. ptr=p;
  44. while (id)
  45. {
  46. printf("%d%c", id->idnum, id->next ? '.':'n');
  47. id=id->next;
  48. }
  49. }
  50. static int decode_to_file(const char *p, size_t n, void *ptr)
  51. {
  52. FILE *fp=(FILE *)ptr;
  53. while (n)
  54. {
  55. --n;
  56. if (putc(*p++, fp) == -1)
  57. {
  58. perror("write");
  59. exit(1);
  60. }
  61. }
  62. return (0);
  63. }
  64. void usage()
  65. {
  66. fprintf(stderr, "Usage: reformime [options]n");
  67. fprintf(stderr, "    -d - parse a delivery status notification.n");
  68. fprintf(stderr, "    -e - extract contents of MIME section.n");
  69. fprintf(stderr, "    -x - extract MIME section to a file.n");
  70. fprintf(stderr, "    -X - pipe MIME section to a program.n");
  71. fprintf(stderr, "    -i - show MIME info.n");
  72. fprintf(stderr, "    -s n.n.n.n - specify MIME section.n");
  73. fprintf(stderr, "    -r - rewrite message, filling in missing MIME header.n");
  74. fprintf(stderr, "    -r7 - also convert 8bit/raw encoding to quoted-printable, if possible.n");
  75. fprintf(stderr, "    -r8 - also convert quoted-printable encoding to 8bit, if possible.n");
  76. fprintf(stderr, "    -c charset - when rewriting, specify default charset.n");
  77. fprintf(stderr, "    -m [file] [file]... - create a MIME message digest.n");
  78. exit(1);
  79. }
  80. static char *tempname(const char *tempdir)
  81. {
  82. char pidbuf[NUMBUFSIZE], timebuf[NUMBUFSIZE], hostnamebuf[256];
  83. time_t t;
  84. char *p;
  85. str_pid_t(getpid(), pidbuf);
  86. time(&t);
  87. str_time_t(t, timebuf);
  88. hostnamebuf[sizeof(hostnamebuf)-1]=0;
  89. if (gethostname(hostnamebuf, sizeof(hostnamebuf)))
  90. hostnamebuf[0]=0;
  91. p=malloc(strlen(tempdir)+strlen(pidbuf)+strlen(timebuf)+
  92. strlen(hostnamebuf)+4);
  93. if (!p) return (0);
  94. sprintf(p, "%s/%s.%s.%s", tempdir, timebuf, pidbuf, hostnamebuf);
  95. return (p);
  96. }
  97. struct rfc2045 *read_message()
  98. {
  99. char buf[BUFSIZ];
  100. struct rfc2045 *p=rfc2045_alloc_ac();
  101. int tempfd= -1;
  102. if (fseek(stdin, 0L, SEEK_END) < 0 ||
  103. fseek(stdin, 0L, SEEK_SET) < 0) /* Pipe, save to temp file */
  104. {
  105. struct passwd *p;
  106. char *tmpdir, *tmpfilename;
  107. /* Create temp file in $HOME/.tmp */
  108. p=getpwuid(getuid());
  109. if (!p)
  110. {
  111. fprintf(stderr, "reformime: unable to read your home directory.n");
  112. exit(1);
  113. }
  114. tmpdir=malloc(strlen(p->pw_dir)+6);
  115. if (!tmpdir ||
  116. !(tmpfilename=tempname(strcat(strcpy(tmpdir,
  117. p->pw_dir), "/.tmp"))))
  118. {
  119. perror("malloc");
  120. exit(1);
  121. }
  122. mkdir(tmpdir, 0700);
  123. if ((tempfd=open(tmpfilename, O_RDWR|O_CREAT, 0600)) < 0)
  124. {
  125. perror("open");
  126. }
  127. unlink(tmpfilename);
  128. free(tmpdir);
  129. free(tmpfilename);
  130. }
  131. while (fgets(buf, sizeof(buf), stdin))
  132. {
  133. rfc2045_parse(p, buf, strlen(buf));
  134. if (tempfd >= 0)
  135. {
  136. const char *p=buf;
  137. size_t l=strlen(p);
  138. while (l)
  139. {
  140. int n=write(tempfd, p, l);
  141. if (n <= 0)
  142. {
  143. perror("write");
  144. exit(1);
  145. }
  146. p += n;
  147. l -= n;
  148. }
  149. }
  150. }
  151. if (tempfd >= 0)
  152. {
  153. close(0);
  154. dup(tempfd);
  155. close(tempfd);
  156. }
  157. return (p);
  158. }
  159. void print_structure(struct rfc2045 *p)
  160. {
  161. rfc2045_decode(p, &do_print_structure, 0);
  162. }
  163. static void notfound(const char *p)
  164. {
  165. fprintf(stderr, "reformime: MIME section %s not found.n", p);
  166. exit(1);
  167. }
  168. static void do_print_info(struct rfc2045 *s)
  169. {
  170. const char *content_type, *transfer_encoding, *charset;
  171. off_t start, end, body;
  172. const char *disposition;
  173. const char *disposition_name;
  174. const char *disposition_filename;
  175. const char *content_name;
  176. off_t nlines, nbodylines;
  177. const char *p;
  178. rfc2045_mimeinfo(s, &content_type, &transfer_encoding, &charset);
  179. rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines);
  180. rfc2045_dispositioninfo(s, &disposition, &disposition_name,
  181. &disposition_filename);
  182. content_name=rfc2045_contentname(s);
  183. printf("content-type: %sn", content_type);
  184. if (content_name)
  185. printf("content-name: %sn", content_name);
  186. printf("content-transfer-encoding: %sn", transfer_encoding);
  187. printf("charset: %sn", charset);
  188. if (disposition && *disposition)
  189. printf("content-disposition: %sn", disposition);
  190. if (disposition_name && *disposition_name)
  191. printf("content-disposition-name: %sn", disposition_name);
  192. if (disposition_filename && *disposition_filename)
  193. printf("content-disposition-filename: %sn",
  194. disposition_filename);
  195. if (*(p=rfc2045_content_id(s)))
  196. printf("content-id: <%s>n", p);
  197. if (*(p=rfc2045_content_description(s)))
  198. printf("content-description: %sn", p);
  199. if (*(p=rfc2045_content_language(s)))
  200. printf("content-language: %sn", p);
  201. if (*(p=rfc2045_content_md5(s)))
  202. printf("content-md5: %sn", p);
  203. printf("starting-pos: %lun", (unsigned long)start);
  204. printf("starting-pos-body: %lun", (unsigned long)body);
  205. printf("ending-pos: %lun", (unsigned long)end);
  206. printf("line-count: %lun", (unsigned long)nlines);
  207. printf("body-line-count: %lun", (unsigned long)nbodylines);
  208. }
  209. static void do_print_info_multiple(struct rfc2045 *p, struct rfc2045id *id,
  210. void *ptr)
  211. {
  212. printf("section: ");
  213. do_print_structure(p, id, ptr);
  214. do_print_info(p);
  215. printf("n");
  216. }
  217. void print_info(struct rfc2045 *p, const char *mimesection)
  218. {
  219. struct rfc2045 *s;
  220. if (mimesection)
  221. {
  222. s=rfc2045_find(p, mimesection);
  223. if (!s)
  224. notfound(mimesection);
  225. printf("section: %sn", mimesection);
  226. do_print_info(s);
  227. return;
  228. }
  229. rfc2045_decode(p, &do_print_info_multiple, 0);
  230. }
  231. static void do_print_section(struct rfc2045 *s, FILE *fp)
  232. {
  233. off_t start, end, body;
  234. off_t nlines;
  235. off_t nbodylines;
  236. rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines);
  237. if (fseek(stdin, body, SEEK_SET) == -1)
  238. {
  239. perror("fseek");
  240. exit(1);
  241. }
  242. rfc2045_cdecode_start(s, &decode_to_file, fp);
  243. while (body < end)
  244. {
  245. char buf[BUFSIZ];
  246. size_t n=sizeof(buf);
  247. if ((off_t)n > end-body) n=end-body;
  248. n=fread(buf, 1, n, stdin);
  249. if (n == 0)
  250. {
  251. perror("fread");
  252. exit(1);
  253. }
  254. rfc2045_cdecode(s, buf, n);
  255. body += n;
  256. }
  257. rfc2045_cdecode_end(s);
  258. }
  259. void print_decode(struct rfc2045 *p, const char *mimesection)
  260. {
  261. struct rfc2045 *s;
  262. if (!mimesection)
  263. usage();
  264. s=rfc2045_find(p, mimesection);
  265. if (!s)
  266. notfound(mimesection);
  267. do_print_section(s, stdout);
  268. }
  269. void rewrite(struct rfc2045 *p, int rwmode)
  270. {
  271. rfc2045_ac_check(p, rwmode);
  272. if (rfc2045_rewrite(p, fileno(stdin), fileno(stdout),
  273. "reformime (" RFC2045PKG " " RFC2045VER ")"))
  274. {
  275. perror("reformime");
  276. exit(1);
  277. }
  278. }
  279. static char *get_suitable_filename(struct rfc2045 *r, const char *pfix)
  280. {
  281. const char *disposition_s;
  282. const char *disposition_name_s;
  283. const char *disposition_filename_s;
  284. const char *content_name_s;
  285. char *p, *q;
  286. char *dyn_disp_name=0;
  287. rfc2045_dispositioninfo(r, &disposition_s, &disposition_name_s,
  288. &disposition_filename_s);
  289. content_name_s=rfc2045_contentname(r);
  290. if (!disposition_filename_s || !*disposition_filename_s)
  291. disposition_filename_s=disposition_name_s;
  292. if (!disposition_filename_s || !*disposition_filename_s)
  293. disposition_filename_s=content_name_s;
  294. if (!disposition_filename_s || !*disposition_filename_s)
  295. {
  296. dyn_disp_name=tempname(".");
  297. disposition_filename_s=dyn_disp_name+2; /* Skip over ./ */
  298. }
  299. p=malloc((pfix ? strlen(pfix):0)+strlen(disposition_filename_s)+1);
  300. if (!p)
  301. {
  302. perror("malloc");
  303. exit(1);
  304. }
  305. *p=0;
  306. if (pfix) strcpy(p, pfix);
  307. q=p+strlen(p);
  308. for (strcpy(q, disposition_filename_s); *q; q++)
  309. if (!isalnum(*q) && *q != '.' && *q != '-')
  310. *q='_';
  311. if (dyn_disp_name) free(dyn_disp_name);
  312. if (!pfix)
  313. {
  314.         const char *content_type_s;
  315.         const char *content_transfer_encoding_s;
  316.         const char *charset_s;
  317. int c;
  318. static char filenamebuf[256];
  319. char *t;
  320. FILE *tty;
  321. if ((tty=fopen("/dev/tty", "r+")) == 0)
  322. {
  323. perror("/dev/tty");
  324. exit(1);
  325. }
  326. rfc2045_mimeinfo(r, &content_type_s,
  327. &content_transfer_encoding_s, &charset_s);
  328. fprintf (tty, "Extract %s? ", content_type_s);
  329. fflush(tty);
  330. c=getc(tty);
  331. if (c != 'n' && c != EOF)
  332. {
  333. int cc;
  334. while ((cc=getc(tty)) != 'n' && cc != EOF)
  335. ;
  336. }
  337. if (c != 'y' && c != 'Y')
  338. {
  339. free(p);
  340. fclose(tty);
  341. return (0);
  342. }
  343. fprintf (tty, "Filename [%s]: ", p);
  344. fgets(filenamebuf, sizeof(filenamebuf)-1, tty);
  345. fclose(tty);
  346. t=strchr(filenamebuf, 'n');
  347. if (t) *t=0;
  348. else
  349. {
  350. fprintf(stderr, "Filename too long.n");
  351. exit(1);
  352. }
  353. if (filenamebuf[0])
  354. {
  355. free(p);
  356. p=strdup(filenamebuf);
  357. if (!p)
  358. {
  359. perror("malloc");
  360. exit(1);
  361. }
  362. }
  363. }
  364. return (p);
  365. }
  366. static void extract_file(struct rfc2045 *p,
  367. const char *filename, int argc, char **argv)
  368. {
  369. char *f=get_suitable_filename(p, filename);
  370. FILE *fp;
  371. if (!f) return;
  372. if ((fp=fopen(f, "w")) == 0)
  373. {
  374. perror(f);
  375. exit(1);
  376. }
  377. do_print_section(p, fp);
  378. if (fflush(fp) || ferror(fp))
  379. {
  380. perror("write");
  381. exit(1);
  382. }
  383. fclose(fp);
  384. free(f);
  385. }
  386. static void extract_pipe(struct rfc2045 *p,
  387. const char *filename,
  388. int argc, char **argv)
  389. {
  390. char *f=get_suitable_filename(p, "FILENAME=");
  391. int pipefd[2];
  392. pid_t pid, p2;
  393. FILE *fp;
  394. int waitstat;
  395. if (argc == 0)
  396. {
  397. fprintf(stderr, "reformime: Invalid -X option.n");
  398. exit(1);
  399. }
  400. if (pipe(pipefd))
  401. {
  402. perror("pipe");
  403. exit(1);
  404. }
  405. if ((fp=fdopen(pipefd[1], "w")) == 0)
  406. {
  407. perror("fdopen");
  408. exit(1);
  409. }
  410. while ((pid=fork()) == -1)
  411. {
  412. sleep(2);
  413. }
  414. if (pid == 0)
  415. {
  416.         const char *content_type_s;
  417.         const char *content_transfer_encoding_s;
  418.         const char *charset_s;
  419. if (!f) f="FILENAME=attachment.dat";
  420. putenv(f);
  421. rfc2045_mimeinfo(p, &content_type_s,
  422. &content_transfer_encoding_s, &charset_s);
  423. f=malloc(strlen(content_type_s)
  424. +sizeof("CONTENT_TYPE="));
  425. if (!f)
  426. {
  427. perror("malloc");
  428. exit(1);
  429. }
  430. strcat(strcpy(f, "CONTENT_TYPE="), content_type_s);
  431. putenv(f);
  432. close(0);
  433. dup(pipefd[0]);
  434. close(pipefd[0]);
  435. close(pipefd[1]);
  436. execv(argv[0], argv);
  437. perror("exec");
  438. _exit(1);
  439. }
  440. close(pipefd[0]);
  441. signal(SIGPIPE, SIG_IGN);
  442. do_print_section(p, fp);
  443. signal(SIGPIPE, SIG_DFL);
  444. fclose(fp);
  445. close(pipefd[1]);
  446. while ((p2=wait(&waitstat)) != pid && p2 != -1)
  447. ;
  448. free(f);
  449. }
  450. static void extract_section(struct rfc2045 *top_rfcp, const char *mimesection,
  451. const char *extract_filename, int argc, char **argv,
  452. void (*extract_func)(struct rfc2045 *, const char *,
  453. int, char **))
  454. {
  455. if (mimesection)
  456. {
  457. top_rfcp=rfc2045_find(top_rfcp, mimesection);
  458. if (!mimesection)
  459. notfound(mimesection);
  460. if (top_rfcp->firstpart)
  461. {
  462. fprintf(stderr, "reformime: MIME section %s is a compound section.n", mimesection);
  463. exit(1);
  464. }
  465. (*extract_func)(top_rfcp, extract_filename, argc, argv);
  466. return;
  467. }
  468. /* Recursive */
  469. if (top_rfcp->firstpart)
  470. {
  471. for (top_rfcp=top_rfcp->firstpart; top_rfcp;
  472. top_rfcp=top_rfcp->next)
  473. extract_section(top_rfcp, mimesection,
  474. extract_filename, argc, argv, extract_func);
  475. return;
  476. }
  477. if (!top_rfcp->isdummy)
  478. (*extract_func)(top_rfcp, extract_filename, argc, argv);
  479. }
  480. static void print_dsn_recip(char *addr, char *action)
  481. {
  482. char *p, *q;
  483. if (!action || !addr)
  484. {
  485. if (action) free(action);
  486. if (addr) free(addr);
  487. return;
  488. }
  489. for (p=action; *p; ++p)
  490. *p=tolower((int)(unsigned char)*p);
  491. for (p=addr; *p && isspace((int)(unsigned char)*p); ++p)
  492. ;
  493. if (strncasecmp(p, "rfc822;", 7))
  494. {
  495. free(action);
  496. free(addr);
  497. return;
  498. }
  499. for (q=action; *q && isspace((int)(unsigned char)*q); ++q)
  500. ;
  501. p += 7;
  502. while (*p && isspace((int)(unsigned char)*p))
  503. ++p;
  504. printf("%s %sn", q, p);
  505. free(action);
  506. free(addr);
  507. }
  508. static void dsn(struct rfc2045 *p, int do_orig)
  509. {
  510. const char *content_type_s;
  511. const char *content_transfer_encoding_s;
  512. const char *charset_s;
  513. off_t start_pos, end_pos, start_body;
  514. off_t dummy;
  515. const char *q;
  516. char buf[BUFSIZ];
  517. unsigned i;
  518. int ch;
  519. char *recip;
  520. char *action;
  521. char *orecip;
  522. rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s,
  523. &charset_s);
  524. if (strcasecmp(content_type_s, "multipart/report") ||
  525. (q=rfc2045_getattr(p->content_type_attr, "report-type")) == 0 ||
  526. strcasecmp(q, "delivery-status") ||
  527. !p->firstpart || !p->firstpart->next ||
  528. !p->firstpart->next->next)
  529. _exit(1);
  530. p=p->firstpart->next->next;
  531. rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s,
  532. &charset_s);
  533. rfc2045_mimepos(p, &start_pos, &end_pos, &start_body, &dummy, &dummy);
  534. if (strcasecmp(content_type_s, "message/delivery-status") ||
  535. fseek(stdin, start_body, SEEK_SET) == -1)
  536. _exit(1);
  537. i=0;
  538. recip=0;
  539. orecip=0;
  540. action=0;
  541. while (start_body < end_pos)
  542. {
  543. if ((ch=getchar()) == EOF) break;
  544. ++start_body;
  545. if (i < sizeof(buf)-1)
  546. buf[i++]= ch;
  547. if (ch != 'n') continue;
  548. ch=getchar();
  549. if (ch != EOF) ungetc(ch, stdin);
  550. if (ch != 'n' && isspace((int)(unsigned char)ch))
  551. continue;
  552. buf[i-1]=0;
  553. if (buf[0] == 0)
  554. {
  555. if (orecip)
  556. {
  557. if (recip) free(recip);
  558. recip=orecip;
  559. orecip=0;
  560. }
  561. print_dsn_recip(recip, action);
  562. recip=0;
  563. action=0;
  564. }
  565. if (strncasecmp(buf, "Final-Recipient:", 16) == 0 &&
  566. recip == 0)
  567. {
  568. recip=strdup(buf+16);
  569. if (!recip)
  570. {
  571. perror("strdup");
  572. exit(2);
  573. }
  574. }
  575. if (strncasecmp(buf, "Original-Recipient:", 19) == 0 &&
  576. orecip == 0 && do_orig)
  577. {
  578. orecip=strdup(buf+19);
  579. if (!orecip)
  580. {
  581. perror("strdup");
  582. exit(2);
  583. }
  584. }
  585. if (strncasecmp(buf, "Action:", 7) == 0 && action == 0)
  586. {
  587. action=strdup(buf+7);
  588. if (!action)
  589. {
  590. perror("strdup");
  591. exit(2);
  592. }
  593. }
  594. i=0;
  595. }
  596. if (orecip)
  597. {
  598. if (recip) free(recip);
  599. recip=orecip;
  600. orecip=0;
  601. }
  602. print_dsn_recip(recip, action);
  603. }
  604. static void mimedigest1(int, char **);
  605. static char mimebuf[BUFSIZ];
  606. static void mimedigest(int argc, char **argv)
  607. {
  608. char *p;
  609. struct filelist { struct filelist *next; char *fn; } *first=0, *last=0;
  610. unsigned pcnt=0;
  611. char **l;
  612. if (argc > 0)
  613. {
  614. mimedigest1(argc, argv);
  615. return;
  616. }
  617. while (fgets(mimebuf, sizeof(mimebuf), stdin))
  618. {
  619. struct filelist *q;
  620. if ((p=strchr(mimebuf, 'n')) != 0) *p=0;
  621. q=malloc(sizeof(struct filelist));
  622. if (!q || !(q->fn=strdup(mimebuf)))
  623. {
  624. perror("malloc");
  625. exit(1);
  626. }
  627. if (last) last->next=q;
  628. else first=q;
  629. last=q;
  630. q->next=0;
  631. ++pcnt;
  632. }
  633. if (pcnt == 0) return;
  634. if ( (l=malloc(sizeof (char *) * pcnt)) == 0)
  635. {
  636. perror("malloc");
  637. }
  638. pcnt=0;
  639. for (last=first; last; last=last->next)
  640. l[pcnt++]=last->fn;
  641. mimedigest1(pcnt, l);
  642. }
  643. static void mimedigest1(int argc, char **argv)
  644. {
  645. time_t t;
  646. char boundarybuf[200];
  647. unsigned boundarycnt=0;
  648. int i;
  649. FILE *fp;
  650. time (&t);
  651. /* Search for a suitable boundary */
  652. do
  653. {
  654. int l;
  655. sprintf(boundarybuf, "reformime_%lu_%u",
  656. (unsigned long)t, ++boundarycnt);
  657. l=strlen(boundarybuf);
  658. for (i=0; i<argc; i++)
  659. {
  660. int err=0;
  661. if ((fp=fopen(argv[i], "r")) == 0)
  662. {
  663. perror(argv[i]);
  664. exit(1);
  665. }
  666. while (fgets(mimebuf, sizeof(mimebuf), fp))
  667. {
  668. if (mimebuf[0] != '-' || mimebuf[1] != '-')
  669. continue;
  670. if (strncasecmp(mimebuf+2, boundarybuf, l) == 0)
  671. {
  672. err=1;
  673. break;
  674. }
  675. }
  676. fclose(fp);
  677. if (err) break;
  678. }
  679. } while (i < argc);
  680. printf("Mime-Version:1.0n"
  681. "Content-Type: multipart/digest; boundary="%s"nn%s",
  682. boundarybuf, RFC2045MIMEMSG);
  683. for (i=0; i<argc; i++)
  684. {
  685. if ((fp=fopen(argv[i], "r")) == 0)
  686. {
  687. perror(argv[i]);
  688. exit(1);
  689. }
  690. printf("n--%snContent-Type: message/rfc822nn",
  691. boundarybuf);
  692. while (fgets(mimebuf, sizeof(mimebuf), fp))
  693. printf("%s", mimebuf);
  694. fclose(fp);
  695. }
  696. printf("n--%s--n", boundarybuf);
  697. }
  698. int main(int argc, char **argv)
  699. {
  700. int argn;
  701. char optc;
  702. char *optarg;
  703. char *mimesection=0;
  704. int doinfo=0, dodecode=0, dorewrite=0, dodsn=0, domimedigest=0;
  705. struct rfc2045 *p;
  706. int rwmode=0;
  707. void (*do_extract)(struct rfc2045 *, const char *, int, char **)=0;
  708. const char *extract_filename=0;
  709. for (argn=1; argn<argc; )
  710. {
  711. if (argv[argn][0] != '-') break;
  712. optarg=0;
  713. optc=argv[argn][1];
  714. if (optc && argv[argn][2]) optarg=argv[argn]+2;
  715. ++argn;
  716. switch (optc) {
  717. case 'c':
  718. if (!optarg && argn < argc)
  719. optarg=argv[argn++];
  720. if (optarg && *optarg)
  721. rfc2045_setdefaultcharset(optarg);
  722. break;
  723. case 's':
  724. if (!optarg && argn < argc)
  725. optarg=argv[argn++];
  726. if (optarg && *optarg) mimesection=optarg;
  727. break;
  728. case 'i':
  729. doinfo=1;
  730. break;
  731. case 'e':
  732. dodecode=1;
  733. break;
  734. case 'r':
  735. dorewrite=1;
  736. if (optarg && *optarg == '7')
  737. rwmode=RFC2045_RW_7BIT;
  738. if (optarg && *optarg == '8')
  739. rwmode=RFC2045_RW_8BIT;
  740. break;
  741. case 'm':
  742. domimedigest=1;
  743. break;
  744. case 'd':
  745. dodsn=1;
  746. break;
  747. case 'D':
  748. dodsn=2;
  749. break;
  750. case 'x':
  751. do_extract=extract_file;
  752. if (optarg)
  753. extract_filename=optarg;
  754. break;
  755. case 'X':
  756. do_extract=extract_pipe;
  757. break;
  758. default:
  759. usage();
  760. }
  761. }
  762. if (domimedigest)
  763. {
  764. mimedigest(argc-argn, argv+argn);
  765. return (0);
  766. }
  767. p=read_message();
  768. if (doinfo)
  769. print_info(p, mimesection);
  770. else if (dodecode)
  771. print_decode(p, mimesection);
  772. else if (dorewrite)
  773. rewrite(p, rwmode);
  774. else if (dodsn)
  775. dsn(p, dodsn == 2);
  776. else if (do_extract)
  777. extract_section(p, mimesection, extract_filename,
  778. argc-argn, argv+argn, do_extract);
  779. else
  780. print_structure(p);
  781. rfc2045_free(p);
  782. exit(0);
  783. return (0);
  784. }