home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume18 / elm2.2 / part13 < prev    next >
Encoding:
Internet Message Format  |  1989-04-12  |  48.7 KB

  1. Subject:  v18i092:  Elm mail system, release 2.2, Part13/24
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
  7. Posting-number: Volume 18, Issue 92
  8. Archive-name: elm2.2/part13
  9.  
  10. #!/bin/sh
  11. # this is part 13 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file src/domains.c continued
  14. #
  15. CurArch=13
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file src/domains.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> src/domains.c
  27. X
  28. X    while (fgets(buffer, SLEN, domainfd) != NULL) {
  29. X      if (buffer[0] == '#')                  /* skip comments */
  30. X        continue;
  31. X      if (strncmp(buffer, mydomain, strlen(mydomain)) == 0) { /* match? */
  32. X         matched++;    /* Gotcha!  Remember this momentous event! */
  33. X         break;
  34. X      }
  35. X    }
  36. X
  37. X    if (! matched) 
  38. X       continue;        /* Nothing.  Not a sausage!  Step through! */
  39. X
  40. X    /** We've matched the domain! **/
  41. X
  42. X    no_ret(buffer);
  43. X
  44. X    (void) strtok(buffer, ",");    /* skip the domain info */
  45. X
  46. X    strcpy(field1, strtok(NULL, ","));    /* fun         */
  47. X    strcpy(field2, strtok(NULL, ","));    /*    stuff     */
  48. X    strcpy(field3, strtok(NULL, ","));    /*       eh?    */
  49. X    
  50. X    path = (char *) NULL;
  51. X
  52. X    /* now we merely need to figure out what permutation this is!
  53. X      
  54. X           Fields are null if they have only a blank in them or are null.
  55. X           If fields 2 and 3 are null, use field 1 as the template.
  56. X            --else--
  57. X           If field 3 is null and 2 is not, use field 2 as the template.
  58. X            --else--
  59. X           Field 3 is the template. */
  60. X         
  61. X
  62. X    if (strcmp(field3," ") == 0 || field3[0] == '\0'){
  63. X      if (strcmp(field2," ") == 0 || field2[0] == '\0')
  64. X        template = (char *) field1;
  65. X      else {
  66. X        path     = (char *) field1;
  67. X        template = (char *) field2;
  68. X      }
  69. X    }
  70. X    else {
  71. X      path     = (char *) field1;
  72. X      template = (char *) field3;
  73. X    }
  74. X    dprint(1, (debugfile,
  75. X      "-> %s\n-> %s\n-> %s\n", field1, field2, field3));
  76. X    dprint(1, (debugfile,
  77. X      "Path-> %s\nTemplate-> %s\n", path, template));
  78. X
  79. X    if (strlen(path) > 0 && path[0] == '>') 
  80. X       path++;    /* skip the '>' character, okay? */
  81. X
  82. X    j = 0;             /* address is zero, right now, right?? */
  83. X    address[j] = '\0';          /* make sure string is too! */
  84. X
  85. X    for (i=0; i < strlen(template); i++) {
  86. X      if (template[i] == '%') {
  87. X        if (! in_percent)               /* just hit a NEW percent! */
  88. X          in_percent = 1;
  89. X        else {          /* just another percent sign on the wall... */
  90. X          address[j++] = '%';
  91. X          address[j] = '\0';             /* ALWAYS NULL terminate */
  92. X          in_percent = 0;
  93. X        }
  94. X      }
  95. X      else if (in_percent) {           /* Hey! a real command string */
  96. X        in_percent = 0;
  97. X        switch (template[i]) {
  98. X          case USERNAME: strcat(address, name);        break;
  99. X          case RMTMNAME: strcat(address, machine);        break;
  100. X          case FULLNAME: strcat(address, machine);
  101. X                 strcat(address, domain);        break;
  102. X          case NPATH   : 
  103. X
  104. X         if ((expanded = find_path_to(machine, FALSE)) == NULL) {
  105. X            dprint(3, (debugfile,
  106. X                "\nCouldn't expand system path '%s' (%s)\n\n",
  107. X                machine, "domains"));
  108. X                error1("Couldn't find a path to %s!", machine);
  109. X                sleep(2);
  110. X                return(NULL);    /* failed!! */
  111. X             }
  112. X             strcat(address, expanded);    /* isn't this fun??? */
  113. X
  114. X             break;
  115. X
  116. X          case PPATH   : 
  117. X
  118. X         if ((expanded = find_path_to(path, FALSE)) == NULL) {
  119. X            dprint(3, (debugfile,
  120. X            "\nCouldn't expand system path '%s' (%s)\n\n",
  121. X            path, "domains"));
  122. X                error1("Couldn't find a path to %s!", path);
  123. X                sleep(2);
  124. X                return(NULL);    /* failed!! */
  125. X             }
  126. X             strcat(address, expanded);    /* isn't this fun??? */
  127. X
  128. X             break;
  129. X
  130. X          case OBSOLETE:    /* fall through.. */
  131. X          default      : dprint(1, (debugfile,
  132. X         "\nError: Bad sequence in template file for domain '%s': %%%c\n\n",
  133. X            domain, template[i]));
  134. X        }
  135. X        j = strlen(address);
  136. X      }
  137. X      else {
  138. X        address[j++] = template[i];
  139. X        address[j] = '\0';            /* null terminate */
  140. X      }
  141. X    }    
  142. X
  143. X    address[j] = '\0';
  144. X
  145. X    } while (strlen(address) < 1);
  146. X
  147. X    return( (char *) address);
  148. X}
  149. SHAR_EOF
  150. echo "File src/domains.c is complete"
  151. chmod 0444 src/domains.c || echo "restore of src/domains.c fails"
  152. echo "x - extracting src/edit.c (Text)"
  153. sed 's/^X//' << 'SHAR_EOF' > src/edit.c &&
  154. X
  155. Xstatic char rcsid[] = "@(#)$Id: edit.c,v 2.12 89/03/25 21:46:03 syd Exp $";
  156. X
  157. X/*******************************************************************************
  158. X *  The Elm Mail System  -  $Revision: 2.12 $   $State: Exp $
  159. X *
  160. X *             Copyright (c) 1986, 1987 Dave Taylor
  161. X *             Copyright (c) 1988, 1989 USENET Community Trust
  162. X *******************************************************************************
  163. X * Bug reports, patches, comments, suggestions should be sent to:
  164. X *
  165. X *    Syd Weinstein, Elm Coordinator
  166. X *    elm@dsinc.UUCP            dsinc!elm
  167. X *
  168. X *******************************************************************************
  169. X * $Log:    edit.c,v $
  170. X * Revision 2.12  89/03/25  21:46:03  syd
  171. X * Initial 2.2 Release checkin
  172. X * 
  173. X *
  174. X ******************************************************************************/
  175. X
  176. X/** This routine is for allowing the user to edit their current folder
  177. X    as they wish. 
  178. X
  179. X**/
  180. X
  181. X#include "headers.h"
  182. X#include <errno.h>
  183. X
  184. Xextern int errno;
  185. X
  186. Xchar   *error_name(), *error_description(), *strcpy();
  187. Xlong   bytes();
  188. Xunsigned long sleep();
  189. X
  190. X#ifdef ALLOW_MAILBOX_EDITING
  191. X
  192. Xedit_mailbox()
  193. X{
  194. X    /** Allow the user to edit their folder, always resynchronizing
  195. X        afterwards.   Due to intense laziness on the part of the
  196. X        programmer, this routine will invoke $EDITOR on the entire
  197. X        file.  The mailer will ALWAYS resync on the folder
  198. X        even if nothing has changed since, not unreasonably, it's
  199. X        hard to figure out what occurred in the edit session...
  200. X    
  201. X        Also note that if the user wants to edit their incoming
  202. X        mailbox they'll actually be editing the tempfile that is
  203. X        an exact copy.  More on how we resync in that case later
  204. X        in this code.
  205. X    **/
  206. X
  207. X    FILE     *real_folder, *temp_folder;
  208. X    char     edited_file[SLEN], buffer[SLEN];
  209. X
  210. X    if(folder_type == SPOOL) {
  211. X      if(save_file_stats(cur_folder) != 0) {
  212. X        error1("Problems saving permissions of folder %s!", cur_folder);
  213. X        Raw(ON);
  214. X        sleep(2);
  215. X        return(0);
  216. X      }
  217. X    }
  218. X      
  219. X    PutLine0(LINES-1,0,"Invoking editor...");
  220. X
  221. X    strcpy(edited_file, (folder_type == NON_SPOOL ? cur_folder : cur_tempfolder));
  222. X    sprintf(buffer, "%s %s", alternative_editor, edited_file);
  223. X
  224. X    Raw(OFF);
  225. X
  226. X    if (system_call(buffer, SH, TRUE) != 0) {
  227. X      error1("Problems invoking editor %s!", alternative_editor);
  228. X      Raw(ON);
  229. X      sleep(2);
  230. X      return(0);
  231. X    }
  232. X
  233. X    Raw(ON);
  234. X
  235. X    if (folder_type == SPOOL) {    /* uh oh... now the toughie...  */
  236. X
  237. X      if (bytes(cur_folder) != mailfile_size) {
  238. X
  239. X         /* SIGH.  We've received mail since we invoked the editor
  240. X        on the folder.  We'll have to do some strange stuff to
  241. X            remedy the problem... */
  242. X
  243. X         PutLine0(LINES, 0, "Warning: new mail received...");
  244. X         CleartoEOLN();
  245. X
  246. X         if ((temp_folder = fopen(edited_file, "a")) == NULL) {
  247. X           dprint(1, (debugfile, 
  248. X            "Attempt to open \"%s\" to append failed in %s\n", 
  249. X            edited_file, "edit_mailbox"));
  250. X           set_error("Couldn't reopen tempfile. Edit LOST!");
  251. X           return(1);
  252. X         }
  253. X         /** Now let's lock the folder up and stream the new stuff 
  254. X         into the temp file... **/
  255. X
  256. X         lock(OUTGOING);    
  257. X         if ((real_folder = fopen(cur_folder, "r")) == NULL) {
  258. X           dprint(1, (debugfile, 
  259. X               "Attempt to open \"%s\" for reading new mail failed in %s\n",
  260. X            cur_folder, "edit_mailbox"));
  261. X           sprintf(buffer, "Couldn't open %s for reading!  Edit LOST!", 
  262. X               cur_folder);
  263. X           set_error(buffer);
  264. X           unlock();
  265. X           return(1);
  266. X         }
  267. X         if (fseek(real_folder, mailfile_size, 0) == -1) {
  268. X           dprint(1, (debugfile,
  269. X            "Couldn't seek to end of cur_folder (offset %ld) (%s)\n",
  270. X            mailfile_size, "edit_mailbox"));
  271. X           set_error("Couldn't seek to end of folder.  Edit LOST!");
  272. X           unlock();
  273. X           return(1);
  274. X         }
  275. X    
  276. X         /** Now we can finally stream the new mail into the tempfile **/
  277. X
  278. X         while (fgets(buffer, SLEN, real_folder) != NULL)
  279. X           fprintf(temp_folder, "%s", buffer);
  280. X
  281. X         fclose(real_folder);
  282. X         fclose(temp_folder);
  283. X
  284. X        } else lock(OUTGOING);
  285. X
  286. X       /* remove real mail_file and then
  287. X        * link or copy the edited mailfile to real mail_file */
  288. X
  289. X       (void)unlink(cur_folder);
  290. X
  291. X       if (link(edited_file, cur_folder) != 0)  {
  292. X         if (errno == EXDEV || errno == EEXIST) {
  293. X           /* attempt to link across file systems */
  294. X              if (copy(edited_file, cur_folder) != 0) {
  295. X         Write_to_screen(
  296. X            "\n\rCouldn't copy %s to mailfile %s!\n\r",
  297. X            2, edited_file, cur_folder);
  298. X         Write_to_screen(
  299. X            "\n\rYou'll need to check out %s for your mail.\n\r",
  300. X            1, edited_file);
  301. X         Write_to_screen("** %s - %s. **\n\r", 2,
  302. X            error_name(errno), error_description(errno));
  303. X         unlock();                    /* ciao!*/
  304. X         emergency_exit();
  305. X           }
  306. X         } else {
  307. X        Write_to_screen("\n\rCouldn't link %s to mailfile %s!\n\r",2,
  308. X          edited_file, cur_folder);
  309. X            Write_to_screen(
  310. X          "\n\rYou'll need to check out %s for your mail.\n\r",
  311. X          1, edited_file);
  312. X        Write_to_screen("** %s - %s. **\n\r", 2,
  313. X          error_name(errno), error_description(errno));
  314. X            unlock();                    /* ciao!*/
  315. X            emergency_exit();
  316. X         }
  317. X       }
  318. X
  319. X       /* restore file permissions before removing lock */
  320. X
  321. X       if(restore_file_stats(cur_folder) != 1) {
  322. X         error1("Problems restoring permissions of folder %s!", cur_folder);
  323. X         Raw(ON);
  324. X         sleep(2);
  325. X       }
  326. X          
  327. X       unlock();
  328. X       unlink(edited_file);    /* remove the edited mailfile */
  329. X       error("Changes incorporated into new mail...");
  330. X
  331. X    } else 
  332. X      error("Resynchronizing with new version of folder...");
  333. X
  334. X    sleep(2);
  335. X    ClearScreen();
  336. X    newmbox(cur_folder, FALSE);
  337. X    showscreen();
  338. X    return(1);
  339. X}
  340. X
  341. X#endif
  342. SHAR_EOF
  343. chmod 0444 src/edit.c || echo "restore of src/edit.c fails"
  344. echo "x - extracting src/editmsg.c (Text)"
  345. sed 's/^X//' << 'SHAR_EOF' > src/editmsg.c &&
  346. X
  347. Xstatic char rcsid[] = "@(#)$Id: editmsg.c,v 2.12 89/03/25 21:46:04 syd Exp $";
  348. X
  349. X/*******************************************************************************
  350. X *  The Elm Mail System  -  $Revision: 2.12 $   $State: Exp $
  351. X *
  352. X *             Copyright (c) 1986, 1987 Dave Taylor
  353. X *             Copyright (c) 1988, 1989 USENET Community Trust
  354. X *******************************************************************************
  355. X * Bug reports, patches, comments, suggestions should be sent to:
  356. X *
  357. X *    Syd Weinstein, Elm Coordinator
  358. X *    elm@dsinc.UUCP            dsinc!elm
  359. X *
  360. X *******************************************************************************
  361. X * $Log:    editmsg.c,v $
  362. X * Revision 2.12  89/03/25  21:46:04  syd
  363. X * Initial 2.2 Release checkin
  364. X * 
  365. X *
  366. X ******************************************************************************/
  367. X
  368. X/** This contains routines to do with starting up and using an editor (or two)
  369. X    from within Elm.  This stuff used to be in mailmsg2.c...
  370. X**/
  371. X
  372. X#include "headers.h"
  373. X#include <errno.h>
  374. X#include <setjmp.h>
  375. X#include <signal.h>
  376. X#include <ctype.h>
  377. X
  378. X#ifdef BSD
  379. X#undef        tolower
  380. X#endif
  381. X
  382. Xextern int errno;
  383. X
  384. Xchar *error_name(), *error_description(), *strcpy(), *format_long();
  385. Xunsigned long sleep();
  386. X
  387. Xint
  388. Xedit_the_message(filename, already_has_text)
  389. Xchar *filename;
  390. Xint  already_has_text;
  391. X{
  392. X    /** Invoke the users editor on the filename.  Return when done. 
  393. X        If 'already has text' then we can't use the no-editor option
  394. X        and must use 'alternative editor' (e.g. $EDITOR or default_editor)
  395. X        instead... **/
  396. X
  397. X    char buffer[SLEN];
  398. X    register int stat, return_value = 0;
  399. X        int     old_raw;
  400. X
  401. X    buffer[0] = '\0';
  402. X
  403. X    if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
  404. X      if (already_has_text) 
  405. X        sprintf(buffer, "%s %s", alternative_editor, filename);
  406. X      else
  407. X        return(no_editor_edit_the_message(filename));
  408. X    }
  409. X
  410. X    PutLine0(LINES, 0, "Invoking editor...");  fflush(stdout);
  411. X    if (strlen(buffer) == 0)
  412. X      sprintf(buffer,"%s %s", editor, filename);
  413. X
  414. X      if( (old_raw = RawState()) == ON)
  415. X    Raw(OFF);
  416. X
  417. X    chown(filename, userid, groupid);    /* file was owned by root! */
  418. X
  419. X    if (cursor_control)
  420. X      transmit_functions(OFF);        /* function keys are local */
  421. X
  422. X    if ((stat = system_call(buffer, SH, TRUE)) != 0) { 
  423. X      dprint(1,(debugfile, 
  424. X          "System call failed with stat %d (edit_the_message)\n", 
  425. X          stat));
  426. X      dprint(1, (debugfile, "** %s - %s **\n", error_name(errno), 
  427. X        error_description(errno)));
  428. X      ClearLine(LINES-1);
  429. X      error1("Can't invoke editor '%s' for composition.", editor);
  430. X      sleep(2);
  431. X      return_value = 1;
  432. X    }
  433. X
  434. X    if (cursor_control)
  435. X      transmit_functions(ON);        /* function keys are local */
  436. X    
  437. X      if ( old_raw == ON)
  438. X    Raw(ON);
  439. X
  440. X    return(return_value);
  441. X}
  442. X
  443. Xextern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], 
  444. X        expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING], 
  445. X        bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
  446. X            subject[SLEN];
  447. X
  448. Xint      interrupts_while_editing;    /* keep track 'o dis stuff         */
  449. Xjmp_buf  edit_location;                /* for getting back from interrupt */
  450. X
  451. Xchar *strip_commas();
  452. Xlong  fsize();
  453. X
  454. Xint
  455. Xno_editor_edit_the_message(filename)
  456. Xchar *filename;
  457. X{
  458. X    /** If the current editor is set to either "builtin" or "none", then
  459. X        invoke this program instead.  As it turns out, this and the 
  460. X        routine above have a pretty incestuous relationship (!)...
  461. X    **/
  462. X
  463. X    FILE *edit_fd;
  464. X    char buffer[SLEN], editor_name[SLEN], buf[SLEN];
  465. X    int      edit_interrupt();
  466. X        int     old_raw;
  467. X#ifdef VOIDSIG
  468. X    void    (*oldint)(), (*oldquit)();
  469. X#else
  470. X    int    (*oldint)(), (*oldquit)();
  471. X#endif
  472. X
  473. X        if (( old_raw = RawState()) == ON)
  474. X    Raw(OFF);
  475. X
  476. X    if ((edit_fd = fopen(filename, "a")) == NULL) {
  477. X      error2("Couldn't open %s for appending [%s].", filename, 
  478. X          error_name(errno));
  479. X      sleep (2);
  480. X      dprint(1, (debugfile,
  481. X        "Error encountered trying to open file %s;\n", filename));
  482. X      dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
  483. X            error_description(errno)));
  484. X          if ( old_raw == ON)
  485. X      Raw(ON);
  486. X      return(1);
  487. X    }
  488. X
  489. X    /** is there already text in this file? **/
  490. X
  491. X    if (fsize(edit_fd) > 0L)
  492. X      printf(
  493. X         "\nPlease continue message, ^D or '.' to end, %cp to list, %c? for help;\n\n",
  494. X        escape_char, escape_char);
  495. X    else
  496. X      printf(
  497. X          "\nPlease enter message, ^D or '.' to end, or %c? <RETURN> for help;\n\n",
  498. X        escape_char);
  499. X
  500. X    oldint  = signal(SIGINT,  edit_interrupt);
  501. X    oldquit = signal(SIGQUIT, edit_interrupt);
  502. X
  503. X    interrupts_while_editing = 0;
  504. X
  505. X    if (setjmp(edit_location) != 0) {
  506. X      if (interrupts_while_editing > 1) {
  507. X        Raw(ON);
  508. X
  509. X        (void) signal(SIGINT,  oldint);
  510. X        (void) signal(SIGQUIT, oldquit);
  511. X
  512. X        if (edit_fd != NULL)    /* insurance... */
  513. X          fclose(edit_fd);
  514. X        return(1);
  515. X      }
  516. X      goto more_input;    /* read input again, please! */
  517. X    }
  518. X    
  519. Xraw_input : Raw(ON);
  520. X
  521. Xmore_input: buffer[0] = '\0';
  522. X
  523. X    while (optionally_enter(buffer, -1,-1, FALSE, FALSE) == 0) {
  524. X
  525. X      interrupts_while_editing = 0;    /* reset to zero... */
  526. X
  527. X      if (strcmp(buffer, ".") == 0)
  528. X        break;    /* '.' is as good as a ^D to us dumb programs :-) */
  529. X      if (buffer[0] == escape_char) {
  530. X        Raw(OFF);
  531. X        switch (tolower(buffer[1])) {
  532. X              case '?' : tilde_help();
  533. X                       printf("(continue)\n"); goto raw_input;
  534. X
  535. X          case TILDE_ESCAPE: move_left(buffer, 1); 
  536. X              Raw(ON);         goto tilde_input;    /*!!*/
  537. X
  538. X          case 't' : get_with_expansion("\nTo: ", to, expanded_to, buffer);
  539. X             goto raw_input;
  540. X          case 'b' : get_with_expansion("\nBcc: ",bcc,expanded_bcc, buffer);
  541. X             goto raw_input;
  542. X          case 'c' : get_with_expansion("\nCc: ", cc, expanded_cc, buffer);
  543. X             goto raw_input;
  544. X          case 's' : get_with_expansion("\nSubject: ", subject,NULL,buffer);
  545. X                goto raw_input;
  546. X
  547. X          case 'h' : get_with_expansion("\nTo: ", to, expanded_to, NULL);    
  548. X                     get_with_expansion("Cc: ", cc, expanded_cc, NULL);
  549. X                     get_with_expansion("Bcc: ", bcc,expanded_bcc, NULL);
  550. X                     get_with_expansion("Subject: ", subject,NULL, NULL);
  551. X             goto raw_input;
  552. X
  553. X          case 'r' : read_in_file(edit_fd, (char *) buffer + 2, 1);
  554. X               goto raw_input;
  555. X          case 'e' : if (strlen(emacs_editor) > 0) 
  556. X                       if (access(emacs_editor, ACCESS_EXISTS) == 0) {
  557. X                         strcpy(buffer, editor);
  558. X                 strcpy(editor, emacs_editor);
  559. X                   fclose(edit_fd);
  560. X                 (void) edit_the_message(filename,0);
  561. X                 strcpy(editor, buffer);
  562. X                 edit_fd = fopen(filename, "a");
  563. X                             printf("(continue entering message, ^D or '.' to end)\n");
  564. X                         goto raw_input;
  565. X                   }
  566. X                   else
  567. X                         printf(
  568. X              "\n(Can't find Emacs on this system!  continue)\n");
  569. X             else
  570. X               printf(
  571. X              "\n(Don't know where Emacs would be...continue)\n");    
  572. X             goto raw_input;
  573. X
  574. X           case 'v' : strcpy(buffer, editor);
  575. X              strcpy(editor, default_editor);
  576. X              fclose(edit_fd);
  577. X              (void) edit_the_message(filename,0);
  578. X              strcpy(editor, buffer);
  579. X              edit_fd = fopen(filename, "a");
  580. X                          printf("(continue entering message, ^D or '.' to end)\n");
  581. X                      goto raw_input;
  582. X
  583. X           case 'o' : printf("\nPlease enter the name of the editor : ");
  584. X              editor_name[0] = '\0';
  585. X              optionally_enter(editor_name,-1,-1, FALSE, FALSE);
  586. X                      if (strlen(editor_name) > 0) {
  587. X                        strcpy(buffer, editor);
  588. X                strcpy(editor, editor_name);
  589. X                fclose(edit_fd);
  590. X                (void) edit_the_message(filename,0);
  591. X                strcpy(editor, buffer);
  592. X                edit_fd = fopen(filename, "a");
  593. X                            printf("(continue entering message, ^D or '.' to end)\n");
  594. X                        goto raw_input;
  595. X                  }
  596. X                printf("(continue)\n");
  597. X                      goto raw_input; 
  598. X
  599. X        case '<' : putchar('\n');
  600. X               if (strlen(buffer) < 3)
  601. X                 (void) printf(
  602. X               "(you need to use a specific command here.  Continue...)\n");
  603. X               else {
  604. X                 sprintf(buf, " > %s.%d 2>&1", temp_edit, getpid());
  605. X                 strcat(buffer, buf);
  606. X                 (void) system_call((char *) buffer+2, SH, TRUE);
  607. X                 sprintf(buffer, "~r %s.%d", temp_edit, getpid());
  608. X                           read_in_file(edit_fd, (char *) buffer + 3, 0);
  609. X                 (void) unlink((char *) buffer+3);
  610. X               }
  611. X                       goto raw_input; 
  612. X
  613. X        case '!' : putchar('\n');
  614. X               if (strlen(buffer) < 3) 
  615. X                 (void) system_call(shell, USER_SHELL, TRUE);
  616. X               else
  617. X                         (void) system_call((char *) buffer+2,
  618. X                   USER_SHELL, TRUE);
  619. X                   printf("(continue)\n");
  620. X               goto raw_input;
  621. X
  622. X         case 'm' : /* same as 'f' but with leading prefix added */
  623. X
  624. X             case 'f' : /* this can be directly translated into a
  625. X                   'readmsg' call with the same params! */
  626. X                putchar('\n');
  627. X                read_in_messages(edit_fd, (char *) buffer + 1);
  628. X                goto raw_input;
  629. X
  630. X             case 'p' : /* print out message so far.  Soooo simple! */
  631. X                print_message_so_far(edit_fd, filename);
  632. X                goto raw_input;
  633. X
  634. X         default  : printf(
  635. X                 "\n(don't know what %c%c is.  Try %c? for help)\n",
  636. X                    escape_char, buffer[1], escape_char);
  637. X           }
  638. X         }
  639. X         else {
  640. Xtilde_input:
  641. X           fprintf(edit_fd, "%s\n", buffer);
  642. X           printf("\r\n");
  643. X         }
  644. X      buffer[0] = '\0';
  645. X    }
  646. X
  647. X    printf("\n<end-of-message>\n\r\n\r");
  648. X
  649. X        if ( old_raw == ON)
  650. X    Raw(ON);
  651. X
  652. X    (void) signal(SIGINT,  oldint);
  653. X    (void) signal(SIGQUIT, oldquit);
  654. X
  655. X    if (edit_fd != NULL)    /* insurance... */
  656. X      fclose(edit_fd);
  657. X
  658. X    return(0);
  659. X}
  660. X
  661. Xtilde_help()
  662. X{
  663. X    /* a simple routine to print out what is available at this level */
  664. X
  665. X        int     old_raw;
  666. X
  667. X        if ( (old_raw = RawState()) == ON)
  668. X    Raw(OFF);
  669. X
  670. X    printf("\n(Available options at this point are;\n\n");
  671. X    printf("\t%c?\tPrint this help menu\n", escape_char);
  672. X    if (escape_char == TILDE_ESCAPE)
  673. X      printf("\t~~\tAdd line prefixed by a single '~' character\n");
  674. X    /* doesn't make sense otherwise... */
  675. X
  676. X    printf("\t%cb\tChange the addresses in the Blind-carbon-copy list\n",
  677. X      escape_char);
  678. X
  679. X    printf("\t%cc\tChange the addresses in the Carbon-copy list\n",
  680. X        escape_char);
  681. X    printf("\t%ce\tInvoke the Emacs editor on the message, if possible\n",
  682. X        escape_char);
  683. X    printf("\t%cf\tadd the specified list of messages, or current\n",
  684. X        escape_char);
  685. X    printf("\t%ch\tchange all available headers (to,cc,bcc,subject)\n",
  686. X        escape_char);
  687. X    printf("\t%cm\tsame as '%cf', but with the current 'prefix'\n",
  688. X        escape_char, escape_char);
  689. X    printf("\t%co\tInvoke a user specified editor on the message\n",
  690. X        escape_char);
  691. X    printf("\t%cp\tprint out message as typed in so far\n", escape_char);
  692. X    printf("\t%cr\tRead in the specified file\n", escape_char);
  693. X    printf("\t%cs\tChange the subject of the message\n", escape_char);
  694. X    printf("\t%ct\tChange the addresses in the To list\n",
  695. X        escape_char);
  696. X    printf("\t%cv\tInvoke the Vi visual editor on the message\n\n",
  697. X        escape_char);
  698. X    printf(
  699. X          "\t%c!\texecute a unix command (or give a shell if no command)\n",
  700. X      escape_char);
  701. X    printf(
  702. X          "\t%c<\texecute a unix command adding the output to the message\n\n",
  703. X      escape_char);
  704. X    printf(
  705. X      "\t.  \tby itself on a line (or a control-D) ends the message\n\n");
  706. X
  707. X        if ( old_raw == ON)
  708. X    Raw(ON);
  709. X}
  710. X
  711. Xread_in_file(fd, filename, show_user_filename)
  712. XFILE *fd;
  713. Xchar *filename;
  714. Xint   show_user_filename;
  715. X{
  716. X    /** Open the specified file and stream it in to the already opened 
  717. X        file descriptor given to us.  When we're done output the number
  718. X        of lines we added, if any... **/
  719. X
  720. X    FILE *myfd;
  721. X    char myfname[SLEN], buffer[SLEN];
  722. X    register int lines = 0;
  723. X
  724. X    while (whitespace(filename[lines])) lines++;
  725. X
  726. X    /** expand any shell variables, '~' or other notation... **/
  727. X    /* temp copy of filename to buffer since expand_env is destructive */
  728. X    strcpy(buffer, &filename[lines]);
  729. X    expand_env(myfname, buffer);
  730. X
  731. X    if (strlen(myfname) == 0) {
  732. X      printf("\n(no filename specified for file read!  Continue...)\n");
  733. X      return;
  734. X    }
  735. X
  736. X    if ((myfd = fopen(myfname,"r")) == NULL) {
  737. X      printf("\n(Couldn't read file '%s'!  Continue...)\n",
  738. X         myfname);
  739. X      return;
  740. X    }
  741. X
  742. X    lines = 0;
  743. X
  744. X    while (fgets(buffer, SLEN, myfd) != NULL) {
  745. X      if(buffer[strlen(buffer)-1] == '\n') lines++;
  746. X        fputs(buffer, fd);
  747. X      fflush(stdout);
  748. X    }
  749. X
  750. X    fclose(myfd);
  751. X
  752. X    if (show_user_filename)
  753. X      printf("\n(added %d line%s from file %s.  Please continue...)\n",
  754. X        lines, plural(lines), myfname);
  755. X    else
  756. X      printf("\n(added %d line%s to message.  Please continue...)\n",
  757. X        lines, plural(lines));
  758. X
  759. X    return;
  760. X}
  761. X
  762. Xprint_message_so_far(edit_fd, filename)
  763. XFILE *edit_fd;
  764. Xchar *filename;
  765. X{
  766. X    /** This prints out the message typed in so far.  We accomplish
  767. X        this in a cheap manner - close the file, reopen it for reading,
  768. X        stream it to the screen, then close the file, and reopen it
  769. X        for appending.  Simple, but effective!
  770. X
  771. X        A nice enhancement would be for this to -> page <- the message
  772. X        if it's sufficiently long.  Too much work for now, though.
  773. X    **/
  774. X    
  775. X    char buffer[SLEN];
  776. X
  777. X    fclose(edit_fd);
  778. X
  779. X    if ((edit_fd = fopen(filename, "r")) == NULL) {
  780. X      printf("\nMayday!  Mayday!  Mayday!\n");
  781. X      printf("\nPanic: Can't open file for reading!  Bail!\n");
  782. X      emergency_exit();
  783. X    }
  784. X
  785. X    printf("\nTo: %s\n", format_long(to, 4));
  786. X    printf("Cc: %s\n", format_long(cc, 4));
  787. X    printf("Bcc: %s\n", format_long(bcc, 5));
  788. X    printf("Subject: %s\n\n", subject);
  789. X
  790. X    while (fgets(buffer, SLEN, edit_fd) != NULL)
  791. X      printf("%s", buffer);
  792. X
  793. X    fclose(edit_fd);
  794. X
  795. X    if ((edit_fd = fopen(filename, "a")) == NULL) {
  796. X      printf("Mayday!  Mayday!  Abandon Ship!  Aiiieeeeee\n");
  797. X      printf("\nPanic: Can't reopen file for appending!\n");
  798. X      emergency_exit();
  799. X    }
  800. X
  801. X    printf("\n(continue entering message, please)\n");
  802. X}
  803. X
  804. Xread_in_messages(fd, buffer)
  805. XFILE *fd;
  806. Xchar *buffer;
  807. X{
  808. X    /** Read the specified messages into the open file.  If the
  809. X        first character of "buffer" is 'm' then prefix it, other-
  810. X        wise just stream it in straight...Since we're using the
  811. X        pipe to 'readmsg' we can also allow the user to specify
  812. X        patterns and such too...
  813. X    **/
  814. X
  815. X    FILE *myfd, *popen();
  816. X    char  local_buffer[SLEN];
  817. X    register int lines = 0, add_prefix=0, mindex;
  818. X
  819. X    if (add_prefix = (tolower(buffer[0]) == 'm'))
  820. X        buffer++;
  821. X
  822. X    if (! isdigit(buffer[0])) 
  823. X      sprintf(local_buffer, "%s %s", readmsg, buffer);
  824. X    else {
  825. X      mindex = atoi(buffer);    /* map requested # to real # */
  826. X      sprintf(local_buffer, "%s %d", readmsg, 
  827. X          headers[mindex-1]->index_number);
  828. X    }
  829. X
  830. X    if ((myfd = popen(local_buffer, "r")) == NULL) {
  831. X       printf("(can't get to 'readmsg' command.  Sorry...)\n");
  832. X       return;    
  833. X    }
  834. X
  835. X    dprint(5, (debugfile, "** readmsg call: \"%s\" **\n", local_buffer));
  836. X
  837. X    while (fgets(local_buffer, SLEN, myfd) != NULL) {
  838. X      if(local_buffer[strlen(local_buffer)-1] == '\n') lines++;
  839. X      if (add_prefix)
  840. X        fprintf(fd, "%s%s", prefixchars, local_buffer);
  841. X      else 
  842. X        fputs(local_buffer, fd);
  843. X    }
  844. X
  845. X    pclose(myfd);
  846. X    
  847. X    if (lines == 0)
  848. X      printf("(Couldn't add the requested message.   Continue)\n");
  849. X    else
  850. X      printf("(added %d line%s to message...  Please continue)\n",
  851. X        lines, plural(lines));
  852. X
  853. X    return;
  854. X}
  855. X
  856. Xget_with_expansion(prompt, buffer, expanded_buffer, sourcebuf)
  857. Xchar *prompt, *buffer, *expanded_buffer, *sourcebuf;
  858. X{
  859. X    /** This is used to prompt for a new value of the specified field.
  860. X        If expanded_buffer == NULL then we won't bother trying to expand
  861. X        this puppy out!  (sourcebuf could be an initial addition)
  862. X    **/
  863. X
  864. X    char mybuffer[VERY_LONG_STRING];
  865. X        int     old_raw;
  866. X
  867. X        if ( (old_raw = RawState()) == OFF)
  868. X      Raw(ON);
  869. X
  870. X    printf(prompt);    fflush(stdout);    /* output! */
  871. X
  872. X    if (sourcebuf != NULL) {
  873. X      while (!whitespace(*sourcebuf) && *sourcebuf != '\0') 
  874. X        sourcebuf++;
  875. X      if (*sourcebuf != '\0') {
  876. X        while (whitespace(*sourcebuf)) 
  877. X          sourcebuf++;
  878. X        if (strlen(sourcebuf) > 0) {
  879. X          strcat(buffer, " ");
  880. X          strcat(buffer, sourcebuf);
  881. X        }
  882. X      }
  883. X    }
  884. X
  885. X    strcpy(mybuffer, buffer);
  886. X
  887. X    optionally_enter(buffer, -1, -1, TRUE, FALSE);    /* already data! */
  888. X
  889. X        if ( old_raw == OFF)
  890. X          Raw(OFF);
  891. X
  892. X    putchar('\n');
  893. X
  894. X    /** if it's changed and we're supposed to expand addresses... **/
  895. X
  896. X    if (strcmp(buffer, mybuffer) != 0 && expanded_buffer != NULL) 
  897. X      if (build_address(strip_commas(buffer), expanded_buffer))
  898. X        printf("%s%s\n\r", prompt, expanded_buffer);
  899. X
  900. X    return;
  901. X}
  902. X
  903. Xedit_interrupt()
  904. X{
  905. X    /** This routine is called when the user hits an interrupt key
  906. X        while in the builtin editor...it increments the number of 
  907. X        times an interrupt is hit and returns it.
  908. X    **/
  909. X
  910. X    signal(SIGINT, edit_interrupt);
  911. X    signal(SIGQUIT, edit_interrupt);
  912. X
  913. X    if (interrupts_while_editing++ == 0)
  914. X      printf("(Interrupt.  One more to cancel this letter...)\n\r");
  915. X
  916. X    longjmp(edit_location, 1);        /* get back */
  917. X}
  918. SHAR_EOF
  919. chmod 0444 src/editmsg.c || echo "restore of src/editmsg.c fails"
  920. echo "x - extracting src/elm.c (Text)"
  921. sed 's/^X//' << 'SHAR_EOF' > src/elm.c &&
  922. X
  923. Xstatic char rcsid[] = "@(#)$Id: elm.c,v 2.33 89/03/25 21:46:10 syd Exp $";
  924. X
  925. X/*******************************************************************************
  926. X *  The Elm Mail System  -  $Revision: 2.33 $   $State: Exp $
  927. X *
  928. X * This file and all associated files and documentation:
  929. X *             Copyright (c) 1986, 1987 Dave Taylor
  930. X *             Copyright (c) 1988, 1989 USENET Community Trust
  931. X *******************************************************************************
  932. X * Bug reports, patches, comments, suggestions should be sent to:
  933. X *
  934. X *    Syd Weinstein, Elm Coordinator
  935. X *    elm@dsinc.UUCP            dsinc!elm
  936. X *
  937. X *******************************************************************************
  938. X * $Log:    elm.c,v $
  939. X * Revision 2.33  89/03/25  21:46:10  syd
  940. X * Initial 2.2 Release checkin
  941. X * 
  942. X *
  943. X ******************************************************************************/
  944. X
  945. X/* Main program of the ELM mail system! 
  946. X*/
  947. X
  948. X#include "elm.h"
  949. X
  950. X#ifdef BSD
  951. X#undef        toupper
  952. X#undef        tolower
  953. X#endif
  954. X
  955. Xlong bytes();
  956. Xchar *format_long(), *parse_arguments();
  957. X
  958. Xmain(argc, argv)
  959. Xint argc;
  960. Xchar *argv[];
  961. X    {
  962. X    int  ch;
  963. X    char address[SLEN], to_whom[SLEN], buffer[SLEN], *req_mfile;
  964. X    int  key_offset;        /** Position offset within keyboard string   **/
  965. X    int  redraw,         /** do we need to rewrite the entire screen? **/
  966. X         nuhead,         /** or perhaps just the headers section...   **/
  967. X         nucurr,         /** or just the current message pointer...   **/
  968. X         nufoot;         /** clear lines 16 thru bottom and new menu  **/
  969. X    int  i,j;              /** Random counting variables (etc)          **/
  970. X    int  pageon,         /** for when we receive new mail...          **/
  971. X         last_in_folder;    /** for when we receive new mail too...      **/
  972. X    long num;        /** another variable for fun..               **/
  973. X    extern char version_buff[];
  974. X
  975. X    req_mfile = parse_arguments(argc, argv, to_whom);
  976. X
  977. X    initialize(req_mfile);
  978. X
  979. X    if (mail_only) {
  980. X       dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", 
  981. X           format_long(to_whom, 3)));
  982. X       if(!batch_only) {
  983. X         sprintf(buffer, "Send only mode [ELM %s]", version_buff);
  984. X         Centerline(1, buffer);
  985. X       }
  986. X       (void) sendmsg(to_whom, "", batch_subject, TRUE,
  987. X         (batch_only ? NO : allow_forms), FALSE); 
  988. X       leave(0);
  989. X    } else if (check_only) {
  990. X       dprint(3, (debugfile, "Check-only: checking \n-> \"%s\"\n", 
  991. X           format_long(to_whom, 3)));
  992. X       (void) build_address(strip_commas(to_whom), buffer); 
  993. X       printf("Expands to: %s",
  994. X         format_long(buffer, strlen("Expands to: ")));
  995. X       leave(0);
  996. X    }
  997. X
  998. X    ScreenSize(&LINES, &COLUMNS);
  999. X
  1000. X    showscreen();
  1001. X
  1002. X    while (1) {
  1003. X      redraw = 0;
  1004. X      nuhead = 0;
  1005. X      nufoot = 0;
  1006. X      nucurr = 0;
  1007. X      if ((num = bytes(cur_folder)) != mailfile_size) {
  1008. X        dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", 
  1009. X            num - mailfile_size));
  1010. X        error("New mail has arrived! Hang on...");
  1011. X        fflush(stdin);    /* just to be sure... */
  1012. X        last_in_folder = message_count;
  1013. X        pageon = header_page;
  1014. X        newmbox(cur_folder, TRUE);    /* last won't be touched! */
  1015. X        clear_error();
  1016. X        header_page = pageon;
  1017. X
  1018. X        if (on_page(current))   /* do we REALLY have to rewrite? */
  1019. X          showscreen();
  1020. X        else {
  1021. X          update_title();
  1022. X          ClearLine(LINES-1);         /* remove reading message... */
  1023. X          error2("%d new message%s received.", 
  1024. X             message_count - last_in_folder,
  1025. X             plural(message_count - last_in_folder));
  1026. X        }
  1027. X        /* mailfile_size = num; */
  1028. X        if (cursor_control)
  1029. X          transmit_functions(ON);    /* insurance */
  1030. X      }
  1031. X
  1032. X      prompt("Command: ");
  1033. X
  1034. X      CleartoEOLN();
  1035. X      ch = GetPrompt();
  1036. X      CleartoEOS();
  1037. X#ifdef DEBUG
  1038. X      if (! movement_command(ch))
  1039. X        dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
  1040. X#endif
  1041. X
  1042. X      set_error("");    /* clear error buffer */
  1043. X
  1044. X      MoveCursor(LINES-3,strlen("Command: "));
  1045. X
  1046. X      switch (ch) {
  1047. X
  1048. X        case '?'     :  if (help(FALSE))
  1049. X                   redraw++;
  1050. X               else
  1051. X                 nufoot++;
  1052. X               break;
  1053. X
  1054. X        case '$'    :  PutLine0(LINES-3, strlen("Command: "),
  1055. X                     "Resynchronize folder");
  1056. X               redraw = resync();
  1057. X               break;
  1058. X
  1059. Xnext_page:
  1060. X        case '+'    :  /* move to next page if we're not on the last */
  1061. X               if((selected &&
  1062. X                 ((header_page+1)*headers_per_page < selected))
  1063. X               ||(!selected &&
  1064. X                 ((header_page+1)*headers_per_page<message_count))){
  1065. X
  1066. X                 header_page++;
  1067. X                 nuhead++;    
  1068. X
  1069. X                 if(move_when_paged) {
  1070. X                   /* move to first message of new page */
  1071. X                   if(selected)
  1072. X                 current = visible_to_index(
  1073. X                   header_page * headers_per_page + 1) + 1;
  1074. X                   else
  1075. X                 current = header_page * headers_per_page + 1;
  1076. X                 }
  1077. X                       } else error("Already on last page.");
  1078. X               break;
  1079. X
  1080. Xprev_page:
  1081. X        case '-'    :  /* move to prev page if we're not on the first */
  1082. X               if(header_page > 0) {
  1083. X                 header_page--;
  1084. X                 nuhead++;    
  1085. X
  1086. X                 if(move_when_paged) {
  1087. X                   /* move to first message of new page */
  1088. X                   if(selected)
  1089. X                 current = visible_to_index(
  1090. X                   header_page * headers_per_page + 1) + 1;
  1091. X                   else
  1092. X                 current = header_page * headers_per_page + 1;
  1093. X                 }
  1094. X                       } else error("Already on first page.");
  1095. X               break;
  1096. X
  1097. Xfirst_msg:
  1098. X        case '='    :  if (selected)
  1099. X                 current = visible_to_index(1)+1;
  1100. X                       else
  1101. X                 current = 1;
  1102. X                       if (get_page(current))
  1103. X                 nuhead++;    
  1104. X               else
  1105. X                 nucurr++;    break;
  1106. X
  1107. Xlast_msg:
  1108. X        case '*'    :  if (selected) 
  1109. X                 current = (visible_to_index(selected)+1);
  1110. X               else
  1111. X                 current = message_count;    
  1112. X                       if (get_page(current))
  1113. X                 nuhead++;    
  1114. X               else
  1115. X                 nucurr++;     break;
  1116. X
  1117. X        case '|'    :  Writechar('|'); 
  1118. X                   softkeys_off();
  1119. X                           redraw = do_pipe();        
  1120. X                       softkeys_on(); break;
  1121. X
  1122. X        case '!'    :  Writechar('!'); 
  1123. X                   softkeys_off();
  1124. X                           redraw = subshell();        
  1125. X                       softkeys_on(); break;
  1126. X
  1127. X        case '%'    :  if (current > 0) {
  1128. X                 get_return(address, current-1);
  1129. X                 clear_error();
  1130. X                 PutLine1(LINES,(COLUMNS-strlen(address))/2,
  1131. X                      "%.78s", address);    
  1132. X               } else {
  1133. X                 error("No mail to get return address of!"); 
  1134. X                 fflush(stdin);
  1135. X               }
  1136. X                   break;
  1137. X
  1138. X        case '/'    :  if (pattern_match()) {
  1139. X                         if (get_page(current))
  1140. X                   nuhead++;
  1141. X                         else
  1142. X                           nucurr++;
  1143. X                       }
  1144. X               else {
  1145. X                  error("pattern not found!");
  1146. X                  fflush(stdin);
  1147. X               }
  1148. X               break;
  1149. X
  1150. X        case '<'    :  /* scan current message for calendar information */
  1151. X#ifdef ENABLE_CALENDAR
  1152. X               PutLine0(LINES-3, strlen("Command: "),     
  1153. X                   "Scan message for calendar entries...");
  1154. X               scan_calendar();
  1155. X#else
  1156. X                error("Sorry. Calendar function disabled.");
  1157. X               fflush(stdin);
  1158. X#endif
  1159. X               break;
  1160. X
  1161. X        case 'a'    :  if(alias()) redraw++;
  1162. X               else nufoot++;     
  1163. X               define_softkeys(MAIN);     break;
  1164. X            
  1165. X        case 'b'    :  PutLine0(LINES-3, strlen("Command: "), 
  1166. X                     "Bounce message");
  1167. X               fflush(stdout);
  1168. X               if (message_count < 1) {
  1169. X                   error("No mail to bounce!");
  1170. X                 fflush(stdin);
  1171. X               }
  1172. X               else 
  1173. X                 nufoot = remail();
  1174. X               break;
  1175. X
  1176. X        case 'c'    :  PutLine0(LINES-3, strlen("Command: "), 
  1177. X                  "Change folder");
  1178. X               define_softkeys(CHANGE);
  1179. X               redraw = change_file();
  1180. X               define_softkeys(MAIN);
  1181. X               break;
  1182. X
  1183. X        case ctrl('D') :
  1184. X        case '^'    :
  1185. X        case 'd'    :  if (message_count < 1) {
  1186. X                 error("No mail to delete!");
  1187. X                 fflush(stdin);
  1188. X               }
  1189. X               else {
  1190. X                 if(ch == ctrl('D')) {
  1191. X
  1192. X                   /* if current message did not become deleted,
  1193. X                    * don't to move to the next undeleted msg. */
  1194. X                   if(!meta_match(DELETED)) break;
  1195. X
  1196. X                 } else 
  1197. X                            delete_msg((ch == 'd'), TRUE);
  1198. X
  1199. X                 if (resolve_mode)     /* move after mail resolved */
  1200. X                   if((i=next_message(current-1, TRUE)) != -1) {
  1201. X                 current = i+1;
  1202. X                     if (get_page(current))
  1203. X                       nuhead++;
  1204. X                     else
  1205. X                       nucurr++;
  1206. X                   }
  1207. X                       }
  1208. X               break;
  1209. X
  1210. X
  1211. X#ifdef ALLOW_MAILBOX_EDITING
  1212. X        case 'e'    :  PutLine0(LINES-3,strlen("Command: "),"Edit folder");
  1213. X               if (current > 0) {
  1214. X                 edit_mailbox();
  1215. X                     if (cursor_control)
  1216. X                           transmit_functions(ON);    /* insurance */
  1217. X                  }
  1218. X               else {
  1219. X                 error("Folder is empty!");
  1220. X                 fflush(stdin);
  1221. X               }
  1222. X               break;
  1223. X#else
  1224. X        case 'e'    : error(
  1225. X            "Folder editing isn't configured in this version of ELM.");
  1226. X              fflush(stdin);
  1227. X              break;
  1228. X#endif
  1229. X        
  1230. X        case 'f'    :  PutLine0(LINES-3, strlen("Command: "), "Forward");
  1231. X               define_softkeys(YESNO);
  1232. X               if (current > 0) {
  1233. X                 if(forward()) redraw++;
  1234. X                 else nufoot++;
  1235. X               } else {
  1236. X                         error("No mail to forward!");
  1237. X                 fflush(stdin);
  1238. X               }
  1239. X               define_softkeys(MAIN);
  1240. X               break;
  1241. X
  1242. X        case 'g'    :  PutLine0(LINES-3,strlen("Command: "), "Group reply");
  1243. X                   fflush(stdout);
  1244. X               if (current > 0) {
  1245. X                 if (headers[current-1]->status & FORM_LETTER) {
  1246. X                   error("Can't group reply to a Form!!");
  1247. X                   fflush(stdin);
  1248. X                 }
  1249. X                 else {
  1250. X                   define_softkeys(YESNO);
  1251. X                           redraw = reply_to_everyone();    
  1252. X                   define_softkeys(MAIN);
  1253. X                         }
  1254. X                       }
  1255. X               else {
  1256. X                 error("No mail to reply to!"); 
  1257. X                 fflush(stdin);
  1258. X               }
  1259. X               break;
  1260. X
  1261. X        case 'h'    :  if (filter)
  1262. X                         PutLine0(LINES-3, strlen("Command: "), 
  1263. X                "Message with headers...");
  1264. X                       else
  1265. X                 PutLine0(LINES-3, strlen("Command: "),"Display message");
  1266. X               if(current > 0) {
  1267. X                 fflush(stdout);
  1268. X                 j = filter;
  1269. X                 filter = FALSE;
  1270. X                 i = show_msg(current);
  1271. X                 while (i)
  1272. X                i = process_showmsg_cmd(i);
  1273. X                 filter = j;
  1274. X                 redraw++;
  1275. X                 (void)get_page(current);
  1276. X               } else error("No mail to read!");
  1277. X               break;
  1278. X
  1279. X        case 'J'    :  if(current > 0) {
  1280. X                 if((i=next_message(current-1, FALSE)) != -1) {
  1281. X                   current = i+1;
  1282. X                   if (get_page(current))
  1283. X                     nuhead++;
  1284. X                   else
  1285. X                     nucurr++;
  1286. X                 } else error("No more messages below.");
  1287. X               } else error("No mail in folder!");
  1288. X               break;
  1289. X
  1290. Xnext_undel_msg:
  1291. X        case 'j'    :  if(current > 0) {
  1292. X                 if((i=next_message(current-1, TRUE)) != -1) {
  1293. X                   current = i+1;
  1294. X                   if (get_page(current))
  1295. X                     nuhead++;
  1296. X                   else
  1297. X                     nucurr++;
  1298. X                 } else error("No more undeleted messages below.");
  1299. X               } else error("No mail in folder!");
  1300. X               break;
  1301. X
  1302. X        case 'K'    :  if(current > 0) {
  1303. X                 if((i=prev_message(current-1, FALSE)) != -1) {
  1304. X                   current = i+1;
  1305. X                   if (get_page(current))
  1306. X                     nuhead++;
  1307. X                   else
  1308. X                     nucurr++;
  1309. X                 } else error("No more messages above.");
  1310. X               } else error("No mail in folder!");
  1311. X               break;
  1312. X
  1313. Xprev_undel_msg:
  1314. X        case 'k'    :  if(current > 0) {
  1315. X                 if((i=prev_message(current-1, TRUE)) != -1) {
  1316. X                   current = i+1;
  1317. X                   if (get_page(current))
  1318. X                     nuhead++;
  1319. X                   else
  1320. X                     nucurr++;
  1321. X                 } else error("No more undeleted messages above.");
  1322. X               } else error("No mail in folder!");
  1323. X               break;
  1324. X
  1325. X        case 'l'    :  PutLine0(LINES-3, strlen("Command: "),
  1326. X                       "Limit displayed messages by...");
  1327. X               clear_error();
  1328. X               if (limit() != 0) {
  1329. X                 get_page(current);
  1330. X                 redraw++;
  1331. X               } else {
  1332. X                 nufoot++;
  1333. X               }
  1334. X               break;
  1335. X
  1336. X        case 'm'    :  PutLine0(LINES-3, strlen("Command: "), "Mail");
  1337. X               redraw = sendmsg("", "", "", TRUE,allow_forms,FALSE); 
  1338. X               break;
  1339. X
  1340. X        case ' '    : 
  1341. X        case ctrl('J'):
  1342. X        case ctrl('M'):PutLine0(LINES-3, strlen("Command: "), 
  1343. X                      "Display message");    
  1344. X               fflush(stdout);
  1345. X               if(current > 0 ) {
  1346. X                 define_softkeys(READ);
  1347. X
  1348. X                 i = show_msg(current);
  1349. X                 while (i)
  1350. X                i = process_showmsg_cmd(i);
  1351. X                 redraw++;
  1352. X                 (void)get_page(current);
  1353. X               }else error ("No mail to read!");
  1354. X               break;
  1355. X
  1356. X        case 'n'    :  PutLine0(LINES-3,strlen("Command: "),"Next Message");
  1357. X               fflush(stdout);
  1358. X               define_softkeys(READ);
  1359. X
  1360. X               if(current > 0 ) {
  1361. X                 define_softkeys(READ);
  1362. X
  1363. X                 i = show_msg(current);
  1364. X                 while (i)
  1365. X                   i = process_showmsg_cmd(i);
  1366. X                 redraw++;
  1367. X                 if (++current > message_count)
  1368. X                   current = message_count;
  1369. X                 (void)get_page(current);
  1370. X               }else error ("No mail to read!");
  1371. X               break;
  1372. X
  1373. X        case 'o'    :  PutLine0(LINES-3, strlen("Command: "), "Options");
  1374. X               if((i=options()) > 0)
  1375. X                 get_page(current);
  1376. X               else if(i < 0)
  1377. X                 leave();
  1378. X               redraw++;    /* always fix da screen... */
  1379. X               break;
  1380. X
  1381. X        case 'p'    :  PutLine0(LINES-3, strlen("Command: "), "Print mail");
  1382. X               fflush(stdout);
  1383. X               if (message_count < 1) {
  1384. X                 error("No mail to print!");
  1385. X                 fflush(stdin);
  1386. X               }
  1387. X               else
  1388. X                 print_msg();            
  1389. X               break;
  1390. X
  1391. X        case 'q'    :  PutLine0(LINES-3, strlen("Command: "), "Quit");
  1392. X
  1393. X               if (mailfile_size != bytes(cur_folder)) {
  1394. X                 error("New Mail!  Quit cancelled...");
  1395. X                 fflush(stdin);
  1396. X                   if (folder_type == SPOOL) unlock();
  1397. X                       }
  1398. X                   else
  1399. X                 quit(TRUE);        
  1400. X
  1401. X               break;
  1402. X
  1403. X        case 'Q'    :  PutLine0(LINES-3, strlen("Command: "), "Quick quit");
  1404. X
  1405. X               if (mailfile_size != bytes(cur_folder)) {
  1406. X                 error("New Mail!  Quick Quit cancelled...");
  1407. X                   if (folder_type == SPOOL) unlock();
  1408. X                       }
  1409. X                   else
  1410. X                 quit(FALSE);        
  1411. X
  1412. X               break;
  1413. X
  1414. X        case 'r'    :  PutLine0(LINES-3, strlen("Command: "), 
  1415. X                  "Reply to message");
  1416. X               if (current > 0) 
  1417. X                         redraw = reply();    
  1418. X               else {
  1419. X                 error("No mail to reply to!"); 
  1420. X                 fflush(stdin);
  1421. X               }
  1422. X               softkeys_on();
  1423. X               break;
  1424. X
  1425. X        case '>'    : /** backwards compatibility **/
  1426. X
  1427. X        case 'C'    :
  1428. X        case 's'    :  if  (message_count < 1) {
  1429. X                 error1("No mail to %s!",
  1430. X                   ch != 'C' ? "save" : "copy");
  1431. X                 fflush(stdin);
  1432. X               }
  1433. X               else {
  1434. X                         PutLine1(LINES-3, strlen("Command: "),
  1435. X                      "%s to folder",
  1436. X                      ch != 'C' ? "Save" : "Copy");
  1437. X                 PutLine0(LINES-3,COLUMNS-40,
  1438. X                "(Use '?' to list your folders)");
  1439. X                 if (save(&redraw, FALSE, (ch != 'C'))
  1440. X                     && resolve_mode && ch != 'C') {
  1441. X
  1442. X                   i = current;
  1443. X                   while (current <= message_count &&
  1444. X                         (headers[current-1]->status & DELETED))
  1445. X                  current++;
  1446. X
  1447. X                   if (current > message_count)
  1448. X                     current = i;    /* reset - overshot! */
  1449. X                 
  1450. X                   if (get_page(current))
  1451. X                     nuhead++;
  1452. X                   else
  1453. X                     nucurr++;        
  1454. X                 }
  1455. X               }
  1456. X               ClearLine(LINES-2);        
  1457. X               break;
  1458. X
  1459. X            case ctrl('T') :
  1460. X        case 't'       :  if (message_count < 1) {
  1461. X                    error("No mail to tag!");
  1462. X                    fflush(stdin);
  1463. X                  }
  1464. X                  else if (ch == 't')
  1465. X                    tag_message(TRUE); 
  1466. X                  else
  1467. X                    meta_match(TAGGED);
  1468. X                          break;
  1469. X
  1470. X        case 'u'    :  if (message_count < 1) {
  1471. X                 error("No mail to mark as undeleted!");
  1472. X                 fflush(stdin);
  1473. X               }
  1474. X               else {
  1475. X                         undelete_msg(TRUE);
  1476. X                 if (resolve_mode)     /* move after mail resolved */
  1477. X                   if((i=next_message(current-1, FALSE)) != -1) {
  1478. X                 current = i+1;
  1479. X                     if (get_page(current))
  1480. X                       nuhead++;
  1481. X                     else
  1482. X                       nucurr++;
  1483. X                   }
  1484. X/*************************************************************************
  1485. X **  What we've done here is to special case the "U)ndelete" command to
  1486. X **  ignore whether the next message is marked for deletion or not.  The
  1487. X **  reason is obvious upon usage - it's a real pain to undelete a series
  1488. X **  of messages without this quirk.  Thanks to Jim Davis @ HPLabs for
  1489. X **  suggesting this more intuitive behaviour.
  1490. X **
  1491. X **  The old way, for those people that might want to see what the previous
  1492. X **  behaviour was to call next_message with TRUE, not FALSE.
  1493. X**************************************************************************/
  1494. X               }
  1495. X               break;
  1496. X
  1497. X        case ctrl('U') : if (message_count < 1) {
  1498. X                   error("No mail to undelete!");
  1499. X                   fflush(stdin);
  1500. X                 }
  1501. X                 else 
  1502. X                   meta_match(UNDELETE);
  1503. X                 break;
  1504. X
  1505. X        case ctrl('Q') :
  1506. X        case '\177' : 
  1507. X        case 'x'    :  PutLine0(LINES-3, strlen("Command: "), "Exit");  
  1508. X                           fflush(stdout);              leave();
  1509. X
  1510. X        case ctrl('L') : redraw++;    break;
  1511. X
  1512. X            case EOF :  leave();  /* Read failed, control tty died? */
  1513. X                        break;
  1514. X        
  1515. X        case '@'    : debug_screen();  redraw++;    break;
  1516. X    
  1517. X        case '#'    : if (message_count) {
  1518. X                debug_message(); 
  1519. X                redraw++;    
  1520. X              } 
  1521. X              else {
  1522. X                error("No mail to check.");
  1523. X                fflush(stdin);
  1524. X              }
  1525. X              break;
  1526. X
  1527. X        case NO_OP_COMMAND : break;    /* noop for timeout loop */
  1528. X
  1529. X        case ESCAPE : if (cursor_control) {
  1530. X                key_offset = 1;
  1531. X                ch = ReadCh(); 
  1532. X  
  1533. X                            if ( ch == '[' || ch == 'O')
  1534. X                            {
  1535. X                              ch = ReadCh();
  1536. X                              key_offset++;
  1537. X                            }
  1538. X  
  1539. X                if(ch == up[key_offset]) goto prev_undel_msg;
  1540. X                else if(ch == down[key_offset]) goto next_undel_msg;
  1541. X                else if(ch == right[key_offset]) goto next_page;
  1542. X                else if(ch == left[key_offset]) goto prev_page;
  1543. X                else if (hp_terminal) {
  1544. X                  switch (ch) {
  1545. X                  case 'U':        goto next_page;
  1546. X                  case 'V':        goto prev_page;
  1547. X                  case 'h':     
  1548. X                  case 'H':        goto first_msg;
  1549. X                  case 'F':        goto last_msg;
  1550. X                  case 'A':
  1551. X                  case 'D':
  1552. X                  case 'i':        goto next_undel_msg;
  1553. X                  case 'B':
  1554. X                  case 'I':
  1555. X                  case 'C':        goto prev_undel_msg;
  1556. X                  default: PutLine2(LINES-3, strlen("Command: "), 
  1557. X                    "%c%c", ESCAPE, ch);
  1558. X                  }
  1559. X                } else /* false hit - output */
  1560. X                  PutLine2(LINES-3, strlen("Command: "), 
  1561. X                      "%c%c", ESCAPE, ch);
  1562. X              }
  1563. X
  1564. X              /* else fall into the default error message! */
  1565. X
  1566. X        default    : if (ch > '0' && ch <= '9') {
  1567. X                PutLine0(LINES-3, strlen("Command: "), 
  1568. X                    "New Current Message");
  1569. X                i = read_number(ch);
  1570. X
  1571. X                if( i > message_count)
  1572. X                  error("Not that many messages.");
  1573. X                else if(selected
  1574. X                && isoff(headers[i-1]->status, VISIBLE))
  1575. X                  error("Message not in limited display.");
  1576. X                else {
  1577. X                  current = i;
  1578. X                  if (get_page(current))
  1579. X                nuhead++;
  1580. X                  else
  1581. X                nucurr++;
  1582. X                }
  1583. X              }
  1584. X              else {
  1585. X                 error("Unknown command. Use '?' for help.");
  1586. X                fflush(stdin);
  1587. X              }
  1588. X      }
  1589. X
  1590. X      if (redraw)
  1591. X        showscreen();
  1592. X
  1593. X      if ((current < 1) || (selected && compute_visible(current) < 1)) {
  1594. X        if (message_count > 0) {
  1595. X          /* We are out of range! Get to first message! */
  1596. X          if (selected)
  1597. X            current = compute_visible(1);
  1598. X          else
  1599. X            current = 1;
  1600. X        }
  1601. X        else
  1602. X          current = 0;
  1603. X      }
  1604. X      else if ((current > message_count)
  1605. X           || (selected && compute_visible(current) > selected)) {
  1606. X        if (message_count > 0) {
  1607. X          /* We are out of range! Get to last (visible) message! */
  1608. X          if (selected)
  1609. X            current = visible_to_index(selected)+1;
  1610. X          else
  1611. X            current = message_count;
  1612. X        }
  1613. X        else
  1614. X          current = 0;
  1615. X      }
  1616. X        
  1617. X      if (nuhead) 
  1618. X        show_headers();
  1619. X      else if (nucurr)
  1620. X        show_current();
  1621. X      else if (nufoot) {
  1622. X        if (mini_menu) {
  1623. X          MoveCursor(LINES-7, 0);  
  1624. X              CleartoEOS();
  1625. X          show_menu();
  1626. X        }
  1627. X        else {
  1628. X          MoveCursor(LINES-4, 0);
  1629. X          CleartoEOS();
  1630. X        }
  1631. X        show_last_error();    /* for those operations that have to
  1632. X                 * clear the footer except for a message.
  1633. X                 */
  1634. X      }
  1635. X
  1636. X    } /* the BIG while loop! */
  1637. X}
  1638. X
  1639. Xdebug_screen()
  1640. X{
  1641. X    /**** spit out all the current variable settings and the table
  1642. X          entries for the current 'n' items displayed. ****/
  1643. X
  1644. X    register int i, j;
  1645. X    char     buffer[SLEN];
  1646. X
  1647. X    ClearScreen();
  1648. X    Raw(OFF);
  1649. X
  1650. X    PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n",
  1651. X            current, message_count);
  1652. X    PutLine2(2,0,"Header_page = %d           \t\t%d possible page(s)\n",
  1653. X        header_page, (int) (message_count / headers_per_page) + 1);
  1654. X
  1655. X    PutLine1(4,0,"\nCurrent mailfile is %s.\n\n", cur_folder);
  1656. X
  1657. X    i = header_page*headers_per_page;    /* starting header */
  1658. X
  1659. X    if ((j = i + (headers_per_page-1)) >= message_count) 
  1660. X      j = message_count-1;
  1661. X
  1662. X    Write_to_screen(
  1663. X"Num      From                     Subject                         Lines  Offset\n\r\n\r",0);
  1664. X
  1665. X    while (i <= j) {
  1666. X       sprintf(buffer, 
  1667. X       "%3d  %-16.16s  %-40.40s  %4d  %d\n\r",
  1668. X            i+1,
  1669. X                headers[i]->from, 
  1670. X                headers[i]->subject,
  1671. X            headers[i]->lines,
  1672. X            headers[i]->offset);
  1673. X        Write_to_screen(buffer, 0);
  1674. X      i++;
  1675. X    }
  1676. X    
  1677. X    Raw(ON);
  1678. X
  1679. X    PutLine0(LINES,0,"Press any key to return.");
  1680. X    (void) ReadCh();
  1681. X}
  1682. X
  1683. X
  1684. Xdebug_message()
  1685. X{
  1686. X    /**** Spit out the current message record.  Include EVERYTHING
  1687. X          in the record structure. **/
  1688. X    
  1689. X    char buffer[SLEN];
  1690. X    register struct header_rec *current_header = headers[current-1];
  1691. X
  1692. X    ClearScreen();
  1693. X    Raw(OFF);
  1694. X
  1695. X    Write_to_screen("\t\t\t----- Message %d -----\n\r\n\r\n\r\n\r", 1,
  1696. SHAR_EOF
  1697. echo "End of part 13"
  1698. echo "File src/elm.c is continued in part 14"
  1699. echo "14" > s2_seq_.tmp
  1700. exit 0
  1701.  
  1702.