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

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