home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume22 / elm2.3 / part18 < prev    next >
Text File  |  1990-06-07  |  50KB  |  1,606 lines

  1. Subject:  v22i077:  ELM mail syste, release 2.3, Part18/26
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 7997dd7c f2ed2d5a 0a47a0a8 5821681e
  5.  
  6. Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
  7. Posting-number: Volume 22, Issue 77
  8. Archive-name: elm2.3/part18
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is part 18 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file src/mailmsg2.c continued
  15. #
  16. CurArch=18
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file src/mailmsg2.c"
  27. sed 's/^X//' << 'SHAR_EOF' >> src/mailmsg2.c
  28. X      if (verify_bounceback() == TRUE) {
  29. X        if (strlen(cc) > 0) strcat(expanded_cc, ", ");
  30. X        strcat(expanded_cc, bounce_off_remote(to));
  31. X      }
  32. X
  33. X    /** grab a copy if the user so desires... **/
  34. X
  35. X    if (*copy_file) /* i.e. if copy_file contains a name */
  36. X      save_copy(expanded_to, expanded_cc, expanded_bcc,
  37. X           filename, copy_file, form);
  38. X
  39. X    /** write all header information into whole_msg_file **/
  40. X
  41. X    if((whole_msg_file=tempnam(temp_dir, "snd.")) == NULL) {
  42. X      dprint(1, (debugfile, "couldn't make temp file nam! (mail)\n"));
  43. X      if(batch_only)
  44. X        printf("Sorry - couldn't make temp file name!\n");
  45. X      else if(mail_only)
  46. X        error("Sorry - couldn't make temp file name.");
  47. X      else
  48. X        set_error("Sorry - couldn't make temp file name.");
  49. X      return(need_redraw);
  50. X    }
  51. X
  52. X    /** try to write headers to new temp file **/
  53. X
  54. X    dprint(6, (debugfile, "Composition file='%s' and mail buffer='%s'\n", 
  55. X            filename, whole_msg_file));
  56. X
  57. X    dprint(2,(debugfile,"--\nTo: %s\nCc: %s\nBcc: %s\nSubject: %s\n---\n", 
  58. X          expanded_to, expanded_cc, expanded_bcc, subject));
  59. X
  60. X    if ((real_reply=
  61. X       write_header_info(whole_msg_file, expanded_to,
  62. X         expanded_cc, expanded_bcc, form == YES, FALSE)) == NULL) {
  63. X
  64. X      /** IT FAILED!!  MEIN GOTT!  Use a dumb mailer instead! **/
  65. X
  66. X      dprint(3, (debugfile, "** write_header failed: %s\n", 
  67. X         error_name(errno)));
  68. X
  69. X      if (cc[0] != '\0')          /* copies! */
  70. X        sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
  71. X
  72. X      quote_args(very_long_buffer, strip_parens(strip_commas(expanded_to)));
  73. X      strcpy(expanded_to, very_long_buffer);
  74. X
  75. X      sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
  76. X          mailx, subject, expanded_to, remove_cmd, filename, filename);
  77. X
  78. X      if(batch_only)
  79. X        printf("Message sent using dumb mailer %s.\n", mailx);
  80. X      else
  81. X        error1("Message sent using dumb mailer %s.", mailx);
  82. X      sleep(2);    /* ensure time to see this prompt! */
  83. X
  84. X    }
  85. X    else {
  86. X
  87. X      copy_message_across(reply, real_reply, FALSE);
  88. X
  89. X          /* Append signature if not done earlier */
  90. X
  91. X          if (!signature_done && !retransmit && copy_msg != FORM)
  92. X               append_sig(real_reply);
  93. X
  94. X      fclose(real_reply);
  95. X
  96. X      if (cc[0] != '\0')                           /* copies! */
  97. X        sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
  98. X
  99. X      if (bcc[0] != '\0') {
  100. X        strcat(expanded_to, " ");
  101. X        strcat(expanded_to, expanded_bcc);
  102. X      }
  103. X
  104. X      remove_hostbang(expanded_to);
  105. X
  106. X      if (strcmp(sendmail, mailer) == 0
  107. X#ifdef SITE_HIDING
  108. X          && ! is_a_hidden_user(username))
  109. X#else
  110. X                             )
  111. X#endif
  112. X        
  113. X         strcpy(mailerflags, (sendmail_verbose ? smflagsv : smflags));
  114. X      else
  115. X         mailerflags[0] ='\0';
  116. X
  117. X      quote_args(very_long_buffer, strip_parens(strip_commas(expanded_to)));
  118. X      strcpy(expanded_to, very_long_buffer);
  119. X
  120. X      sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s", 
  121. X        mailer, mailerflags, expanded_to,
  122. X        remove_cmd, whole_msg_file, whole_msg_file);
  123. X    }
  124. X    
  125. X    fclose(reply);
  126. X
  127. X    if(batch_only)
  128. X      printf("Sending mail...\n");
  129. X    else {
  130. X      PutLine0(LINES,0,"Sending mail...");
  131. X      CleartoEOLN();
  132. X    }
  133. X
  134. X    /* Take note of mailer return value */
  135. X
  136. X    if ( sys_status = system_call(very_long_buffer, SH, FALSE, FALSE) ) {
  137. X        /* problem case: */
  138. X        if (mail_only || batch_only)
  139. X           printf("\r\nmailer returned error status %d\r\n", sys_status);
  140. X        else {
  141. X           sprintf(very_long_buffer, "mailer returned error status %d", sys_status);
  142. X           set_error(very_long_buffer);
  143. X        }
  144. X    } else {
  145. X        /* Success case: */
  146. X        if(batch_only)
  147. X          printf("Mail sent!\n");
  148. X        else if(mail_only)
  149. X          error("Mail sent!");
  150. X        else
  151. X          set_error("Mail sent!");
  152. X    }
  153. X
  154. X    /* Unlink temp file now.
  155. X     * This is a precaution in case the message was encrypted.
  156. X     * I.e. even though this file is readable by the owner only,
  157. X     * encryption is supposed to hide things even from someone
  158. X     * with root privelges. The best we can do is not let this
  159. X     * file just hang after we're finished with it.
  160. X     */
  161. X    (void)unlink(filename);
  162. X
  163. X    return(need_redraw);
  164. X}
  165. X
  166. X/*
  167. X * remove_hostbang - Given an expanded list of addresses, remove all
  168. X * occurrences of "thishost!" at the beginning of addresses.
  169. X * This hack is useful in itself, but it is required now because of the
  170. X * kludge disallowing alias expansion on return addresses.
  171. X */
  172. X
  173. Xremove_hostbang(addrs)
  174. Xchar *addrs;
  175. X{
  176. X    int i, j, hlen, flen;
  177. X
  178. X    if ((hlen = strlen(hostname)) < 1)
  179. X      return;
  180. X
  181. X    flen = strlen(hostfullname);
  182. X    i = j = 0;
  183. X
  184. X    while (addrs[i]) {
  185. X      if (i == 0 || isspace(addrs[i - 1])) {
  186. X        if (strncmp(&addrs[i], hostname, hlen) == 0 &&
  187. X          addrs[i + hlen] == '!') {
  188. X            i += hlen + 1;
  189. X            continue;
  190. X        }
  191. X        if (strncmp(&addrs[i], hostfullname, flen) == 0 &&
  192. X          addrs[i + flen] == '!') {
  193. X            i += flen + 1;
  194. X            continue;
  195. X        }
  196. X      }
  197. X      addrs[j++] = addrs[i++];
  198. X    }
  199. X    addrs[j] = 0;
  200. X}
  201. X
  202. Xmail_form(address, subj)
  203. Xchar *address, *subj;
  204. X{
  205. X    /** copy the appropriate variables to the shared space... */
  206. X
  207. X    strcpy(subject, subj);
  208. X    strcpy(to, address);
  209. X    strcpy(expanded_to, address);
  210. X
  211. X    return(mail(FORM, NO, NO));
  212. X}
  213. X
  214. Xint
  215. Xrecall_last_msg(filename, copy_msg, cancelled_msg, already_has_text)
  216. Xchar *filename;
  217. Xint  copy_msg, *cancelled_msg, *already_has_text;
  218. X{
  219. X    char ch;
  220. X
  221. X    /** If filename exists and we've recently cancelled a message,
  222. X        the ask if the user wants to use that message instead!  This
  223. X        routine returns TRUE if the user wants to retransmit the last
  224. X        message, FALSE otherwise...
  225. X    **/
  226. X
  227. X    register int retransmit = FALSE;
  228. X
  229. X    if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
  230. X      Raw(ON);
  231. X      CleartoEOLN();
  232. X      if (copy_msg)
  233. X        PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
  234. X             BACKSPACE);
  235. X      else
  236. X        PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c", 
  237. X             BACKSPACE);
  238. X      fflush(stdout);
  239. X      ch = ReadCh();
  240. X      if (tolower(ch) != 'n') {
  241. X        Write_to_screen("Yes.",0);    
  242. X            retransmit++;
  243. X        *already_has_text = TRUE;
  244. X      }
  245. X      else 
  246. X        Write_to_screen("No.",0);    
  247. X
  248. X      fflush(stdout);
  249. X
  250. X      *cancelled_msg = 0;
  251. X    }
  252. X
  253. X    return(retransmit);
  254. X}
  255. X
  256. Xint
  257. Xverify_transmission(filename, form_letter)
  258. Xchar *filename;
  259. Xint  *form_letter;
  260. X{
  261. X    /** Ensure the user wants to send this.  This routine returns
  262. X        the character entered.  Modified compliments of Steve Wolf 
  263. X        to add the'dead.letter' feature.
  264. X        Also added form letter support... 
  265. X    **/
  266. X
  267. X    FILE *deadfd, *messagefd;
  268. X    char ch, buffer[SLEN], fname[SLEN];
  269. X    int x_coord, y_coord;
  270. X
  271. X    while(1) {
  272. X      /* clear bottom part of screen */
  273. X      MoveCursor(LINES-2,0);
  274. X      CleartoEOS();
  275. X
  276. X      /* display prompt and menu according to
  277. X       * user level and what's available on the menu */
  278. X      if (user_level == 0) {
  279. X        PutLine0(LINES-2,0,
  280. X      "Please choose one of the following options by parenthesized letter: s");
  281. X        GetXYLocation(&x_coord, &y_coord);
  282. X        y_coord--;    /* backspace over default answer */
  283. X        Centerline(LINES-1,
  284. X          "e)dit message, edit h)eaders, s)end it, or f)orget it.");
  285. X      } else {
  286. X        PutLine0(LINES-2, 0, "And now: s");
  287. X        GetXYLocation(&x_coord, &y_coord);
  288. X        y_coord--;    /* backspace over default answer */
  289. X        if (*form_letter == PREFORMATTED)  {
  290. X           strcpy(buffer, "Choose ");
  291. X        } else if (*form_letter == YES) {
  292. X           strcpy(buffer, "Choose e)dit form, ");
  293. X        } else if (*form_letter == MAYBE)  {
  294. X           strcpy(buffer, "Choose e)dit msg, m)ake form, ");
  295. X        } else {
  296. X           strcpy(buffer, "Choose e)dit message, ");
  297. X        }
  298. X#ifdef ALLOW_SUBSHELL
  299. X        strcat(buffer, "!)shell, ");
  300. X#endif
  301. X        strcat(buffer, "h)eaders, c)opy file, s)end, or f)orget.");
  302. X        Centerline(LINES-1, buffer);
  303. X      }
  304. X
  305. X      /* wait for answer */
  306. X      fflush(stdin);
  307. X      fflush(stdout);
  308. X      Raw(ON);    /* double check... testing only... */
  309. X      MoveCursor(x_coord, y_coord);
  310. X      ch = ReadCh();
  311. X      ch = tolower(ch);
  312. X
  313. X      /* process answer */
  314. X      switch (ch) {
  315. X         case 'f': Write_to_screen("Forget",0);
  316. X               if (mail_only) {
  317. X             /** try to save it as a dead letter file **/
  318. X             save_file_stats(fname);
  319. X             sprintf(fname, "%s/%s", home, dead_letter);
  320. X             if ((deadfd = fopen(fname,"a")) == NULL) {
  321. X               dprint(1, (debugfile,
  322. X           "\nAttempt to append to deadletter file '%s' failed: %s\n\r",
  323. X                   fname, error_name(errno)));
  324. X               error("Message not saved, Sorry.");
  325. X             }
  326. X             else if ((messagefd = fopen(filename, "r")) == NULL) {
  327. X               dprint(1, (debugfile,
  328. X                 "\nAttempt to read reply file '%s' failed: %s\n\r",
  329. X                   filename, error_name(errno)));
  330. X               error("Message not saved, Sorry.");
  331. X             } else {
  332. X               /* if we get here we're okay for everything */
  333. X               while (fgets(buffer, SLEN, messagefd) != NULL)
  334. X                 fputs(buffer, deadfd);
  335. X
  336. X               fclose(messagefd);
  337. X               fclose(deadfd);
  338. X               restore_file_stats(fname);
  339. X
  340. X               error1("Message saved in file \"$HOME/%s\".",
  341. X                 dead_letter);
  342. X
  343. X            }
  344. X               } else if (user_level != 0)
  345. X            set_error("Message kept. Can be restored at next f)orward, m)ail or r)eply.");
  346. X               break;
  347. X
  348. X         case '\n' :
  349. X         case '\r' :
  350. X         case 's'  : Write_to_screen("Send",0);
  351. X             ch = 's';        /* make sure! */
  352. X             break;
  353. X
  354. X         case 'm'  : if (*form_letter == MAYBE) {
  355. X               *form_letter = YES;
  356. X                   switch (check_form_file(filename)) {
  357. X                 case -1 : return('f');
  358. X                 case 0  : *form_letter = MAYBE;  /* check later!*/
  359. X                       error("No fields in form!");
  360. X                       return('e');
  361. X                 default : continue;
  362. X                       }
  363. X             }
  364. X             else {
  365. X                        Write_to_screen("%c??", 1, 07);    /* BEEP */
  366. X                sleep(1);
  367. X                    continue;
  368. X                     }
  369. X         case 'e'  :  if (*form_letter != PREFORMATTED) {
  370. X                Write_to_screen("Edit",0);
  371. X                     if (*form_letter == YES) 
  372. X                  *form_letter = MAYBE;
  373. X                      }
  374. X              else {
  375. X                        Write_to_screen("%c??", 1, 07);    /* BEEP */
  376. X                sleep(1);
  377. X                    continue;
  378. X                     }
  379. X             break;
  380. X
  381. X         case 'h'  : Write_to_screen("Headers",0);
  382. X             break;
  383. X
  384. X         case 'c'  : Write_to_screen("Copy file",0);
  385. X             break;
  386. X
  387. X         case '!'  : break;
  388. X
  389. X         default   : Write_to_screen("%c??", 1, 07);    /* BEEP */
  390. X             sleep(1);
  391. X                 continue;
  392. X       }
  393. X
  394. X       return(ch);
  395. X    }
  396. X}
  397. X
  398. XFILE *
  399. Xwrite_header_info(filename, long_to, long_cc, long_bcc, form, copy)
  400. Xchar *filename, *long_to, *long_cc, *long_bcc;
  401. Xint   form, copy;
  402. X{
  403. X    /** Try to open filedesc as the specified filename.  If we can,
  404. X        then write all the headers into the file.  The routine returns
  405. X        'filedesc' if it succeeded, NULL otherwise.  Added the ability
  406. X        to have backquoted stuff in the users .elmheaders file!
  407. X        If copy is TRUE, then treat this as the saved copy of outbound
  408. X        mail.
  409. X    **/
  410. X
  411. X    char opentype[2];
  412. X    long time(), thetime;
  413. X    char *ctime();
  414. X    static FILE *filedesc;        /* our friendly file descriptor  */
  415. X
  416. X#ifdef SITE_HIDING
  417. X    char  buffer[SLEN];
  418. X    int   is_hidden_user;        /* someone we should know about?  */
  419. X#endif
  420. X
  421. X    char  *get_arpa_date();
  422. X
  423. X    if(copy)
  424. X        strcpy(opentype, "a");
  425. X    else
  426. X        strcpy(opentype, "w");
  427. X
  428. X    save_file_stats(filename);
  429. X    if ((filedesc = fopen(filename, opentype)) == NULL) {
  430. X      dprint(1, (debugfile,
  431. X        "Attempt to open file %s for writing failed! (write_header_info)\n",
  432. X         filename));
  433. X      dprint(1, (debugfile, "** %s - %s **\n\n", error_name(errno),
  434. X         error_description(errno)));
  435. X      error2("Error %s encountered trying to write to %s.", 
  436. X        error_name(errno), filename);
  437. X      sleep(2);
  438. X      return(NULL);        /* couldn't open it!! */
  439. X    }
  440. X
  441. X    restore_file_stats(filename);
  442. X
  443. X    if(copy) {    /* Add top line that mailer would add */
  444. X#ifdef MMDF
  445. X      fprintf(filedesc, MSG_SEPERATOR);
  446. X#endif /* MMDF */
  447. X      thetime = time((long *) 0);
  448. X      fprintf(filedesc,"From %s %s", username, ctime(&thetime));
  449. X    }
  450. X
  451. X#ifdef SITE_HIDING
  452. X    if ( !copy && (is_hidden_user = is_a_hidden_user(username))) {
  453. X      /** this is the interesting part of this trick... **/
  454. X      sprintf(buffer, "From %s!%s %s\n",  HIDDEN_SITE_NAME,
  455. X          username, get_ctime_date());
  456. X      fprintf(filedesc, "%s", buffer);
  457. X      dprint(1,(debugfile, "\nadded: %s", buffer));
  458. X      /** so is this perverted or what? **/
  459. X    }
  460. X#endif
  461. X
  462. X
  463. X    /** Subject moved to top of headers for mail because the
  464. X        pure System V.3 mailer, in its infinite wisdom, now
  465. X        assumes that anything the user sends is part of the 
  466. X        message body unless either:
  467. X        1. the "-s" flag is used (although it doesn't seem
  468. X           to be supported on all implementations??)
  469. X        2. the first line is "Subject:".  If so, then it'll
  470. X           read until a blank line and assume all are meant
  471. X           to be headers.
  472. X        So the gory solution here is to move the Subject: line
  473. X        up to the top.  I assume it won't break anyone elses program
  474. X        or anything anyway (besides, RFC-822 specifies that the *order*
  475. X        of headers is irrelevant).  Gahhhhh....
  476. X    **/
  477. X
  478. X    fprintf(filedesc, "Subject: %s\n", subject);
  479. X
  480. X      fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
  481. X
  482. X    fprintf(filedesc,"Date: %s\n", get_arpa_date());
  483. X
  484. X#ifndef DONT_ADD_FROM
  485. X# ifdef SITE_HIDING
  486. X    if (is_hidden_user)
  487. X      fprintf(filedesc,"From: %s <%s!%s!%s>\n", full_username,
  488. X          hostname, HIDDEN_SITE_NAME, username);
  489. X    else
  490. X# else
  491. X#  ifdef  INTERNET
  492. X#   ifdef  USE_DOMAIN
  493. X    fprintf(filedesc,"From: %s <%s@%s>\n", full_username, 
  494. X        username, hostfullname);
  495. X#   else
  496. X    fprintf(filedesc,"From: %s <%s@%s>\n", full_username,
  497. X        username, hostname);
  498. X#   endif
  499. X#  else
  500. X    fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
  501. X        hostname, username);
  502. X#  endif
  503. X# endif
  504. X#endif
  505. X
  506. X    if (cc[0] != '\0')
  507. X        fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
  508. X
  509. X    if (copy && (bcc[0] != '\0'))
  510. X        fprintf(filedesc, "Bcc: %s\n", format_long(long_bcc, strlen("Bcc: ")));
  511. X
  512. X    if (strlen(action) > 0)
  513. X        fprintf(filedesc, "Action: %s\n", action);
  514. X    
  515. X    if (strlen(priority) > 0)
  516. X        fprintf(filedesc, "Priority: %s\n", priority);
  517. X    
  518. X    if (strlen(expires) > 0)
  519. X        fprintf(filedesc, "Expires: %s\n", expires);
  520. X    
  521. X    if (strlen(reply_to) > 0)
  522. X        fprintf(filedesc, "Reply-To: %s\n", reply_to);
  523. X
  524. X    if (strlen(in_reply_to) > 0)
  525. X        fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
  526. X
  527. X    if (strlen(user_defined_header) > 0)
  528. X        fprintf(filedesc, "%s\n", user_defined_header);
  529. X
  530. X    add_mailheaders(filedesc);
  531. X
  532. X    if (form)
  533. X      fprintf(filedesc, "Content-Type: mailform\n");
  534. X
  535. X#ifndef NOXHEADER
  536. X    fprintf(filedesc, "X-Mailer: ELM [version %s]\n\n", version_buff);
  537. X#endif /* !NOXHEADER */
  538. X
  539. X    return((FILE *) filedesc);
  540. X}
  541. X
  542. Xcopy_message_across(source, dest, copy)
  543. XFILE *source, *dest;
  544. Xint copy;
  545. X{
  546. X    /** Copy the message in the file pointed to by source to the
  547. X        file pointed to by dest.
  548. X        If copy is TRUE, treat as a saved copy of outbound mail. **/
  549. X
  550. X    int  crypted = FALSE;            /* are we encrypting?  */
  551. X    int  encoded_lines = 0;            /* # lines encoded     */
  552. X    char buffer[SLEN];            /* file reading buffer */
  553. X
  554. X    while (fgets(buffer, SLEN, source) != NULL) {
  555. X      if (buffer[0] == '[') {
  556. X        if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
  557. X          crypted = TRUE;
  558. X        else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
  559. X          crypted = FALSE;
  560. X        else if ((strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
  561. X              || (strncmp(buffer, DONT_SAVE2, strlen(DONT_SAVE2)) == 0)) {
  562. X          if(copy) break;  /* saved copy doesn't want anything after this */
  563. X          else continue;   /* next line? */
  564. X        }
  565. X      }
  566. X      else if (crypted) {
  567. X        if (batch_only) {
  568. X          printf(
  569. X        "Sorry. Cannot send encrypted mail in \"batch mode\".\n\r");
  570. X          leave();
  571. X        } else if (! gotten_key++)
  572. X          getkey(ON);
  573. X        else if (! encoded_lines)
  574. X          get_key_no_prompt();        /* reinitialize.. */
  575. X        encode(buffer);
  576. X        encoded_lines++;
  577. X      }
  578. X
  579. X      if (copy && (strncmp(buffer, "From ", 5) == 0))
  580. X        /* Add in the > to a From on our copy */
  581. X        fprintf(dest, ">%s", buffer);
  582. X
  583. X      else if (!copy && strcmp(buffer, ".\n") == 0)
  584. X        /* Because some mail transport agents take a lone period to
  585. X         * mean EOF, we add a blank space on outbound message.
  586. X         */
  587. X        fputs(". \n", dest);
  588. X        else
  589. X          if (fputs(buffer, dest) == EOF) {
  590. X        Write_to_screen("\n\rWrite failed in copy_message_across\n\r", 0);
  591. X        emergency_exit();
  592. X        }
  593. X    } 
  594. X#ifdef MMDF
  595. X    if (copy) fputs(MSG_SEPERATOR, dest);
  596. X#else
  597. X    if (copy) fputs("\n", dest);    /* ensure a blank line at the end */
  598. X#endif /* MMDF */
  599. X}
  600. X
  601. Xint
  602. Xverify_bounceback()
  603. X{
  604. X    char    ch;
  605. X
  606. X    /** Ensure the user wants to have a bounceback copy too.  (This is
  607. X        only called on messages that are greater than the specified 
  608. X        threshold hops and NEVER for non-uucp addresses.... Returns
  609. X        TRUE iff the user wants to bounce a copy back.... 
  610. X     **/
  611. X
  612. X    MoveCursor(LINES,0);
  613. X    CleartoEOLN();
  614. X    PutLine1(LINES,0, 
  615. X          "\"Bounce\" a copy off the remote machine? (y/n) y%c",
  616. X          BACKSPACE);
  617. X    fflush(stdin);    /* wait for answer! */
  618. X    fflush(stdout);
  619. X    ch = ReadCh();
  620. X    if (tolower(ch) != 'y') { 
  621. X      Write_to_screen("No.", 0);
  622. X      fflush(stdout);
  623. X      return(FALSE);
  624. X    }
  625. X    Write_to_screen("Yes.", 0);
  626. X    fflush(stdout);
  627. X
  628. X    return(TRUE);
  629. X}
  630. X
  631. X
  632. Xint
  633. Xappend_sig(file)
  634. XFILE *file;
  635. X{
  636. X    /* Append the correct signature file to file.  Return TRUE if
  637. X           we append anything.  */
  638. X
  639. X        /* Look at the to and cc list to determine which one to use */
  640. X
  641. X    /* We could check the bcc list too, but we don't want people to
  642. X           know about bcc, even indirectly */
  643. X
  644. X    /* Some people claim that  user@anything.same_domain should be 
  645. X       considered local.  Since it's not the same machine, better be 
  646. X           safe and use the remote sig (presumably it has more complete
  647. X           information).  You can't necessarily finger someone in the
  648. X           same domain. */
  649. X
  650. X      if (!batch_only && (local_signature[0] || remote_signature[0])) {
  651. X
  652. X            char filename2[SLEN];
  653. X        char *sig;
  654. X
  655. X          if (index(expanded_to, '!') || index(expanded_cc,'!'))
  656. X              sig = remote_signature;        /* ! always means remote */
  657. X            else {
  658. X          /* check each @ for @thissite.domain */
  659. X          /* if any one is different than this, then use remote sig */
  660. X          int len;
  661. X          char *ptr;
  662. X          char sitename[SLEN];
  663. X          sprintf(sitename,"@%s",hostfullname);
  664. X          len = strlen(sitename);
  665. X              sig = local_signature;
  666. X              for (ptr = index(expanded_to,'@'); ptr;  /* check To: list */
  667. X              ptr = index(ptr+1,'@')) {
  668. X        if (strncmp(ptr,sitename,len) != 0
  669. X            || (*(ptr+len) != ',' && *(ptr+len) != 0
  670. X            && *(ptr+len) != ' ')) {
  671. X              sig = remote_signature;
  672. X                  break;
  673. X                }
  674. X              }
  675. X              if (sig == local_signature)           /* still local? */ 
  676. X                for (ptr = index(expanded_cc,'@'); ptr;   /* check Cc: */
  677. X            ptr = index(ptr+1,'@')) {
  678. X          if (strncmp(ptr,sitename,len) != 0
  679. X              || (*(ptr+len) != ',' && *(ptr+len) != 0 
  680. X              && *(ptr+len) != ' ')) {
  681. X                sig = remote_signature;
  682. X                    break;
  683. X                  }
  684. X                }
  685. X            }
  686. X
  687. X            if (sig[0]) {  /* if there is a signature file */
  688. X          if (sig_dashes) /* dashes are optional */
  689. X            fprintf(file, "\n-- \n");  /* News 2.11 compatibility? */
  690. X          if (sig[0] != '/')
  691. X            sprintf(filename2, "%s/%s", home, sig);
  692. X          else
  693. X            strcpy(filename2, sig);
  694. X          (void) append(file, filename2);
  695. X
  696. X              return TRUE;
  697. X            }
  698. X          }
  699. X
  700. Xreturn FALSE;
  701. X
  702. X}
  703. SHAR_EOF
  704. echo "File src/mailmsg2.c is complete"
  705. chmod 0444 src/mailmsg2.c || echo "restore of src/mailmsg2.c fails"
  706. echo "x - extracting src/mailtime.c (Text)"
  707. sed 's/^X//' << 'SHAR_EOF' > src/mailtime.c &&
  708. X
  709. Xstatic char rcsid[] = "@(#)$Id: mailtime.c,v 4.1 90/04/28 22:43:31 syd Exp $";
  710. X
  711. X/*******************************************************************************
  712. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  713. X *
  714. X *             Copyright (c) 1986, 1987 Dave Taylor
  715. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  716. X *******************************************************************************
  717. X * Bug reports, patches, comments, suggestions should be sent to:
  718. X *
  719. X *    Syd Weinstein, Elm Coordinator
  720. X *    elm@DSI.COM            dsinc!elm
  721. X *
  722. X *******************************************************************************
  723. X * $Log:    mailtime.c,v $
  724. X * Revision 4.1  90/04/28  22:43:31  syd
  725. X * checkin of Elm 2.3 as of Release PL0
  726. X * 
  727. X *
  728. X ******************************************************************************/
  729. X
  730. X/** This set of routines is used to figure out when the user last read
  731. X    their mail and to also figure out if a given message is new or not.
  732. X
  733. X**/
  734. X
  735. X#include "headers.h"
  736. X
  737. X#include <sys/types.h>
  738. X#include <sys/stat.h>
  739. X#ifdef I_TIME
  740. X#  include <time.h>
  741. X#endif
  742. X#ifdef I_SYSTIME
  743. X#  include <sys/time.h>
  744. X#endif
  745. X
  746. Xresolve_received(entry)
  747. Xstruct header_rec *entry;
  748. X{
  749. X    /** Entry has the data for computing the time and date the 
  750. X        message was received.  Fix it and return **/
  751. X
  752. X    switch (tolower(entry->month[0])) {
  753. X      case 'j' : if (tolower(entry->month[1]) == 'a')
  754. X               entry->received.month = JANUARY;
  755. X             else if (tolower(entry->month[2]) == 'n')
  756. X                   entry->received.month = JUNE;
  757. X             else
  758. X                   entry->received.month = JULY;
  759. X                 break;
  760. X      case 'f' : entry->received.month = FEBRUARY;
  761. X              break;
  762. X      case 'm' : if (tolower(entry->month[2]) == 'r')
  763. X                   entry->received.month = MARCH;
  764. X             else
  765. X               entry->received.month = MAY;
  766. X                 break;
  767. X      case 'a' : if (tolower(entry->month[1]) == 'p')
  768. X                   entry->received.month = APRIL;
  769. X                 else
  770. X                   entry->received.month = AUGUST;
  771. X             break;
  772. X      case 's' : entry->received.month = SEPTEMBER;
  773. X             break;
  774. X      case 'o' : entry->received.month = OCTOBER;
  775. X             break;
  776. X      case 'n' : entry->received.month = NOVEMBER;
  777. X               break;
  778. X      case 'd' : entry->received.month = DECEMBER;
  779. X             break;
  780. X    }
  781. X
  782. X    sscanf(entry->day, "%d", &(entry->received.day));
  783. X
  784. X    sscanf(entry->year, "%d", &(entry->received.year));
  785. X    if (entry->received.year > 100) entry->received.year -= 1900;
  786. X
  787. X    sscanf(entry->time, "%d:%d", &(entry->received.hour),
  788. X           &(entry->received.minute));
  789. X}
  790. SHAR_EOF
  791. chmod 0444 src/mailtime.c || echo "restore of src/mailtime.c fails"
  792. echo "x - extracting src/mkhdrs.c (Text)"
  793. sed 's/^X//' << 'SHAR_EOF' > src/mkhdrs.c &&
  794. X
  795. Xstatic char rcsid[] = "@(#)$Id: mkhdrs.c,v 4.1 90/04/28 22:43:32 syd Exp $";
  796. X
  797. X/*******************************************************************************
  798. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  799. X *
  800. X *             Copyright (c) 1986, 1987 Dave Taylor
  801. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  802. X *******************************************************************************
  803. X * Bug reports, patches, comments, suggestions should be sent to:
  804. X *
  805. X *    Syd Weinstein, Elm Coordinator
  806. X *    elm@DSI.COM            dsinc!elm
  807. X *
  808. X *******************************************************************************
  809. X * $Log:    mkhdrs.c,v $
  810. X * Revision 4.1  90/04/28  22:43:32  syd
  811. X * checkin of Elm 2.3 as of Release PL0
  812. X * 
  813. X *
  814. X ******************************************************************************/
  815. X
  816. X/** This contains all the header generating routines for the ELM
  817. X    program.
  818. X
  819. X**/
  820. X
  821. X#include "headers.h"
  822. X
  823. Xextern char in_reply_to[SLEN];
  824. X
  825. Xchar *strcpy();
  826. Xunsigned long sleep();
  827. X
  828. Xgenerate_reply_to(msg)
  829. Xint msg;
  830. X{
  831. X    /** Generate an 'in-reply-to' message... **/
  832. X    char buffer[SLEN];
  833. X
  834. X
  835. X    if (msg == -1)        /* not a reply! */
  836. X      in_reply_to[0] = '\0';
  837. X    else {
  838. X      if (chloc(headers[msg]->from, '!') != -1)
  839. X        tail_of(headers[msg]->from, buffer, 0);
  840. X      else
  841. X        strcpy(buffer, headers[msg]->from);
  842. X      sprintf(in_reply_to, "%s; from \"%s\" at %s %s, %s %s",
  843. X                  headers[msg]->messageid[0] == '\0'? "<no.id>":
  844. X          headers[msg]->messageid,
  845. X          buffer,
  846. X          headers[msg]->month,
  847. X          headers[msg]->day,
  848. X          headers[msg]->year,
  849. X          headers[msg]->time);
  850. X    }
  851. X}
  852. X
  853. Xadd_mailheaders(filedesc)
  854. XFILE *filedesc;
  855. X{
  856. X    /** Add the users .mailheaders file if available.  Allow backquoting 
  857. X        in the file, too, for fortunes, etc...*shudder*
  858. X    **/
  859. X
  860. X    FILE *fd;
  861. X    char filename[SLEN], buffer[SLEN];
  862. X
  863. X    sprintf(filename, "%s/%s", home, mailheaders);
  864. X
  865. X    if ((fd = fopen(filename, "r")) != NULL) {
  866. X      while (fgets(buffer, SLEN, fd) != NULL)
  867. X        if (strlen(buffer) < 2) {
  868. X          dprint(2, (debugfile,
  869. X             "Strlen of line from .elmheaders is < 2 (write_header_info)"));
  870. X          error1("Warning: blank line in %s ignored!", filename);
  871. X          sleep(2);
  872. X        }
  873. X        else if (occurances_of(BACKQUOTE, buffer) >= 2) 
  874. X          expand_backquote(buffer, filedesc);
  875. X        else 
  876. X          fprintf(filedesc, "%s", buffer);
  877. X
  878. X        fclose(fd);
  879. X    }
  880. X}
  881. X
  882. Xexpand_backquote(buffer, filedesc)
  883. Xchar *buffer;
  884. XFILE *filedesc;
  885. X{
  886. X    /** This routine is called with a line of the form:
  887. X        Fieldname: `command`
  888. X        and is expanded accordingly..
  889. X    **/
  890. X
  891. X    FILE *fd;
  892. X    char command[SLEN], command_buffer[SLEN], fname[SLEN],
  893. X         prefix[SLEN];
  894. X    register int i, j = 0;
  895. X
  896. X    for (i=0; buffer[i] != BACKQUOTE; i++)
  897. X      prefix[j++] = buffer[i];
  898. X    prefix[j] = '\0';
  899. X
  900. X    j = 0;
  901. X
  902. X    for (i=chloc(buffer, BACKQUOTE)+1; buffer[i] != BACKQUOTE;i++)
  903. X      command[j++] = buffer[i];
  904. X    command[j] = '\0';
  905. X
  906. X    sprintf(fname,"%s%s%d", temp_dir, temp_print, getpid());
  907. X
  908. X    sprintf(command_buffer, "%s > %s", command, fname);
  909. X
  910. X    system_call(command_buffer, SH, FALSE, FALSE);
  911. X
  912. X    if ((fd = fopen(fname, "r")) == NULL) {
  913. X      error1("Backquoted command \"%s\" in elmheaders failed.", command);
  914. X      return;    
  915. X    }
  916. X
  917. X    /* If we get a line that is less than 80 - length of prefix then we
  918. X       can toss it on the same line, otherwise, simply prepend each line
  919. X       *starting with this line* with a leading tab and cruise along */
  920. X
  921. X    if (fgets(command_buffer, SLEN, fd) == NULL) 
  922. X      fprintf(filedesc, prefix);
  923. X    else {
  924. X      if (strlen(command_buffer) + strlen(prefix) < 80) 
  925. X        fprintf(filedesc, "%s%s", prefix, command_buffer);
  926. X      else
  927. X        fprintf(filedesc, "%s\n\t%s", prefix, command_buffer);
  928. X      
  929. X      while (fgets(command_buffer, SLEN, fd) != NULL) 
  930. X        fprintf(filedesc, "\t%s", command_buffer);
  931. X    
  932. X      fclose(fd);
  933. X    }
  934. X
  935. X    unlink(fname);    /* don't leave the temp file laying around! */
  936. X}
  937. SHAR_EOF
  938. chmod 0444 src/mkhdrs.c || echo "restore of src/mkhdrs.c fails"
  939. echo "x - extracting src/newmbox.c (Text)"
  940. sed 's/^X//' << 'SHAR_EOF' > src/newmbox.c &&
  941. X
  942. Xstatic char rcsid[] = "@(#)$Id: newmbox.c,v 4.1 90/04/28 22:43:34 syd Exp $";
  943. X
  944. X/*******************************************************************************
  945. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  946. X *
  947. X *             Copyright (c) 1988, USENET Community Trust
  948. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  949. X *******************************************************************************
  950. X * Bug reports, patches, comments, suggestions should be sent to:
  951. X *
  952. X *    Syd Weinstein, Elm Coordinator
  953. X *    elm@DSI.COM            dsinc!elm
  954. X *
  955. X *******************************************************************************
  956. X * $Log:    newmbox.c,v $
  957. X * Revision 4.1  90/04/28  22:43:34  syd
  958. X * checkin of Elm 2.3 as of Release PL0
  959. X * 
  960. X *
  961. X ******************************************************************************/
  962. X
  963. X/**  read new folder **/
  964. X
  965. X#include <ctype.h>
  966. X#include "headers.h"
  967. X
  968. X#ifdef BSD
  969. X#undef tolower        /* we have our own "tolower" routine instead! */
  970. X#endif
  971. X
  972. X#include <sys/types.h>        
  973. X#include <sys/stat.h>
  974. X#include <errno.h>
  975. X
  976. X#ifdef I_TIME
  977. X#  include <time.h>
  978. X#endif
  979. X#ifdef I_SYSTIME
  980. X#  include <sys/time.h>
  981. X#endif
  982. X
  983. Xextern int errno;
  984. X
  985. Xchar *error_name(), *error_description();
  986. Xchar *malloc(), *realloc(), *strcpy(), *strncpy(), *rindex(), *index();
  987. Xunsigned long sleep();
  988. Xvoid rewind();
  989. Xvoid exit();
  990. Xlong bytes();
  991. X
  992. Xint
  993. Xnewmbox(new_file, adds_only)
  994. Xchar *new_file;
  995. Xint adds_only;
  996. X{
  997. X    /** Read a folder.
  998. X
  999. X        new_file    - name of folder  to read. It is up to the calling
  1000. X              function to make sure that the file can be
  1001. X              read by the user. This is not checked in this
  1002. X              function. The reason why it is not checked here
  1003. X              is due to the situation where the user wants to
  1004. X              change folders: the new folder must be checked
  1005. X              for access *before* leaving the old one, which
  1006. X              is before this function gets called.
  1007. X        adds_only    - set if we only want to read newly added messages to
  1008. X                same old folder.
  1009. X
  1010. X    **/
  1011. X
  1012. X    int  same_file;
  1013. X    int  new_folder_type;
  1014. X    int err;
  1015. X    char new_tempfile[SLEN];
  1016. X
  1017. X    /* determine type of new mailfile and calculate temp file name */
  1018. X    if((new_folder_type = get_folder_type(new_file)) == SPOOL)
  1019. X      mk_temp_mail_fn(new_tempfile, new_file);
  1020. X    else
  1021. X      *new_tempfile = '\0';
  1022. X
  1023. X    /* determine whether we are changing files */
  1024. X    same_file = !(strcmp(new_file, cur_folder));
  1025. X
  1026. X    /* If we are changing files and we are changing to a spool file,
  1027. X     * make sure there isn't a temp file for it, because if
  1028. X     * there is, someone else is using ELM to read the new file,
  1029. X     * and we don't want to be reading it at the same time.
  1030. X     */
  1031. X    if((new_folder_type == SPOOL) && (!same_file)) {
  1032. X      if (access(new_tempfile, ACCESS_EXISTS) != -1) {
  1033. X        if(folder_type != NO_NAME) ClearScreen();
  1034. X        Centerline(15,
  1035. X          "Hey! An instantiation of ELM is already reading this mail!");
  1036. X        Centerline(17,
  1037. X          "If this is in error, then you'll need to save a copy of the");
  1038. X        Centerline(18, "the following file then remove it:");
  1039. X        Centerline(19, new_tempfile);
  1040. X        MoveCursor(LINES, 0);  /* so shell prompt upon exit is on newline */
  1041. X        silently_exit();
  1042. X      }
  1043. X    }
  1044. X
  1045. X    /* If we were reading a spool file and we are not just reading
  1046. X     * in the additional new messages to the same file, we need to
  1047. X     * remove the corresponding tempfile.
  1048. X     */
  1049. X
  1050. X    if((folder_type == SPOOL) && !adds_only) {
  1051. X      if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
  1052. X        if (unlink(cur_tempfolder) != 0) {
  1053. X          error2("Sorry, can't unlink the temp file %s [%s]!\n\r",
  1054. X            cur_tempfolder, error_name(errno));
  1055. X          silently_exit();
  1056. X        }
  1057. X      }
  1058. X    }
  1059. X
  1060. X    /* Okay! Now establish this new file as THE file */
  1061. X    strcpy(cur_folder, new_file);
  1062. X    folder_type = new_folder_type;
  1063. X    strcpy(cur_tempfolder, new_tempfile);
  1064. X
  1065. X    clear_error();
  1066. X    clear_central_message();
  1067. X
  1068. X    if (mailfile != NULL)
  1069. X      (void) fclose(mailfile);  /* close it first, to avoid too many open */
  1070. X
  1071. X    if ((mailfile = fopen(cur_folder,"r")) == NULL)  {
  1072. X      if (errno != ENOENT ) { /* error on anything but file not exist */
  1073. X        err = errno;
  1074. X        Write_to_screen("\n\rfail on open in newmbox, open %s failed!!\n\r", 1,
  1075. X            cur_folder);
  1076. X        Write_to_screen("** %s - %s. **\n\r", 2,
  1077. X            error_name(err), error_description(err));
  1078. X        dprint(1, (debugfile, "fail on open in newbox, file %s!!\n",
  1079. X            cur_folder));
  1080. X        rm_temps_exit();
  1081. X      }
  1082. X      else {
  1083. X        mailfile_size = 0;         /* must non-existant folder */
  1084. X        message_count = 0;
  1085. X        selected = 0;
  1086. X      }
  1087. X    } else {                          /* folder exists, read headers */
  1088. X      read_headers(adds_only);
  1089. X    }
  1090. X
  1091. X    if(!same_file)        /* limit mode off if this is a new file */
  1092. X      selected = 0;
  1093. X    if (!adds_only)        /* limit mode off if recreating headers */
  1094. X      selected = 0;        /* because we loose the 'Visible' flag */
  1095. X
  1096. X    dprint(1, (debugfile,
  1097. X      "New folder %s type %s temp file %s (%s)\n", cur_folder, 
  1098. X      (folder_type == SPOOL ? "spool" : "non-spool"),
  1099. X      (*cur_tempfolder ? cur_tempfolder : "none"), "newmbox"));
  1100. X
  1101. X    return(0);
  1102. X}
  1103. X
  1104. Xint
  1105. Xget_folder_type(filename)
  1106. Xchar *filename;
  1107. X{
  1108. X    /** returns the type of mailfile filename is
  1109. X        NO_NAME = no name
  1110. X        SPOOL = consisting only of mailhome plus base file name
  1111. X            (no intervening directory name)
  1112. X        NON_SPOOL = a name that is not SPOOL type above
  1113. X     **/
  1114. X
  1115. X    char *last_slash;
  1116. X
  1117. X    /* if filename is null or is of zero length */
  1118. X    if((filename == NULL) || (*filename == '\0'))
  1119. X      return(NO_NAME);
  1120. X
  1121. X    /* if filename begins with mailhome,
  1122. X     * and there is a slash in filename,
  1123. X     * and there is a filename after it (i.e. last slash is not last char),
  1124. X     * and the last character of mailhome is last slash in filename,
  1125. X     * it's a spool file .
  1126. X     */
  1127. X    if((first_word(filename, mailhome)) &&
  1128. X      ((last_slash = rindex(filename, '/')) != NULL) &&
  1129. X      (*(last_slash+1) != '\0') &&
  1130. X      (filename + strlen(mailhome) - 1 == last_slash))
  1131. X        return(SPOOL);
  1132. X    /* if file name == default mailbox, its a spool file also
  1133. X     * even if its not in the spool directory. (SVR4)
  1134. X     */
  1135. X    if (strcmp(filename, defaultfile) == 0)
  1136. X        return(SPOOL);
  1137. X
  1138. X    return(NON_SPOOL);
  1139. X}
  1140. X
  1141. Xmk_temp_mail_fn(tempfn, mbox)
  1142. Xchar *tempfn, *mbox;
  1143. X{
  1144. X    /** create in tempfn the name of the temp file corresponding to
  1145. X        mailfile mbox. Mbox is presumed to be a file in mailhome;
  1146. X        Strangeness may result if it is not!
  1147. X     **/
  1148. X
  1149. X    char *cp;
  1150. X
  1151. X    sprintf(tempfn, "%s%s", default_temp, temp_mbox);
  1152. X    if((cp = rindex(mbox, '/')) != NULL) {
  1153. X      cp++;
  1154. X      if (strcmp(cp, "mbox") == 0 || strcmp(cp, "mailbox") == 0 ||
  1155. X        *cp == '.')
  1156. X        strcat(tempfn, username);
  1157. X      else
  1158. X        strcat(tempfn, cp);
  1159. X    }
  1160. X}
  1161. X
  1162. Xint
  1163. Xread_headers(add_new_only)
  1164. Xint add_new_only;
  1165. X{
  1166. X    /** Reads the headers into the headers[] array and leaves the
  1167. X        file rewound for further I/O requests.   If the file being
  1168. X        read is a mail spool file (ie incoming) then it is copied to
  1169. X        a temp file and closed, to allow more mail to arrive during 
  1170. X        the elm session.  If 'add_new_only' is set, the program will copy
  1171. X        the status flags from the previous data structure to the new 
  1172. X        one if possible and only read in newly added messages.
  1173. X    **/
  1174. X
  1175. X    FILE *temp;
  1176. X    struct header_rec *current_header = NULL;
  1177. X    char buffer[LONG_STRING], *c;
  1178. X    long fbytes = 0L, line_bytes = 0L;
  1179. X    register int line = 0, count = 0, another_count,
  1180. X      subj = 0, copyit = 0, in_header = 0;
  1181. X    int count_x, count_y = 17, err;
  1182. X    int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE;
  1183. X
  1184. X    static int first_read = 0;
  1185. X#ifdef MMDF
  1186. X        int newheader = 0;
  1187. X#endif /* MMDF */
  1188. X
  1189. X    if (folder_type == SPOOL) {
  1190. X      lock(INCOMING);    /* ensure no mail arrives while we do this! */
  1191. X      if (! add_new_only) {
  1192. X        if (access(cur_tempfolder, ACCESS_EXISTS) != -1) {
  1193. X          /* Hey!  What the hell is this?  The temp file already exists? */
  1194. X          /* Looks like a potential clash of processes on the same file! */
  1195. X          unlock();                     /* so remove lock file! */
  1196. X          error("What's this?  The temp folder already exists??");
  1197. X          sleep(2);
  1198. X          error("Ahhhh... I give up.");
  1199. X          silently_exit();    /* leave without tampering with it! */
  1200. X        }
  1201. X        if ((temp = fopen(cur_tempfolder,"w")) == NULL) {
  1202. X         err = errno;
  1203. X         unlock();    /* remove lock file! */
  1204. X         Raw(OFF);
  1205. X         Write_to_screen(
  1206. X             "\n\rCouldn't open file %s for use as temp file.\n\r",
  1207. X             1, cur_tempfolder);
  1208. X         Write_to_screen("** %s - %s. **\n\r", 2,
  1209. X             error_name(err), error_description(err));
  1210. X         dprint(1, (debugfile,
  1211. X                "Error: Couldn't open file %s as temp mbox.  errno %s (%s)\n",
  1212. X             cur_tempfolder, error_name(err), "read_headers"));
  1213. X         rm_temps_exit();
  1214. X        }
  1215. X       copyit++;
  1216. X       chown(cur_tempfolder, userid, groupid);
  1217. X       chmod(cur_tempfolder, 0700);    /* shut off file for other people! */
  1218. X     }
  1219. X     else {
  1220. X       if ((temp = fopen(cur_tempfolder,"a")) == NULL) {
  1221. X         err = errno;
  1222. X         unlock();    /* remove lock file! */
  1223. X         Raw(OFF);
  1224. X         Write_to_screen(
  1225. X             "\n\rCouldn't reopen file %s for use as temp file.\n\r",
  1226. X             1, cur_tempfolder);
  1227. X         Write_to_screen("** %s - %s. **\n\r", 2,
  1228. X             error_name(err), error_description(err));
  1229. X         dprint(1, (debugfile, 
  1230. X                "Error: Couldn't reopen file %s as temp mbox.  errno %s (%s)\n",
  1231. X             cur_tempfolder, error_name(err), "read_headers"));
  1232. X         rm_temps_exit();
  1233. X        }
  1234. X       copyit++;
  1235. X      }
  1236. X    }
  1237. X
  1238. X    if (! first_read++) {
  1239. X      ClearLine(LINES-1);
  1240. X      ClearLine(LINES);
  1241. X      if (add_new_only)
  1242. X        PutLine2(LINES, 0, "Reading in %s, message: %d", cur_folder, 
  1243. X             message_count);
  1244. X      else
  1245. X        PutLine1(LINES, 0, "Reading in %s, message: 0", cur_folder);
  1246. X      count_x = LINES;
  1247. X          count_y = 22 + strlen(cur_folder);
  1248. X    }
  1249. X    else {
  1250. X      count_x = LINES-2;
  1251. X      PutLine0(LINES-2, 0, "Reading message: 0");
  1252. X    }
  1253. X
  1254. X    if (add_new_only) {
  1255. X       if (fseek(mailfile, mailfile_size, 0) == -1) {
  1256. X         err = errno;
  1257. X         Write_to_screen(
  1258. X        "\n\rCouldn't seek to %ld (end of folder) in %s!\n\r", 2,
  1259. X             mailfile_size, cur_folder);    
  1260. X         Write_to_screen("** %s - %s. **\n\r", 2,
  1261. X             error_name(err), error_description(err));
  1262. X         dprint(1, (debugfile,
  1263. X     "Error: Couldn't seek to end of folder %s: (offset %ld) Errno %s (%s)\n",
  1264. X            cur_folder, mailfile_size, error_name(err), "read_headers"));
  1265. X         emergency_exit();
  1266. X       }
  1267. X       count = message_count;        /* next available  */
  1268. X       fbytes = mailfile_size;        /* start correctly */
  1269. X    }
  1270. X
  1271. X    /** find the size of the folder then unlock the file **/
  1272. X
  1273. X    mailfile_size = bytes(cur_folder);
  1274. X    unlock();
  1275. X
  1276. X    /** now let's copy it all across accordingly... **/
  1277. X
  1278. X    while (fbytes < mailfile_size) {
  1279. X
  1280. X      if (fgets(buffer, LONG_STRING, mailfile) == NULL) break;
  1281. X
  1282. X      if (copyit)
  1283. X        if (fputs(buffer, temp) == EOF) {
  1284. X        err = errno;
  1285. X        Write_to_screen("\n\rWrite to tempfile %s failed!!\n\r", 1,
  1286. X                cur_tempfolder);
  1287. X        Write_to_screen("** %s - %s. **\n\r", 2,
  1288. X                error_name(err), error_description(err));
  1289. X        dprint(1, (debugfile, "Can't write to tempfile %s!!\n",
  1290. X               cur_tempfolder));
  1291. X        rm_temps_exit();
  1292. X        }
  1293. X      line_bytes = (long) strlen(buffer); 
  1294. X
  1295. X      /* Fix below to increment line count ONLY if we got a full line.
  1296. X       * Input lines longer than the fgets buffer size would
  1297. X       * get counted each time a subsequent part of them was
  1298. X       * read in. This meant that when the faulty line count was used
  1299. X       * to display the message, part of the next message
  1300. X       * was displayed at the end of the message.
  1301. X       */
  1302. X      if(buffer[strlen(buffer)-1] == '\n') line++;
  1303. X
  1304. X      if (fbytes == 0L || first_line) {     /* first line of file... */    
  1305. X        if (folder_type == SPOOL) {
  1306. X          if (first_word(buffer, "Forward to ")) {
  1307. X            set_central_message("Mail being forwarded to %s", 
  1308. X                   (char *) (buffer + 11));
  1309. X            forwarding_mail = TRUE;
  1310. X          }
  1311. X        }
  1312. X
  1313. X        /** flush leading blank lines before next test... **/
  1314. X        if (strlen(buffer) == 1) {
  1315. X          fbytes++;
  1316. X          continue;    
  1317. X        }
  1318. X        else
  1319. X          first_line = FALSE;
  1320. X              
  1321. X#ifdef MMDF
  1322. X        if (!forwarding_mail && strcmp(buffer, MSG_SEPERATOR) != 0 ) {
  1323. X#else
  1324. X        if (! first_word(buffer, "From ") && !forwarding_mail) {
  1325. X#endif /* MMDF */
  1326. X          PutLine0(LINES, 0,
  1327. X          "\n\rFolder is corrupt!!  I can't read it!!\n\r\n\r");
  1328. X          fflush(stderr);
  1329. X          dprint(1, (debugfile, 
  1330. X               "\n\n**** First mail header is corrupt!! ****\n\n"));
  1331. X          dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
  1332. X              mail_only++;    /* to avoid leave() cursor motion */
  1333. X              leave();
  1334. X        }
  1335. X      }
  1336. X
  1337. X#ifdef MMDF
  1338. X      if (strcmp(buffer, MSG_SEPERATOR) == 0) {
  1339. X            newheader = !newheader;
  1340. X#else
  1341. X      if (first_word(buffer,"From ")) {
  1342. X#endif /* MMDF */
  1343. X        /** allocate new header pointers, if needed... **/
  1344. X
  1345. X        if (count >= max_headers) {
  1346. X          struct header_rec **new_headers;
  1347. X          int new_max;
  1348. X
  1349. X          new_max = max_headers + KLICK;
  1350. X          if (max_headers == 0) {
  1351. X        new_headers = (struct header_rec **)
  1352. X          malloc(new_max * sizeof(struct header_rec *));
  1353. X          }
  1354. X          else {
  1355. X        new_headers = (struct header_rec **)
  1356. X          realloc(headers, new_max * sizeof(struct header_rec *));
  1357. X          }
  1358. X          if (new_headers == NULL) {
  1359. X            error1(
  1360. X      "\n\r\n\rCouldn't allocate enough memory! Message #%d.\n\r\n\r",
  1361. X            count);
  1362. X            leave();
  1363. X          }
  1364. X          headers = new_headers;
  1365. X          while (max_headers < new_max)
  1366. X        headers[max_headers++] = NULL;
  1367. X        }
  1368. X          
  1369. X        /** allocate new header structure, if needed... **/
  1370. X
  1371. X        if (headers[count] == NULL) {
  1372. X          struct header_rec *h;
  1373. X
  1374. X          if ((h = (struct header_rec *)
  1375. X            malloc(sizeof(struct header_rec))) == NULL) {
  1376. X            error1(
  1377. X      "\n\r\n\rCouldn't allocate enough memory! Message #%d.\n\r\n\r",
  1378. X            count);
  1379. X            leave();
  1380. X          }
  1381. X          headers[count] = h;
  1382. X        }
  1383. X
  1384. X        if (real_from(buffer, headers[count])) {
  1385. X          current_header = headers[count];
  1386. X
  1387. X          current_header->offset = (long) fbytes;
  1388. X          current_header->index_number = count+1;
  1389. X          /* set default status - always 'visible'  - and
  1390. X           * if a spool file, presume 'new', otherwise
  1391. X           * 'read', for the time being until overridden
  1392. X           * by a Status: header.
  1393. X           * We presume 'read' for nonspool mailfile messages
  1394. X           * to be compatible messages stored with older versions of elm,
  1395. X           * which didn't support a Status: header.
  1396. X           */
  1397. X          if(folder_type == SPOOL)
  1398. X        current_header->status = VISIBLE | NEW | UNREAD;
  1399. X          else
  1400. X        current_header->status = VISIBLE;
  1401. X
  1402. X          strcpy(current_header->subject, "");    /* clear subj    */
  1403. X          strcpy(current_header->to, "");        /* clear to    */
  1404. X          strcpy(current_header->mailx_status, "");    /* clear status flags */
  1405. X          strcpy(current_header->messageid, "<no.id>"); /* set no id into message id */
  1406. X          current_header->encrypted = 0;        /* clear encrypted */
  1407. X          current_header->exit_disposition = UNSET;
  1408. X          current_header->status_chgd = FALSE;
  1409. X
  1410. X          /* Set the number of lines for the _preceding_ message,
  1411. X           * but only if there was a preceding message and
  1412. X           * only if it wasn't calculated already. It would
  1413. X           * have been calculated already if we are only
  1414. X           * reading headers of new messages that have just arrived,
  1415. X           * and the preceding message was one of the old ones.
  1416. X           */
  1417. X          if ((count) && (!add_new_only || count > message_count))
  1418. X            headers[count-1]->lines = line;
  1419. X
  1420. X          count++;
  1421. X          subj = 0;
  1422. X          line = 0;
  1423. X          in_header = 1;
  1424. X          PutLine1(count_x, count_y, "%d", count);
  1425. X#ifdef MMDF
  1426. X        } else if (newheader) {
  1427. X          current_header = headers[count];
  1428. X
  1429. X          current_header->offset = (long) fbytes;
  1430. X          current_header->index_number = count+1;
  1431. X
  1432. X          /* set default status - always 'visible'  - and
  1433. X           * if a spool file, presume 'new', otherwise
  1434. X           * 'read', for the time being until overridden
  1435. X           * by a Status: header.
  1436. X           * We presume 'read' for nonspool mailfile messages
  1437. X           * to be compatible messages stored with older versions of elm,
  1438. X           * which didn't support a Status: header.
  1439. X           */
  1440. X          if(folder_type == SPOOL)
  1441. X        current_header->status = VISIBLE | NEW | UNREAD;
  1442. X          else
  1443. X        current_header->status = VISIBLE;
  1444. X
  1445. X          strcpy(current_header->from, "");        /* clear from    */
  1446. X          strcpy(current_header->dayname, "");    /* clear dayname */
  1447. X          strcpy(current_header->month, "");    /* clear month   */
  1448. X          strcpy(current_header->day, "");        /* clear day     */
  1449. X          strcpy(current_header->time, "");        /* clear time    */
  1450. X          strcpy(current_header->year, "");        /* clear year    */
  1451. X          strcpy(current_header->subject, "");    /* clear subj    */
  1452. X          strcpy(current_header->to, "");        /* clear to    */
  1453. X          strcpy(current_header->mailx_status, "");    /* clear status flags */
  1454. X          strcpy(current_header->messageid, "<no.id>"); /* set no id into message id */
  1455. X          current_header->encrypted = 0;        /* clear encrypted */
  1456. X          current_header->exit_disposition = UNSET;
  1457. X          current_header->status_chgd = FALSE;
  1458. X
  1459. X          /* Set the number of lines for the _preceding_ message,
  1460. X           * but only if there was a preceding message and
  1461. X           * only if it wasn't calculated already. It would
  1462. X           * have been calculated already if we are only
  1463. X           * reading headers of new messages that have just arrived,
  1464. X           * and the preceding message was one of the old ones.
  1465. X           */
  1466. X          if ((count) && (!add_new_only || count > message_count))
  1467. X            headers[count-1]->lines = line;
  1468. X
  1469. X          count++;
  1470. X          subj = 0;
  1471. X          line = 0;
  1472. X          in_header = 1;
  1473. X          PutLine1(count_x, count_y, "%d", count);
  1474. X          dprint(1, (debugfile, 
  1475. X               "\n\n**** Added header record ****\n\n"));
  1476. X#endif /* MMDF */
  1477. X        } else if (count == 0) {
  1478. X          /* if this is the first "From" in file but the "From" line is
  1479. X           * not of the proper format, we've got a corrupt folder.
  1480. X           */
  1481. X          PutLine0(LINES, 0,
  1482. X          "\n\rFolder is corrupt!!  I can't read it!!\n\r\n\r");
  1483. X          fflush(stderr);
  1484. X          dprint(1, (debugfile, 
  1485. X               "\n\n**** First mail header is corrupt!! ****\n\n"));
  1486. X          dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer));
  1487. X              mail_only++;    /* to avoid leave() cursor motion */
  1488. X              leave();
  1489. X        }
  1490. X      }
  1491. X      else if (in_header) {
  1492. X#ifdef MMDF
  1493. X        if (first_word(buffer,"From "))
  1494. X          real_from(buffer, current_header);
  1495. X#endif /* MMDF */
  1496. X        if (first_word(buffer,">From:"))
  1497. X          parse_arpa_who(buffer, current_header->from, FALSE);
  1498. X        else if (first_word(buffer,">From")) 
  1499. X          forwarded(buffer, current_header); /* return address */
  1500. X        else if (first_word(buffer,"Subject:") ||
  1501. X             first_word(buffer,"Subj:") ||
  1502. X             first_word(buffer,"Re:")) {
  1503. X          if (! subj++) {
  1504. X            remove_first_word(buffer);
  1505. X            copy_sans_escape(current_header->subject, buffer, STRING);
  1506. X        remove_possible_trailing_spaces(current_header->subject);
  1507. X          }
  1508. X        }
  1509. X        else if (first_word(buffer,"From:")) {
  1510. X#ifdef MMDF
  1511. X          parse_arpa_who(buffer, current_header->from, TRUE);
  1512. X          dprint(1, (debugfile, 
  1513. X               "\n\n**** Calling parse_arpa_who for from ****\n\n"));
  1514. X#else
  1515. X          parse_arpa_who(buffer, current_header->from, FALSE);
  1516. X#endif /* MMDF */
  1517. X
  1518. X        }
  1519. X        else if (first_word(buffer, "Message-Id:") ||
  1520. X             first_word(buffer, "Message-ID:")) {
  1521. X          buffer[strlen(buffer)-1] = '\0';
  1522. X          strcpy(current_header->messageid,
  1523. X             (char *) buffer + 12);
  1524. X        }
  1525. X
  1526. X        else if (first_word(buffer, "Expires:"))
  1527. X          process_expiration_date((char *) buffer + 9, 
  1528. X                      &(current_header->status));
  1529. X        
  1530. X        /** when it was sent... **/
  1531. X
  1532. X        else if (first_word(buffer, "Date:")) {
  1533. X          dprint(1, (debugfile, 
  1534. X               "\n\n**** Calling parse_arpa_date ****\n\n"));
  1535. X          remove_first_word(buffer);
  1536. X          parse_arpa_date(buffer, current_header);
  1537. X        }
  1538. X
  1539. X        /** some status things about the message... **/
  1540. X
  1541. X        else if (first_word(buffer, "Priority:") || 
  1542. X             first_word(buffer, "Importance: 2"))
  1543. X          current_header->status |= URGENT;
  1544. X        else if (first_word(buffer, "Sensitivity: 2"))
  1545. X          current_header->status |= PRIVATE;
  1546. X        else if (first_word(buffer, "Sensitivity: 3"))
  1547. X          current_header->status |= CONFIDENTIAL;
  1548. X        else if (first_word(buffer, "Content-Type: mailform"))
  1549. X          current_header->status |= FORM_LETTER;
  1550. X        else if (first_word(buffer, "Action:"))
  1551. X          current_header->status |= ACTION;
  1552. X
  1553. X        /** next let's see if it's to us or not... **/
  1554. X
  1555. X        else if (first_word(buffer, "To:")) {
  1556. X          in_to_list = TRUE;
  1557. X          current_header->to[0] = '\0';    /* nothing yet */
  1558. X          figure_out_addressee((char *) buffer +3, 
  1559. X                   current_header->to);
  1560. X        }
  1561. X        else if (first_word(buffer, "Status:")) {
  1562. X          remove_first_word(buffer);
  1563. X          strncpy(current_header->mailx_status, buffer, WLEN-1);
  1564. X          current_header->mailx_status[WLEN-1] ='\0';
  1565. X
  1566. X          c = index(current_header->mailx_status, '\n');
  1567. X          if (c != NULL)
  1568. X        *c = '\0';
  1569. X          remove_possible_trailing_spaces(current_header->mailx_status);
  1570. X
  1571. X          /* Okay readjust the status. If there's an 'R', message
  1572. X           * is read; if there is no 'R' but there is an 'O', message
  1573. X           * is unread. In any case it isn't new because a new message
  1574. X           * wouldn't have a Status: header.
  1575. X           */
  1576. X          if (index(current_header->mailx_status, 'R') != NULL)
  1577. X        current_header->status &= ~(NEW | UNREAD);
  1578. X          else if (index(current_header->mailx_status, 'O') != NULL) {
  1579. X        current_header->status &= ~NEW;
  1580. X        current_header->status |= UNREAD;
  1581. X          }
  1582. X        }
  1583. X
  1584. X        else if (buffer[0] == LINE_FEED || buffer[0] == '\0') {
  1585. X          if (in_header) {
  1586. X            in_header = 0;    /* in body of message! */
  1587. X            fix_date(current_header);
  1588. X          }
  1589. X        }
  1590. X        else if (in_header) {
  1591. X           if ((!whitespace(buffer[0])) && index(buffer, ':') == NULL) {
  1592. X            in_header = 0;    /* in body of message! */
  1593. X            fix_date(current_header);
  1594. X          }
  1595. X        }
  1596. X        else if (in_to_list == TRUE) {
  1597. X          if (whitespace(buffer[0]))
  1598. X            figure_out_addressee(buffer, current_header->to);
  1599. SHAR_EOF
  1600. echo "End of part 18"
  1601. echo "File src/newmbox.c is continued in part 19"
  1602. echo "19" > s2_seq_.tmp
  1603. exit 0
  1604.  
  1605. exit 0 # Just in case...
  1606.