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

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