home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / elm2.3 / part19 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  49.3 KB

  1. Subject:  v22i078:  ELM mail syste, release 2.3, Part19/26
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 5f0002cc 3e147682 7c5920ad cf90a46f
  5.  
  6. Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
  7. Posting-number: Volume 22, Issue 78
  8. Archive-name: elm2.3/part19
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is part 19 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file src/newmbox.c continued
  15. #
  16. CurArch=19
  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/newmbox.c"
  27. sed 's/^X//' << 'SHAR_EOF' >> src/newmbox.c
  28. X          else in_to_list = FALSE;
  29. X        }
  30. X      }
  31. X      if (!in_header && first_word(buffer, START_ENCODE))
  32. X        current_header->encrypted = 1;
  33. X      fbytes += (long) line_bytes;
  34. X    }
  35. X
  36. X    if (count)
  37. X      headers[count-1]->lines = line + 1;
  38. X
  39. X    if (folder_type == SPOOL) {
  40. X      unlock();    /* remove lock file! */
  41. X      if ((ferror(mailfile)) || (fclose(mailfile) == EOF)) {
  42. X          err = errno;
  43. X          Write_to_screen("\n\rClose on folder %s failed!!\n\r", 1,
  44. X                  cur_folder);
  45. X          Write_to_screen("** %s - %s. **\n\r", 2,
  46. X                  error_name(err), error_description(err));
  47. X          dprint(1, (debugfile, "Can't close on folder %s!!\n",
  48. X             cur_folder));
  49. X          rm_temps_exit();
  50. X      }
  51. X      if ((ferror(temp)) || (fclose(temp) == EOF)) {
  52. X          err = errno;
  53. X          Write_to_screen("\n\rClose on tempfile %s failed!!\n\r", 1,
  54. X                  cur_tempfolder);
  55. X          Write_to_screen("** %s - %s. **\n\r", 2,
  56. X                  error_name(err), error_description(err));
  57. X          dprint(1, (debugfile, "Can't close on tempfile %s!!\n",
  58. X             cur_tempfolder));
  59. X          rm_temps_exit();
  60. X      }
  61. X      /* sanity check on append - is resulting temp file longer??? */
  62. X      if ( bytes(cur_tempfolder) != mailfile_size) {
  63. X         Write_to_screen(
  64. X           "\n\rnewmbox - length of mbox. != spool mailbox length!!\n\r",
  65. X        0);
  66. X        dprint(0, (debugfile, "newmbox - mbox. != spool mail length"));
  67. X        rm_temps_exit();
  68. X      }
  69. X      if ((mailfile = fopen(cur_tempfolder,"r")) == NULL) {
  70. X        err = errno;
  71. X        MoveCursor(LINES,0);
  72. X        Raw(OFF);
  73. X        Write_to_screen(
  74. X           "\n\rAugh! Couldn't reopen %s as temp file.\n\r",
  75. X               1, cur_tempfolder);
  76. X        Write_to_screen("** %s - %s. **\n\r", 2, error_name(err),
  77. X           error_description(err));
  78. X        dprint(1, (debugfile,
  79. X          "Error: Reopening %s as temp file failed!  errno %s (%s)\n",
  80. X               cur_tempfolder, error_name(errno), "read_headers"));
  81. X        leave();
  82. X      }
  83. X    }
  84. X    else 
  85. X          rewind(mailfile);
  86. X
  87. X    /* Sort folder *before* we establish the current message, so that
  88. X     * the current message is based on the post-sort order.
  89. X     * Note that we have to set the global variable message_count
  90. X     * before the sort for the sort to correctly keep the correct
  91. X     * current message if we are only adding new messages here. */
  92. X
  93. X    message_count = count;
  94. X    sort_mailbox(count, 1);
  95. X
  96. X    /* Now lets figure what the current message should be.
  97. X     * If we are only reading in newly added messages from a mailfile
  98. X     * that already had some messages, current should remain the same.
  99. X     * If we have a folder of no messages, current should be zero.
  100. X     * Otherwise, if we have point_to_new on then the current message
  101. X     * is the first message of status NEW if there is one.
  102. X     * If we don't have point_to_new on or if there are no messages of
  103. X     * of status NEW, then the current message is the first message.
  104. X     */
  105. X    if(!(add_new_only && current != 0)) {
  106. X      if(count == 0)
  107. X        current = 0;
  108. X      else {
  109. X        current = 1;
  110. X        if (point_to_new) {
  111. X          for(another_count = 0; another_count < count; another_count++) {
  112. X        if(ison(headers[another_count]->status, NEW)) {
  113. X          current = another_count+1;
  114. X          break;    /* first one found give up */
  115. X        }
  116. X          }
  117. X        }
  118. X      }
  119. X    }
  120. X        get_page(current);
  121. X    return(count);
  122. X}
  123. SHAR_EOF
  124. echo "File src/newmbox.c is complete"
  125. chmod 0444 src/newmbox.c || echo "restore of src/newmbox.c fails"
  126. echo "x - extracting src/opt_utils.c (Text)"
  127. sed 's/^X//' << 'SHAR_EOF' > src/opt_utils.c &&
  128. X
  129. Xstatic char rcsid[] = "@(#)$Id: opt_utils.c,v 4.1 90/04/28 22:43:37 syd Exp $";
  130. X
  131. X/*******************************************************************************
  132. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  133. X *
  134. X *             Copyright (c) 1986, 1987 Dave Taylor
  135. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  136. X *******************************************************************************
  137. X * Bug reports, patches, comments, suggestions should be sent to:
  138. X *
  139. X *    Syd Weinstein, Elm Coordinator
  140. X *    elm@DSI.COM            dsinc!elm
  141. X *
  142. X *******************************************************************************
  143. X * $Log:    opt_utils.c,v $
  144. X * Revision 4.1  90/04/28  22:43:37  syd
  145. X * checkin of Elm 2.3 as of Release PL0
  146. X * 
  147. X *
  148. X ******************************************************************************/
  149. X
  150. X/** This file contains routines that might be needed for the various
  151. X     machines that the mailer can run on.  Please check the Makefile
  152. X     for more help and/or information. 
  153. X
  154. X**/
  155. X
  156. X#include "headers.h"
  157. X#include <ctype.h>
  158. X
  159. X#ifdef PWDINSYS
  160. X#  include <sys/pwd.h>
  161. X#else
  162. X#  include <pwd.h>
  163. X#endif
  164. X
  165. X#ifdef BSD
  166. X#undef tolower
  167. X#undef toupper
  168. X#endif
  169. X
  170. X#ifndef GETHOSTNAME
  171. X# ifdef DOUNAME
  172. X#  include <sys/types.h>
  173. X#  include <sys/utsname.h>
  174. X# endif
  175. X#endif
  176. X
  177. Xchar *index();
  178. X
  179. X#ifndef GETHOSTNAME
  180. X
  181. Xgethostname(cur_hostname,size) /* get name of current host */
  182. Xchar *cur_hostname;
  183. Xint size;
  184. X{
  185. X    /** Return the name of the current host machine. **/
  186. X
  187. X#if defined(XENIX) & !defined(DOUNAME)
  188. X    char    buf[32];
  189. X    FILE    *fp;
  190. X    char    *p;
  191. X
  192. X    if ((fp = fopen("/etc/systemid", "r")) != 0) {
  193. X      fgets(buf, sizeof(buf) - 1, fp);
  194. X      fclose(fp);
  195. X      if ((p = index(buf, '\n')) != NULL)
  196. X        *p = '\0';
  197. X      (void) strncpy(cur_hostname, buf, size - 1);
  198. X      cur_hostname[size - 1] = '\0';
  199. X      return 0;
  200. X    }
  201. X
  202. X#else   /* XENIX */
  203. X
  204. X#ifdef DOUNAME
  205. X    /** This routine compliments of Scott McGregor at the HP
  206. X        Corporate Computing Center **/
  207. X     
  208. X    int uname();
  209. X    struct utsname name;
  210. X
  211. X    (void) uname(&name);
  212. X    (void) strncpy(cur_hostname,name.nodename,size-1);
  213. X#else
  214. X    (void) strncpy(cur_hostname, HOSTNAME, size-1);
  215. X#endif    /* DOUNAME */
  216. X
  217. X    cur_hostname[size - 1] = '\0';
  218. X    return 0;
  219. X
  220. X#endif  /* XENIX */
  221. X}
  222. X
  223. X#endif  /* GETHOSTNAME */
  224. X
  225. X
  226. Xgethostdomain(hostdom, size)    /* get domain of current host */
  227. Xchar *hostdom;
  228. Xint size;
  229. X{
  230. X    char    buf[64];
  231. X    FILE    *fp;
  232. X    char    *p;
  233. X
  234. X    if (size < 2)
  235. X      return -1;
  236. X
  237. X    if ((fp = fopen(hostdomfile, "r")) != 0) {
  238. X      fgets(buf, sizeof(buf) - 1, fp);
  239. X      fclose(fp);
  240. X      if ((p = index(buf, '\n')) != NULL)
  241. X        *p = '\0';
  242. X    }
  243. X    else {
  244. X      strncpy(buf, DEFAULT_DOMAIN, sizeof(buf) - 1);
  245. X    }
  246. X    if (buf[0] != '\0' && buf[0] != '.') {
  247. X      *hostdom++ = '.';
  248. X      --size;
  249. X    }
  250. X    (void) strncpy(hostdom, buf, size - 1);
  251. X    hostdom[size - 1] = '\0';
  252. X
  253. X    return 0;
  254. X}
  255. X
  256. X
  257. X#ifdef NEED_CUSERID
  258. X
  259. Xchar *cuserid(uname)
  260. X     char *uname;
  261. X{
  262. X    /** Added for compatibility with Bell systems, this is the last-ditch
  263. X        attempt to get the users login name, after getlogin() fails.  It
  264. X        instantiates "uname" to the name of the user...(it also tries
  265. X        to use "getlogin" again, just for luck)
  266. X    **/
  267. X    /** This wasn't really compatible.  According to our man page, 
  268. X     ** It was inconsistent.  If the parameter is NULL then you return
  269. X     ** the name in a static area.  Else the ptr is supposed to be a
  270. X     ** pointer to l_cuserid bytes of memory [probally 9 bytes]...
  271. X     ** It's not mention what it should return if you copy the name
  272. X     ** into the array, so I chose NULL.
  273. X     **                     Sept 20, 1988
  274. X     **                    **WJL**
  275. X     **/
  276. X
  277. X  struct passwd *password_entry;
  278. X#ifndef _POSIX_SOURCE
  279. X  struct passwd *getpwuid();
  280. X#endif
  281. X  char   *name, *getlogin();
  282. X  static char buf[10];
  283. X  register returnonly = 0;
  284. X  
  285. X  if (uname == NULL) ++returnonly;
  286. X  
  287. X  if ((name = getlogin()) != NULL) {
  288. X    if (returnonly) {
  289. X      return(name);
  290. X    } else {
  291. X      strcpy(uname, name);
  292. X      return name;
  293. X    }
  294. X  } 
  295. X  else 
  296. X    if (( password_entry = getpwuid(getuid())) != NULL) 
  297. X      {
  298. X    if (returnonly) 
  299. X      {
  300. X        return(password_entry->pw_name);
  301. X      }
  302. X    else 
  303. X      {
  304. X        strcpy(uname, password_entry->pw_name);
  305. X        return name;
  306. X      }
  307. X      } 
  308. X    else 
  309. X      {
  310. X    return NULL;
  311. X      }
  312. X}
  313. X
  314. X#endif
  315. X
  316. X#if defined(BSD) && !defined(_POSIX_SOURCE)
  317. X
  318. X/** some supplementary string functions for Berkeley Unix systems **/
  319. X
  320. Xint
  321. Xtolower(ch)
  322. Xchar ch;
  323. X{
  324. X    /** This should be a macro call, but if you use this as a macro
  325. X        calls to 'tolower' where the argument is a function call will
  326. X        cause the function to be called TWICE which is obviously the
  327. X        wrong behaviour.  On the other hand, to just blindly translate
  328. X        assuming the character is always uppercase can cause BIG
  329. X        problems, so...
  330. X    **/
  331. X
  332. X    return ( isupper(ch) ? ch - 'A' + 'a' : ch );
  333. X}
  334. X
  335. Xint
  336. Xtoupper(ch)
  337. Xchar ch;
  338. X{
  339. X    /** see comment for above routine - tolower() **/
  340. X
  341. X    return ( islower(ch) ? ch - 'a' + 'A' : ch );
  342. X}
  343. X
  344. Xchar *strtok(source, keys)
  345. Xchar *source, *keys;
  346. X{
  347. X    /** This function returns a pointer to the next word in source
  348. X        with the string considered broken up at the characters 
  349. X        contained in 'keys'.  Source should be a character pointer
  350. X        when this routine is first called, then NULL subsequently.
  351. X        When strtok has exhausted the source string, it will 
  352. X        return NULL as the next word. 
  353. X
  354. X        WARNING: This routine will DESTROY the string pointed to
  355. X        by 'source' when first invoked.  If you want to keep the
  356. X        string, make a copy before using this routine!!
  357. X     **/
  358. X
  359. X    register int  last_ch;
  360. X    static   char *sourceptr;
  361. X         char *return_value;
  362. X
  363. X    if (source != NULL)
  364. X      sourceptr = source;
  365. X    
  366. X    if (*sourceptr == '\0') 
  367. X      return(NULL);        /* we hit end-of-string last time!? */
  368. X
  369. X    sourceptr += strspn(sourceptr, keys);    /* skip leading crap */
  370. X    
  371. X    if (*sourceptr == '\0') 
  372. X      return(NULL);        /* we've hit end-of-string */
  373. X
  374. X    last_ch = strcspn(sourceptr, keys);    /* end of good stuff */
  375. X
  376. X    return_value = sourceptr;        /* and get the ret   */
  377. X
  378. X    sourceptr += last_ch;            /* ...value          */
  379. X
  380. X    if (*sourceptr != '\0')        /* don't forget if we're at END! */
  381. X      sourceptr++;               /* and skipping for next time */
  382. X
  383. X    return_value[last_ch] = '\0';        /* ..ending right    */
  384. X    
  385. X    return((char *) return_value);        /* and we're outta here! */
  386. X}
  387. X
  388. Xchar *strpbrk(source, keys)
  389. Xchar *source, *keys;
  390. X{
  391. X    /** Returns a pointer to the first character of source that is any
  392. X        of the specified keys, or NULL if none of the keys are present
  393. X        in the source string. 
  394. X    **/
  395. X
  396. X    register int loc = 0, key_index = 0;
  397. X
  398. X    while (source[loc] != '\0') {
  399. X      key_index = 0;
  400. X      while (keys[key_index] != '\0')
  401. X        if (keys[key_index++] == source[loc])
  402. X          return((char *) (source + loc));
  403. X      loc++;
  404. X    }
  405. X    
  406. X    return(NULL);
  407. X}
  408. X
  409. X#endif
  410. X
  411. X#ifndef STRSPN
  412. X
  413. Xstrspn(source, keys)
  414. Xchar *source, *keys;
  415. X{
  416. X    /** This function returns the length of the substring of
  417. X        'source' (starting at zero) that consists ENTIRELY of
  418. X        characters from 'keys'.  This is used to skip over a
  419. X        defined set of characters with parsing, usually. 
  420. X    **/
  421. X
  422. X    register int loc = 0, key_index = 0;
  423. X
  424. X    while (source[loc] != '\0') {
  425. X      key_index = 0;
  426. X      while (keys[key_index] != source[loc])
  427. X        if (keys[key_index++] == '\0')
  428. X          return(loc);
  429. X      loc++;
  430. X    }
  431. X
  432. X    return(loc);
  433. X}
  434. X
  435. X#endif
  436. X
  437. X#ifndef STRCSPN
  438. X
  439. Xstrcspn(source, keys)
  440. Xchar *source, *keys;
  441. X{
  442. X    /** This function returns the length of the substring of
  443. X        'source' (starting at zero) that consists entirely of
  444. X        characters NOT from 'keys'.  This is used to skip to a
  445. X        defined set of characters with parsing, usually. 
  446. X        NOTE that this is the opposite of strspn() above
  447. X    **/
  448. X
  449. X    register int loc = 0, key_index = 0;
  450. X
  451. X    while (source[loc] != '\0') {
  452. X      key_index = 0;
  453. X      while (keys[key_index] != '\0')
  454. X        if (keys[key_index++] == source[loc])
  455. X          return(loc);
  456. X      loc++;
  457. X    }
  458. X
  459. X    return(loc);
  460. X}
  461. X
  462. X#endif
  463. X
  464. X#ifndef TEMPNAM
  465. X/* and a tempnam for temporary files */
  466. Xstatic int cnt = 0;
  467. X
  468. Xchar *tempnam( dir, pfx)
  469. X char *dir, *pfx;
  470. X{
  471. X    char space[SLEN];
  472. X    char *newspace;
  473. X
  474. X    char    *malloc();
  475. X
  476. X    if (dir == NULL) {
  477. X        dir = "/usr/tmp";
  478. X    } else if (*dir == '\0') {
  479. X        dir = "/usr/tmp";
  480. X    }
  481. X    
  482. X    if (pfx == NULL) {
  483. X        pfx = "";
  484. X    }
  485. X
  486. X    sprintf(space, "%s%s%d.%d", dir, pfx, getpid(), cnt);
  487. X    cnt++;
  488. X    
  489. X    newspace = malloc(strlen(space) + 1);
  490. X    if (newspace != NULL) {
  491. X        strcpy(newspace, space);
  492. X    }
  493. X    return newspace;
  494. X}
  495. X
  496. X#endif
  497. X
  498. X#ifndef GETOPT
  499. X
  500. X/*LINTLIBRARY*/
  501. X#define NULL    0
  502. X#define EOF    (-1)
  503. X#define ERR(s, c)    if(opterr){\
  504. X    extern int strlen(), write();\
  505. X    char errbuf[2];\
  506. X    errbuf[0] = c; errbuf[1] = '\n';\
  507. X    (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
  508. X    (void) write(2, s, (unsigned)strlen(s));\
  509. X    (void) write(2, errbuf, 2);}
  510. X
  511. Xextern int strcmp();
  512. X
  513. Xint    opterr = 1;
  514. Xint    optind = 1;
  515. Xint    optopt;
  516. Xchar    *optarg;
  517. X
  518. Xint
  519. Xgetopt(argc, argv, opts)
  520. Xint    argc;
  521. Xchar    **argv, *opts;
  522. X{
  523. X    static int sp = 1;
  524. X    register int c;
  525. X    register char *cp;
  526. X
  527. X    if(sp == 1)
  528. X        if(optind >= argc ||
  529. X           argv[optind][0] != '-' || argv[optind][1] == '\0')
  530. X            return(EOF);
  531. X        else if(strcmp(argv[optind], "--") == NULL) {
  532. X            optind++;
  533. X            return(EOF);
  534. X        }
  535. X    optopt = c = argv[optind][sp];
  536. X    if(c == ':' || (cp=index(opts, c)) == NULL) {
  537. X        ERR(": illegal option -- ", c);
  538. X        if(argv[optind][++sp] == '\0') {
  539. X            optind++;
  540. X            sp = 1;
  541. X        }
  542. X        return('?');
  543. X    }
  544. X    if(*++cp == ':') {
  545. X        if(argv[optind][sp+1] != '\0')
  546. X            optarg = &argv[optind++][sp+1];
  547. X        else if(++optind >= argc) {
  548. X            ERR(": option requires an argument -- ", c);
  549. X            sp = 1;
  550. X            return('?');
  551. X        } else
  552. X            optarg = argv[optind++];
  553. X        sp = 1;
  554. X    } else {
  555. X        if(argv[optind][++sp] == '\0') {
  556. X            sp = 1;
  557. X            optind++;
  558. X        }
  559. X        optarg = NULL;
  560. X    }
  561. X    return(c);
  562. X}
  563. X
  564. X#endif
  565. X
  566. X#ifndef RENAME
  567. Xint rename(tmpfname, fname)
  568. Xchar *tmpfname, *fname;
  569. X{
  570. X    int status;
  571. X
  572. X    (void) unlink(fname);
  573. X    if ((status = link(tmpfname, fname)) != 0)
  574. X        return(status);
  575. X    (void) unlink(tmpfname);
  576. X    return(0);
  577. X}
  578. X#endif
  579. SHAR_EOF
  580. chmod 0444 src/opt_utils.c || echo "restore of src/opt_utils.c fails"
  581. echo "x - extracting src/options.c (Text)"
  582. sed 's/^X//' << 'SHAR_EOF' > src/options.c &&
  583. X
  584. Xstatic char rcsid[] = "@(#)$Id: options.c,v 4.1 90/04/28 22:43:38 syd Exp $";
  585. X
  586. X/*******************************************************************************
  587. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  588. X *
  589. X *             Copyright (c) 1986, 1987 Dave Taylor
  590. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  591. X *******************************************************************************
  592. X * Bug reports, patches, comments, suggestions should be sent to:
  593. X *
  594. X *    Syd Weinstein, Elm Coordinator
  595. X *    elm@DSI.COM            dsinc!elm
  596. X *
  597. X *******************************************************************************
  598. X * $Log:    options.c,v $
  599. X * Revision 4.1  90/04/28  22:43:38  syd
  600. X * checkin of Elm 2.3 as of Release PL0
  601. X * 
  602. X *
  603. X ******************************************************************************/
  604. X
  605. X/** This set of routines allows the alteration of a number of paramaters
  606. X    in the Elm mailer, including the following;
  607. X
  608. X    calendar-file    <where to put calendar entries>
  609. X    display pager    <how to page messages>
  610. X    editor        <name of composition editor>
  611. X    folder-dir    <folder directory>
  612. X    sort-by        <how to sort folders>
  613. X    sent-mail    <file to save outbound message copies to>
  614. X    printmail    <how to print messages>
  615. X    full_username    <your full user name for outgoing mail>
  616. X
  617. X    arrow-cursor    <on or off>
  618. X    menu-display    <on or off>
  619. X
  620. X    user-level    <BEGINNER|INTERMEDIATE|EXPERT>
  621. X        names-only      <on or off>
  622. X    
  623. X    And others as they seem useful.
  624. X
  625. X**/
  626. X
  627. X#include "headers.h"
  628. X
  629. X#ifdef BSD
  630. X#undef tolower
  631. X#endif
  632. X
  633. X#undef onoff
  634. X#define   onoff(n)    (n == 1? "ON ":"OFF")
  635. X
  636. Xchar *one_liner_for(), *level_name();
  637. Xunsigned long sleep();
  638. X
  639. Xoptions()
  640. X{
  641. X    /** change options... **/
  642. X    /* return:
  643. X     *    > 0    if restort was done - to indicate we might need to
  644. X     *         change the page of our headers as a consequence
  645. X     *        of the new sort order
  646. X     *    < 0    if user entered 'x' to quit elm immediately
  647. X     *    0    otherwise
  648. X     */
  649. X
  650. X    int    ch,
  651. X             resort = 0;
  652. X    char    *strcpy(),
  653. X             temp[SLEN];    /* needed when an option is run through
  654. X                 * expand_env(), because that function
  655. X                 * is destructive of the original
  656. X                 */
  657. X
  658. X    display_options();
  659. X
  660. X    clearerr(stdin);
  661. X
  662. X    while(1) {
  663. X      ClearLine(LINES-4);
  664. X
  665. X      Centerline(LINES-4,
  666. X "Select first letter of option line, '>' to save, or 'i' to return to index.");
  667. X
  668. X      PutLine0(LINES-2, 0, "Command: ");
  669. X
  670. X      ch = ReadCh();
  671. X      ch = tolower(ch);
  672. X
  673. X      clear_error();    /* remove possible "sorting" message etc... */ 
  674. X
  675. X      one_liner(one_liner_for(ch));
  676. X
  677. X      switch (ch) {
  678. X        case 'c' : optionally_enter(raw_calendar_file, 2, 23, FALSE, FALSE);
  679. X               strcpy(temp, raw_calendar_file);
  680. X               expand_env(calendar_file, temp);
  681. X               break;
  682. X        case 'd' : optionally_enter(raw_pager, 3, 23, FALSE, FALSE); 
  683. X               strcpy(temp, raw_pager);
  684. X               expand_env(pager, temp);
  685. X               clear_pages = (equal(pager, "builtin+") || 
  686. X                         equal(pager, "internal+")); 
  687. X               break;
  688. X        case 'e' : optionally_enter(raw_editor, 4, 23, FALSE, FALSE);
  689. X               strcpy(temp, raw_editor);
  690. X               expand_env(editor, temp);
  691. X                   break;
  692. X        case 'f' : optionally_enter(raw_folders, 5, 23, FALSE, FALSE);
  693. X               strcpy(temp, raw_folders);
  694. X               expand_env(folders, temp);
  695. X               break;
  696. X        case 's' : if(change_sort(6,23)) resort++;            break;
  697. X        case 'o' : optionally_enter(raw_sentmail, 7, 23, FALSE, FALSE);
  698. X               strcpy(temp, raw_sentmail);
  699. X               expand_env(sent_mail, temp);
  700. X               break;
  701. X        case 'p' : optionally_enter(raw_printout, 8, 23, FALSE, FALSE);
  702. X               strcpy(temp, raw_printout);
  703. X               expand_env(printout, temp);
  704. X               break;
  705. X        case 'y' : optionally_enter(full_username, 9, 23, FALSE, FALSE);
  706. X               break;
  707. X        case 'a' : on_or_off(&arrow_cursor, 12, 23);         break;
  708. X        case 'm' : on_or_off(&mini_menu, 13, 23);            
  709. X               headers_per_page = LINES - (mini_menu ? 13 : 8); break;
  710. X
  711. X        case 'u' : switch_user_level(&user_level,15, 23);        break;
  712. X        case 'n' : on_or_off(&names_only, 16, 23);            break;
  713. X    
  714. X        case '?' : options_help(); 
  715. X                   PutLine0(LINES-2,0,"Command: ");            break;
  716. X       
  717. X        case '>' : printf("Save options in .elm/elmrc...");
  718. X               fflush(stdout);    save_options();        break;
  719. X
  720. X        case 'x' :    return(-1);    /* exit elm */
  721. X        case 'q' :    /* pop back up to previous level, in this case == 'i' */
  722. X        case 'i' :  /* return to index screen */
  723. X            return(resort ? 1 : 0);
  724. X        case ctrl('L'): display_options();                break;
  725. X        default: error("Command unknown!");
  726. X      }
  727. X
  728. X    }
  729. X}
  730. X    
  731. Xdisplay_options()
  732. X{
  733. X    /** Display all the available options.. **/
  734. X    
  735. X    char *sort_name();
  736. X    
  737. X    ClearScreen();
  738. X    Centerline(0,"-- ELM Options Editor --");
  739. X
  740. X#ifdef ENABLE_CALENDAR
  741. X    PutLine1(2, 0, "C)alendar file       : %s", raw_calendar_file);
  742. X#endif
  743. X    PutLine1(3, 0, "D)isplay mail using  : %s", raw_pager);
  744. X    PutLine1(4, 0, "E)ditor              : %s", raw_editor);
  745. X    PutLine1(5, 0, "F)older directory    : %s", raw_folders);
  746. X    PutLine1(6, 0, "S)orting criteria    : %s", sort_name(FULL));
  747. X    PutLine1(7, 0, "O)utbound mail saved : %s", raw_sentmail);
  748. X    PutLine1(8, 0, "P)rint mail using    : %s", raw_printout);
  749. X    PutLine1(9, 0, "Y)our full name      : %s", full_username);
  750. X
  751. X    PutLine1(12,0, "A)rrow cursor        : %s", onoff(arrow_cursor));
  752. X    PutLine1(13,0, "M)enu display        : %s", onoff(mini_menu));
  753. X
  754. X    PutLine1(15,0, "U)ser level          : %s", level_name(user_level));
  755. X    PutLine1(16,0, "N)ames only          : %s", onoff(names_only));
  756. X}
  757. X
  758. Xon_or_off(var, x, y)
  759. Xint *var, x,y;
  760. X{
  761. X    /** 'var' field at x.y toggles between on and off... **/
  762. X
  763. X    char ch;
  764. X
  765. X         PutLine0(x, y+6, 
  766. X        "(use <space> to toggle, any other key to leave)");
  767. X
  768. X    MoveCursor(x,y+3);    /* at end of value... */
  769. X
  770. X    do {
  771. X      ch = ReadCh();
  772. X
  773. X      if (ch == SPACE) {
  774. X        *var = ! *var;
  775. X        PutLine0(x,y, onoff(*var));
  776. X      }
  777. X    } while (ch == SPACE);
  778. X
  779. X    MoveCursor(x,y+4);     CleartoEOLN();    /* remove help prompt */
  780. X}
  781. X
  782. X
  783. Xswitch_user_level(ulevel, x, y)
  784. Xint *ulevel, x, y;
  785. X{
  786. X    /** step through possible user levels... **/
  787. X
  788. X         PutLine0(x, y+20, "<space> to change");
  789. X
  790. X    MoveCursor(x,y);    /* at end of value... */
  791. X
  792. X    while (ReadCh() == ' ') {
  793. X      *ulevel = (*ulevel >= 2? 0 : *ulevel + 1);
  794. X      PutLine1(x,y, "%s", level_name(*ulevel));
  795. X    }
  796. X
  797. X    MoveCursor(x,y+20);     CleartoEOLN();    /* remove help prompt */
  798. X}
  799. X    
  800. Xchange_sort(x, y)
  801. Xint x,y;
  802. X{
  803. X    /** change the sorting scheme... **/
  804. X    /** return !0 if new sort order, else 0 **/
  805. X    
  806. X    int last_sortby,    /* so we know if it changes... */
  807. X        sign = 1;        /* are we reverse sorting??    */
  808. X    int ch;            /* character typed in ...      */
  809. X
  810. X    last_sortby = sortby;    /* remember current ordering   */
  811. X
  812. X    PutLine0(x, COLUMNS-29, "(SPACE for next, or R)everse)");
  813. X    sort_one_liner(sortby);
  814. X    MoveCursor(x, y);
  815. X
  816. X    do {
  817. X      ch = ReadCh();
  818. X      ch = tolower(ch);
  819. X      switch (ch) {
  820. X        case SPACE : if (sortby < 0) { 
  821. X                   sign = -1; 
  822. X                   sortby = - sortby; 
  823. X               }
  824. X             else sign = 1;        /* insurance! */
  825. X               sortby = sign * ((sortby + 1) % (STATUS+2));
  826. X             if (sortby == 0) sortby = sign;  /* snicker */
  827. X               PutLine0(x, y, sort_name(PAD));
  828. X             sort_one_liner(sortby);
  829. X               MoveCursor(x, y);
  830. X             break;
  831. X
  832. X        case 'r'   : sortby = - sortby;
  833. X               PutLine0(x, y, sort_name(PAD));
  834. X             sort_one_liner(sortby);
  835. X               MoveCursor(x, y);
  836. X     }
  837. X        } while (ch == SPACE || ch == 'r');
  838. X
  839. X    MoveCursor(x, COLUMNS-30);    CleartoEOLN();
  840. X
  841. X    if (sortby != last_sortby) {
  842. X      error("Resorting folder...");
  843. X      sleep(1);
  844. X      sort_mailbox(message_count, 0);
  845. X    }
  846. X    ClearLine(LINES-2);        /* clear sort_one_liner()! */
  847. X    return(sortby-last_sortby);
  848. X}
  849. X
  850. Xone_liner(string)
  851. Xchar *string;
  852. X{
  853. X    /** A single-line description of the selected item... **/
  854. X
  855. X    ClearLine(LINES-4);
  856. X    if (string)
  857. X        Centerline(LINES-4, string);
  858. X}
  859. X
  860. Xsort_one_liner(sorting_by)
  861. Xint sorting_by;
  862. X{
  863. X    /** A one line summary of the particular sorting scheme... **/
  864. X
  865. X    ClearLine(LINES-2);
  866. X
  867. X    switch (sorting_by) {
  868. X      
  869. X      case -SENT_DATE : Centerline(LINES-2,
  870. X"This sort will order most-recently-sent to least-recently-sent");    break;
  871. X      case -RECEIVED_DATE : Centerline(LINES-2,
  872. X"This sort will order most-recently-received to least-recently-received");
  873. X                 break;
  874. X      case -MAILBOX_ORDER : Centerline(LINES-2,
  875. X"This sort will order most-recently-added-to-folder to least-recently");
  876. X                 break;
  877. X      case -SENDER : Centerline(LINES-2,
  878. X"This sort will order by sender name, in reverse alphabetical order");    break;
  879. X      case -SIZE   : Centerline(LINES-2,
  880. X"This sort will order messages by longest to shortest");        break;
  881. X      case -SUBJECT : Centerline(LINES-2,
  882. X"This sort will order by subject, in reverse alphabetical order");    break;
  883. X      case -STATUS  : Centerline(LINES-2,
  884. X"This sort will order by reverse status - Deleted through Tagged...");    break;
  885. X
  886. X      case SENT_DATE : Centerline(LINES-2,
  887. X"This sort will order least-recently-sent to most-recently-sent");    break;
  888. X      case RECEIVED_DATE : Centerline(LINES-2,
  889. X"This sort will order least-recently-received to most-recently-received");
  890. X                        break;
  891. X      case MAILBOX_ORDER : Centerline(LINES-2,
  892. X"This sort will order least-recently-added-to-folder to most-recently");
  893. X                 break;
  894. X      case SENDER : Centerline(LINES-2,
  895. X                "This sort will order by sender name");    break;
  896. X      case SIZE   : Centerline(LINES-2,
  897. X                "This sort will order messages by shortest to longest");
  898. X            break;
  899. X      case SUBJECT : Centerline(LINES-2,
  900. X                    "This sort will order messages by subject");    break;
  901. X      case STATUS  : Centerline(LINES-2,
  902. X"This sort will order by status - Tagged through Deleted...");        break;
  903. X    }
  904. X}
  905. X
  906. Xchar *one_liner_for(c)
  907. Xchar c;
  908. X{
  909. X    /** returns the one-line description of the command char... **/
  910. X
  911. X    switch (c) {
  912. X        case 'c' : return(
  913. X"This is the file where calendar entries from messages are saved.");
  914. X
  915. X        case 'd' : return(
  916. X"This is the program invoked to display individual messages (try 'builtin')");
  917. X
  918. X        case 'e' : return(
  919. X"This is the editor that will be used for sending messages, etc.");
  920. X
  921. X        case 'f' : return(
  922. X"This is the folders directory used when '=' (etc) is used in filenames");
  923. X
  924. X        case 'm' : return(
  925. X"This determines if you have the mini-menu displayed or not");
  926. X
  927. X        case 'n' : return(
  928. X"Whether to display the names and addresses on mail, or names only");
  929. X        case 'o' : return(
  930. X"This is where copies of outbound messages are saved automatically.");
  931. X
  932. X        case 'p' : return(
  933. X"This is how printouts are generated.  \"%s\" will be replaced by the filename.");
  934. X
  935. X        case 's' : return(
  936. X"This is used to specify the sorting criteria for the folders");
  937. X
  938. X        case 'y' : return(
  939. X"When mail is sent out, this is what your full name will be recorded as.");
  940. X
  941. X        case 'a' : return(
  942. X"This defines whether the ELM cursor is an arrow or a highlight bar.");
  943. X
  944. X       case 'u' : return(
  945. X"The level of knowledge you have about the ELM mail system.");
  946. X
  947. X        default : return(NULL);    /* nothing if we don't know! */
  948. X    }
  949. X}
  950. X
  951. Xoptions_help()
  952. X{
  953. X    /** help menu for the options screen... **/
  954. X
  955. X    char c, *ptr;
  956. X
  957. X    Centerline(LINES-3,
  958. X  "Press the key you want help for, '?' for a key list, or '.' to exit help");
  959. X
  960. X    lower_prompt("Key : ");
  961. X
  962. X    while ((c = ReadCh()) != '.') {
  963. X      c = tolower(c);
  964. X      if (c == '?') {
  965. X         display_helpfile(OPTIONS_HELP);
  966. X         display_options();
  967. X         return;
  968. X      }
  969. X      if ((ptr = one_liner_for(c)) != NULL)
  970. X        error2("%c = %s.", c, ptr);
  971. X      else
  972. X        error1("%c isn't used in this section.", c);
  973. X      lower_prompt("Key : ");
  974. X    }
  975. X}
  976. X
  977. Xchar *level_name(n)
  978. Xint n;
  979. X{
  980. X    /** return the 'name' of the level... **/
  981. X
  982. X    switch (n) {
  983. X      case 0 : return("Beginning User   ");
  984. X      case 1 : return("Intermediate User");
  985. X      default: return("Expert User      ");
  986. X    }
  987. X}
  988. SHAR_EOF
  989. chmod 0444 src/options.c || echo "restore of src/options.c fails"
  990. echo "x - extracting src/out_utils.c (Text)"
  991. sed 's/^X//' << 'SHAR_EOF' > src/out_utils.c &&
  992. X
  993. Xstatic char rcsid[] = "@(#)$Id: out_utils.c,v 4.1 90/04/28 22:43:40 syd Exp $";
  994. X
  995. X/*******************************************************************************
  996. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  997. X *
  998. X *             Copyright (c) 1986, 1987 Dave Taylor
  999. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  1000. X *******************************************************************************
  1001. X * Bug reports, patches, comments, suggestions should be sent to:
  1002. X *
  1003. X *    Syd Weinstein, Elm Coordinator
  1004. X *    elm@DSI.COM            dsinc!elm
  1005. X *
  1006. X *******************************************************************************
  1007. X * $Log:    out_utils.c,v $
  1008. X * Revision 4.1  90/04/28  22:43:40  syd
  1009. X * checkin of Elm 2.3 as of Release PL0
  1010. X * 
  1011. X *
  1012. X ******************************************************************************/
  1013. X
  1014. X/** This file contains routines used for output in the ELM program.
  1015. X
  1016. X**/
  1017. X
  1018. X#include "headers.h"
  1019. X
  1020. X
  1021. Xstatic char err_buffer[SLEN];        /* store last error message */
  1022. X
  1023. Xstatic char central_message_buffer[SLEN];
  1024. X
  1025. Xchar *strcpy();
  1026. X
  1027. Xshow_last_error()
  1028. X{
  1029. X    /** rewrite last error message! **/
  1030. X
  1031. X    error(err_buffer);
  1032. X}
  1033. X
  1034. Xclear_error()
  1035. X{
  1036. X    MoveCursor(LINES,0);
  1037. X    CleartoEOLN();
  1038. X    err_buffer[0] = '\0';
  1039. X}
  1040. X
  1041. Xset_error(s)
  1042. Xchar *s;
  1043. X{
  1044. X    strcpy(err_buffer, s);
  1045. X}
  1046. X
  1047. Xerror(s)
  1048. Xchar *s;
  1049. X{
  1050. X    /** outputs error 's' to screen at line 22, centered! **/
  1051. X
  1052. X    if(batch_only)
  1053. X      printf("%s\n\r", s);
  1054. X    else {
  1055. X      MoveCursor(LINES,0);
  1056. X      CleartoEOLN();
  1057. X      PutLine0(LINES,(COLUMNS-strlen(s))/2,s);
  1058. X      fflush(stdout);
  1059. X    }
  1060. X    strcpy(err_buffer, s);    /* save it too! */
  1061. X}
  1062. X
  1063. X/*VARARGS1*/
  1064. X
  1065. Xerror1(s, a)
  1066. Xchar *s, *a;
  1067. X{
  1068. X    /** same as error, but with a 'printf' argument **/
  1069. X    char buffer[SLEN];
  1070. X
  1071. X    sprintf(buffer,s,a);
  1072. X    error(buffer);
  1073. X}
  1074. X
  1075. X/*VARARGS1*/
  1076. X
  1077. Xerror2(s, a1, a2)
  1078. Xchar *s, *a1, *a2;
  1079. X{
  1080. X    /** same as error, but with two 'printf' arguments **/
  1081. X    char buffer[SLEN];
  1082. X
  1083. X    sprintf(buffer,s, a1, a2);
  1084. X    error(buffer);
  1085. X}
  1086. X
  1087. X/*VARARGS1*/
  1088. X
  1089. Xerror3(s, a1, a2, a3)
  1090. Xchar *s, *a1, *a2, *a3;
  1091. X{
  1092. X    /** same as error, but with three 'printf' arguments **/
  1093. X    char buffer[SLEN];
  1094. X
  1095. X    sprintf(buffer,s, a1, a2, a3);
  1096. X    error(buffer);
  1097. X}
  1098. X
  1099. Xlower_prompt(s)
  1100. Xchar *s;
  1101. X{
  1102. X    /** prompt user for input on LINES-1 line, left justified **/
  1103. X
  1104. X    PutLine0(LINES-1,0,s);
  1105. X    CleartoEOLN();
  1106. X}
  1107. X
  1108. Xprompt(s)
  1109. Xchar *s;
  1110. X{
  1111. X    /** prompt user for input on LINES-3 line, left justified **/
  1112. X
  1113. X    PutLine0(LINES-3,0,s);
  1114. X    CleartoEOLN();
  1115. X}
  1116. X
  1117. X
  1118. Xset_central_message(string, arg)
  1119. Xchar *string, *arg;
  1120. X{
  1121. X    /** set up the given message to be displayed in the center of
  1122. X        the current window **/ 
  1123. X
  1124. X    sprintf(central_message_buffer, string, arg);
  1125. X}
  1126. X
  1127. Xdisplay_central_message()
  1128. X{
  1129. X    /** display the message if set... **/
  1130. X
  1131. X    if (central_message_buffer[0] != '\0') {
  1132. X      ClearLine(LINES-15);
  1133. X      Centerline(LINES-15, central_message_buffer);
  1134. X      fflush(stdout);
  1135. X    }
  1136. X}
  1137. X
  1138. Xclear_central_message()
  1139. X{
  1140. X    /** clear the central message buffer **/
  1141. X
  1142. X    central_message_buffer[0] = '\0';
  1143. X}
  1144. SHAR_EOF
  1145. chmod 0444 src/out_utils.c || echo "restore of src/out_utils.c fails"
  1146. echo "x - extracting src/pattern.c (Text)"
  1147. sed 's/^X//' << 'SHAR_EOF' > src/pattern.c &&
  1148. X
  1149. Xstatic char rcsid[] = "@(#)$Id: pattern.c,v 4.1 90/04/28 22:43:42 syd Exp $";
  1150. X
  1151. X/*******************************************************************************
  1152. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  1153. X *
  1154. X *             Copyright (c) 1986, 1987 Dave Taylor
  1155. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  1156. X *******************************************************************************
  1157. X * Bug reports, patches, comments, suggestions should be sent to:
  1158. X *
  1159. X *    Syd Weinstein, Elm Coordinator
  1160. X *    elm@DSI.COM            dsinc!elm
  1161. X *
  1162. X *******************************************************************************
  1163. X * $Log:    pattern.c,v $
  1164. X * Revision 4.1  90/04/28  22:43:42  syd
  1165. X * checkin of Elm 2.3 as of Release PL0
  1166. X * 
  1167. X *
  1168. X ******************************************************************************/
  1169. X
  1170. X/**    General pattern matching for the ELM mailer.     
  1171. X
  1172. X**/
  1173. X
  1174. X#include <errno.h>
  1175. X
  1176. X#include "headers.h"
  1177. X
  1178. Xstatic char pattern[SLEN] = { "" };
  1179. Xstatic char alt_pattern[SLEN] = { "" };
  1180. X
  1181. Xextern int errno;
  1182. X
  1183. Xchar *error_name(), *shift_lower(), *strcpy();
  1184. X
  1185. Xint
  1186. Xmeta_match(function)
  1187. Xint function;
  1188. X{
  1189. X    char    ch;
  1190. X
  1191. X    /** Perform specific function based on whether an entered string 
  1192. X        matches either the From or Subject lines.. 
  1193. X        Return TRUE if the current message was matched, else FALSE.
  1194. X    **/
  1195. X
  1196. X    register int i, tagged=0, count=0, curtag = 0;
  1197. X    static char     meta_pattern[SLEN];
  1198. X
  1199. X    PutLine1(LINES-3, strlen("Command: "), 
  1200. X         "%s messages that match pattern...", 
  1201. X         function==TAGGED?"Tag": function==DELETED?"Delete":"Undelete");
  1202. X
  1203. X    if (function == TAGGED) {    /* are messages already tagged??? */
  1204. X      for (i=0; i < message_count; i++)
  1205. X        if (ison(headers[i]->status,TAGGED))
  1206. X          tagged++;
  1207. X
  1208. X      if (tagged) {
  1209. X        if (tagged > 2) 
  1210. X          PutLine0(LINES-2,0, "Some messages are already tagged.");
  1211. X        else
  1212. X          PutLine0(LINES-2,0, "A message is already tagged.");
  1213. X    
  1214. X        Write_to_screen("Remove tag%s? y%c", 2, plural(tagged),BACKSPACE);
  1215. X
  1216. X        ch = ReadCh();
  1217. X        if (tolower(ch) != 'n') {    /* remove tags... */
  1218. X          Write_to_screen("Yes.", 0);
  1219. X          for (i=0; i < message_count; i++) {
  1220. X            clearit(headers[i]->status,TAGGED);
  1221. X        show_new_status(i);
  1222. X          }
  1223. X        } else
  1224. X          Write_to_screen("No.", 0);
  1225. X      }
  1226. X    }
  1227. X    
  1228. X    PutLine0(LINES-2,0, "Enter pattern: "); CleartoEOLN();
  1229. X
  1230. X    optionally_enter(meta_pattern, LINES-2, strlen("Enter pattern: "),
  1231. X      FALSE, FALSE);
  1232. X
  1233. X    if (strlen(meta_pattern) == 0) {
  1234. X      ClearLine(LINES-2);
  1235. X      return(curtag);
  1236. X    }
  1237. X
  1238. X    strcpy(meta_pattern, shift_lower(meta_pattern));   /* lowercase it */
  1239. X
  1240. X    for (i = 0; i < message_count; i++) {
  1241. X      if (from_matches(i, meta_pattern)) {
  1242. X        if ((selected && headers[i]->status & VISIBLE) || ! selected) {
  1243. X          if (function == UNDELETE)
  1244. X            clearit(headers[i]->status, DELETED);
  1245. X          else
  1246. X            setit(headers[i]->status, function);
  1247. X          show_new_status(i);
  1248. X          if(i == current - 1) curtag++;
  1249. X          count++;
  1250. X        }
  1251. X      }
  1252. X      else if (subject_matches(i, meta_pattern)) {
  1253. X        if ((selected && headers[i]->status & VISIBLE) || ! selected) {
  1254. X          if (function == UNDELETE)
  1255. X            clearit(headers[i]->status, DELETED);
  1256. X          else
  1257. X            setit(headers[i]->status, function);
  1258. X          show_new_status(i);
  1259. X          if(i == current - 1) curtag++;
  1260. X          count++;
  1261. X        }
  1262. X      }
  1263. X    }
  1264. X
  1265. X    ClearLine(LINES-2);    /* remove "pattern: " prompt */
  1266. X    
  1267. X    if (count > 0)
  1268. X      error3("%s %d messsage%s.", 
  1269. X             function==TAGGED? "Tagged" : 
  1270. X           function==DELETED? "Marked for deletion" : "Undeleted",
  1271. X         count, plural(count));
  1272. X    else
  1273. X      error1("No matches. No messages %s.",
  1274. X         function==TAGGED? "tagged" : 
  1275. X           function==DELETED? "marked for deletion": "undeleted");
  1276. X
  1277. X    return(curtag);
  1278. X}
  1279. X      
  1280. Xint
  1281. Xpattern_match()
  1282. X{
  1283. X    /** Get a pattern from the user and try to match it with the
  1284. X        from/subject lines being displayed.  If matched (ignoring
  1285. X        case), move current message pointer to that message, if
  1286. X        not, error and return ZERO **/
  1287. X
  1288. X    register int i;
  1289. X
  1290. X    PutLine0(LINES-3,40,"/ = Match anywhere in messages.");
  1291. X    
  1292. X    PutLine0(LINES-1,0, "Match pattern:");
  1293. X
  1294. X    if (pattern_enter(pattern, alt_pattern, LINES-1, 16, 
  1295. X        "Match pattern (in entire folder):"))
  1296. X      if (strlen(alt_pattern) > 0) {
  1297. X        strcpy(alt_pattern, shift_lower(alt_pattern));
  1298. X        return(match_in_message(alt_pattern));
  1299. X      }
  1300. X      else
  1301. X        return(1);
  1302. X      
  1303. X    if (strlen(pattern) == 0) 
  1304. X      return(0);
  1305. X    else
  1306. X      strcpy(pattern, shift_lower(pattern));
  1307. X
  1308. X    for (i = current; i < message_count; i++) {
  1309. X      if (from_matches(i, pattern)) {
  1310. X        if (!selected || (selected && headers[i]->status & VISIBLE)) {
  1311. X          current = ++i;
  1312. X          return(1);
  1313. X        }
  1314. X      }
  1315. X      else if (subject_matches(i, pattern)) {
  1316. X        if (!selected || (selected && headers[i]->status & VISIBLE)) {
  1317. X          current = ++i;
  1318. X          return(1);
  1319. X        }
  1320. X      }
  1321. X    }
  1322. X
  1323. X    return(0);
  1324. X}
  1325. X
  1326. Xint
  1327. Xfrom_matches(message_number, pat)
  1328. Xint message_number;
  1329. Xchar *pat;
  1330. X{
  1331. X    /** Returns true iff the pattern occurs in it's entirety
  1332. X        in the from line of the indicated message **/
  1333. X
  1334. X    return( in_string(shift_lower(headers[message_number]->from), 
  1335. X        pat) );
  1336. X}
  1337. X
  1338. Xint
  1339. Xsubject_matches(message_number, pat)
  1340. Xint message_number;
  1341. Xchar *pat;
  1342. X{
  1343. X    /** Returns true iff the pattern occurs in it's entirety
  1344. X        in the subject line of the indicated message **/
  1345. X
  1346. X    return( in_string(shift_lower(headers[message_number]->subject), 
  1347. X        pat) );
  1348. X}
  1349. X
  1350. Xmatch_in_message(pat)
  1351. Xchar *pat;
  1352. X{
  1353. X    /** Match a string INSIDE a message...starting at the current 
  1354. X        message read each line and try to find the pattern.  As
  1355. X        soon as we do, set current and leave! 
  1356. X        Returns 1 if found, 0 if not
  1357. X    **/
  1358. X
  1359. X    char buffer[LONG_STRING];
  1360. X    int  message_number, lines, line;
  1361. X
  1362. X    message_number = current-1;
  1363. X
  1364. X    error("Searching folder for pattern...");
  1365. X
  1366. X    while (message_number < message_count) {
  1367. X
  1368. X      if (fseek(mailfile, headers[message_number]->offset, 0L) == -1) {
  1369. X
  1370. X        dprint(1, (debugfile,
  1371. X        "Error: seek %ld bytes into file failed. errno %d (%s)\n",
  1372. X        headers[message_number]->offset, errno, 
  1373. X        "match_in_message"));
  1374. X        error2("ELM [match] failed looking %ld bytes into file (%s).",
  1375. X           headers[message_number]->offset, error_name(errno));
  1376. X        return(1);    /* fake it out to avoid replacing error message */
  1377. X      }
  1378. X
  1379. X      line = 0;
  1380. X      lines = headers[message_number]->lines;
  1381. X
  1382. X      while (fgets(buffer, LONG_STRING, mailfile) != NULL && line < lines) {
  1383. X    
  1384. X        if(buffer[strlen(buffer)-1] == '\n') line++;
  1385. X
  1386. X        if (in_string(shift_lower(buffer), pat)) {
  1387. X          current = message_number+1; 
  1388. X          clear_error();
  1389. X          return(1);
  1390. X        }
  1391. X      }
  1392. X
  1393. X      /** now we've passed the end of THIS message...increment and 
  1394. X          continue the search with the next message! **/
  1395. X
  1396. X      message_number++;
  1397. X    }
  1398. X
  1399. X    return(0);
  1400. X}
  1401. SHAR_EOF
  1402. chmod 0444 src/pattern.c || echo "restore of src/pattern.c fails"
  1403. echo "x - extracting src/pmalloc.c (Text)"
  1404. sed 's/^X//' << 'SHAR_EOF' > src/pmalloc.c &&
  1405. X
  1406. Xstatic char rcsid[] = "@(#)$Id: pmalloc.c,v 4.1 90/04/28 22:43:43 syd Exp $";
  1407. X
  1408. X/*******************************************************************************
  1409. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  1410. X *
  1411. X *             Copyright (c) 1986, 1987 Dave Taylor
  1412. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  1413. X *******************************************************************************
  1414. X * Bug reports, patches, comments, suggestions should be sent to:
  1415. X *
  1416. X *    Syd Weinstein, Elm Coordinator
  1417. X *    elm@DSI.COM            dsinc!elm
  1418. X *
  1419. X *******************************************************************************
  1420. X * $Log:    pmalloc.c,v $
  1421. X * Revision 4.1  90/04/28  22:43:43  syd
  1422. X * checkin of Elm 2.3 as of Release PL0
  1423. X * 
  1424. X *
  1425. X ******************************************************************************/
  1426. X
  1427. X/** This routine contains a cheap permanent version of the malloc call to 
  1428. X    speed up the initial allocation of the weedout headers and the uuname 
  1429. X    data.  
  1430. X
  1431. X      This routine is originally from Jim Davis of HP Labs, with some 
  1432. X    mods by me.
  1433. X**/
  1434. X
  1435. X#include <stdio.h>
  1436. X#include "defs.h"
  1437. X
  1438. X/*VARARGS0*/
  1439. X
  1440. Xchar *pmalloc(size)
  1441. Xint size; 
  1442. X{
  1443. X    /** return the address of a specified block **/
  1444. X
  1445. X    static char *our_block = NULL;
  1446. X    static int   free_mem  = 0;
  1447. X
  1448. X    char   *return_value, *malloc();
  1449. X
  1450. X    /** if bigger than our threshold, just do the real thing! **/
  1451. X
  1452. X    if (size > PMALLOC_THRESHOLD) 
  1453. X       return(malloc(size));
  1454. X
  1455. X    /** if bigger than available space, get more, tossing what's left **/
  1456. X
  1457. X    if (size > free_mem) {
  1458. X      if ((our_block = malloc(PMALLOC_BUFFER_SIZE)) == NULL) {
  1459. X        fprintf(stderr, "\n\r\n\rCouldn't malloc %d bytes!!\n\r\n\r",
  1460. X            PMALLOC_BUFFER_SIZE);
  1461. X        leave();    
  1462. X          }
  1463. X      our_block += 4;  /* just for safety, don't give back true address */
  1464. X      free_mem = PMALLOC_BUFFER_SIZE-4;
  1465. X    }
  1466. X    
  1467. X    return_value  = our_block;    /* get the memory */
  1468. X    size = ((size+3)/4)*4;        /* Go to quad byte boundary */
  1469. X    our_block += size;        /* use it up      */
  1470. X    free_mem  -= size;        /*  and decrement */
  1471. X
  1472. X    return( (char *) return_value);
  1473. X}
  1474. SHAR_EOF
  1475. chmod 0444 src/pmalloc.c || echo "restore of src/pmalloc.c fails"
  1476. echo "x - extracting src/quit.c (Text)"
  1477. sed 's/^X//' << 'SHAR_EOF' > src/quit.c &&
  1478. X
  1479. Xstatic char rcsid[] = "@(#)$Id: quit.c,v 4.1 90/04/28 22:43:44 syd Exp $";
  1480. X
  1481. X/*******************************************************************************
  1482. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  1483. X *
  1484. X *             Copyright (c) 1986, 1987 Dave Taylor
  1485. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  1486. X *******************************************************************************
  1487. X * Bug reports, patches, comments, suggestions should be sent to:
  1488. X *
  1489. X *    Syd Weinstein, Elm Coordinator
  1490. X *    elm@DSI.COM            dsinc!elm
  1491. X *
  1492. X *******************************************************************************
  1493. X * $Log:    quit.c,v $
  1494. X * Revision 4.1  90/04/28  22:43:44  syd
  1495. X * checkin of Elm 2.3 as of Release PL0
  1496. X * 
  1497. X *
  1498. X ******************************************************************************/
  1499. X
  1500. X/** quit: leave the current folder and quit the program.
  1501. X  
  1502. X**/
  1503. X
  1504. X#include "headers.h"
  1505. X#include <errno.h>
  1506. X
  1507. Xextern int errno;        /* system error number on failure */
  1508. X
  1509. Xlong bytes();
  1510. X
  1511. Xquit(prompt)
  1512. Xint prompt;
  1513. X{
  1514. X    /* a wonderfully short routine!! */
  1515. X
  1516. X    if (leave_mbox(FALSE, TRUE, prompt) == -1)
  1517. X      /* new mail - leave not done - can't change to another file yet
  1518. X       * check for change in mailfile_size in main() will do the work
  1519. X       * of calling newmbox to add in the new messages to the current
  1520. X       * file and fix the sorting sequence that leave_mbox may have
  1521. X       * changed for its own purposes */
  1522. X      return;
  1523. X
  1524. X    leave();
  1525. X}
  1526. X
  1527. Xint
  1528. Xresync()
  1529. X{
  1530. X    /** Resync on the current folder. Leave current and read it back in.
  1531. X        Return indicates whether a redraw of the screen is needed.
  1532. X     **/
  1533. X
  1534. X      if(leave_mbox(TRUE, FALSE, TRUE) ==-1)
  1535. X        /* new mail - leave not done - can't change to another file yet
  1536. X         * check for change in mailfile_size in main() will do the work
  1537. X         * of calling newmbox to add in the new messages to the current
  1538. X         * file and fix the sorting sequence that leave_mbox may have
  1539. X         * changed for its own purposes */
  1540. X        return(FALSE);
  1541. X
  1542. X      if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) {
  1543. X        dprint(1, (debugfile,
  1544. X          "Error: given file %s as folder - unreadable (%s)!\n", 
  1545. X          cur_folder, error_name(errno)));
  1546. X        fprintf(stderr,"Can't open folder '%s' for reading!\n", cur_folder);
  1547. X        leave();
  1548. X        }
  1549. X
  1550. X      newmbox(cur_folder, FALSE);
  1551. X      return(TRUE);
  1552. X}
  1553. X
  1554. Xchange_file()
  1555. X{
  1556. X      /* Prompt user for name of folder to change to.
  1557. X       * If all okay with that folder, leave the current folder.
  1558. X       * If leave goes okay (i.e. no new messages in current folder),
  1559. X       * change to the folder that the user specified.
  1560. X       *
  1561. X       * Return value indicates whether a redraw is needed.
  1562. X       */
  1563. X
  1564. X      int redraw = FALSE;
  1565. X      char newfile[SLEN];
  1566. X      static char helpmsg[LONG_STRING];
  1567. X
  1568. X      char    *nameof();
  1569. X
  1570. X
  1571. X      /* get new file name */
  1572. X
  1573. X      MoveCursor(LINES-3, 30);
  1574. X      CleartoEOS();
  1575. X      PutLine0(LINES-3, 38, "(Use '?' for help/to list your folders.)");
  1576. X      PutLine0(LINES-2,0,"Change to which folder: ");
  1577. X      while(1) {
  1578. X        newfile[0] = '\0';
  1579. X        (void) optionally_enter(newfile, LINES-2, 24, FALSE, FALSE);
  1580. X        clear_error();
  1581. X
  1582. X        if(*newfile == '\0') {    /* if user didn't enter a file name */
  1583. X          MoveCursor(LINES-3, 30);    /* abort changing file process */
  1584. X          CleartoEOS();
  1585. X          return(redraw);
  1586. X
  1587. X        } else if (strcmp(newfile, "?") == 0) {
  1588. X
  1589. X          /* user wants to list folders */
  1590. X          if(!*helpmsg) {    /* format helpmsg if not yet done */
  1591. X
  1592. X        strcpy(helpmsg,
  1593. X          "\n\r\n\rEnter: <nothing> to not change to a new folder,");
  1594. X        strcat(helpmsg,
  1595. X          "\n\r       '!' to change to your incoming mailbox (");
  1596. X        strcat(helpmsg, defaultfile);
  1597. X        strcat(helpmsg,
  1598. X          ")\n\r       '>' to change to your \"received\" folder (");
  1599. X        strcat(helpmsg, nameof(recvd_mail));
  1600. X        strcat(helpmsg,
  1601. X          ")\n\r       '<' to change to your \"sent\" folder (");
  1602. X        strcat(helpmsg, nameof(sent_mail));
  1603. X        strcat(helpmsg, ")\n\r       or a filename");
  1604. X        strcat(helpmsg,
  1605. X          " (leading '=' denotes your folder directory ");
  1606. X        strcat(helpmsg, folders);
  1607. X        strcat(helpmsg, ").\n\r");
  1608. X          }
  1609. X          list_folders(4, helpmsg);
  1610. X          PutLine0(LINES-2,0,"Change to which folder: ");    /* reprompt */
  1611. X          redraw = TRUE;        /* we'll need to clean the screen */
  1612. X
  1613. X        } else {
  1614. X
  1615. X          /* user entered a file name - expand it */
  1616. X          if (! expand_filename(newfile, TRUE))
  1617. X        continue;    /* prompt again */
  1618. X
  1619. X          /* don't accept the same file as the current */
  1620. X          if (strcmp(newfile, cur_folder) == 0) {
  1621. X        error("Already reading that folder!");
  1622. X        continue;    /* prompt again */
  1623. X          }
  1624. X
  1625. X          /* Make sure this is a file the user can open, unless it's the
  1626. X           * default mailfile, which is openable even if empty */
  1627. X          if ((errno = can_access(newfile, READ_ACCESS)) != 0 ) {
  1628. X        if (strcmp(newfile, defaultfile) != 0 || errno != ENOENT) {
  1629. X          error1("Can't open folder '%s' for reading!", newfile);
  1630. X          continue;     /* prompt again */
  1631. X        }
  1632. X          }
  1633. X          break;    /* exit loop - we got the name of a good file */
  1634. X        }
  1635. X      }
  1636. X
  1637. X      /* All's clear with the new file to go ahead and leave the current. */
  1638. X      MoveCursor(LINES-3, 30);
  1639. X      CleartoEOS();
  1640. X
  1641. X      if(leave_mbox(FALSE, FALSE, TRUE) ==-1) {
  1642. X        /* new mail - leave not done - can't change to another file yet
  1643. X         * check for change in mailfile_size in main() will do the work
  1644. X         * of calling newmbox to add in the new messages to the current
  1645. X         * file and fix the sorting sequence that leave_mbox may have
  1646. X         * changed for its own purposes */
  1647. X        return(redraw);
  1648. X      }
  1649. X
  1650. X      redraw = 1;
  1651. X      newmbox(newfile, FALSE);
  1652. X      return(redraw);
  1653. X}
  1654. SHAR_EOF
  1655. chmod 0444 src/quit.c || echo "restore of src/quit.c fails"
  1656. echo "x - extracting src/read_rc.c (Text)"
  1657. sed 's/^X//' << 'SHAR_EOF' > src/read_rc.c &&
  1658. X
  1659. Xstatic char rcsid[] = "@(#)$Id: read_rc.c,v 4.1 90/04/28 22:43:46 syd Exp $";
  1660. X
  1661. X/*******************************************************************************
  1662. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  1663. X *
  1664. X *             Copyright (c) 1986, 1987 Dave Taylor
  1665. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  1666. X *******************************************************************************
  1667. X * Bug reports, patches, comments, suggestions should be sent to:
  1668. X *
  1669. X *    Syd Weinstein, Elm Coordinator
  1670. X *    elm@DSI.COM            dsinc!elm
  1671. X *
  1672. X *******************************************************************************
  1673. X * $Log:    read_rc.c,v $
  1674. X * Revision 4.1  90/04/28  22:43:46  syd
  1675. X * checkin of Elm 2.3 as of Release PL0
  1676. X * 
  1677. X *
  1678. X ******************************************************************************/
  1679. X
  1680. X/** This file contains programs to allow the user to have a .elm/elmrc file
  1681. X    in their home directory containing any of the following: 
  1682. X
  1683. X    fullname= <username string>
  1684. X    maildir = <directory>
  1685. X    tmpdir  = <directory>
  1686. X    sentmail = <file>
  1687. X    editor  = <editor>
  1688. X    receviedmail= <file>
  1689. X    calendar= <calendar file name>
  1690. X    shell   = <shell>
  1691. X    print   = <print command>
  1692. X    weedout = <list of headers to weed out>
  1693. X    prefix  = <copied message prefix string>
  1694. X    pager   = <command to use for displaying messages>
  1695. X    
  1696. X    escape  = <single character escape, default = '~' >
  1697. X
  1698. X--
  1699. X    signature = <.signature file for all outbound mail>
  1700. XOR:
  1701. X    localsignature = <.signature file for local mail>
  1702. X    remotesignature = <.signature file for non-local mail>
  1703. X--
  1704. X
  1705. X    bounceback= <hop count threshold, or zero to disable>
  1706. X    timeout = <seconds for main menu timeout or zero to disable>
  1707. X    userlevel = <0=amateur, 1=okay, 2 or greater = expert!>
  1708. X
  1709. X    sortby  = <sent, received, from, size, subject, mailbox, status>
  1710. X
  1711. X    alternatives = <list of addresses that forward to us>
  1712. X
  1713. X    and/or the logical arguments:
  1714. X    
  1715. X    autocopy    [on|off]
  1716. X    askcc        [on|off]
  1717. X    copy        [on|off]    
  1718. X    resolve     [on|off]
  1719. X    weed        [on|off]
  1720. X    noheader    [on|off]
  1721. X    titles      [on|off]
  1722. X    savebyname  [on|off]
  1723. X    forcename   [on|off]
  1724. X    movepage    [on|off]
  1725. X    pointnew    [on|off]
  1726. X    hpkeypad    [on|off]
  1727. X    hpsoftkeys  [on|off]
  1728. X    alwayskeep [on|off]
  1729. X    alwaysstore [on|off]
  1730. X    alwaysdel   [on|off]
  1731. X    arrow        [on|off]
  1732. X    menus        [on|off]
  1733. X    forms        [on|off]
  1734. X    warnings    [on|off]
  1735. X    names        [on|off]
  1736. X    ask        [on|off]
  1737. X    keepempty   [on|off]
  1738. X    promptafter[on|off]
  1739. X    sigdashes   [on|off]
  1740. X
  1741. X
  1742. X    Lines starting with '#' are considered comments and are not checked
  1743. X    any further!
  1744. X
  1745. X    Modified 10/85 to know about "Environment" variables..
  1746. X    Modified 12/85 for the 'prefix' option
  1747. X    Modified  2/86 for the new 3.3 flags
  1748. X    Modified  8/86 (was I supposed to be keeping this up to date?)
  1749. X**/
  1750. X
  1751. X#include <ctype.h>
  1752. X#include "headers.h"
  1753. X
  1754. X#ifdef BSD
  1755. X#undef tolower
  1756. X#endif
  1757. X
  1758. Xextern char *pmalloc();
  1759. Xextern int errno;
  1760. X
  1761. Xchar  *error_name(), *error_description(), *shift_lower(),
  1762. X      *strtok(), *getenv(), *strcpy();
  1763. Xvoid  exit();
  1764. X
  1765. X#define  metachar(c)    (c == '+' || c == '%' || c == '=')
  1766. X
  1767. X#define ASSIGNMENT      0
  1768. X#define WEEDOUT        1
  1769. X#define ALTERNATIVES    2
  1770. X
  1771. Xread_rc_file()
  1772. X{
  1773. X    /** this routine does all the actual work of reading in the
  1774. X        .rc file... **/
  1775. X
  1776. X    FILE *file;
  1777. X    char buffer[SLEN], filename[SLEN], *cp, word1[SLEN], word2[SLEN];
  1778. X    int  i, ch, len,
  1779. X      rc_has_recvdmail = 0, rc_has_sentmail = 0, lineno = 0, errors = 0;
  1780. X
  1781. X    /* Establish some defaults in case elmrc is incomplete or not there.
  1782. X     * Defaults for other elmrc options were established in their
  1783. X     * declaration - in elm.h.  And defaults for sent_mail and recvd_mail
  1784. X     * are established after the elmrc is read in since these default
  1785. X     * are based on the folders directory name, which may be given
  1786. X     * in the emrc.
  1787. X     * Also establish alternative_editor here since it is based on
  1788. X     * the default editor and not on the one that might be given in the
  1789. X     * elmrc.
  1790. X     */
  1791. X     
  1792. X    default_weedlist();
  1793. X
  1794. X    alternative_addresses = NULL;     /* none yet! */
  1795. X
  1796. X    raw_local_signature[0] = raw_remote_signature[0] =
  1797. X        local_signature[0] = remote_signature[0] = '\0';
  1798. X        /* no defaults for those */
  1799. X
  1800. X    strcpy(raw_shell,((cp = getenv("SHELL")) == NULL)? default_shell : cp);
  1801. X    strcpy(shell, raw_shell);
  1802. X
  1803. X    strcpy(raw_pager,((cp = getenv("PAGER")) == NULL)? default_pager : cp);
  1804. X    strcpy(pager, raw_pager);
  1805. X
  1806. X    strcpy(raw_editor,((cp = getenv("EDITOR")) == NULL)? default_editor:cp);
  1807. X
  1808. X    strcpy(temp_dir,((cp = getenv("TMPDIR")) == NULL)? default_temp:cp);
  1809. X    if (temp_dir[strlen (temp_dir)-1] != '/')
  1810. X                strcat(temp_dir, "/");
  1811. X
  1812. X    strcpy(alternative_editor, raw_editor);
  1813. X    strcpy(editor, raw_editor);
  1814. X
  1815. X    strcpy(raw_printout, default_printout);
  1816. X    strcpy(printout, raw_printout);
  1817. X
  1818. X    sprintf(raw_folders, "%s/%s", home, default_folders);
  1819. X    strcpy(folders, raw_folders);
  1820. X
  1821. X    sprintf(raw_calendar_file, "%s/%s", home, dflt_calendar_file);
  1822. X    strcpy(calendar_file, raw_calendar_file);
  1823. X
  1824. X    /* see if the user has a $HOME/.elm directory */
  1825. X    sprintf(filename, "%s/.elm", home);
  1826. X    if (access(filename, 00) == -1) {
  1827. X      if(batch_only)  {
  1828. X        printf("\n\rNotice:\
  1829. X\n\rThis version of ELM requires the use of a .elm directory to store your\
  1830. X\n\relmrc and alias files. I'd like to create the directory .elm for you\
  1831. X\n\rand set it up, but I can't in \"batch mode\".\
  1832. X\n\rPlease run ELM in \"normal mode\" first.\n\r");
  1833. X        exit(0);
  1834. X      }
  1835. X
  1836. X      printf("\n\rNotice:\
  1837. X\n\rThis version of ELM requires the use of a .elm directory in your home\
  1838. SHAR_EOF
  1839. echo "End of part 19"
  1840. echo "File src/read_rc.c is continued in part 20"
  1841. echo "20" > s2_seq_.tmp
  1842. exit 0
  1843.