home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume9 / elm2 / part05 < prev    next >
Text File  |  1987-03-08  |  58KB  |  1,975 lines

  1. Subject:  v09i005:  ELM Mail System, Part05/19
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: Dave Taylor <hplabs!taylor>
  6. Mod.sources: Volume 9, Issue 5
  7. Archive-name: elm2/Part05
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If this archive is complete, you will see the message:
  13. #        "End of archive 5 (of 19)."
  14. # Contents:  filter/actions.c filter/rules.c hdrs/elm.h hdrs/headers.h
  15. #   src/calendar.c src/hdrconfg.c src/help.c src/pattern.c src/utils.c
  16. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  17. echo shar: Extracting \"filter/actions.c\" \(5857 characters\)
  18. if test -f filter/actions.c ; then 
  19.   echo shar: Will not over-write existing file \"filter/actions.c\"
  20. else
  21. sed "s/^X//" >filter/actions.c <<'END_OF_filter/actions.c'
  22. X/**            actions.c            **/
  23. X
  24. X/** RESULT oriented routines *chuckle*.  These routines implement the
  25. X    actions that result from either a specified rule being true or from
  26. X    the default action being taken.
  27. X
  28. X    (C) Copyright 1986, Dave Taylor
  29. X**/
  30. X
  31. X#include <stdio.h>
  32. X#include <pwd.h>
  33. X#include <ctype.h>
  34. X#include <fcntl.h>
  35. X
  36. X#include "defs.h"
  37. X#include "filter.h"
  38. X
  39. Xmail_message(address)
  40. Xchar *address;
  41. X{
  42. X    /** Called with an address to send mail to.   For various reasons
  43. X        that are too disgusting to go into herein, we're going to actually
  44. X        open the users mailbox and by hand add this message.  Yech.
  45. X        NOTE, of course, that if we're going to MAIL the message to someone
  46. X        else, that we'll try to do nice things with it on the fly...
  47. X    **/
  48. X
  49. X    FILE *pipefd, *tempfd, *mailfd;
  50. X    int  attempts = 0, ret, in_header = TRUE, line_count = 0;
  51. X    char tempfile[SLEN], mailbox[SLEN], lockfile[SLEN],
  52. X         buffer[VERY_LONG_STRING];
  53. X
  54. X    if (verbose && ! log_actions_only)
  55. X      printf("%sfilter (%s): Mailing message to %s\n", 
  56. X          BEEP, username, address);
  57. X
  58. X    if (! show_only) {
  59. X      sprintf(tempfile, "%s.%d", filter_temp, getpid());
  60. X
  61. X      if ((tempfd = fopen(tempfile, "r")) < 0) {
  62. X        fprintf(stderr, "%sfilter (%s): Can't open temp file %s!!\n", 
  63. X            BEEP, username, tempfile);
  64. X        exit(1);
  65. X      }
  66. X         
  67. X      if (strcmp(address, username) != 0) {    /* mailing to someone else */
  68. X        
  69. X        if (already_been_forwarded) {    /* potential looping! */
  70. X          if (contains(from, username)) {
  71. X            fprintf(stderr, 
  72. X    "%sfilter (%s): Filter loop detected!  Message left in file %s.%d\n", 
  73. X            BEEP, username, filter_temp, getpid());
  74. X            exit(0);
  75. X          }
  76. X        }
  77. X
  78. X        sprintf(buffer, "%s %s %s", sendmail, smflags, address);
  79. X
  80. X        if ((pipefd = popen(buffer, "w")) == NULL) {
  81. X          fprintf(stderr, "%sfilter (%s): popen %s failed!\n", 
  82. X              BEEP, buffer);
  83. X          sprintf(buffer, "((%s %s %s ; %s %s) & ) < %s &",
  84. X              sendmail , smflags, address, remove, tempfile, tempfile);
  85. X          system(buffer);
  86. X          return;
  87. X        }
  88. X
  89. X        fprintf(pipefd, "Subject: \"%s\"\n", subject);
  90. X        fprintf(pipefd, "From: The Filter of %s@%s <%s>\n", 
  91. X            username, hostname, username);
  92. X        fprintf(pipefd, "To: %s\n", address);
  93. X        fprintf(pipefd, "X-Filtered-By: filter, version %s\n\n", VERSION);
  94. X
  95. X        fprintf(pipefd, "-- Begin filtered message --\n\n");
  96. X    
  97. X        while (fgets(buffer, LONG_SLEN, tempfd) != NULL)
  98. X          if (already_been_forwarded && in_header)
  99. X            in_header = (strlen(buffer) == 1? 0 : in_header);
  100. X          else
  101. X            fprintf(pipefd," %s", buffer);
  102. X
  103. X        fprintf(pipefd, "\n-- End of filtered message --\n");
  104. X        fclose(pipefd);
  105. X        fclose(tempfd);
  106. X    
  107. X        return;        /* YEAH!  Wot a slick program, eh? */
  108. X      
  109. X      }
  110. X      
  111. X      /** else it is to the current user... **/
  112. X
  113. X      sprintf(mailbox,  "%s%s", mailhome, username);
  114. X      sprintf(lockfile,  "%s%s.lock", mailhome, username);
  115. X
  116. X      while ((ret=creat(lockfile, 0777)) < 0  && attempts++ < 10) 
  117. X        sleep(2);    /* wait two seconds, okay?? */
  118. X
  119. X      if (ret < 0) {
  120. X        fprintf(stderr, "%sfilter (%s): Couldn't create lockfile %s\n",
  121. X            BEEP, username, lockfile);
  122. X        strcpy(mailbox,"[due to lock not being allowed]");
  123. X        /* doing that copy will make sure the next 'open' fails... */
  124. X      }
  125. X
  126. X      if (mailbox[0] == '[' || (mailfd=fopen(mailbox,"a")) == NULL) {
  127. X
  128. X        fprintf(stderr, "%sfilter (%s): Can't open mailbox %s!\n",
  129. X            BEEP, username, mailbox);
  130. X
  131. X        sprintf(mailbox, "%s/%s", home, EMERGENCY_MAILBOX);
  132. X        if ((mailfd=fopen(mailbox, "a")) == NULL) {
  133. X          fprintf(stderr,"%sfilter (%s): Can't open %s either!!\n",
  134. X              BEEP, username, mailbox);
  135. X
  136. X          sprintf(mailbox,"%s/%s", home, EMERG_MBOX); 
  137. X          if ((mailfd = fopen(mailbox, "a")) == NULL) {
  138. X             fprintf(stderr,"%sfilter (%s): Can't open %s either!!!!\n",
  139. X              BEEP, username, mailbox);
  140. X             fprintf(stderr, 
  141. X                 "%sfilter (%s): I can't open ANY mailboxes!  Augh!!\n",
  142. X             BEEP, username);
  143. X             fclose(tempfd);
  144. X         unlink(lockfile);
  145. X             leave("Cannot open any mailbox");    /* DIE DIE DIE DIE!! */
  146. X          }
  147. X          else
  148. X            fprintf(stderr,"%sfilter (%s): Using %s as emergency mailbox\n",
  149. X            BEEP, username, mailbox);
  150. X        }
  151. X        else
  152. X          fprintf(stderr,"%sfilter (%s): Using %s as emergency mailbox\n",
  153. X              BEEP, username, mailbox);
  154. X      }
  155. X
  156. X      while (fgets(buffer, sizeof(buffer), tempfd) != NULL) {
  157. X        line_count++;
  158. X        if (the_same(buffer, "From ") && line_count > 1)
  159. X          fprintf(mailfd, ">%s", buffer);
  160. X        else
  161. X          fputs(buffer, mailfd);
  162. X      }
  163. X
  164. X      fclose(mailfd);
  165. X      unlink(lockfile);    /* blamo! */
  166. X      fclose(tempfd);
  167. X    }
  168. X}
  169. X
  170. Xsave_message(foldername)
  171. Xchar *foldername;
  172. X{
  173. X    /** Save the message in a folder.  Use full file buffering to
  174. X        make this work without contention problems **/
  175. X
  176. X    FILE  *fd, *tempfd;
  177. X    char  filename[SLEN], buffer[LONG_SLEN];
  178. X
  179. X    if (verbose)
  180. X      printf("%sfilter (%s): Message saved in folder %s\n", 
  181. X          BEEP, username, foldername);
  182. X    
  183. X    if (!show_only) {
  184. X      sprintf(filename, "%s.%d", filter_temp, getpid());
  185. X
  186. X      if ((fd = fopen(foldername, "a")) == NULL) {
  187. X        fprintf(stderr, 
  188. X         "%sfilter (%s): can't save message to requested folder %s!\n",
  189. X            BEEP, username, foldername);
  190. X        return(1);
  191. X      }
  192. X
  193. X      if ((tempfd = fopen(filename, "r")) == NULL) {
  194. X         fprintf(stderr, 
  195. X             "%sfilter (%s): can't open temp file for reading!\n",
  196. X             BEEP, username);
  197. X         return(1);
  198. X      }
  199. X
  200. X      while (fgets(buffer, sizeof(buffer), tempfd) != NULL)
  201. X        fputs(buffer, fd);
  202. X    
  203. X      fclose(fd);
  204. X      fclose(tempfd);
  205. X    }
  206. X
  207. X     return(0);
  208. X}
  209. X
  210. Xexecute(command)
  211. Xchar *command;
  212. X{
  213. X    /** execute the indicated command, feeding as standard input the
  214. X        message we have.
  215. X    **/
  216. X
  217. X    char buffer[LONG_SLEN];
  218. X
  219. X    if (verbose)
  220. X      printf("%sfilter (%s): Executing %s\n", 
  221. X          BEEP, username, command);
  222. X
  223. X    if (! show_only) {
  224. X      sprintf(buffer, "%s %s.%d | %s", cat, filter_temp, getpid(), command);
  225. X      system(buffer);
  226. X    }
  227. X}
  228. END_OF_filter/actions.c
  229. if test 5857 -ne `wc -c <filter/actions.c`; then
  230.     echo shar: \"filter/actions.c\" unpacked with wrong size!?
  231. fi
  232. # end of overwriting check
  233. fi
  234. echo shar: Extracting \"filter/rules.c\" \(6383 characters\)
  235. if test -f filter/rules.c ; then 
  236.   echo shar: Will not over-write existing file \"filter/rules.c\"
  237. else
  238. sed "s/^X//" >filter/rules.c <<'END_OF_filter/rules.c'
  239. X/**            rules.c            **/
  240. X
  241. X/** This file contains all the rule routines, including those that apply the
  242. X    specified rules and the routine to print the rules out.
  243. X
  244. X    (C) Copyright 1986, Dave Taylor
  245. X**/
  246. X
  247. X#include <stdio.h>
  248. X#include <pwd.h>
  249. X#include <ctype.h>
  250. X#ifdef BSD
  251. X# include <sys/time.h>
  252. X#else
  253. X# include <time.h>
  254. X#endif
  255. X#include <fcntl.h>
  256. X
  257. X#include "defs.h"
  258. X#include "filter.h"
  259. X
  260. Xint
  261. Xaction_from_ruleset()
  262. X{
  263. X    /** Given the set of rules we've read in and the current to, from, 
  264. X        and subject, try to match one.  Return the ACTION of the match
  265. X            or LEAVE if none found that apply.
  266. X    **/
  267. X
  268. X    register int index = 0, not, relation, try_next_rule, x;
  269. X    struct condition_rec *cond;
  270. X
  271. X    while (index < total_rules) {
  272. X      cond = rules[index].condition;
  273. X      try_next_rule = 0;
  274. X
  275. X      while (cond != NULL && ! try_next_rule) {
  276. X        
  277. X        not = (cond->relation < 0);
  278. X        relation = abs(cond->relation);
  279. X    
  280. X        switch (cond->matchwhat) {
  281. X
  282. X          case TO     : x = contains(to, cond->argument1);         break;
  283. X          case FROM   : x = contains(from, cond->argument1);     break;
  284. X          case SUBJECT: x = contains(subject, cond->argument1);    break;
  285. X          case LINES  : x = compare(lines, relation, cond->argument1);break;
  286. X               
  287. X          case CONTAINS: fprintf(stderr,
  288. X       "%sfilter (%s): Error: rules based on 'contains' are not implemented!\n",
  289. X                 BEEP, username);
  290. X                 exit(0);
  291. X        }
  292. X
  293. X        if ((not && x) || ((! not) && (! x))) /* this test failed (LISP?) */
  294. X          try_next_rule++;
  295. X        else
  296. X          cond = cond->next;          /* next condition, if any?  */
  297. X      }
  298. X
  299. X      if (! try_next_rule) {
  300. X        rule_choosen = index;
  301. X         return(rules[rule_choosen].action);
  302. X      }
  303. X      index++;
  304. X    }
  305. X
  306. X    rule_choosen = -1;
  307. X    return(LEAVE);
  308. X}
  309. X
  310. X#define get_the_time()    if (!gotten_time) {           \
  311. X               thetime = time( (long *) 0);   \
  312. X               timerec = localtime(&thetime); \
  313. X               gotten_time++;           \
  314. X            }
  315. X
  316. Xexpand_macros(word, buffer, line)
  317. Xchar *word, *buffer;
  318. Xint  line;
  319. X{
  320. X    /** expand the allowable macros in the word;
  321. X        %d    = day of the month  
  322. X        %D    = day of the week  
  323. X            %h    = hour (0-23)     
  324. X        %m    = month of the year
  325. X        %r    = return address of sender
  326. X           %s    = subject of message
  327. X           %S    = "Re: subject of message"  (only add Re: if not there)
  328. X        %t    = hour:minute     
  329. X        %y    = year          
  330. X        or simply copies word into buffer.
  331. X    **/
  332. X
  333. X    struct tm *localtime(), *timerec;
  334. X    long     time(), thetime;
  335. X    register int i, j=0, gotten_time = 0, reading_a_percent_sign = 0;
  336. X
  337. X    for (i = 0; i < strlen(word); i++) {
  338. X      if (reading_a_percent_sign) {
  339. X        reading_a_percent_sign = 0;
  340. X        switch (word[i]) {
  341. X
  342. X          case 'r' : buffer[j] = '\0';
  343. X             strcat(buffer, from);
  344. X                     j = strlen(buffer);
  345. X             break;
  346. X
  347. X          case 's' : buffer[j] = '\0';
  348. X             strcat(buffer, subject);
  349. X                     j = strlen(buffer);
  350. X             break;
  351. X
  352. X          case 'S' : buffer[j] = '\0';
  353. X             if (! the_same(subject, "Re:")) 
  354. X               strcat(buffer, subject);
  355. X             strcat(buffer, subject);
  356. X                     j = strlen(buffer);
  357. X             break;
  358. X
  359. X          case 'd' : get_the_time(); buffer[j] = '\0';
  360. X             strcat(buffer, itoa(timerec->tm_mday,FALSE));
  361. X                     j = strlen(buffer);
  362. X             break;
  363. X
  364. X          case 'D' : get_the_time(); buffer[j] = '\0';
  365. X             strcat(buffer, itoa(timerec->tm_wday,FALSE));
  366. X                     j = strlen(buffer);
  367. X             break;
  368. X
  369. X          case 'm' : get_the_time(); buffer[j] = '\0';
  370. X             strcat(buffer, itoa(timerec->tm_mon,FALSE));
  371. X                     j = strlen(buffer);
  372. X             break;
  373. X
  374. X          case 'y' : get_the_time(); buffer[j] = '\0';
  375. X             strcat(buffer, itoa(timerec->tm_year,FALSE));
  376. X                     j = strlen(buffer);
  377. X             break;
  378. X
  379. X          case 'h' : get_the_time(); buffer[j] = '\0';
  380. X             strcat(buffer, itoa(timerec->tm_hour,FALSE));
  381. X                     j = strlen(buffer);
  382. X             break;
  383. X
  384. X          case 't' : get_the_time(); buffer[j] = '\0';
  385. X             strcat(buffer, itoa(timerec->tm_hour,FALSE));
  386. X             strcat(buffer, ":");
  387. X             strcat(buffer, itoa(timerec->tm_min,TRUE));
  388. X                     j = strlen(buffer);
  389. X             break;
  390. X
  391. X          default  : fprintf(stderr,
  392. X   "%sfilter (%s): Error on line %d translating %%%c macro in word \"%s\"!\n",
  393. X                     BEEP, username, line, word[i], word);
  394. X             exit(1);
  395. X        }
  396. X      }
  397. X      else if (word[i] == '%') 
  398. X        reading_a_percent_sign++;
  399. X      else 
  400. X        buffer[j++] = word[i];
  401. X    }
  402. X    buffer[j] = '\0';
  403. X}
  404. X
  405. Xprint_rules()
  406. X{
  407. X    /** print the rules out.  A double check, of course! **/
  408. X
  409. X    register int i = -1;
  410. X    char     *whatname(), *actionname();
  411. X    struct   condition_rec *cond;
  412. X
  413. X    while (++i < total_rules) {
  414. X      printf("\nRule %d:  if (", i+1);
  415. X
  416. X      cond = rules[i].condition;
  417. X
  418. X      while (cond != NULL) {
  419. X        if (cond->relation < 0)
  420. X          printf("not %s %s %s%s%s", 
  421. X              whatname(cond->matchwhat),
  422. X              relationname(- (cond->relation)),
  423. X              quoteit(cond->matchwhat),
  424. X              cond->argument1,
  425. X              quoteit(cond->matchwhat));
  426. X        else
  427. X          printf("%s %s %s%s%s",
  428. X              whatname(cond->matchwhat),
  429. X              relationname(cond->relation),
  430. X              quoteit(cond->matchwhat),
  431. X              cond->argument1,
  432. X              quoteit(cond->matchwhat));
  433. X
  434. X        cond = cond->next;
  435. X
  436. X        if (cond != NULL) printf(" and ");
  437. X      }
  438. X        
  439. X      printf(") then\n\t  %s %s\n", 
  440. X         actionname(rules[i].action), 
  441. X         rules[i].argument2);
  442. X    }
  443. X    printf("\n");
  444. X}
  445. X
  446. Xchar *whatname(n)
  447. Xint n;
  448. X{
  449. X    static char buffer[10];
  450. X
  451. X    switch(n) {
  452. X      case FROM   : return("from");
  453. X      case TO     : return("to");
  454. X      case SUBJECT: return("subject");
  455. X      case LINES  : return ("lines");
  456. X      case CONTAINS: return("contains");
  457. X      default     : sprintf(buffer, "?%d?", n); return((char *)buffer);
  458. X    }
  459. X}
  460. X
  461. Xchar *actionname(n)
  462. Xint n;
  463. X{
  464. X    switch(n) {
  465. X      case DELETE  : return("Delete");
  466. X      case SAVE    : return("Save");
  467. X      case SAVECC  : return("Copy and Save");
  468. X      case FORWARD : return("Forward");
  469. X      case LEAVE   : return("Leave"); 
  470. X      case EXEC    : return("Execute");
  471. X      default      : return("?action?");
  472. X    }
  473. X}
  474. X
  475. Xint
  476. Xcompare(line, relop, arg)
  477. Xint line, relop;
  478. Xchar *arg;
  479. X{
  480. X    /** Given the actual number of lines in the message, the relop
  481. X        relation, and the number of lines in the rule, as a string (!),
  482. X           return TRUE or FALSE according to which is correct.
  483. X    **/
  484. X
  485. X    int rule_lines;
  486. X
  487. X    rule_lines = atoi(arg);
  488. X
  489. X    switch (relop) {
  490. X      case LE: return(line <= rule_lines);
  491. X      case LT: return(line <  rule_lines);
  492. X      case GE: return(line >= rule_lines);
  493. X      case GT: return(line >  rule_lines);
  494. X      case NE: return(line != rule_lines);
  495. X      case EQ: return(line == rule_lines);
  496. X    }
  497. X    return(-1);
  498. X}
  499. END_OF_filter/rules.c
  500. if test 6383 -ne `wc -c <filter/rules.c`; then
  501.     echo shar: \"filter/rules.c\" unpacked with wrong size!?
  502. fi
  503. # end of overwriting check
  504. fi
  505. echo shar: Extracting \"hdrs/elm.h\" \(5581 characters\)
  506. if test -f hdrs/elm.h ; then 
  507.   echo shar: Will not over-write existing file \"hdrs/elm.h\"
  508. else
  509. sed "s/^X//" >hdrs/elm.h <<'END_OF_hdrs/elm.h'
  510. X/**            elm.h                **/
  511. X
  512. X/**  Main header file for ELM mail system.  **/
  513. X
  514. X/**  (C) Copyright 1986, Dave Taylor   **/
  515. X
  516. X#include <stdio.h>
  517. X#include <fcntl.h>
  518. X
  519. X#include "../hdrs/curses.h"
  520. X#include "../hdrs/defs.h"
  521. X
  522. X/******** static character string containing the version number  *******/
  523. X
  524. Xstatic char ident[] = { WHAT_STRING };
  525. X
  526. X/******** and another string for the copyright notice            ********/
  527. X
  528. Xstatic char copyright[] = { "@(#)          (C) Copyright 1986, Dave Taylor" };
  529. X
  530. X/******** global variables accessable by all pieces of the program *******/
  531. X
  532. Xint current = 0;        /* current message number  */
  533. Xint header_page = 0;         /* current header page     */
  534. Xint last_header_page = -1;         /* last header page        */
  535. Xint message_count = 0;        /* max message number      */
  536. Xint headers_per_page;        /* number of headers/page  */
  537. Xchar infile[SLEN];        /* name of current mailbox */
  538. Xchar hostname[SLEN];        /* name of machine we're on*/
  539. Xchar username[SLEN];        /* return address name!    */
  540. Xchar full_username[SLEN];    /* Full username - gecos   */
  541. Xchar home[SLEN];        /* home directory of user  */
  542. Xchar folders[SLEN];        /* folder home directory   */
  543. Xchar mailbox[SLEN];        /* mailbox name if defined */
  544. Xchar editor[SLEN];        /* editor for outgoing mail*/
  545. Xchar alternative_editor[SLEN];    /* alternative editor...   */
  546. Xchar printout[SLEN];        /* how to print messages   */
  547. Xchar savefile[SLEN];        /* name of file to save to */
  548. Xchar calendar_file[SLEN];    /* name of file for clndr  */
  549. Xchar prefixchars[SLEN];        /* prefix char(s) for msgs */
  550. Xchar shell[SLEN];        /* current system shell    */
  551. Xchar pager[SLEN];        /* what pager to use       */
  552. Xchar batch_subject[SLEN];    /* subject buffer for batchmail */
  553. Xchar local_signature[SLEN];    /* local msg signature file     */
  554. Xchar remote_signature[SLEN];    /* remote msg signature file    */
  555. X
  556. Xchar backspace,            /* the current backspace char */
  557. X     kill_line;            /* the current kill-line char */
  558. X
  559. Xchar up[SHORT], down[SHORT];    /* cursor control seq's    */
  560. Xint  cursor_control = FALSE;    /* cursor control avail?   */
  561. X
  562. Xchar start_highlight[SHORT],
  563. X     end_highlight[SHORT];    /* stand out mode...       */
  564. X
  565. Xint  has_highlighting = FALSE;    /* highlighting available? */
  566. X
  567. Xchar *weedlist[MAX_IN_WEEDLIST];
  568. Xint  weedcount;
  569. X
  570. Xint allow_forms = NO;        /* flag: are AT&T Mail forms okay?  */
  571. Xint file_changed = 0;        /* flag: true if infile changed     */
  572. Xint mini_menu = 1;        /* flag: menu specified?        */
  573. Xint mbox_specified = 0;        /* flag: specified alternate mbox?  */
  574. Xint check_first = 1;        /* flag: verify mail to be sent!    */
  575. Xint auto_copy = 0;        /* flag: automatically copy source? */
  576. Xint filter = 1;            /* flag: weed out header lines?        */
  577. Xint resolve_mode = 1;        /* flag: delete saved mail?        */
  578. Xint auto_cc = 0;        /* flag: mail copy to user?        */
  579. Xint noheader = 1;        /* flag: copy + header to file?     */
  580. Xint title_messages = 1;        /* flag: title message display?     */
  581. Xint edit_outbound = 0;        /* flag: edit outbound headers?        */
  582. Xint hp_terminal = 0;        /* flag: are we on HP term?        */
  583. Xint hp_softkeys = 0;        /* flag: are there softkeys?        */
  584. Xint save_by_name = 1;        /* flag: save mail by login name?   */
  585. Xint mail_only = 0;        /* flag: send mail then leave?      */
  586. Xint check_only = 0;        /* flag: check aliases then leave?  */
  587. Xint move_when_paged = 0;    /* flag: move when '+' or '-' used? */
  588. Xint point_to_new = 1;        /* flag: start pointing at new msg? */
  589. Xint bounceback = 0;        /* flag: bounce copy off remote?    */
  590. Xint signature = 0;        /* flag: include $home/.signature?  */
  591. Xint always_leave = 0;        /* flag: always leave msgs pending? */
  592. Xint always_del = 0;        /* flag: always delete marked msgs? */
  593. Xint arrow_cursor = 0;        /* flag: use "->" cursor regardless?*/
  594. Xint debug = 0;             /* flag: default is no debug!       */
  595. Xint read_in_aliases = 0;    /* flag: have we read in aliases??  */
  596. Xint warnings = 1;        /* flag: output connection warnings?*/
  597. Xint user_level = 0;        /* flag: how good is the user?      */
  598. Xint selected = 0;        /* flag: used for select stuff      */
  599. Xint names_only = 1;        /* flag: display user names only?   */
  600. Xint question_me = 1;        /* flag: ask questions as we leave? */
  601. Xint keep_empty_files = 0;    /* flag: leave empty mailbox files? */
  602. X
  603. X#ifdef UTS
  604. X int isatube = 0;        /* flag: are we on an IBM 3270?     */
  605. X#endif
  606. X
  607. Xint sortby = REVERSE SENT_DATE;    /* how to sort incoming mail...     */
  608. X
  609. Xlong timeout = 600L;        /* timeout (secs) on main prompt    */
  610. X
  611. Xint mailbox_defined = 0;    /** mailbox specified?    **/
  612. X
  613. X/** set up some default values for a 'typical' terminal *snicker* **/
  614. X
  615. Xint LINES=23;            /** lines per screen      **/
  616. Xint COLUMNS=80;            /** columns per page      **/
  617. X
  618. Xlong size_of_pathfd;        /** size of pathfile, 0 if none **/
  619. X
  620. XFILE *mailfile;            /* current mailbox file     */
  621. XFILE *debugfile;        /* file for debug output    */
  622. XFILE *pathfd;            /* path alias file          */
  623. XFILE *domainfd;            /* domain file            */
  624. X
  625. Xlong mailfile_size;        /* size of current mailfile */
  626. X
  627. Xint   max_headers;        /* number of headers allocated */
  628. X
  629. Xstruct header_rec *header_table;
  630. X
  631. Xstruct alias_rec user_hash_table[MAX_UALIASES];
  632. Xstruct alias_rec system_hash_table[MAX_SALIASES];
  633. X
  634. Xstruct date_rec last_read_mail; /* last time we read mailbox  */
  635. X
  636. Xstruct lsys_rec *talk_to_sys;   /* what machines do we talk to? */
  637. X
  638. Xstruct addr_rec *alternative_addresses;    /* how else do we get mail? */
  639. X
  640. Xint system_files = 0;        /* do we have system aliases? */
  641. Xint user_files = 0;        /* do we have user aliases?   */
  642. X
  643. Xint system_data;        /* fileno of system data file */
  644. Xint user_data;            /* fileno of user data file   */
  645. X
  646. Xint userid;            /* uid for current user          */
  647. Xint groupid;            /* groupid for current user   */
  648. END_OF_hdrs/elm.h
  649. if test 5581 -ne `wc -c <hdrs/elm.h`; then
  650.     echo shar: \"hdrs/elm.h\" unpacked with wrong size!?
  651. fi
  652. # end of overwriting check
  653. fi
  654. echo shar: Extracting \"hdrs/headers.h\" \(5735 characters\)
  655. if test -f hdrs/headers.h ; then 
  656.   echo shar: Will not over-write existing file \"hdrs/headers.h\"
  657. else
  658. sed "s/^X//" >hdrs/headers.h <<'END_OF_hdrs/headers.h'
  659. X/**        headers.h        **/
  660. X
  661. X/**  header file for ELM mail system.  **/
  662. X
  663. X/**  (C) Copyright 1985, Dave Taylor   **/
  664. X
  665. X#include <stdio.h>
  666. X#include <fcntl.h>
  667. X
  668. X#include "curses.h"
  669. X#include "defs.h"
  670. X
  671. X/******** global variables accessable by all pieces of the program *******/
  672. X
  673. Xextern int current;        /* current message number  */
  674. Xextern int header_page;         /* current header page     */
  675. Xextern int last_header_page;    /* last header page        */
  676. Xextern int message_count;    /* max message number      */
  677. Xextern int headers_per_page;    /* number of headers/page  */
  678. Xextern char infile[SLEN];    /* name of current mailbox */
  679. Xextern char hostname[SLEN];    /* name of machine we're on*/
  680. Xextern char username[SLEN];    /* return address name!    */
  681. Xextern char full_username[SLEN];/* Full username - gecos   */
  682. Xextern char home[SLEN];        /* home directory of user  */
  683. Xextern char folders[SLEN];    /* folder home directory   */
  684. Xextern char mailbox[SLEN];    /* mailbox name if defined */
  685. Xextern char editor[SLEN];    /* default editor for mail */
  686. Xextern char alternative_editor[SLEN];/* the 'other' editor */
  687. Xextern char printout[SLEN];    /* how to print messages   */
  688. Xextern char savefile[SLEN];    /* name of file to save to */
  689. Xextern char calendar_file[SLEN];/* name of file for clndr  */
  690. Xextern char prefixchars[SLEN];    /* prefix char(s) for msgs */
  691. Xextern char shell[SLEN];    /* default system shell    */
  692. Xextern char pager[SLEN];    /* what pager to use...    */
  693. Xextern char batch_subject[SLEN];/* subject buffer for batchmail */
  694. Xextern char local_signature[SLEN];/* local msg signature file   */
  695. Xextern char remote_signature[SLEN];/* remote msg signature file */
  696. X
  697. Xextern char backspace,        /* the current backspace char  */
  698. X        kill_line;        /* the current kill_line char  */
  699. X
  700. Xextern char up[SHORT], 
  701. X        down[SHORT];    /* cursor control seq's    */
  702. Xextern int  cursor_control;    /* cursor control avail?   */
  703. X
  704. Xextern char start_highlight[SHORT],
  705. X        end_highlight[SHORT];  /* standout mode... */
  706. X
  707. Xextern int  has_highlighting;    /* highlighting available? */
  708. X
  709. X/** the following two are for arbitrary weedout lists.. **/
  710. X
  711. Xextern char *weedlist[MAX_IN_WEEDLIST];
  712. Xextern int  weedcount;        /* how many headers to check?        */
  713. X
  714. Xextern int  allow_forms;    /* flag: are AT&T Mail forms okay?    */
  715. Xextern int  file_changed;    /* flag: true iff infile changed      */
  716. Xextern int  mini_menu;        /* flag: display menu?               */
  717. Xextern int  mbox_specified;     /* flag: specified alternate mailbox? */
  718. Xextern int  check_first;    /* flag: verify mail to be sent!      */
  719. Xextern int  auto_copy;        /* flag: auto copy source into reply? */
  720. Xextern int  filter;        /* flag: weed out header lines?          */
  721. Xextern int  resolve_mode;    /* flag: resolve before moving mode?  */
  722. Xextern int  auto_cc;        /* flag: mail copy to yourself?       */
  723. Xextern int  noheader;        /* flag: copy + header to file?       */
  724. Xextern int  title_messages;    /* flag: title message display?       */
  725. Xextern int  edit_outbound;    /* flag: edit outbound headers?       */
  726. Xextern int  hp_terminal;    /* flag: are we on an hp terminal?    */
  727. Xextern int  hp_softkeys;    /* flag: are there softkeys?          */
  728. Xextern int  save_by_name;      /* flag: save mail by login name?     */
  729. Xextern int  mail_only;        /* flag: send mail then leave?        */
  730. Xextern int  check_only;        /* flag: check aliases and leave?     */
  731. Xextern int  move_when_paged;    /* flag: move when '+' or '-' used?   */
  732. Xextern int  point_to_new;    /* flag: start pointing at new msgs?  */
  733. Xextern int  bounceback;        /* flag: bounce copy off remote?      */
  734. Xextern int  signature;        /* flag: include $home/.signature?    */
  735. Xextern int  always_leave;    /* flag: always leave mail pending?   */
  736. Xextern int  always_del;        /* flag: always delete marked msgs?   */
  737. Xextern int  arrow_cursor;    /* flag: use "->" regardless?          */
  738. Xextern int  debug;        /* flag: debugging mode on?           */
  739. Xextern int  read_in_aliases;    /* flag: have we read in aliases yet? */
  740. Xextern int  warnings;        /* flag: output connection warnings?  */
  741. Xextern int  user_level;        /* flag: how knowledgable is user?    */
  742. Xextern int  selected;        /* flag: used for select stuff        */
  743. Xextern int  names_only;        /* flag: display names but no addrs?  */
  744. Xextern int  question_me;    /* flag: ask questions as we leave?   */
  745. Xextern int  keep_empty_files;    /* flag: keep empty files??          */
  746. X
  747. X#ifdef UTS
  748. Xextern int  isatube;        /* flag: are we on an IBM 3270 tube?  */
  749. X#endif
  750. X
  751. Xextern int  sortby;        /* how to sort mailboxes          */
  752. X
  753. Xextern long timeout;        /* seconds for main level timeout     */
  754. X
  755. Xextern int mailbox_defined;    /** specified mailbox?  **/
  756. X
  757. Xextern int LINES;        /** lines per screen    **/
  758. Xextern int COLUMNS;        /** columns per line    **/
  759. X
  760. Xextern long size_of_pathfd;    /** size of pathfile, 0 if none **/
  761. X
  762. Xextern FILE *mailfile;        /* current mailbox file     */
  763. Xextern FILE *debugfile;        /* file for debut output    */
  764. Xextern FILE *pathfd;        /* path alias file          */
  765. Xextern FILE *domainfd;        /* domains file         */
  766. X
  767. Xextern long mailfile_size;    /* size of current mailfile */
  768. X
  769. Xextern int  max_headers;    /* number of headers currently allocated */
  770. X
  771. Xextern struct header_rec *header_table;
  772. X
  773. Xextern struct alias_rec user_hash_table  [MAX_UALIASES];
  774. Xextern struct alias_rec system_hash_table[MAX_SALIASES];
  775. X
  776. Xextern struct date_rec last_read_mail;
  777. X
  778. Xextern struct lsys_rec *talk_to_sys;    /* who do we talk to? */
  779. X
  780. Xextern struct addr_rec *alternative_addresses;    /* how else do we get mail? */
  781. X
  782. Xextern int system_files;    /* do we have system aliases? */
  783. Xextern int user_files;        /* do we have user aliases?   */
  784. X
  785. Xextern int system_data;        /* fileno of system data file */
  786. Xextern int user_data;        /* fileno of user data file   */
  787. X
  788. Xextern int userid;        /* uid for current user          */
  789. Xextern int groupid;        /* groupid for current user   */
  790. END_OF_hdrs/headers.h
  791. if test 5735 -ne `wc -c <hdrs/headers.h`; then
  792.     echo shar: \"hdrs/headers.h\" unpacked with wrong size!?
  793. fi
  794. # end of overwriting check
  795. fi
  796. echo shar: Extracting \"src/calendar.c\" \(5495 characters\)
  797. if test -f src/calendar.c ; then 
  798.   echo shar: Will not over-write existing file \"src/calendar.c\"
  799. else
  800. sed "s/^X//" >src/calendar.c <<'END_OF_src/calendar.c'
  801. X/**            calendar.c        **/
  802. X
  803. X/** This routine implements a rather snazzy idea suggested by Warren
  804. X    Carithers of the Rochester Institute of Technology that allows
  805. X    mail to contain entries formatted in a manner that will allow direct
  806. X    copying into a users calendar program.
  807. X
  808. X    Never able to leave good-enough alone, I've extended this idea to a
  809. X    further one - the knowledge of a different type of calendar program
  810. X    too.  Specifically, the current message can contain either of;
  811. X
  812. X    -> Mon 04/21 1:00p meet with chairman candidate
  813. X
  814. X    or 
  815. X
  816. X    - >April 21
  817. X    -   
  818. X    -     1:00 pm: Meet with Chairman Candidate
  819. X    -
  820. X
  821. X    The first type will have the leading '->' removed and all subsequent
  822. X    white space, creating a simple one-line entry in the users calendar
  823. X    file.   The second type will remove the '-' and the leading white
  824. X    spaces and leave everything else intact (that is, the file in the
  825. X    second example would be appended with ">April 21" followed by a
  826. X    blank line, the 1:00 pm meeting info, and another blank line.
  827. X    
  828. X    The file to include this in is either the default as defined in the
  829. X    sysdefs.h file (see CALENDAR_FILE) or a filename contained in the
  830. X    users ".elmrc" file, "calendar= <filename>".
  831. X
  832. X    (C) Copyright 1986 Dave Taylor
  833. X**/
  834. X
  835. X#include "headers.h"
  836. X
  837. X#ifdef ENABLE_CALENDAR        /* if not defined, this will be an empty file */
  838. X
  839. X#include <errno.h>
  840. X
  841. Xextern int errno;
  842. X
  843. Xchar *error_name(), *error_description(), *strcpy();
  844. X
  845. Xscan_calendar()
  846. X{
  847. X    FILE *calendar;
  848. X    int  count;
  849. X
  850. X    /* First step is to open the celendar file for appending... **/
  851. X
  852. X    if (can_open(calendar_file, "a") != 0) {
  853. X      dprint1(2, "Error: wrong permissions to append to calendar %s\n",
  854. X          calendar_file);
  855. X      dprint2(2, "** %s - %s **\n",
  856. X          error_name(errno), error_description(errno));
  857. X      error1("Not able to append to file %s!", calendar_file);
  858. X      return; 
  859. X    }
  860. X
  861. X    if ((calendar = fopen(calendar_file,"a")) == NULL) {
  862. X      dprint1(2, "Error: couldn't append to calendar file %s (save)\n", 
  863. X           calendar_file);
  864. X      dprint2(2, "** %s - %s **\n",
  865. X          error_name(errno), error_description(errno));
  866. X      error1("Couldn't append to file %s!", calendar_file);
  867. X      return; 
  868. X    }
  869. X    
  870. X    count = extract_info(calendar);
  871. X
  872. X    fclose(calendar);
  873. X
  874. X    chown(calendar_file, userid, groupid);    /* ensure owned by user */
  875. X
  876. X    if (count > 0)
  877. X      error2("%d entr%s saved in calendar file", 
  878. X         count, count > 1 ? "ies" : "y");
  879. X    else 
  880. X      error("No calendar entries found in that message");
  881. X
  882. X    return;
  883. X}
  884. X
  885. Xint
  886. Xextract_info(save_to_fd)
  887. XFILE *save_to_fd;
  888. X{
  889. X    /** Save the relevant parts of the current message to the given
  890. X        calendar file.  The only parameter is an opened file
  891. X        descriptor, positioned at the end of the existing file **/
  892. X        
  893. X    register int entries = 0, ok = 1, lines, index, in_entry = FALSE;
  894. X    char buffer[SLEN];
  895. X
  896. X        /** get to the first line of the message desired **/
  897. X
  898. X        if (fseek(mailfile, header_table[current-1].offset, 0) == -1) {
  899. X             dprint2(1,"ERROR: Attempt to seek %d bytes into file failed (%s)",
  900. X        header_table[current-1].offset, "extract_info");
  901. X             error1("ELM [seek] failed trying to read %d bytes into file",
  902. X             header_table[current-1].offset);
  903. X             return(0);
  904. X        }
  905. X
  906. X        /* how many lines in message? */
  907. X
  908. X        lines = header_table[current-1].lines;
  909. X
  910. X        /* now while not EOF & still in message... scan it! */
  911. X
  912. X        while (ok && lines--) {
  913. X          ok = (int) (fgets(buffer, LONG_SLEN, mailfile) != NULL);
  914. X      
  915. X      /* now let's see if it matches the basic pattern... */
  916. X
  917. X      if ((index = calendar_line(buffer)) > -1) {
  918. X
  919. X        if (buffer[index] == '>') {    /* single line entry */
  920. X          if (remove_through_ch(buffer, '>')) {
  921. X            fprintf(save_to_fd,"%s", buffer);
  922. X            entries++;
  923. X          }
  924. X        }
  925. X        else {                /* multi-line entry  */
  926. X            fprintf(save_to_fd, "%s", (char *) (buffer + index + 1));
  927. X            in_entry = TRUE;    
  928. X          }
  929. X           }
  930. X       else if (in_entry) {
  931. X         in_entry = FALSE;
  932. X         entries++;
  933. X       }
  934. X    }
  935. X
  936. X    dprint2(4,"Got %d calender entr%s.\n", entries, entries > 1? "ies":"y");
  937. X
  938. X    return(entries);
  939. X}
  940. X
  941. Xint
  942. Xcalendar_line(string)
  943. Xchar *string;
  944. X{
  945. X    /** Iff the input line is of the form;
  946. X
  947. X          {white space} <one or more '-'> 
  948. X    
  949. X        this routine will return the index of the NEXT character
  950. X        after the dashed sequence...If this pattern doesn't occur, 
  951. X        or if any other problems are encountered, it'll return "-1"
  952. X    **/
  953. X
  954. X    register int loc = 0;
  955. X
  956. X    if (chloc(string,'-') == -1)       /* no dash??? */
  957. X      return(-1);            /* that was easy! */
  958. X
  959. X    /** skip leading white space... **/
  960. X
  961. X    while (whitespace(string[loc])) loc++;       /* MUST have '-' too! */
  962. X
  963. X    if (string[loc] != '-')    return(-1);       /* nice try, sleazo! */
  964. X
  965. X    while (string[loc] == '-') loc++;
  966. X
  967. X    if (loc >= strlen(string)) return(-1);    /* Empty line... */
  968. X
  969. X    /* otherwise.... */  
  970. X
  971. X    return(loc);
  972. X}
  973. X    
  974. X
  975. Xint
  976. Xremove_through_ch(string, ch)
  977. Xchar *string;
  978. Xchar  ch;
  979. X{
  980. X    /** removes all characters from zero to ch in the string, and 
  981. X        any 'white-space' following the 'n'th char... if it hits a
  982. X            NULL string, it returns FALSE, otherwise it'll return TRUE!
  983. X    **/
  984. X
  985. X    char buffer[SLEN];
  986. X    register int index = 0, i = 0;
  987. X
  988. X    while (string[index] != ch && string[index] != '\0')
  989. X      index++;
  990. X    
  991. X    if (index >= strlen(string)) 
  992. X      return(FALSE);    /* crash! burn! */
  993. X
  994. X    index++;    /* get past the 'ch' character... */
  995. X
  996. X    while (whitespace(string[index])) index++;
  997. X
  998. X    while (index < strlen(string))
  999. X      buffer[i++] = string[index++];
  1000. X
  1001. X    buffer[i] = '\0';
  1002. X
  1003. X    strcpy(string, buffer);
  1004. X    
  1005. X    return(TRUE);
  1006. X}
  1007. X
  1008. X#endif
  1009. END_OF_src/calendar.c
  1010. if test 5495 -ne `wc -c <src/calendar.c`; then
  1011.     echo shar: \"src/calendar.c\" unpacked with wrong size!?
  1012. fi
  1013. # end of overwriting check
  1014. fi
  1015. echo shar: Extracting \"src/hdrconfg.c\" \(5434 characters\)
  1016. if test -f src/hdrconfg.c ; then 
  1017.   echo shar: Will not over-write existing file \"src/hdrconfg.c\"
  1018. else
  1019. sed "s/^X//" >src/hdrconfg.c <<'END_OF_src/hdrconfg.c'
  1020. X/**            hdrconfg.c            **/
  1021. X
  1022. X/**   This file contains the routines necessary to be able to modify
  1023. X      the mail headers of messages on the way off the machine.  The
  1024. X      headers currently supported for modification are:
  1025. X
  1026. X    Subject:
  1027. X    To:
  1028. X    Cc:
  1029. X    Bcc:
  1030. X    Reply-To:
  1031. X
  1032. X    Expiration-Date:
  1033. X    Priority:
  1034. X        In-Reply-To:
  1035. X    Action:
  1036. X
  1037. X    <user defined>
  1038. X    
  1039. X      (C) Copyright 1985, Dave Taylor
  1040. X**/
  1041. X
  1042. X#include <stdio.h>
  1043. X#include "headers.h"
  1044. X
  1045. X#include <ctype.h>
  1046. X
  1047. X#ifdef BSD
  1048. X#undef toupper
  1049. X#endif
  1050. X
  1051. X/* these are all defined in the mailmsg file! */
  1052. X
  1053. Xextern char subject[SLEN], action[SLEN], in_reply_to[SLEN], expires[SLEN], 
  1054. X            priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING], 
  1055. X        cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING], 
  1056. X        expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN];
  1057. X
  1058. X#ifdef ALLOW_BCC
  1059. Xextern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
  1060. X#endif
  1061. X
  1062. Xchar *strip_commas(), *strcpy();
  1063. X
  1064. Xedit_headers()
  1065. X{
  1066. X    /** Edit headers.  **/
  1067. X
  1068. X    int unexpanded_to = TRUE, unexpanded_cc = TRUE;
  1069. X#ifdef ALLOW_BCC
  1070. X    int unexpanded_bcc = TRUE;
  1071. X#endif
  1072. X    char c;
  1073. X    
  1074. X    if (mail_only) goto outta_here;        /* how did we get HERE??? */
  1075. X
  1076. X    display_headers();
  1077. X
  1078. X    while (TRUE) {    /* forever */
  1079. X      PutLine0(LINES-1,0,"Choice: ");
  1080. X      CleartoEOLN();
  1081. X      c = toupper(getchar());
  1082. X      clear_error();
  1083. X      switch (c) {
  1084. X        case RETURN:
  1085. X        case LINE_FEED:
  1086. X        case 'Q' : goto outta_here;
  1087. X        case ctrl('L') : display_headers();
  1088. X               break;
  1089. X        case 'T' : if (optionally_enter(to, 2, 5, TRUE) == -1)
  1090. X                     goto outta_here;
  1091. X                   build_address(strip_commas(to), expanded_to);
  1092. X               unexpanded_to = FALSE; 
  1093. X               break;
  1094. X        case 'S' : if (optionally_enter(subject, 7, 9, FALSE) == -1)
  1095. X             goto outta_here;
  1096. X               break;
  1097. X#ifdef ALLOW_BCC
  1098. X        case 'B' : if (optionally_enter(bcc, 4, 5, TRUE) == -1)
  1099. X             goto outta_here;
  1100. X                 build_address(strip_commas(bcc), expanded_bcc);
  1101. X               unexpanded_bcc = FALSE;
  1102. X               break;
  1103. X#endif
  1104. X        case 'C' : if (optionally_enter(cc, 3, 5, TRUE) == -1)
  1105. X             goto outta_here;
  1106. X                 build_address(strip_commas(cc), expanded_cc);
  1107. X               unexpanded_cc = FALSE;
  1108. X               break;
  1109. X        case 'R' : if (optionally_enter(reply_to, 5, 10, FALSE) == -1)
  1110. X             goto outta_here;
  1111. X               break;
  1112. X        case 'A' : if (optionally_enter(action, 9, 9, FALSE) == -1)
  1113. X             goto outta_here;
  1114. X               break;
  1115. X        case 'E' : enter_date(10, 17, expires);
  1116. X               break;
  1117. X        case 'P' : if (optionally_enter(priority, 11,10, FALSE) == -1)
  1118. X             goto outta_here;
  1119. X               break;
  1120. X        case 'U' : if (optionally_enter(user_defined_header,14,0,FALSE)==-1)
  1121. X             goto outta_here;
  1122. X               else
  1123. X                 check_user_header(user_defined_header);
  1124. X               break;
  1125. X        case 'I' : if (strlen(in_reply_to) > 0) {
  1126. X                     if (optionally_enter(in_reply_to, 12,13, FALSE) == -1)
  1127. X               goto outta_here;
  1128. X             break;        
  1129. X               }
  1130. X               /** else fall through as an error **/
  1131. X        default  : error("Unknown header being specified!");
  1132. X      }
  1133. X    } 
  1134. X
  1135. Xoutta_here:    /* this section re-expands aliases before we leave... */
  1136. X
  1137. X    if (unexpanded_to)
  1138. X      build_address(strip_commas(to), expanded_to);
  1139. X    if (unexpanded_cc)
  1140. X      build_address(strip_commas(cc), expanded_cc);
  1141. X#ifdef ALLOW_BCC
  1142. X    if (unexpanded_bcc)
  1143. X      build_address(strip_commas(bcc), expanded_bcc);
  1144. X#endif
  1145. X}
  1146. X
  1147. Xdisplay_headers()
  1148. X{
  1149. X    ClearScreen();
  1150. X
  1151. X    Centerline(0,"Message Header Edit Screen");
  1152. X
  1153. X    PutLine1(2,0,"To : %s", to);
  1154. X    PutLine1(3,0,"Cc : %s", cc); CleartoEOLN();
  1155. X#ifdef ALLOW_BCC
  1156. X    PutLine1(4,0,"Bcc: %s", bcc); CleartoEOLN();
  1157. X#endif
  1158. X    PutLine1(5,0,"Reply-To: %s", reply_to); CleartoEOS();
  1159. X
  1160. X    PutLine1(7,0,"Subject: %s", subject);
  1161. X    PutLine1(9,0,"Action : %s", action);
  1162. X    PutLine1(10,0,"Expiration-Date: %s", expires);
  1163. X    PutLine1(11,0,"Priority: %s", priority);
  1164. X    if (strlen(in_reply_to) > 0)
  1165. X      PutLine1(12,0,"In-Reply-To: %s", in_reply_to);
  1166. X
  1167. X    if (strlen(user_defined_header) > 0)
  1168. X      PutLine1(14,0, "%s", user_defined_header);
  1169. X
  1170. X    Centerline(LINES-5, 
  1171. X"Choose first letter of existing header, U)ser defined header, or <return>");
  1172. X}
  1173. X
  1174. Xenter_date(x, y, buffer)
  1175. Xint x, y;
  1176. Xchar *buffer;
  1177. X{
  1178. X    /** Enter the number of days this message is valid for, then
  1179. X        display at (x,y) the actual date of expiration.  This 
  1180. X        routine relies heavily on the routine 'days_ahead()' in
  1181. X        the file date.c
  1182. X    **/
  1183. X
  1184. X    int days;
  1185. X
  1186. X    PutLine0(LINES-1,0, "How many days in the future should it expire? ");
  1187. X    CleartoEOLN();
  1188. X    Raw(OFF);
  1189. X    gets(buffer);
  1190. X    Raw(ON);
  1191. X    sscanf(buffer, "%d", &days);
  1192. X    if (days < 1)
  1193. X      error("That doesn't make sense!");
  1194. X    else if (days > 14)
  1195. X      error("Expiration date must be within two weeks of today");
  1196. X    else {
  1197. X      days_ahead(days, buffer);
  1198. X      PutLine0(x, y, buffer);
  1199. X    }
  1200. X}
  1201. X
  1202. Xcheck_user_header(header)
  1203. Xchar *header;
  1204. X{
  1205. X    /** check the header format...if bad print error and erase! **/
  1206. X
  1207. X    register int i = -1;
  1208. X
  1209. X    if (strlen(header) == 0)
  1210. X       return;
  1211. X
  1212. X    if (whitespace(header[0])) {
  1213. X      error ("you can't have leading white space in a header!");
  1214. X      header[0] = '\0';
  1215. X      ClearLine(14);
  1216. X      return;
  1217. X    }
  1218. X
  1219. X    if (header[0] == ':') {
  1220. X      error ("you can't have a colon as the first character!");
  1221. X      header[0] = '\0';
  1222. X      ClearLine(14);
  1223. X      return;
  1224. X    }
  1225. X
  1226. X    while (header[++i] != ':') {
  1227. X      if (header[i] == '\0') {
  1228. X        error("you need a colon ending the field!");
  1229. X        header[0] = '\0';
  1230. X        ClearLine(14);
  1231. X        return;
  1232. X      }
  1233. X      else if (whitespace(header[i])) {
  1234. X        error("You can't have white space imbedded in the header name!");
  1235. X        header[0] = '\0';
  1236. X        ClearLine(14);
  1237. X        return;
  1238. X      }
  1239. X    }
  1240. X    
  1241. X    return;
  1242. X}
  1243. END_OF_src/hdrconfg.c
  1244. if test 5434 -ne `wc -c <src/hdrconfg.c`; then
  1245.     echo shar: \"src/hdrconfg.c\" unpacked with wrong size!?
  1246. fi
  1247. # end of overwriting check
  1248. fi
  1249. echo shar: Extracting \"src/help.c\" \(5969 characters\)
  1250. if test -f src/help.c ; then 
  1251.   echo shar: Will not over-write existing file \"src/help.c\"
  1252. else
  1253. sed "s/^X//" >src/help.c <<'END_OF_src/help.c'
  1254. X/**            help.c            **/
  1255. X
  1256. X/*** help routine for ELM program 
  1257. X
  1258. X     (C) Copyright 1985, Dave Taylor
  1259. X
  1260. X***/
  1261. X
  1262. X#include <ctype.h>
  1263. X
  1264. X#ifdef BSD
  1265. X# undef tolower
  1266. X#endif
  1267. X
  1268. X#include "headers.h"
  1269. X
  1270. Xhelp()
  1271. X{
  1272. X    /** Process the request for help [section] from the user **/
  1273. X
  1274. X    char ch;        /* character buffer for input */
  1275. X    char *s;        /* string pointer...          */
  1276. X
  1277. X    MoveCursor(LINES-7,0);
  1278. X    CleartoEOS();
  1279. X
  1280. X    Centerline(LINES-7, "ELM Help System");
  1281. X    Centerline(LINES-5,
  1282. X           "Press keys you want help for, '?' for a list, or '.' to end");
  1283. X
  1284. X    PutLine0(LINES-3, 0, "Help on key: ");
  1285. X
  1286. X    do {
  1287. X      MoveCursor(LINES-3, strlen("Help on key: "));
  1288. X      ch = tolower(ReadCh());
  1289. X      
  1290. X      if (ch == '.') return(0);    /* zero means footer rewrite only */
  1291. X
  1292. X      s = "Unknown command.  Use '?' for a list of commands...";
  1293. X
  1294. X      switch (ch) {
  1295. X
  1296. X        case '?': display_helpfile(MAIN_HELP);    return(1);
  1297. X
  1298. X        case '$': s =
  1299. X  "$ = Force a resync of the current mailbox.  This will 'purge' deleted mail";
  1300. X        break;
  1301. X
  1302. X        case '!': s = 
  1303. X   "! = Escape to the Unix shell of your choice, or just to enter commands";
  1304. X           break;
  1305. X        case '@': s = 
  1306. X       "@ = Debug - display a summary of the messages on the header page";
  1307. X           break;
  1308. X        case '|': s = 
  1309. X "| = Pipe the current message or tagged messages to the command specified";
  1310. X           break;
  1311. X        case '#': s = 
  1312. X      "# = Debug - display all information known about current message";
  1313. X          break;
  1314. X        case '%': s = 
  1315. X   "% = Debug - display the computed return address of the current message";
  1316. X           break;
  1317. X        case '*': s = "* = Go to the last message in the current mailbox";
  1318. X           break;
  1319. X        case '-': s = 
  1320. X           "- = Go to the previous page of messages in the current mailbox";
  1321. X           break;
  1322. X        case '=': s = 
  1323. X                  "'=' = Go to the first message in the current mailbox";
  1324. X           break;
  1325. X        case ' ': 
  1326. X        case '+': s = 
  1327. X        "+ = Go to the next page of messages in the current mailbox";
  1328. X           break;
  1329. X        case '/': s = "/ = Search for specified pattern in mailbox";
  1330. X           break;
  1331. X        case '<': s = 
  1332. X           "< = Scan current message for calendar entries (if enabled)";
  1333. X           break;
  1334. X        case '>': s = 
  1335. X           "> = Save current message or tagged messages to specified file";
  1336. X           break;
  1337. X        case '^': s = 
  1338. X           "^ = Toggle the Delete/Undelete status of the current message";
  1339. X           break;
  1340. X        case 'a': s = 
  1341. X       "a = Enter the alias sub-menu section.  Create and display aliases";
  1342. X           break;
  1343. X        case 'b': s = 
  1344. X    "b = Bounce (remail) a message to someone as if you have never seen it";
  1345. X           break;
  1346. X        case 'c': s = 
  1347. X       "c = Change mailboxes, leaving the current mailbox as if 'quitting'";
  1348. X           break;
  1349. X        case 'd': s = "d = Mark the current message for future deletion";
  1350. X           break;
  1351. X        case ctrl('D') :
  1352. X    s = "^D = Mark for deletion all messages with the specified pattern";
  1353. X        break;
  1354. X        case 'e': s = 
  1355. X       "e = Invoke the editor on the entire mailbox, resync'ing when done";
  1356. X           break;
  1357. X        case 'f': s = 
  1358. X      "f = Forward the current message to someone, return address is yours";
  1359. X           break;
  1360. X        case 'g': s = 
  1361. X "g = Group reply not only to the sender, but to everyone who received msg";
  1362. X           break;
  1363. X        case 'h': s = 
  1364. X           "h = Display message with all Headers (ignore weedout list)";
  1365. X           break;
  1366. X        case 'j': s = 
  1367. X       "j = Go to the next message.  This is the same as the DOWN arrow";
  1368. X           break;
  1369. X        case 'k': s = 
  1370. X       "k = Go to the previous message.  This is the same as the UP arrow";
  1371. X           break;
  1372. X        case 'm': s = 
  1373. X               "m = Create and send mail to the specified person or persons";
  1374. X           break;
  1375. X        case 'n': s = 
  1376. X               "n = Read the current message, then move current to next messge";
  1377. X           break;
  1378. X        case 'o': s = "o = Go to the options submenu";
  1379. X           break;
  1380. X        case 'p': s = 
  1381. X        "p = Print the current message or the tagged messages";
  1382. X           break;
  1383. X        case 'q': s = 
  1384. X        "q = Quit the mailer, asking about deletion, saving, etc";
  1385. X           break;
  1386. X        case 'r': s = 
  1387. X  "r = Reply to the message.  This only sends to the originator of the message";
  1388. X           break;
  1389. X        case 's': s = 
  1390. X               "s = Save current message or tagged messages to specified file";
  1391. X           break;
  1392. X        case 't': s = 
  1393. X               "t = Tag a message for further operations (or untag if tagged)";
  1394. X           break;
  1395. X        case ctrl('T') :
  1396. X        s = "^T = tag all messages with the specified pattern";
  1397. X        break;
  1398. X        case 'u': 
  1399. X        s = "u = Undelete - remove the deletion mark on the message";
  1400. X           break;
  1401. X        case 'x': s = "x = Exit the mail system quickly";
  1402. X           break;
  1403. X        
  1404. X        case '\n':
  1405. X        case '\r': s = "<return> = Read the current message";
  1406. X           break;
  1407. X    
  1408. X        case ctrl('L'): s = "^L = Rewrite the screen";    
  1409. X           break;
  1410. X            case ctrl('?'):                        /* DEL */
  1411. X        case ctrl('Q'): s = "Exit the mail system quickly";
  1412. X           break;
  1413. X        default : if (isdigit(ch)) 
  1414. X                s = "<number> = Make specified number the current message";
  1415. X      }
  1416. X
  1417. X      ClearLine(LINES-1);
  1418. X      Centerline(LINES-1, s);
  1419. X
  1420. X    } while (ch != '.');
  1421. X    
  1422. X    /** we'll never actually get here, but that's okay... **/
  1423. X
  1424. X    return(0);
  1425. X}
  1426. X
  1427. Xdisplay_helpfile(section)
  1428. Xint section;
  1429. X{
  1430. X    /*** Help me!  Read file 'helpfile.<section>' and echo to screen ***/
  1431. X
  1432. X    FILE *hfile;
  1433. X    char buffer[SLEN];
  1434. X    int  lines=0;
  1435. X
  1436. X    sprintf(buffer, "%s/%s.%d", helphome, helpfile, section);
  1437. X    if ((hfile = fopen(buffer,"r")) == NULL) {
  1438. X      dprint1(1,"Error: Couldn't open helpfile %s (help)\n", buffer);
  1439. X      error1("couldn't open helpfile %s",buffer);
  1440. X      return(FALSE);
  1441. X    }
  1442. X    
  1443. X    ClearScreen();
  1444. X
  1445. X    while (fgets(buffer, SLEN, hfile) != NULL) {
  1446. X      if (lines > LINES-3) {
  1447. X        PutLine0(LINES,0,"Press any key to continue: ");
  1448. X        (void) ReadCh();
  1449. X        lines = 0;
  1450. X        ClearScreen();
  1451. X        Write_to_screen("%s\r", 1, buffer);
  1452. X      }
  1453. X      else 
  1454. X        Write_to_screen("%s\r", 1, buffer);
  1455. X
  1456. X      lines++;
  1457. X    }
  1458. X
  1459. X        PutLine0(LINES,0,"Press any key to return: ");
  1460. X
  1461. X    (void) ReadCh();
  1462. X    clear_error();
  1463. X
  1464. X    return(TRUE);
  1465. X}
  1466. END_OF_src/help.c
  1467. if test 5969 -ne `wc -c <src/help.c`; then
  1468.     echo shar: \"src/help.c\" unpacked with wrong size!?
  1469. fi
  1470. # end of overwriting check
  1471. fi
  1472. echo shar: Extracting \"src/pattern.c\" \(5598 characters\)
  1473. if test -f src/pattern.c ; then 
  1474.   echo shar: Will not over-write existing file \"src/pattern.c\"
  1475. else
  1476. sed "s/^X//" >src/pattern.c <<'END_OF_src/pattern.c'
  1477. X/**            pattern.c            **/
  1478. X
  1479. X/**    General pattern matching for the ELM mailer.     
  1480. X
  1481. X       (C) Copyright 1986 Dave Taylor
  1482. X**/
  1483. X
  1484. X#include <errno.h>
  1485. X
  1486. X#include "headers.h"
  1487. X
  1488. Xstatic char pattern[SLEN] = { "" };
  1489. Xstatic char alt_pattern[SLEN] = { "" };
  1490. X
  1491. Xextern int errno;
  1492. X
  1493. Xchar *error_name(), *shift_lower(), *strcpy();
  1494. X
  1495. Xmeta_match(function)
  1496. Xint function;
  1497. X{
  1498. X    /** Perform specific function based on whether an entered string 
  1499. X        matches either the From or Subject lines.. 
  1500. X    **/
  1501. X
  1502. X    register int i, tagged=0, count=0;
  1503. X    static char     meta_pattern[SLEN];
  1504. X
  1505. X    PutLine1(LINES-3, strlen("Command: "), 
  1506. X         "%s messages that match pattern...", 
  1507. X         function==TAGGED?"Tag": function==DELETED?"Delete":"Undelete");
  1508. X
  1509. X    if (function == TAGGED) {    /* are messages already tagged??? */
  1510. X      for (i=0; i < message_count; i++)
  1511. X        if (ison(header_table[i].status,TAGGED))
  1512. X          tagged++;
  1513. X
  1514. X      if (tagged) {
  1515. X        if (tagged > 2) 
  1516. X          PutLine0(LINES-2,0, "Some messages are already tagged");
  1517. X        else
  1518. X          PutLine0(LINES-2,0, "A message is already tagged");
  1519. X    
  1520. X        Write_to_screen("- Remove tag%s? y%c", 2, plural(tagged),BACKSPACE);
  1521. X
  1522. X        if (tolower(ReadCh()) != 'n') {    /* remove tags... */
  1523. X          for (i=0; i < message_count; i++) {
  1524. X            clearit(header_table[i].status,TAGGED);
  1525. X        show_new_status(i);
  1526. X          }
  1527. X        }
  1528. X      }
  1529. X    }
  1530. X    
  1531. X    PutLine0(LINES-2,0, "Enter pattern: "); CleartoEOLN();
  1532. X
  1533. X    optionally_enter(meta_pattern, LINES-2,strlen("Enter pattern: "),FALSE);
  1534. X
  1535. X    if (strlen(meta_pattern) == 0) {
  1536. X      ClearLine(LINES-2);
  1537. X      return(0);
  1538. X    }
  1539. X
  1540. X    strcpy(meta_pattern, shift_lower(meta_pattern));   /* lowercase it */
  1541. X
  1542. X    for (i = 0; i < message_count; i++) {
  1543. X      if (from_matches(i, meta_pattern)) {
  1544. X        if ((selected && header_table[i].status & VISIBLE) || ! selected) {
  1545. X          if (function == UNDELETE)
  1546. X            clearit(header_table[i].status, DELETED);
  1547. X          else
  1548. X            setit(header_table[i].status, function);
  1549. X          show_new_status(i);
  1550. X          count++;
  1551. X        }
  1552. X      }
  1553. X      else if (subject_matches(i, meta_pattern)) {
  1554. X        if ((selected && header_table[i].status & VISIBLE) || ! selected) {
  1555. X          if (function == UNDELETE)
  1556. X            clearit(header_table[i].status, DELETED);
  1557. X          else
  1558. X            setit(header_table[i].status, function);
  1559. X          show_new_status(i);
  1560. X          count++;
  1561. X        }
  1562. X      }
  1563. X    }
  1564. X
  1565. X    ClearLine(LINES-2);    /* remove "pattern: " prompt */
  1566. X    
  1567. X    if (count > 0)
  1568. X      error3("%s %d messsage%s", 
  1569. X             function==TAGGED? "tagged" : 
  1570. X           function==DELETED? "marked for deletion" : "undeleted",
  1571. X         count, plural(count));
  1572. X    else
  1573. X      error1("no matches - no messages %s",
  1574. X         function==TAGGED? "tagged" : 
  1575. X           function==DELETED? "marked for deletion": "undeleted");
  1576. X
  1577. X    return(0);
  1578. X}
  1579. X      
  1580. Xint
  1581. Xpattern_match()
  1582. X{
  1583. X    /** Get a pattern from the user and try to match it with the
  1584. X        from/subject lines being displayed.  If matched (ignoring
  1585. X        case), move current message pointer to that message, if
  1586. X        not, error and return ZERO **/
  1587. X
  1588. X    register int i;
  1589. X
  1590. X    PutLine0(LINES-3,40,"/ = match anywhere in messages");
  1591. X    
  1592. X    PutLine0(LINES-1,0, "Match Pattern:");
  1593. X
  1594. X    if (pattern_enter(pattern, alt_pattern, LINES-1, 16, 
  1595. X        "Match Pattern (in entire mailbox):"))
  1596. X      if (strlen(alt_pattern) > 0) {
  1597. X        strcpy(alt_pattern, shift_lower(alt_pattern));
  1598. X        return(match_in_message(alt_pattern));
  1599. X      }
  1600. X      else
  1601. X        return(1);
  1602. X      
  1603. X    if (strlen(pattern) == 0) 
  1604. X      return(0);
  1605. X    else
  1606. X      strcpy(pattern, shift_lower(pattern));
  1607. X
  1608. X    for (i = current; i < message_count; i++) {
  1609. X      if (from_matches(i, pattern)) {
  1610. X        if (!selected || (selected && header_table[i].status & VISIBLE)) {
  1611. X          current = ++i;
  1612. X          return(1);
  1613. X        }
  1614. X      }
  1615. X      else if (subject_matches(i, pattern)) {
  1616. X        if (!selected || (selected && header_table[i].status & VISIBLE)) {
  1617. X          current = ++i;
  1618. X          return(1);
  1619. X        }
  1620. X      }
  1621. X    }
  1622. X
  1623. X    return(0);
  1624. X}
  1625. X
  1626. Xint
  1627. Xfrom_matches(message_number, pat)
  1628. Xint message_number;
  1629. Xchar *pat;
  1630. X{
  1631. X    /** Returns true iff the pattern occurs in it's entirety
  1632. X        in the from line of the indicated message **/
  1633. X
  1634. X    return( in_string(shift_lower(header_table[message_number].from), 
  1635. X        pat) );
  1636. X}
  1637. X
  1638. Xint
  1639. Xsubject_matches(message_number, pat)
  1640. Xint message_number;
  1641. Xchar *pat;
  1642. X{
  1643. X    /** Returns true iff the pattern occurs in it's entirety
  1644. X        in the subject line of the indicated message **/
  1645. X
  1646. X    return( in_string(shift_lower(header_table[message_number].subject), 
  1647. X        pat) );
  1648. X}
  1649. X
  1650. Xmatch_in_message(pat)
  1651. Xchar *pat;
  1652. X{
  1653. X    /** Match a string INSIDE a message...starting at the current 
  1654. X        message read each line and try to find the pattern.  As
  1655. X        soon as we do, set current and leave! 
  1656. X        Returns 1 if found, 0 if not
  1657. X    **/
  1658. X
  1659. X    char buffer[LONG_STRING];
  1660. X    int  message_number, lines, line;
  1661. X
  1662. X    message_number = current-1;
  1663. X
  1664. X    error("searching mailbox for pattern...");
  1665. X
  1666. X    while (message_number < message_count) {
  1667. X
  1668. X      if (fseek(mailfile, header_table[message_number].offset, 0L) != 0) {
  1669. X
  1670. X        dprint3(1,"Error: seek %ld bytes into file failed. errno %d (%s)\n",
  1671. X              header_table[message_number].offset, errno, 
  1672. X             "match_in_message");
  1673. X        error2("ELM [match] failed looking %ld bytes into file (%s)",
  1674. X           header_table[message_number].offset, error_name(errno));
  1675. X        return(1);    /* fake it out to avoid replacing error message */
  1676. X      }
  1677. X
  1678. X      line = 0;
  1679. X      lines = header_table[message_number].lines;
  1680. X
  1681. X      while (fgets(buffer, LONG_STRING, mailfile) != NULL && line < lines) {
  1682. X    
  1683. X        line++;
  1684. X
  1685. X        if (in_string(shift_lower(buffer), pat)) {
  1686. X          current = message_number+1; 
  1687. X          clear_error();
  1688. X          return(1);
  1689. X        }
  1690. X      }
  1691. X
  1692. X      /** now we've passed the end of THIS message...increment and 
  1693. X          continue the search with the next message! **/
  1694. X
  1695. X      message_number++;
  1696. X    }
  1697. X
  1698. X    return(0);
  1699. X}
  1700. END_OF_src/pattern.c
  1701. if test 5598 -ne `wc -c <src/pattern.c`; then
  1702.     echo shar: \"src/pattern.c\" unpacked with wrong size!?
  1703. fi
  1704. # end of overwriting check
  1705. fi
  1706. echo shar: Extracting \"src/utils.c\" \(5852 characters\)
  1707. if test -f src/utils.c ; then 
  1708.   echo shar: Will not over-write existing file \"src/utils.c\"
  1709. else
  1710. sed "s/^X//" >src/utils.c <<'END_OF_src/utils.c'
  1711. X/**        utils.c        **/
  1712. X
  1713. X/** Utility routines for ELM 
  1714. X
  1715. X    All routines herein: (C) Copyright 1985 Dave Taylor
  1716. X**/
  1717. X
  1718. X#include "headers.h"
  1719. X#include <sys/types.h>
  1720. X#include <sys/stat.h>
  1721. X#include <ctype.h>
  1722. X#include <errno.h>
  1723. X
  1724. X#ifdef BSD
  1725. X#undef tolower
  1726. X#endif
  1727. X
  1728. X#include <signal.h>
  1729. X
  1730. Xextern int errno;
  1731. X
  1732. Xchar *error_name();
  1733. Xvoid   exit();
  1734. X
  1735. Xshow_mailfile_stats()
  1736. X{
  1737. X    /** when we're about to die, let's try to dump lots of good stuff
  1738. X        to the debug file... **/
  1739. X
  1740. X    struct stat buffer;
  1741. X
  1742. X    if (debug == 0) return;        /* Damn!  Can't do it! */
  1743. X
  1744. X    if (fstat(fileno(mailfile), &buffer) == 0) {
  1745. X      dprint1(1,"\nDump of stats for mailfile %s;\n", infile);
  1746. X
  1747. X      dprint3(1, "\tinode: %d, mode: %o, uid: %d, ",
  1748. X            buffer.st_ino, buffer.st_mode, buffer.st_uid);
  1749. X      dprint2(1,"gid: %d, size: %d\n\n", buffer.st_gid, buffer.st_size);
  1750. X
  1751. X      dprint1(1,"\toffset into file = %l\n", ftell(mailfile));
  1752. X    }
  1753. X    else
  1754. X      dprint2(1,"\nfstat on mailfile '%s' failed with error %s!!\n\n",
  1755. X            infile, error_name(errno));
  1756. X}
  1757. X    
  1758. Xemergency_exit()
  1759. X{
  1760. X    /** used in dramatic cases when we must leave without altering
  1761. X        ANYTHING about the system... **/
  1762. X
  1763. X    dprint0(1,
  1764. X     "\nERROR: Something dreadful is happening!  Taking emergency exit!!\n\n");
  1765. X    dprint0(1,"  possibly leaving behind the following files;\n");
  1766. X    dprint2(1,"     The mailbox tempfile : %s%s\n", temp_mbox, username);
  1767. X    dprint2(1,"     The mailbox lock file: %s%s.lock\n", mailhome, username);
  1768. X    dprint2(1,"     The composition file : %s%d\n", temp_file, getpid());
  1769. X    dprint2(1,"     The header comp file : %s%d\n", temp_file, getpid()+1);
  1770. X    dprint2(1,"     The readmsg data file: %s/%s\n", home, readmsg_file);
  1771. X
  1772. X    Raw(OFF);
  1773. X    if (cursor_control)  transmit_functions(OFF);
  1774. X    if (hp_terminal)     softkeys_off();
  1775. X
  1776. X    if (cursor_control)
  1777. X      MoveCursor(LINES, 0);
  1778. X
  1779. X    PutLine0(LINES,0, "\nEmergency Exit taken!  All temp files intact!\n\n");
  1780. X
  1781. X    exit(1);
  1782. X}
  1783. X
  1784. X/*ARGSUSED*/
  1785. X/*VARARGS0*/
  1786. X
  1787. Xleave(val)
  1788. Xint val;    /* not used, placeholder for signal catching! */
  1789. X{
  1790. X    char buffer[SLEN];
  1791. X
  1792. X    dprint0(2,"\nLeaving mailer normally (leave)\n");
  1793. X
  1794. X    Raw(OFF);
  1795. X    if (cursor_control)  transmit_functions(OFF);
  1796. X    if (hp_terminal)     softkeys_off();
  1797. X
  1798. X    sprintf(buffer,"%s%d",temp_file, getpid());  /* editor buffer */
  1799. X    (void) unlink(buffer);
  1800. X
  1801. X    sprintf(buffer,"%s%d",temp_file, getpid()+1);  /* editor buffer */
  1802. X    (void) unlink(buffer);
  1803. X
  1804. X    sprintf(buffer,"%s%s",temp_mbox, username);  /* temp mailbox */
  1805. X    (void) unlink(buffer);
  1806. X
  1807. X    sprintf(buffer,"%s/%s", home, readmsg_file);  /* readmsg temp */
  1808. X    (void) unlink(buffer);
  1809. X
  1810. X    sprintf(buffer,"%s%s.lock",mailhome, username); /* lock file */
  1811. X    (void) unlink(buffer);
  1812. X
  1813. X    if (! mail_only) {
  1814. X      MoveCursor(LINES,0);
  1815. X      Writechar('\n');
  1816. X    }
  1817. X
  1818. X    exit(0);
  1819. X}
  1820. X
  1821. Xsilently_exit()
  1822. X{
  1823. X    /** This is the same as 'leave', but it doesn't remove any non-pid
  1824. X        files.  It's used when we notice that we're trying to create a
  1825. X        temp mail file and one already exists!!
  1826. X    **/
  1827. X    char buffer[SLEN];
  1828. X
  1829. X    dprint0(2,"\nLeaving mailer quietly (silently_exit)\n");
  1830. X
  1831. X    Raw(OFF);
  1832. X    if (cursor_control)  transmit_functions(OFF);
  1833. X    if (hp_terminal)     softkeys_off();
  1834. X
  1835. X    sprintf(buffer,"%s%d",temp_file, getpid());  /* editor buffer */
  1836. X    (void) unlink(buffer);
  1837. X
  1838. X    sprintf(buffer,"%s%d",temp_file, getpid()+1);  /* editor buffer */
  1839. X    (void) unlink(buffer);
  1840. X
  1841. X    if (! mail_only) {
  1842. X      MoveCursor(LINES,0);
  1843. X      Writechar('\n');
  1844. X    }
  1845. X
  1846. X    exit(0);
  1847. X}
  1848. X
  1849. X/*ARGSUSED0*/
  1850. X
  1851. Xleave_locked(val)
  1852. Xint val;    /* not used, placeholder for signal catching! */
  1853. X{
  1854. X    /** same as leave routine, but don't disturb lock file **/
  1855. X
  1856. X    char buffer[SLEN];
  1857. X
  1858. X        dprint0(3,
  1859. X        "\nLeaving mailer due to presence of lock file (leave_locked)\n");
  1860. X
  1861. X    Raw(OFF);
  1862. X    if (cursor_control)  transmit_functions(OFF);
  1863. X    if (hp_terminal)     softkeys_off();
  1864. X
  1865. X    sprintf(buffer,"%s%d",temp_file, getpid());  /* editor buffer */
  1866. X    (void) unlink(buffer);
  1867. X
  1868. X    sprintf(buffer,"%s%d",temp_file, getpid()+1);  /* editor buffer */
  1869. X    (void) unlink(buffer);
  1870. X
  1871. X    sprintf(buffer,"%s%s",temp_mbox, username);  /* temp mailbox */
  1872. X    (void) unlink(buffer);
  1873. X
  1874. X    MoveCursor(LINES,0);
  1875. X    Writechar('\n');
  1876. X
  1877. X    exit(0);
  1878. X}
  1879. X
  1880. Xint
  1881. Xget_page(msg_pointer)
  1882. Xint msg_pointer;
  1883. X{
  1884. X    /** Ensure that 'current' is on the displayed page,
  1885. X        returning non-zero iff the page changed! **/
  1886. X
  1887. X    register int first_on_page, last_on_page;
  1888. X
  1889. X    dprint1(6,"* get_page(%d) returns...", msg_pointer);
  1890. X
  1891. X    first_on_page = (header_page * headers_per_page) + 1;
  1892. X
  1893. X    last_on_page = first_on_page + headers_per_page - 1;
  1894. X
  1895. X    dprint2(8,"[first-on-page=%d, last-on-page=%d]",
  1896. X        first_on_page, last_on_page);
  1897. X
  1898. X    if (selected)    /* but what is it on the SCREEN??? */
  1899. X      msg_pointer = compute_visible(msg_pointer-1);
  1900. X
  1901. X    if (selected && msg_pointer > selected) {
  1902. X      dprint0(6,"FALSE - too far!\n");
  1903. X      return(FALSE);    /* too far - page can't change! */
  1904. X    }
  1905. X
  1906. X    if (msg_pointer > last_on_page) {
  1907. X      header_page = (int) (msg_pointer-(selected? 0:1)) / headers_per_page;
  1908. X      dprint3(6,"TRUE (%d > %d  New hp=%d)!\n",
  1909. X        msg_pointer, last_on_page, header_page);
  1910. X      return(1);
  1911. X    }
  1912. X    else if (msg_pointer < first_on_page) {
  1913. X      header_page = (int) (msg_pointer-1) / headers_per_page;
  1914. X      dprint3(6,"TRUE (%d < %d   New hp=%d)!\n",
  1915. X        msg_pointer, first_on_page, header_page);
  1916. X      return(1);
  1917. X    }
  1918. X    else {
  1919. X      dprint2(6,"FALSE [first=%d last=%d]\n",
  1920. X          first_on_page, last_on_page);
  1921. X      return(0);
  1922. X    }
  1923. X}
  1924. X
  1925. Xchar *nameof(filename)
  1926. Xchar *filename;
  1927. X{
  1928. X    /** checks to see if 'filename' has any common prefixes, if
  1929. X        so it returns a string that is the same filename, but 
  1930. X        with '=' as the folder directory, or '~' as the home
  1931. X        directory..
  1932. X    **/
  1933. X
  1934. X    static char buffer[STRING];
  1935. X    register int i = 0, index = 0;
  1936. X
  1937. X    if (strncmp(filename, folders, strlen(folders)) == 0) {
  1938. X      buffer[i++] = '=';
  1939. X      index = strlen(folders);
  1940. X    }
  1941. X    else if (strncmp(filename, home, strlen(home)) == 0) {
  1942. X      buffer[i++] = '~';
  1943. X      index = strlen(home);
  1944. X    }
  1945. X    else index = 0;
  1946. X
  1947. X    while (filename[index] != '\0')
  1948. X      buffer[i++] = filename[index++];
  1949. X    buffer[i] = '\0';
  1950. X    
  1951. X    return( (char *) buffer);
  1952. X}
  1953. END_OF_src/utils.c
  1954. if test 5852 -ne `wc -c <src/utils.c`; then
  1955.     echo shar: \"src/utils.c\" unpacked with wrong size!?
  1956. fi
  1957. # end of overwriting check
  1958. fi
  1959. echo shar: End of archive 5 \(of 19\).
  1960. cp /dev/null ark5isdone
  1961. DONE=true
  1962. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1963.     if test ! -f ark${I}isdone ; then
  1964.     echo shar: You still need to run archive ${I}.
  1965.     DONE=false
  1966.     fi
  1967. done
  1968. if test "$DONE" = "true" ; then
  1969.     echo You have unpacked all 19 archives.
  1970.     echo "See the Instructions file"
  1971.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1972. fi
  1973. ##  End of shell archive.
  1974. exit 0
  1975.