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

  1. Subject:  v09i006:  ELM Mail System, Part06/19
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: Dave Taylor <hplabs!taylor>
  6. Mod.sources: Volume 9, Issue 6
  7. Archive-name: elm2/Part06
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If this archive is complete, you will see the message:
  13. #        "End of archive 6 (of 19)."
  14. # Contents:  hdrs/defs.h hdrs/sysdefs.h hdrs/sysdefs.master
  15. #   hdrs/sysdefs.old src/file.c src/initialize.uts src/limit.c
  16. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  17. echo shar: Extracting \"hdrs/defs.h\" \(7730 characters\)
  18. if test -f hdrs/defs.h ; then 
  19.   echo shar: Will not over-write existing file \"hdrs/defs.h\"
  20. else
  21. sed "s/^X//" >hdrs/defs.h <<'END_OF_hdrs/defs.h'
  22. X/**        defs.h            **/
  23. X
  24. X/**  define file for ELM mail system.  **/
  25. X
  26. X/**  (C) Copyright 1985 Dave Taylor    **/
  27. X
  28. X#include "sysdefs.h"    /* system/configurable defines */
  29. X
  30. X#define VERSION        "1.5" /* Version number!  WHAT_STRING should agree */
  31. X
  32. X#define WHAT_STRING    "@(#) Version 1.5, January, 1987"
  33. X
  34. X#define KLICK        10
  35. X
  36. X#define SLEN        256        /* long for ensuring no overwrites... */
  37. X#define SHORT        5        /* super short strings!          */
  38. X#define NLEN        20        /* name length for aliases            */
  39. X#define SHORT_SLEN      40
  40. X#define STRING        100    /* reasonable string length for most..      */
  41. X#define LONG_SLEN    250    /* for mail addresses from remote machines! */
  42. X#define LONG_STRING    500    /* even longer string for group expansion   */
  43. X#define VERY_LONG_STRING 2500    /* huge string for group alias expansion    */
  44. X
  45. X#define BREAK        '\0'          /* default interrupt    */
  46. X#define BACKSPACE    '\b'         /* backspace character  */
  47. X#define TAB        '\t'            /* tab character        */
  48. X#define RETURN        '\r'         /* carriage return char */
  49. X#define LINE_FEED    '\n'         /* line feed character  */
  50. X#define FORMFEED    '\f'         /* form feed (^L) char  */
  51. X#define COMMA        ','        /* comma character      */
  52. X#define SPACE        ' '        /* space character      */
  53. X#define DOT        '.'        /* period/dot character */
  54. X#define BANG        '!'        /* exclaimation mark!   */
  55. X#define AT_SIGN        '@'        /* at-sign character    */
  56. X#define PERCENT        '%'        /* percent sign char.   */
  57. X#define COLON        ':'        /* the colon ..        */
  58. X#define BACKQUOTE    '`'        /* backquote character  */
  59. X#ifdef TILDE
  60. X# undef TILDE
  61. X#endif
  62. X#define TILDE        '~'        /* escape character~    */
  63. X#define ESCAPE        '\033'        /* the escape        */
  64. X
  65. X#define NO_OP_COMMAND    '\0'        /* no-op for timeouts   */
  66. X
  67. X#define STANDARD_INPUT  0        /* file number of stdin */
  68. X
  69. X#ifndef TRUE
  70. X#define TRUE        1
  71. X#define FALSE        0
  72. X#endif
  73. X
  74. X#define NO        0
  75. X#define YES        1
  76. X#define MAYBE        2        /* a definite define, eh?  */
  77. X#define FORM        3        /*      <nevermind>        */
  78. X#define PREFORMATTED    4        /* forwarded form...       */
  79. X
  80. X#define PAD        0        /* for printing name of    */
  81. X#define FULL        1        /*   the sort we're using  */
  82. X
  83. X#define OUTGOING    0        /* defines for lock file   */
  84. X#define INCOMING    1        /* creation..see lock()    */
  85. X
  86. X#define SH        0        /* defines for system_call */
  87. X#define USER_SHELL    1        /* to work correctly!      */
  88. X
  89. X#define EXECUTE_ACCESS    01        /* These five are        */
  90. X#define WRITE_ACCESS    02        /*    for the calls       */
  91. X#define READ_ACCESS    04        /*       to access()       */
  92. X#define ACCESS_EXISTS    00        /*           <etc>         */
  93. X#define EDIT_ACCESS    06        /*  (this is r+w access)   */
  94. X
  95. X#define BIG_NUM        999999        /* big number!             */
  96. X#define BIGGER_NUM    9999999     /* bigger number!          */
  97. X
  98. X#define START_ENCODE    "[encode]"
  99. X#define END_ENCODE    "[clear]"
  100. X
  101. X#define DONT_SAVE    "[no save]"
  102. X
  103. X#define alias_file    ".aliases"
  104. X#define group_file    ".groups"
  105. X#define system_file    ".systems"
  106. X
  107. X/** some defines for the 'userlevel' variable... **/
  108. X
  109. X#define RANK_AMATEUR    0
  110. X#define AMATEUR        1
  111. X#define OKAY_AT_IT    2
  112. X#define GOOD_AT_IT    3
  113. X#define EXPERT        4
  114. X#define SUPER_AT_IT    5
  115. X
  116. X/** some defines for the "status" field of the header record **/
  117. X
  118. X#define TAGGED        1        /* these are bit masks */
  119. X#define DELETED        2
  120. X#define EXPIRED        4
  121. X#define ACTION        8
  122. X#define NEW        16
  123. X#define PRIORITY    32
  124. X#define FORM_LETTER    64
  125. X#define VISIBLE        128
  126. X
  127. X#define UNDELETE    0        /* purely for ^U function... */
  128. X
  129. X/** some months... **/
  130. X
  131. X#define JANUARY        0            /* months of the year */
  132. X#define FEBRUARY    1
  133. X#define MARCH        2
  134. X#define APRIL        3
  135. X#define MAY        4
  136. X#define JUNE        5
  137. X#define JULY        6
  138. X#define AUGUST        7
  139. X#define SEPTEMBER    8
  140. X#define OCTOBER        9
  141. X#define NOVEMBER    10
  142. X#define DECEMBER    11
  143. X
  144. X#define equal(s,w)    (strcmp(s,w) == 0)
  145. X#define min(a,b)    a < b? a : b
  146. X#define ctrl(c)            c - 'A' + 1    /* control character mapping */
  147. X#define plural(n)    n == 1 ? "" : "s"
  148. X#define lastch(s)    s[strlen(s)-1]
  149. X#define no_ret(s)    if (lastch(s) == '\n') lastch(s) = '\0' 
  150. X#define first_word(s,w) (strncmp(s,w, strlen(w)) == 0)
  151. X#define ClearLine(n)    MoveCursor(n,0); CleartoEOLN()
  152. X#define whitespace(c)    (c == ' ' || c == '\t')
  153. X#define quote(c)    (c == '"' || c == '\'') 
  154. X#define onoff(n)    (n == 0 ? "OFF" : "ON")
  155. X
  156. X/** The next function is so certain commands can be processed from the showmsg
  157. X    routine without rewriting the main menu in between... **/
  158. X
  159. X#define special(c)    (c == 'j' || c == 'k')
  160. X
  161. X/** and a couple for dealing with status flags... **/
  162. X
  163. X#define ison(n,mask)    (n & mask)
  164. X#define isoff(n,mask)    (~ison(n, mask))
  165. X
  166. X#define setit(n,mask)        n |= mask
  167. X#define clearit(n, mask)    n &= ~mask
  168. X
  169. X/** a few for the usage of function keys... **/
  170. X
  171. X#define f1    1
  172. X#define f2    2
  173. X#define f3    3
  174. X#define f4    4
  175. X#define f5    5
  176. X#define f6    6
  177. X#define f7    7
  178. X#define f8    8
  179. X
  180. X#define MAIN    0
  181. X#define ALIAS   1
  182. X#define YESNO    2
  183. X#define CHANGE  3
  184. X#define READ    4
  185. X
  186. X#define MAIN_HELP    0
  187. X#define ALIAS_HELP   1
  188. X#define OPTIONS_HELP 2
  189. X
  190. X/** some possible sort styles... **/
  191. X
  192. X#define REVERSE        -        /* for reverse sorting           */
  193. X#define SENT_DATE    1        /* the date message was sent     */
  194. X#define RECEIVED_DATE    2        /* the date message was received */
  195. X#define SENDER        3        /* the name/address of sender    */
  196. X#define SIZE        4        /* the # of lines of the message */
  197. X#define SUBJECT        5        /* the subject of the message    */
  198. X#define STATUS        6        /* the status (deleted, etc)     */
  199. X
  200. X/* some stuff for our own malloc call - pmalloc */
  201. X
  202. X#define PMALLOC_THRESHOLD    256    /* if greater, then just use malloc */
  203. X#define PMALLOC_BUFFER_SIZE    2048    /* internal [memory] buffer size... */
  204. X
  205. X/* wouldn't it be nice to have variable argument macros... */
  206. X
  207. X#define dprint0(n,s)         if (debug >= n) { \
  208. X                fprintf(debugfile, s); fflush(debugfile); }
  209. X
  210. X#define dprint1(n,s,a)         if (debug >= n) { \
  211. X                fprintf(debugfile, s, a);  fflush(debugfile); }
  212. X
  213. X#define dprint2(n,s,a,b)     if (debug >= n) { \
  214. X                    fprintf(debugfile, s, a, b); fflush(debugfile);}
  215. X
  216. X#define dprint3(n,s,a,b,c)   if (debug >= n) { fprintf(debugfile, \
  217. X                s, a, b, c); fflush(debugfile); }
  218. X
  219. X#define dprint4(n,s,a,b,c,d)  if (debug >= n) { fprintf(debugfile, \
  220. X                s, a, b, c, d); fflush(debugfile); }
  221. X
  222. X#define dprint5(n,s,a,b,c,d,e) if (debug >= n) { fprintf(debugfile, \
  223. X                    s, a, b, c, d, e); fflush(debugfile); }
  224. X
  225. X#define dprint6(n,s,a,b,c,d,e,f) if (debug >= n) { fprintf(debugfile, \
  226. X                    s, a, b, c, d, e, f); fflush(debugfile); }
  227. X
  228. X/* I guess this corrects it, though.  Wretched stuff though! */
  229. X
  230. X/* some random records... */
  231. X
  232. Xstruct date_rec {
  233. X    int  month;        /** this record stores a **/
  234. X    int  day;        /**   specific date and  **/
  235. X    int  year;        /**     time...         **/
  236. X    int  hour;
  237. X    int  minute;
  238. X       };
  239. X
  240. Xstruct header_rec {
  241. X    int  lines;        /** # of lines in the message  **/
  242. X    int  status;        /** Urgent, Deleted, Expired?  **/
  243. X    int  index_number;    /** relative loc in file...    **/
  244. X    long offset;        /** offset in bytes of message **/
  245. X    struct date_rec received; /** when elm received here   **/
  246. X    char from[STRING];    /** who sent the message?      **/
  247. X    char to[STRING];    /** who it was sent to           **/
  248. X    char dayname[8];    /**  when the                  **/
  249. X    char month[10];        /**        message             **/
  250. X    char day[3];        /**          was            **/
  251. X    char year[5];        /**            sent            **/
  252. X    char time[NLEN];    /**              to you!       **/
  253. X    char subject[STRING];   /** The subject of the mail    **/
  254. X       };
  255. X
  256. Xstruct alias_rec {
  257. X    char   name[NLEN];    /* alias name                  */
  258. X    long   byte;        /* offset into data file for address */
  259. X       };
  260. X
  261. Xstruct lsys_rec {
  262. X    char   name[NLEN];    /* name of machine connected to      */
  263. X    struct lsys_rec *next;    /* linked list pointer to next       */
  264. X       };
  265. X
  266. Xstruct addr_rec {
  267. X     char   address[NLEN];    /* machine!user you get mail as      */
  268. X     struct addr_rec *next;    /* linked list pointer to next       */
  269. X    };
  270. X
  271. X#ifdef SHORTNAMES    /* map long names to shorter ones */
  272. X# include <shortnames.h>
  273. X#endif
  274. END_OF_hdrs/defs.h
  275. if test 7730 -ne `wc -c <hdrs/defs.h`; then
  276.     echo shar: \"hdrs/defs.h\" unpacked with wrong size!?
  277. fi
  278. # end of overwriting check
  279. fi
  280. echo shar: Extracting \"hdrs/sysdefs.h\" \(7274 characters\)
  281. if test -f hdrs/sysdefs.h ; then 
  282.   echo shar: Will not over-write existing file \"hdrs/sysdefs.h\"
  283. else
  284. sed "s/^X//" >hdrs/sysdefs.h <<'END_OF_hdrs/sysdefs.h'
  285. X/**            sysdefs.h            **/
  286. X
  287. X/**  System level, configurable, defines for the ELM mail system.  **/
  288. X
  289. X/**  (C) Copyright 1986 Dave Taylor                                **/
  290. X
  291. X/** Define the following if you think that the information in messages
  292. X    that have "Reply-To:" and/or "From:" fields with addresses will
  293. X    contain valid addressing information.  If this isn't defined, the
  294. X    calculated return address will ALWAYS be used instead.  (note that
  295. X    this doesn't necessarily preclude the use of G)roup replies).
  296. X**/
  297. X
  298. X/** #define USE_EMBEDDED_ADDRESSES **/    
  299. X
  300. X
  301. X#define FIND_DELTA    10        /* byte region where the binary search
  302. X                       on the path alias file is fruitless 
  303. X                                           (can't be within this boundary)    */
  304. X
  305. X#define MAX_SALIASES    503    /* number of system aliases allowed      */
  306. X#define MAX_UALIASES    251    /* number of user aliases allowed      */
  307. X#define MAX_IN_WEEDLIST 150    /* max headers to weed out               */
  308. X
  309. X#define MAX_HOPS    35    /* max hops in return addr to E)veryone  */
  310. X
  311. X#define MAX_ATTEMPTS    6    /* #times to attempt lock file creation */
  312. X
  313. X/** see leavembox.c to determine if this should be defined or not....The 
  314. X    default is to NOT have it defined.
  315. X**/
  316. X
  317. X/** #define REMOVE_AT_LAST **/
  318. X
  319. X#define DEFAULT_BATCH_SUBJECT  "no subject (file transmission)"
  320. X
  321. X/** If you want to have the mailer know about valid mailboxes on the
  322. X    host machine (assumes no delivery agent aliases) then you should
  323. X    undefine this (the default is to have it defined)...
  324. X**/
  325. X
  326. X#define NOCHECK_VALIDNAME
  327. X
  328. X/** If your machine doesn't have virtual memory (specifically the vfork() 
  329. X    command) then you should define the following....        
  330. X**/
  331. X
  332. X/** #define NO_VM **/
  333. X
  334. X/** If you're running sendmail, or another transport agent that can 
  335. X    handle the blind-carbon-copy list define the following
  336. X**/
  337. X
  338. X#define ALLOW_BCC
  339. X
  340. X/** If you have pathalias, can we get to it as a DBM file??? **/
  341. X
  342. X/** #define USE_DBM **/
  343. X
  344. X/** If you want the mailer to check the pathalias database BEFORE it
  345. X    looks to see if a specified machine is in the L.sys database (in
  346. X    some cases routing is preferable to direct lines) then you should
  347. X    define the following...
  348. X**/
  349. X
  350. X/** #define LOOK_CLOSE_AFTER_SEARCH **/
  351. X
  352. X
  353. X/** If you'd rather the program automatically used the 'uuname' command
  354. X    to figure out what machines it talks to (instead of trying to get
  355. X    it from L.sys first) then define the following...
  356. X**/
  357. X
  358. X#define USE_UUNAME
  359. X
  360. X/** If you don't want the program to even TOUCH the addresses handed to 
  361. X    it - deferring all expansion to sendmail/smail, then define the following;
  362. X**/
  363. X
  364. X/** #define DONT_TOUCH_ADDRESSES **/
  365. X
  366. X/** Perhaps you'd also like the program not to try to minimize the addresses
  367. X    stored when you 'alias current message'.  If so, define the following
  368. X**/
  369. X
  370. X/** #define DONT_OPTIMIZE_RETURN **/
  371. X
  372. X/** If you'd like "newmail" to automatically go into background when you
  373. X    start it up (instead of the "newmail &" junk with the process id output,
  374. X    then define the following...
  375. X**/
  376. X
  377. X#define AUTO_BACKGROUND
  378. X
  379. X/** If you'd rather your mail transport agent (ie sendmail) put the From:
  380. X    line into the message, define the following...
  381. X**/
  382. X
  383. X#define DONT_ADD_FROM
  384. X
  385. X/** If your machine prefers the Internet notation of user@host for the
  386. X    From: line and addresses, define the following...(the default is to 
  387. X    use this rather than the USENET notation - check your pathalias file!)
  388. X
  389. X**/
  390. X
  391. X#define INTERNET_ADDRESS_FORMAT
  392. X
  393. X/** If you're on a machine that prefers UUCP to Internet addresses, then
  394. X    define the following (the basic change is that on a machine that
  395. X    receives messages of the form <path>!user@<localhost> the displayed
  396. X    address will be <path>!user instead of user@<localhost>.
  397. X
  398. X    BOGUS_INTERNET is the address that your local system appends to 
  399. X    messages occasionally.  The algorithm is simply to REMOVE the
  400. X    BOGUS_INTERNET string.  This is horrible.  *sigh*
  401. X
  402. X**/
  403. X
  404. X#define PREFER_UUCP
  405. X#define BOGUS_INTERNET    "@hplabs.HP.COM"
  406. X
  407. X/** If you're running ACSNET and/or want to have your domain name
  408. X    attached to your hostname on outbound mail then you can define
  409. X    the following (default are not defined)
  410. X**/
  411. X
  412. X/** #define USE_DOMAIN **/
  413. X#define DOMAIN        "<enter your domain here>"
  414. X
  415. X/** If you are going to be running the mailer with setgid mail (or
  416. X    something similar) you'll need to define the following to ensure
  417. X    that the users mailbox in the spool directory has the correct
  418. X    group (NOT the users group)
  419. X**/
  420. X
  421. X#define SAVE_GROUP_MAILBOX_ID
  422. X
  423. X/** If you want a neat feature that enables scanning of the message
  424. X    body for entries to add to the users ".calendar" (or whatever)
  425. X    file, define this.
  426. X**/
  427. X
  428. X#define ENABLE_CALENDAR
  429. X#define dflt_calendar_file    "calendar"    /* in HOME directory */
  430. X
  431. X/** If you want to implement 'site hiding' in the mail, then you'll need to
  432. X    uncomment the following lines and set them to reasonable values.  See 
  433. X    the configuration guide for more details....
  434. X**/
  435. X
  436. X/****************************************************************************
  437. X
  438. X#undef    DONT_ADD_FROM        
  439. X
  440. X#define   SITE_HIDING
  441. X#define   HIDDEN_SITE_NAME    "fake-machine-name"
  442. X#define   HIDDEN_SITE_USERS    "/usr/mail/lists/hidden_site_users"
  443. X
  444. X****************************************************************************/
  445. X
  446. X/** Do we have the 'gethostname()' call?  If not, define the following **/
  447. X/** #define NEED_GETHOSTNAME **/
  448. X
  449. X/** are you stuck on a machine that has short names?  If so, define the
  450. X    following **/
  451. X
  452. X/** #define SHORTNAMES **/
  453. X
  454. X#define NOTES_HEADER        "/***** "
  455. X#define NOTES_FOOTER        "/* ---------- */"
  456. X
  457. X#ifdef BSD
  458. X# define system_hash_file    "/usr/spool/mail/.alias_hash"
  459. X# define system_data_file    "/usr/spool/mail/.alias_data"
  460. X#else
  461. X# define system_hash_file    "/usr/mail/.alias_hash"
  462. X# define system_data_file    "/usr/mail/.alias_data"
  463. X#endif
  464. X
  465. X#define pathfile        "/usr/lib/nmail.paths"
  466. X#define domains            "/usr/lib/domains"
  467. X
  468. X#define Lsys            "/usr/lib/uucp/L.sys"
  469. X
  470. X/** where to put the output of the elm -d command... (in home dir) **/
  471. X#define DEBUG        "ELM:debug.info"
  472. X#define OLDEBUG        "ELM:debug.last"
  473. X
  474. X#define temp_file    "/tmp/snd."
  475. X#define temp_form_file    "/tmp/form."
  476. X#define temp_mbox    "/tmp/mbox."
  477. X#define temp_print      "/tmp/print."
  478. X#define temp_uuname    "/tmp/uuname."
  479. X#define mailtime_file    ".last_read_mail"
  480. X#define readmsg_file    ".readmsg"
  481. X
  482. X#define emacs_editor    "/usr/local/bin/emacs"
  483. X
  484. X#ifdef BSD
  485. X# define default_editor    "/usr/ucb/vi"
  486. X# define mailhome    "/usr/spool/mail/"
  487. X#else
  488. X# define default_editor    "/usr/bin/vi"
  489. X# define mailhome    "/usr/mail/"
  490. X#endif
  491. X
  492. X# define default_pager    "builtin"
  493. X
  494. X#define sendmail    "/usr/lib/sendmail"
  495. X#define smflags        "-oi -oem"    /* ignore dots and mail back errors */
  496. X#define mailer        "/bin/rmail"
  497. X#ifdef BSD
  498. X# define mailx        "/usr/ucb/Mail"
  499. X#else
  500. X# define mailx        "/usr/bin/mailx"
  501. X#endif
  502. X
  503. X#define helphome    "/usr/local/lib"
  504. X#define helpfile    "elm-help"
  505. X
  506. X#define ELMRC_INFO    "/usr/local/lib/elmrc-info"
  507. X
  508. X#define elmrcfile    "/.elmrc"
  509. X#define mailheaders    ".elmheaders"
  510. X#define dead_letter    "Cancelled.mail"
  511. X
  512. X#define unedited_mail    "emergency.mbox"
  513. X
  514. X#define newalias    "newalias -q 1>&2 > /dev/null"
  515. X#define readmsg        "readmsg"
  516. X
  517. X#define remove        "/bin/rm -f"        /* how to remove a file */
  518. X#define cat        "/bin/cat"        /* how to display files */
  519. X#define uuname        "uuname"        /* how to get a uuname  */
  520. END_OF_hdrs/sysdefs.h
  521. if test 7274 -ne `wc -c <hdrs/sysdefs.h`; then
  522.     echo shar: \"hdrs/sysdefs.h\" unpacked with wrong size!?
  523. fi
  524. # end of overwriting check
  525. fi
  526. echo shar: Extracting \"hdrs/sysdefs.master\" \(7256 characters\)
  527. if test -f hdrs/sysdefs.master ; then 
  528.   echo shar: Will not over-write existing file \"hdrs/sysdefs.master\"
  529. else
  530. sed "s/^X//" >hdrs/sysdefs.master <<'END_OF_hdrs/sysdefs.master'
  531. X/**            sysdefs.h            **/
  532. X
  533. X/**  System level, configurable, defines for the ELM mail system.  **/
  534. X
  535. X/**  (C) Copyright 1986 Dave Taylor                                **/
  536. X
  537. X/** Define the following if you think that the information in messages
  538. X    that have "Reply-To:" and/or "From:" fields with addresses will
  539. X    contain valid addressing information.  If this isn't defined, the
  540. X    calculated return address will ALWAYS be used instead.  (note that
  541. X    this doesn't necessarily preclude the use of G)roup replies).
  542. X**/
  543. X
  544. X#define USE_EMBEDDED_ADDRESSES    
  545. X
  546. X
  547. X#define FIND_DELTA    10        /* byte region where the binary search
  548. X                       on the path alias file is fruitless 
  549. X                                           (can't be within this boundary)    */
  550. X
  551. X#define MAX_SALIASES    >503<    /* number of system aliases allowed      */
  552. X#define MAX_UALIASES    >251<    /* number of user aliases allowed      */
  553. X#define MAX_IN_WEEDLIST 150    /* max headers to weed out               */
  554. X
  555. X#define MAX_HOPS    35    /* max hops in return addr to E)veryone  */
  556. X
  557. X#define MAX_ATTEMPTS    >6<    /* #times to attempt lock file creation */
  558. X
  559. X/** see leavembox.c to determine if this should be defined or not....The 
  560. X    default is to NOT have it defined.
  561. X**/
  562. X
  563. X#define REMOVE_AT_LAST
  564. X
  565. X#define DEFAULT_BATCH_SUBJECT  "no subject (file transmission)"
  566. X
  567. X/** If you want to have the mailer know about valid mailboxes on the
  568. X    host machine (assumes no delivery agent aliases) then you should
  569. X    undefine this (the default is to have it defined)...
  570. X**/
  571. X
  572. X#define NOCHECK_VALIDNAME
  573. X
  574. X/** If your machine doesn't have virtual memory (specifically the vfork() 
  575. X    command) then you should define the following....        
  576. X**/
  577. X
  578. X/** #define NO_VM **/
  579. X
  580. X/** If you're running sendmail, or another transport agent that can 
  581. X    handle the blind-carbon-copy list define the following
  582. X**/
  583. X
  584. X/** #define ALLOW_BCC **/
  585. X
  586. X/** If you have pathalias, can we get to it as a DBM file??? **/
  587. X
  588. X/** #define USE_DBM **/
  589. X
  590. X/** If you want the mailer to check the pathalias database BEFORE it
  591. X    looks to see if a specified machine is in the L.sys database (in
  592. X    some cases routing is preferable to direct lines) then you should
  593. X    define the following...
  594. X**/
  595. X
  596. X#define LOOK_CLOSE_AFTER_SEARCH
  597. X
  598. X
  599. X/** If you'd rather the program automatically used the 'uuname' command
  600. X    to figure out what machines it talks to (instead of trying to get
  601. X    it from L.sys first) then define the following...
  602. X**/
  603. X
  604. X#define USE_UUNAME
  605. X
  606. X/** If you don't want the program to even TOUCH the addresses handed to 
  607. X    it - deferring all expansion to sendmail/smail, then define the following;
  608. X**/
  609. X
  610. X/** #define DONT_TOUCH_ADDRESSES **/
  611. X
  612. X/** Perhaps you'd also like the program not to try to minimize the addresses
  613. X    stored when you 'alias current message'.  If so, define the following
  614. X**/
  615. X
  616. X/** #define DONT_OPTIMIZE_RETURN **/
  617. X
  618. X/** If you'd like "newmail" to automatically go into background when you
  619. X    start it up (instead of the "newmail &" junk with the process id output,
  620. X    then define the following...
  621. X**/
  622. X
  623. X#define AUTO_BACKGROUND
  624. X
  625. X/** If you'd rather your mail transport agent (ie sendmail) put the From:
  626. X    line into the message, define the following...
  627. X**/
  628. X
  629. X#define DONT_ADD_FROM
  630. X
  631. X/** If your machine prefers the Internet notation of user@host for the
  632. X    From: line and addresses, define the following...(the default is to 
  633. X    use this rather than the USENET notation - check your pathalias file!)
  634. X
  635. X**/
  636. X
  637. X#define INTERNET_ADDRESS_FORMAT
  638. X
  639. X/** If you're on a machine that prefers UUCP to Internet addresses, then
  640. X    define the following (the basic change is that on a machine that
  641. X    receives messages of the form <path>!user@<localhost> the displayed
  642. X    address will be <path>!user instead of user@<localhost>.
  643. X
  644. X    BOGUS_INTERNET is the address that your local system appends to 
  645. X    messages occasionally.  The algorithm is simply to REMOVE the
  646. X    BOGUS_INTERNET string.  This is horrible.  *sigh*
  647. X
  648. X**/
  649. X
  650. X#define PREFER_UUCP
  651. X#define BOGUS_INTERNET    "@hplabs.HP.COM"
  652. X
  653. X/** If you're running ACSNET and/or want to have your domain name
  654. X    attached to your hostname on outbound mail then you can define
  655. X    the following (default are not defined)
  656. X**/
  657. X
  658. X#define USE_DOMAIN
  659. X#define DOMAIN        "<enter your domain here>"
  660. X
  661. X/** If you are going to be running the mailer with setgid mail (or
  662. X    something similar) you'll need to define the following to ensure
  663. X    that the users mailbox in the spool directory has the correct
  664. X    group (NOT the users group)
  665. X**/
  666. X
  667. X#define SAVE_GROUP_MAILBOX_ID
  668. X
  669. X/** If you want a neat feature that enables scanning of the message
  670. X    body for entries to add to the users ".calendar" (or whatever)
  671. X    file, define this.
  672. X**/
  673. X
  674. X#define ENABLE_CALENDAR
  675. X#define dflt_calendar_file    "calendar"    /* in HOME directory */
  676. X
  677. X/** If you want to implement 'site hiding' in the mail, then you'll need to
  678. X    uncomment the following lines and set them to reasonable values.  See 
  679. X    the configuration guide for more details....
  680. X**/
  681. X
  682. X/****************************************************************************
  683. X
  684. X#undef    DONT_ADD_FROM        
  685. X
  686. X#define   SITE_HIDING
  687. X#define   HIDDEN_SITE_NAME    "fake-machine-name"
  688. X#define   HIDDEN_SITE_USERS    "/usr/mail/lists/hidden_site_users"
  689. X
  690. X****************************************************************************/
  691. X
  692. X/** Do we have the 'gethostname()' call?  If not, define the following **/
  693. X/** #define NEED_GETHOSTNAME **/
  694. X
  695. X/** are you stuck on a machine that has short names?  If so, define the
  696. X    following **/
  697. X
  698. X/** #define SHORTNAMES **/
  699. X
  700. X#define NOTES_HEADER        "/***** "
  701. X#define NOTES_FOOTER        "/* ---------- */"
  702. X
  703. X#ifdef BSD
  704. X# define system_hash_file    "/usr/spool/mail/.alias_hash"
  705. X# define system_data_file    "/usr/spool/mail/.alias_data"
  706. X#else
  707. X# define system_hash_file    "/usr/mail/.alias_hash"
  708. X# define system_data_file    "/usr/mail/.alias_data"
  709. X#endif
  710. X
  711. X#define pathfile        "/usr/lib/nmail.paths"
  712. X#define domains            "/usr/lib/domains"
  713. X
  714. X#define Lsys            "/usr/lib/uucp/L.sys"
  715. X
  716. X/** where to put the output of the elm -d command... (in home dir) **/
  717. X#define DEBUG        "ELM:debug.info"
  718. X#define OLDEBUG        "ELM:debug.last"
  719. X
  720. X#define temp_file    "/tmp/snd."
  721. X#define temp_form_file    "/tmp/form."
  722. X#define temp_mbox    "/tmp/mbox."
  723. X#define temp_print      "/tmp/print."
  724. X#define temp_uuname    "/tmp/uuname."
  725. X#define mailtime_file    ".last_read_mail"
  726. X#define readmsg_file    ".readmsg"
  727. X
  728. X#define emacs_editor    "/usr/local/bin/emacs"
  729. X
  730. X#ifdef BSD
  731. X# define default_editor    "/usr/ucb/vi"
  732. X# define mailhome    "/usr/spool/mail/"
  733. X#else
  734. X# define default_editor    "/usr/bin/vi"
  735. X# define mailhome    "/usr/mail/"
  736. X#endif
  737. X
  738. X# define default_pager    "builtin"
  739. X
  740. X#define sendmail    "/usr/lib/sendmail"
  741. X#define smflags        "-oi -oem"    /* ignore dots and mail back errors */
  742. X#define mailer        "/bin/rmail"
  743. X#ifdef BSD
  744. X# define mailx        "/usr/ucb/Mail"
  745. X#else
  746. X# define mailx        "/usr/bin/mailx"
  747. X#endif
  748. X
  749. X#define helphome    "/usr/local/lib"
  750. X#define helpfile    "elm-help"
  751. X
  752. X#define ELMRC_INFO    "/usr/local/lib/elmrc-info"
  753. X
  754. X#define elmrcfile    "/.elmrc"
  755. X#define mailheaders    ".elmheaders"
  756. X#define dead_letter    "Cancelled.mail"
  757. X
  758. X#define unedited_mail    "emergency.mbox"
  759. X
  760. X#define newalias    "newalias -q 1>&2 > /dev/null"
  761. X#define readmsg        "readmsg"
  762. X
  763. X#define remove        "/bin/rm -f"        /* how to remove a file */
  764. X#define cat        "/bin/cat"        /* how to display files */
  765. X#define uuname        "uuname"        /* how to get a uuname  */
  766. END_OF_hdrs/sysdefs.master
  767. if test 7256 -ne `wc -c <hdrs/sysdefs.master`; then
  768.     echo shar: \"hdrs/sysdefs.master\" unpacked with wrong size!?
  769. fi
  770. chmod +x hdrs/sysdefs.master
  771. # end of overwriting check
  772. fi
  773. echo shar: Extracting \"hdrs/sysdefs.old\" \(7274 characters\)
  774. if test -f hdrs/sysdefs.old ; then 
  775.   echo shar: Will not over-write existing file \"hdrs/sysdefs.old\"
  776. else
  777. sed "s/^X//" >hdrs/sysdefs.old <<'END_OF_hdrs/sysdefs.old'
  778. X/**            sysdefs.h            **/
  779. X
  780. X/**  System level, configurable, defines for the ELM mail system.  **/
  781. X
  782. X/**  (C) Copyright 1986 Dave Taylor                                **/
  783. X
  784. X/** Define the following if you think that the information in messages
  785. X    that have "Reply-To:" and/or "From:" fields with addresses will
  786. X    contain valid addressing information.  If this isn't defined, the
  787. X    calculated return address will ALWAYS be used instead.  (note that
  788. X    this doesn't necessarily preclude the use of G)roup replies).
  789. X**/
  790. X
  791. X/** #define USE_EMBEDDED_ADDRESSES **/    
  792. X
  793. X
  794. X#define FIND_DELTA    10        /* byte region where the binary search
  795. X                       on the path alias file is fruitless 
  796. X                                           (can't be within this boundary)    */
  797. X
  798. X#define MAX_SALIASES    503    /* number of system aliases allowed      */
  799. X#define MAX_UALIASES    251    /* number of user aliases allowed      */
  800. X#define MAX_IN_WEEDLIST 150    /* max headers to weed out               */
  801. X
  802. X#define MAX_HOPS    35    /* max hops in return addr to E)veryone  */
  803. X
  804. X#define MAX_ATTEMPTS    6    /* #times to attempt lock file creation */
  805. X
  806. X/** see leavembox.c to determine if this should be defined or not....The 
  807. X    default is to NOT have it defined.
  808. X**/
  809. X
  810. X/** #define REMOVE_AT_LAST **/
  811. X
  812. X#define DEFAULT_BATCH_SUBJECT  "no subject (file transmission)"
  813. X
  814. X/** If you want to have the mailer know about valid mailboxes on the
  815. X    host machine (assumes no delivery agent aliases) then you should
  816. X    undefine this (the default is to have it defined)...
  817. X**/
  818. X
  819. X#define NOCHECK_VALIDNAME
  820. X
  821. X/** If your machine doesn't have virtual memory (specifically the vfork() 
  822. X    command) then you should define the following....        
  823. X**/
  824. X
  825. X/** #define NO_VM **/
  826. X
  827. X/** If you're running sendmail, or another transport agent that can 
  828. X    handle the blind-carbon-copy list define the following
  829. X**/
  830. X
  831. X#define ALLOW_BCC
  832. X
  833. X/** If you have pathalias, can we get to it as a DBM file??? **/
  834. X
  835. X/** #define USE_DBM **/
  836. X
  837. X/** If you want the mailer to check the pathalias database BEFORE it
  838. X    looks to see if a specified machine is in the L.sys database (in
  839. X    some cases routing is preferable to direct lines) then you should
  840. X    define the following...
  841. X**/
  842. X
  843. X/** #define LOOK_CLOSE_AFTER_SEARCH **/
  844. X
  845. X
  846. X/** If you'd rather the program automatically used the 'uuname' command
  847. X    to figure out what machines it talks to (instead of trying to get
  848. X    it from L.sys first) then define the following...
  849. X**/
  850. X
  851. X#define USE_UUNAME
  852. X
  853. X/** If you don't want the program to even TOUCH the addresses handed to 
  854. X    it - deferring all expansion to sendmail/smail, then define the following;
  855. X**/
  856. X
  857. X/** #define DONT_TOUCH_ADDRESSES **/
  858. X
  859. X/** Perhaps you'd also like the program not to try to minimize the addresses
  860. X    stored when you 'alias current message'.  If so, define the following
  861. X**/
  862. X
  863. X/** #define DONT_OPTIMIZE_RETURN **/
  864. X
  865. X/** If you'd like "newmail" to automatically go into background when you
  866. X    start it up (instead of the "newmail &" junk with the process id output,
  867. X    then define the following...
  868. X**/
  869. X
  870. X#define AUTO_BACKGROUND
  871. X
  872. X/** If you'd rather your mail transport agent (ie sendmail) put the From:
  873. X    line into the message, define the following...
  874. X**/
  875. X
  876. X#define DONT_ADD_FROM
  877. X
  878. X/** If your machine prefers the Internet notation of user@host for the
  879. X    From: line and addresses, define the following...(the default is to 
  880. X    use this rather than the USENET notation - check your pathalias file!)
  881. X
  882. X**/
  883. X
  884. X#define INTERNET_ADDRESS_FORMAT
  885. X
  886. X/** If you're on a machine that prefers UUCP to Internet addresses, then
  887. X    define the following (the basic change is that on a machine that
  888. X    receives messages of the form <path>!user@<localhost> the displayed
  889. X    address will be <path>!user instead of user@<localhost>.
  890. X
  891. X    BOGUS_INTERNET is the address that your local system appends to 
  892. X    messages occasionally.  The algorithm is simply to REMOVE the
  893. X    BOGUS_INTERNET string.  This is horrible.  *sigh*
  894. X
  895. X**/
  896. X
  897. X#define PREFER_UUCP
  898. X#define BOGUS_INTERNET    "@hplabs.HP.COM"
  899. X
  900. X/** If you're running ACSNET and/or want to have your domain name
  901. X    attached to your hostname on outbound mail then you can define
  902. X    the following (default are not defined)
  903. X**/
  904. X
  905. X/** #define USE_DOMAIN **/
  906. X#define DOMAIN        "<enter your domain here>"
  907. X
  908. X/** If you are going to be running the mailer with setgid mail (or
  909. X    something similar) you'll need to define the following to ensure
  910. X    that the users mailbox in the spool directory has the correct
  911. X    group (NOT the users group)
  912. X**/
  913. X
  914. X#define SAVE_GROUP_MAILBOX_ID
  915. X
  916. X/** If you want a neat feature that enables scanning of the message
  917. X    body for entries to add to the users ".calendar" (or whatever)
  918. X    file, define this.
  919. X**/
  920. X
  921. X#define ENABLE_CALENDAR
  922. X#define dflt_calendar_file    "calendar"    /* in HOME directory */
  923. X
  924. X/** If you want to implement 'site hiding' in the mail, then you'll need to
  925. X    uncomment the following lines and set them to reasonable values.  See 
  926. X    the configuration guide for more details....
  927. X**/
  928. X
  929. X/****************************************************************************
  930. X
  931. X#undef    DONT_ADD_FROM        
  932. X
  933. X#define   SITE_HIDING
  934. X#define   HIDDEN_SITE_NAME    "fake-machine-name"
  935. X#define   HIDDEN_SITE_USERS    "/usr/mail/lists/hidden_site_users"
  936. X
  937. X****************************************************************************/
  938. X
  939. X/** Do we have the 'gethostname()' call?  If not, define the following **/
  940. X/** #define NEED_GETHOSTNAME **/
  941. X
  942. X/** are you stuck on a machine that has short names?  If so, define the
  943. X    following **/
  944. X
  945. X/** #define SHORTNAMES **/
  946. X
  947. X#define NOTES_HEADER        "/***** "
  948. X#define NOTES_FOOTER        "/* ---------- */"
  949. X
  950. X#ifdef BSD
  951. X# define system_hash_file    "/usr/spool/mail/.alias_hash"
  952. X# define system_data_file    "/usr/spool/mail/.alias_data"
  953. X#else
  954. X# define system_hash_file    "/usr/mail/.alias_hash"
  955. X# define system_data_file    "/usr/mail/.alias_data"
  956. X#endif
  957. X
  958. X#define pathfile        "/usr/lib/nmail.paths"
  959. X#define domains            "/usr/lib/domains"
  960. X
  961. X#define Lsys            "/usr/lib/uucp/L.sys"
  962. X
  963. X/** where to put the output of the elm -d command... (in home dir) **/
  964. X#define DEBUG        "ELM:debug.info"
  965. X#define OLDEBUG        "ELM:debug.last"
  966. X
  967. X#define temp_file    "/tmp/snd."
  968. X#define temp_form_file    "/tmp/form."
  969. X#define temp_mbox    "/tmp/mbox."
  970. X#define temp_print      "/tmp/print."
  971. X#define temp_uuname    "/tmp/uuname."
  972. X#define mailtime_file    ".last_read_mail"
  973. X#define readmsg_file    ".readmsg"
  974. X
  975. X#define emacs_editor    "/usr/local/bin/emacs"
  976. X
  977. X#ifdef BSD
  978. X# define default_editor    "/usr/ucb/vi"
  979. X# define mailhome    "/usr/spool/mail/"
  980. X#else
  981. X# define default_editor    "/usr/bin/vi"
  982. X# define mailhome    "/usr/mail/"
  983. X#endif
  984. X
  985. X# define default_pager    "builtin"
  986. X
  987. X#define sendmail    "/usr/lib/sendmail"
  988. X#define smflags        "-oi -oem"    /* ignore dots and mail back errors */
  989. X#define mailer        "/bin/rmail"
  990. X#ifdef BSD
  991. X# define mailx        "/usr/ucb/Mail"
  992. X#else
  993. X# define mailx        "/usr/bin/mailx"
  994. X#endif
  995. X
  996. X#define helphome    "/usr/local/lib"
  997. X#define helpfile    "elm-help"
  998. X
  999. X#define ELMRC_INFO    "/usr/local/lib/elmrc-info"
  1000. X
  1001. X#define elmrcfile    "/.elmrc"
  1002. X#define mailheaders    ".elmheaders"
  1003. X#define dead_letter    "Cancelled.mail"
  1004. X
  1005. X#define unedited_mail    "emergency.mbox"
  1006. X
  1007. X#define newalias    "newalias -q 1>&2 > /dev/null"
  1008. X#define readmsg        "readmsg"
  1009. X
  1010. X#define remove        "/bin/rm -f"        /* how to remove a file */
  1011. X#define cat        "/bin/cat"        /* how to display files */
  1012. X#define uuname        "uuname"        /* how to get a uuname  */
  1013. END_OF_hdrs/sysdefs.old
  1014. if test 7274 -ne `wc -c <hdrs/sysdefs.old`; then
  1015.     echo shar: \"hdrs/sysdefs.old\" unpacked with wrong size!?
  1016. fi
  1017. # end of overwriting check
  1018. fi
  1019. echo shar: Extracting \"src/file.c\" \(6634 characters\)
  1020. if test -f src/file.c ; then 
  1021.   echo shar: Will not over-write existing file \"src/file.c\"
  1022. else
  1023. sed "s/^X//" >src/file.c <<'END_OF_src/file.c'
  1024. X/**        file.c        **/
  1025. X
  1026. X/** File I/O routines, mostly the save to file command...
  1027. X
  1028. X    (C) Copyright 1986, Dave Taylor
  1029. X**/
  1030. X
  1031. X#include "headers.h"
  1032. X#include <ctype.h>
  1033. X#include <errno.h>
  1034. X
  1035. X#ifdef BSD
  1036. X#undef tolower
  1037. X#endif
  1038. X
  1039. Xextern int errno;
  1040. X
  1041. Xchar *error_name(), *error_description(), *strcpy(), *getenv();
  1042. Xunsigned long sleep();
  1043. X
  1044. Xint
  1045. Xsave(redraw)
  1046. Xint *redraw;
  1047. X{
  1048. X    /** Save all tagged messages + current in a file.  If no messages
  1049. X        are tagged, save the current message instead!  This routine
  1050. X        will return ZERO if the operation failed.
  1051. X        'redraw' is set to TRUE iff we use the '?' and mess up
  1052. X        the screen.  Pretty reasonable, eh?
  1053. X    **/
  1054. X
  1055. X    register int tagged = 0, i, oldstat, appending = 0;
  1056. X    register int iterations = 0, continue_looping;
  1057. X    char filename[SLEN], address[LONG_SLEN], buffer[SLEN];
  1058. X    FILE *save_file;
  1059. X
  1060. X    oldstat = header_table[current-1].status;    /* remember */
  1061. X
  1062. X    for (i=0; i < message_count; i++)
  1063. X      if (ison(header_table[i].status, TAGGED))
  1064. X        tagged++;
  1065. X
  1066. X    if (tagged == 0) {
  1067. X      tagged = 1;
  1068. X      setit(header_table[current-1].status, TAGGED);
  1069. X    }
  1070. X
  1071. X    dprint2(4,"%d message%s tagged for saving (save)\n", tagged,
  1072. X        plural(tagged));
  1073. X
  1074. X    do {
  1075. X
  1076. X      continue_looping = 0;    /* clear the flag, ho hum... */
  1077. X
  1078. X      if (iterations++) {
  1079. X        printf("File message%s in: ", plural(tagged));
  1080. X        fflush(stdout);
  1081. X      }
  1082. X      else
  1083. X        PutLine1(LINES-2, 0, "File message%s in: ", plural(tagged));
  1084. X
  1085. X      if (save_by_name) {
  1086. X        /** build default filename to save to **/
  1087. X        get_return(address);
  1088. X        get_return_name(address, buffer, TRUE);
  1089. X        sprintf(filename, "=%s", buffer);
  1090. X      }
  1091. X      else
  1092. X        filename[0] = '\0';
  1093. X
  1094. X      if (iterations > 1) {
  1095. X        optionally_enter(filename, -1, -1, FALSE);
  1096. X      } 
  1097. X      else {
  1098. X        if (tagged > 1)
  1099. X          optionally_enter(filename, LINES-2, 19, FALSE);
  1100. X        else    
  1101. X          optionally_enter(filename, LINES-2, 18, FALSE);
  1102. X      }
  1103. X  
  1104. X      if (iterations == 1)
  1105. X        MoveCursor(LINES-1,0);
  1106. X
  1107. X      if (strlen(filename) == 0) {  /** <return> means 'cancel', right? **/
  1108. X        header_table[current-1].status = oldstat;    /* BACK! */
  1109. X        return(0);
  1110. X      }
  1111. X     
  1112. X      if (strcmp(filename,"?") == 0) {
  1113. X        *redraw = TRUE;    /* set the flag so we know what to do later */
  1114. X        list_folders();
  1115. X        continue_looping++;
  1116. X      }
  1117. X    } while (continue_looping);
  1118. X
  1119. X    if (! expand_filename(filename)) {
  1120. X      dprint1(2,"Error: Failed on expansion of filename %s (save)\n", 
  1121. X           filename);
  1122. X      header_table[current-1].status = oldstat;    /* BACK! */
  1123. X      return(0);    /* failed expanding name! */
  1124. X    }
  1125. X
  1126. X    if (access(filename,ACCESS_EXISTS))     /* already there!! */
  1127. X      appending = 1;
  1128. X      
  1129. X#ifdef BSD4.1
  1130. X    if ((errno = ((can_open(filename, "a") & ~0x0200) >>8))) {
  1131. X#else
  1132. X    if ((errno = can_open(filename, "a"))) {
  1133. X#endif
  1134. X      error1("Wrong permissions to save message to file %s!", filename);
  1135. X      dprint2(2,"Error: access permission on file %s denied (%s)! (save)\n",
  1136. X          filename, error_name(errno));
  1137. X      header_table[current-1].status = oldstat;    /* BACK! */
  1138. X      return(0);
  1139. X    }
  1140. X
  1141. X    dprint1(4,"Saving mail to file '%s'...\n", filename);
  1142. X
  1143. X    if ((save_file = fopen(filename,"a")) == NULL) {
  1144. X      dprint1(2, "Error: couldn't append to specified file %s (save)\n", 
  1145. X           filename);
  1146. X      error1("Couldn't append to file %s!", filename);
  1147. X      header_table[current-1].status = oldstat;    /* BACK! */
  1148. X      return(0); 
  1149. X    }
  1150. X
  1151. X    for (i=0; i < message_count; i++)     /* save each tagged msg */
  1152. X      if (header_table[i].status & TAGGED)
  1153. X        save_message(i, filename, save_file, (tagged > 1), appending++);
  1154. X
  1155. X    fclose(save_file);
  1156. X
  1157. X    chown(filename, userid, groupid);    /* owned by user */
  1158. X    if (tagged > 1)
  1159. X      error1("Message%s saved", plural(tagged));
  1160. X    return(1);
  1161. X}
  1162. X
  1163. Xint
  1164. Xsave_message(number, filename, fd, pause, appending)
  1165. Xint number, pause, appending;
  1166. Xchar *filename;
  1167. XFILE *fd;
  1168. X{
  1169. X    /** Save an actual message to a file.  This is called by 
  1170. X        "save()" only!  The parameters are the message number,
  1171. X        and the name and file descriptor of the file to save to.
  1172. X        If 'pause' is true, a sleep(2) will be done after the
  1173. X        saved message appears on the screen...
  1174. X        'appending' is only true if the file already exists 
  1175. X    **/
  1176. X
  1177. X    register int save_current;
  1178. X    
  1179. X    dprint1(4, "\tSaving message %d to file...\n", number);
  1180. X
  1181. X    save_current = current;
  1182. X    current = number+1;
  1183. X    copy_message("", fd, FALSE, FALSE);
  1184. X    current = save_current;
  1185. X
  1186. X    if (resolve_mode)
  1187. X      setit(header_table[number].status, DELETED); /* deleted, but ...   */
  1188. X    clearit(header_table[number].status, TAGGED);  /* not tagged anymore */
  1189. X    clearit(header_table[number].status, NEW);     /* it's not new now!  */
  1190. X
  1191. X    if (! appending)    /* don't ask */
  1192. X      error2("Message %d appended to file %s", number+1, filename);
  1193. X    else
  1194. X      error2("Message %d saved to file %s", number+1, filename);
  1195. X
  1196. X    show_new_status(number);    /* update screen, if needed */
  1197. X
  1198. X    if (pause) sleep(2);
  1199. X}
  1200. X
  1201. Xint
  1202. Xexpand_filename(filename)
  1203. Xchar *filename;
  1204. X{
  1205. X    /** Expands '~' and '=' to specified file names, also will try to 
  1206. X        expand shell variables if encountered.. '+' and '%' are synonymous 
  1207. X        with '=' (folder dir)... **/
  1208. X
  1209. X    char buffer[SLEN], varname[SLEN], env_value[SLEN], *ptr;
  1210. X    register int i = 1, index = 0;
  1211. X    char *getenv();
  1212. X
  1213. X    ptr = filename;
  1214. X    while (*ptr == ' ') ptr++;    /* leading spaces GONE! */
  1215. X    strcpy(filename, ptr);
  1216. X
  1217. X    /** New stuff - make sure no illegal char as last **/
  1218. X
  1219. X    if (lastch(filename) == '\n' || lastch(filename) == '\r')
  1220. X      lastch(filename) = '\0';
  1221. X      
  1222. X    if (filename[0] == '~') {
  1223. X      sprintf(buffer, "%s%s%s", home, 
  1224. X        (filename[1] != '/' && lastch(folders) != '/')? "/" : "",
  1225. X          (char *) filename + 1);
  1226. X      strcpy(filename, buffer);
  1227. X    }
  1228. X    else if (filename[0] == '=' || filename[0] == '+' || 
  1229. X          filename[0] == '%') {
  1230. X      if (strlen(folders) == 0) {
  1231. X        dprint2(3,"Error: maildir not defined - can't expand '%c' (%s)\n",
  1232. X             filename[0], "expand_filename");
  1233. X        error1("MAILDIR not defined.  Can't expand '%c'", filename[0]);
  1234. X        return(0);
  1235. X      }
  1236. X      sprintf(buffer, "%s%s%s", folders, 
  1237. X        (filename[1] != '/' && lastch(folders) != '/')? "/" : "",
  1238. X        (char *) filename + 1);
  1239. X      strcpy(filename, buffer);
  1240. X    }
  1241. X    else if (filename[0] == '$') {    /* env variable! */
  1242. X      while (isalnum(filename[i]))
  1243. X        varname[index++] = filename[i++];
  1244. X      varname[index] = '\0';
  1245. X
  1246. X      env_value[0] = '\0';            /* null string for strlen! */
  1247. X      if (getenv(varname) != NULL)
  1248. X        strcpy(env_value, getenv(varname));
  1249. X
  1250. X      if (strlen(env_value) == 0) {
  1251. X        dprint2(3,"Error: Can't expand environment variable $%s (%s)\n",
  1252. X            varname, "expand_filename");
  1253. X        error1("Don't know what the value of $%s is!", varname);
  1254. X        return(0);
  1255. X      }
  1256. X
  1257. X      sprintf(buffer, "%s%s%s", env_value, 
  1258. X          (filename[i] != '/' && lastch(env_value) != '/')? "/" : "",
  1259. X          (char *) filename + i);
  1260. X      strcpy(filename, buffer);
  1261. X    }
  1262. X      
  1263. X    return(1);
  1264. X}
  1265. END_OF_src/file.c
  1266. if test 6634 -ne `wc -c <src/file.c`; then
  1267.     echo shar: \"src/file.c\" unpacked with wrong size!?
  1268. fi
  1269. # end of overwriting check
  1270. fi
  1271. echo shar: Extracting \"src/initialize.uts\" \(7197 characters\)
  1272. if test -f src/initialize.uts ; then 
  1273.   echo shar: Will not over-write existing file \"src/initialize.uts\"
  1274. else
  1275. sed "s/^X//" >src/initialize.uts <<'END_OF_src/initialize.uts'
  1276. XFrom hpccc!mcgregor@hplabs.ARPA Fri May  9 16:05:10 1986
  1277. XReceived: from hplabs.ARPA by hpldat ; Fri, 9 May 86 16:05:01 pdt
  1278. XMessage-Id: <8605092305.AA00689@hpldat>
  1279. XReceived: by hplabs.ARPA ; Fri, 9 May 86 16:01:29 pdt
  1280. XFrom: Scott McGregor <hpccc!mcgregor@hplabs.ARPA>
  1281. XTo: taylor@hplabs
  1282. XDate: Fri, 9 May 86 15:23:16 PDT
  1283. XSubject: initialize.c
  1284. XX-Mailer: msg [version 3.3a]
  1285. X
  1286. X/**        initialize.c        **/
  1287. X
  1288. X/***** Initialize - read in all the defaults etc etc 
  1289. X       (C) Copyright 1985 Dave Taylor
  1290. X*****/
  1291. X
  1292. X#include "headers.h"
  1293. X
  1294. X#ifdef BSD
  1295. X#  include <sgtty.h>
  1296. X#else
  1297. X#  include <termio.h>
  1298. X#endif
  1299. X
  1300. X#include <pwd.h>
  1301. X
  1302. X#ifdef BSD
  1303. X#  include <sys/time.h>
  1304. X#else
  1305. X#  include <time.h>
  1306. X#endif
  1307. X
  1308. X#include <signal.h>
  1309. X#include <ctype.h>
  1310. X#include <errno.h>
  1311. X
  1312. X#ifdef BSD
  1313. X#undef tolower
  1314. X#endif
  1315. X
  1316. X
  1317. Xextern int errno;        /* system error number on failure */
  1318. X
  1319. Xchar *error_name(), *error_description();
  1320. X
  1321. Xchar *expand_logname(), *getenv(), *getlogin();
  1322. X
  1323. Xinitialize(InitScreen_to)
  1324. Xint InitScreen_to;
  1325. X{
  1326. X    struct passwd *pass, *getpwnam();
  1327. X
  1328. X    register int i;
  1329. X    int      quit_signal(), term_signal(), ill_signal(),
  1330. X         fpe_signal(),  bus_signal(),  segv_signal(),
  1331. X             alarm_signal();
  1332. X    char     buffer[SLEN], *cp;
  1333. X    
  1334. X    userid  = getuid();
  1335. X    groupid = getgid();    
  1336. X
  1337. X    strcpy(home,((cp = getenv("HOME")) == NULL)? "" : cp);
  1338. X    strcpy(shell,((cp = getenv("SHELL")) == NULL)? "" : cp);
  1339. X
  1340. X    if (debug) {        /* setup for dprintf statements! */
  1341. X      char filename[SLEN];
  1342. X      sprintf(filename, "%s/%s", home, DEBUG);
  1343. X      if ((debugfile = fopen(filename, "w")) == NULL) {
  1344. X        debug = 0;    /* otherwise 'leave' will try to log! */
  1345. X        leave(fprintf(stderr,"Could not open file %s for debug output!\n",
  1346. X          filename));
  1347. X      }
  1348. X      if (InitScreen_to) {
  1349. X          InitScreen();
  1350. X      }
  1351. X      chown(filename, userid, groupid); /* file owned by user */
  1352. X
  1353. X      fprintf(debugfile, "Debug output of the MSG program.  Version %s\n\n",
  1354. X          VERSION);
  1355. X    }
  1356. X#ifndef UTS
  1357. X    signal(SIGINT,  SIG_IGN);
  1358. X    signal(SIGQUIT, quit_signal);        /* Quit signal                 */
  1359. X    signal(SIGTERM, term_signal);         /* Terminate signal         */
  1360. X    signal(SIGILL,  ill_signal);        /* Illegal instruction      */
  1361. X    signal(SIGFPE,  fpe_signal);        /* Floating point exception */
  1362. X    signal(SIGBUS,  bus_signal);        /* Bus error              */
  1363. X    signal(SIGSEGV, segv_signal);        /* Segmentation Violation   */
  1364. X#endif
  1365. X    signal(SIGALRM, alarm_signal);        /* Process Timer Alarm        */
  1366. X
  1367. X    if (isa3270()) {
  1368. X      isatube++;
  1369. X      dprint0(1, "** We're using a 3270 tube!! **\n");
  1370. X    }
  1371. X
  1372. X#ifndef UTS
  1373. X    get_connections();          /* who do we talk to directly?? */
  1374. X#endif
  1375. X    open_domain_file();        /* if we got it, we want it!  */
  1376. X
  1377. X    get_term_chars();
  1378. X    
  1379. X    gethostname(hostname, sizeof(hostname));
  1380. X    if ((cp = getlogin()) == NULL)
  1381. X      cuserid(username);
  1382. X    else
  1383. X      strcpy(username, cp);
  1384. X
  1385. X    /* now let's get the full username.. */
  1386. X
  1387. X    if ((pass = getpwnam(username)) == NULL) {
  1388. X      error("Couldn't read password entry??");
  1389. X      strcpy(full_username, username);
  1390. X    }
  1391. X    else {
  1392. X      for (i=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
  1393. X           i++)
  1394. X          if (pass->pw_gecos[i] == '&') {
  1395. X            full_username[i] = '\0';
  1396. X            strcat(full_username, expand_logname());
  1397. X            i = strlen(full_username) - 2;
  1398. X          }
  1399. X          else
  1400. X            full_username[i] = pass->pw_gecos[i];
  1401. X      full_username[i] = '\0'; 
  1402. X    }
  1403. X
  1404. X    if ((cp = getenv("EDITOR")) == NULL)
  1405. X      strcpy(editor,default_editor);
  1406. X    else
  1407. X      strcpy(editor, cp);
  1408. X
  1409. X    if (! mail_only) {
  1410. X      mailbox[0] = '\0';
  1411. X      strcpy(prefixchars, "> ");     /* default message prefix */
  1412. X    }
  1413. X
  1414. X    read_rc_file();        /* reading the .msgrc next... */
  1415. X
  1416. X    /** now try to expand the specified filename... **/
  1417. X
  1418. X    if (strlen(infile) > 0) {
  1419. X      (void) expand_filename(infile);
  1420. X      if ((errno = can_access(infile, READ_ACCESS))) {
  1421. X        dprint2(1,"Error: given file %s as mailbox - unreadable (%s)!\n", 
  1422. X             infile, error_name(errno));
  1423. X        fprintf(stderr,"Can't open mailbox '%s' for reading!\n", infile);
  1424. X        exit(1);
  1425. X      }
  1426. X    }
  1427. X
  1428. X    /** check to see if the user has defined a LINES or COLUMNS
  1429. X        value different to that in the termcap entry (for
  1430. X        windowing systems, of course!) **/
  1431. X
  1432. X    if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
  1433. X      sscanf(cp, "%d", &LINES);
  1434. X      LINES -= 1;    /* kludge for HP Window system? ... */
  1435. X    }
  1436. X
  1437. X    if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
  1438. X      sscanf(cp, "%d", &COLUMNS);
  1439. X
  1440. X    /** fix the shell if needed **/
  1441. X
  1442. X    if (shell[0] != '/') {
  1443. X       sprintf(buffer, "/bin/%s", shell);
  1444. X       strcpy(shell, buffer);
  1445. X    }
  1446. X
  1447. X    if (! mail_only) {
  1448. X      mailbox_defined = (mailbox[0] != '\0'); 
  1449. X
  1450. X      /* get the cursor control keys... */
  1451. X
  1452. X      if ((cp = return_value_of("ku")) == NULL || strlen(cp) != 2)
  1453. X        cursor_control = FALSE;
  1454. X      else {
  1455. X        strcpy(up, cp);
  1456. X        if ((cp = return_value_of("kd")) == NULL || strlen(cp) != 2)
  1457. X          cursor_control = FALSE;
  1458. X        else {
  1459. X          strcpy(down, cp);
  1460. X          cursor_control = TRUE;
  1461. X          transmit_functions(ON);
  1462. X        }
  1463. X      }
  1464. X
  1465. X      strcpy(start_highlight, "->");
  1466. X      end_highlight[0] = '\0';
  1467. X
  1468. X      if (!arrow_cursor) {    /* try to use inverse bar instead */
  1469. X        if ((cp = return_value_of("so")) != NULL) {
  1470. X          strcpy(start_highlight, cp);
  1471. X          if ((cp = return_value_of("se")) == NULL)
  1472. X            strcpy(start_highlight, "->");
  1473. X          else {
  1474. X            strcpy(end_highlight, cp);
  1475. X            has_highlighting = TRUE;
  1476. X          }
  1477. X        }
  1478. X      }
  1479. X    }
  1480. X
  1481. X    if (read_aliases)
  1482. X        read_alias_files();
  1483. X
  1484. X    if (! mail_only) {
  1485. X      if (mini_menu)
  1486. X        headers_per_page = LINES - 13;
  1487. X      else
  1488. X        headers_per_page = LINES -  8;    /* 5 more headers! */
  1489. X
  1490. X      newmbox(1,FALSE, TRUE);    /* read in the mailbox! */
  1491. X    }
  1492. X
  1493. X    init_findnode();    /* set up the path alias stuff */
  1494. X
  1495. X    dprint0(2,"\n-- end of initialization phase --\n");
  1496. X
  1497. X    dprint3(2,"\thostname = %s\n\tusername = %s\n\tfull_username = \"%s\"\n",
  1498. X             hostname, username, full_username);
  1499. X
  1500. X    dprint3(2,"\thome = %s\n\teditor = %s\n\tmailbox = %s\n",
  1501. X         home, editor, mailbox);
  1502. X
  1503. X    dprint3(2,"\tinfile = %s\n\tfolder-dir = %s\n\tprintout = \"%s\"\n",
  1504. X         infile, folders, printout);
  1505. X    
  1506. X    dprint3(2,"\tsavefile = %s\n\tprefix = \"%s\"\n\tshell = %s\n",
  1507. X        savefile, prefixchars, shell);
  1508. X    
  1509. X    dprint0(1,"-- beginning execution phase --\n\n");
  1510. X}
  1511. X
  1512. Xget_term_chars()
  1513. X{
  1514. X    /** This routine sucks out the special terminal characters
  1515. X        ERASE and KILL for use in the input routine.  The meaning 
  1516. X            of the characters are (dare I say it?) fairly obvious... **/
  1517. X
  1518. X#ifdef BSD
  1519. X    struct sgttyb term_buffer;
  1520. X
  1521. X# define TCGETA    TIOCGETP
  1522. X
  1523. X#else 
  1524. X    struct termio term_buffer;
  1525. X#endif
  1526. X
  1527. X    if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
  1528. X      dprint1(1,"Error: %s encountered on ioctl call (get_term_chars)\n", 
  1529. X           error_name(errno));
  1530. X      /* set to defaults for terminal driver */
  1531. X      backspace = BACKSPACE;
  1532. X      kill_line = ctrl('U');
  1533. X    }
  1534. X    else {
  1535. X#ifdef BSD
  1536. X      backspace = term_buffer.sg_erase;
  1537. X      kill_line = term_buffer.sg_kill;
  1538. X#else
  1539. X      backspace = term_buffer.c_cc[VERASE];
  1540. X      kill_line = term_buffer.c_cc[VKILL];
  1541. X#endif
  1542. X    }
  1543. X}
  1544. X
  1545. Xchar *expand_logname()
  1546. X{
  1547. X    /** Return logname in a nice format (for expanding "&" in the
  1548. X        /etc/passwd file) **/
  1549. X
  1550. X    static char buffer[SLEN];
  1551. X    register int i;
  1552. X
  1553. X    if (strlen(username) == 0)
  1554. X      buffer[0] = '\0';
  1555. X    else {
  1556. X      buffer[0] = toupper(username[0]);
  1557. X
  1558. X      for (i=1; username[i] != '\0'; i++)
  1559. X        buffer[i] = tolower(username[i]);
  1560. X
  1561. X      buffer[i] = '\0';
  1562. X    }
  1563. X
  1564. X    return( (char *) buffer);    
  1565. X}
  1566. X
  1567. END_OF_src/initialize.uts
  1568. if test 7197 -ne `wc -c <src/initialize.uts`; then
  1569.     echo shar: \"src/initialize.uts\" unpacked with wrong size!?
  1570. fi
  1571. # end of overwriting check
  1572. fi
  1573. echo shar: Extracting \"src/limit.c\" \(6658 characters\)
  1574. if test -f src/limit.c ; then 
  1575.   echo shar: Will not over-write existing file \"src/limit.c\"
  1576. else
  1577. sed "s/^X//" >src/limit.c <<'END_OF_src/limit.c'
  1578. X/**            limit.c            **/
  1579. X
  1580. X/** This stuff is inspired by MH and dmail and is used to 'select'
  1581. X    a subset of the existing mail in the folder based on one of a
  1582. X    number of criteria.  The basic tricks are pretty easy - we have
  1583. X    as status of VISIBLE associated with each header stored in the
  1584. X    (er) mind of the computer (!) and simply modify the commands to
  1585. X    check that flag...the global variable `selected' is set to the
  1586. X    number of messages currently selected, or ZERO if no select.
  1587. X
  1588. X       (C) Copyright 1986, Dave Taylor
  1589. X**/
  1590. X
  1591. X#include "headers.h"
  1592. X
  1593. X#define TO        1
  1594. X#define FROM        2
  1595. X
  1596. Xchar *shift_lower();
  1597. X
  1598. Xint
  1599. Xlimit()
  1600. X{
  1601. X    /** returns non-zero if we did enough to redraw the screen **/
  1602. X    
  1603. X    char criteria[STRING], first[STRING], rest[STRING];
  1604. X    int  last_current;
  1605. X
  1606. X    if (selected) {
  1607. X      PutLine1(LINES-2, 0, 
  1608. X        "Already have selection criteria - add more? (y/n) n%c",
  1609. X        BACKSPACE);
  1610. X      ReadCh(criteria[0]);
  1611. X      if (tolower(criteria[0]) == 'y') 
  1612. X        PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
  1613. X      else {
  1614. X        selected = 0;
  1615. X        PutLine0(LINES-3, COLUMNS-30, "Use '?' for help");
  1616. X      }
  1617. X      
  1618. X    }
  1619. X
  1620. X    PutLine1(LINES-2, 0, "Enter criteria: ");
  1621. X    CleartoEOLN();
  1622. X
  1623. X    criteria[0] = '\0';
  1624. X    optionally_enter(criteria, LINES-2, 16, FALSE);
  1625. X    
  1626. X    if (strlen(criteria) == 0) return(0);
  1627. X
  1628. X    split_word(criteria, first, rest);
  1629. X    
  1630. X    if (equal(first, "all")) {
  1631. X       selected = 0;
  1632. X       return(TRUE);
  1633. X    }
  1634. X
  1635. X    last_current = current;
  1636. X    current = -1;
  1637. X
  1638. X    if (equal(first, "subj") || equal(first, "subject"))
  1639. X      selected = limit_selection(SUBJECT, rest, selected);
  1640. X    else if (equal(first, "to"))
  1641. X      selected = limit_selection(TO, rest, selected);
  1642. X    else if (equal(first, "from"))
  1643. X      selected = limit_selection(FROM, rest, selected);
  1644. X    else {
  1645. X      selected = 0;
  1646. X      error1("Don't understand \"%s\" as a selection criteria!", first);
  1647. X      sleep(2);
  1648. X    }
  1649. X
  1650. X    if (! selected)
  1651. X      current = last_current;
  1652. X    else
  1653. X      current = visible_to_index(1)+1;    /* map it and shift up 1 */
  1654. X
  1655. X    if (! selected)
  1656. X      set_error("no items selected");
  1657. X    else {
  1658. X      sprintf(first, "%d items selected", selected);
  1659. X      set_error(first);
  1660. X    }
  1661. X    
  1662. X    return(selected);
  1663. X}
  1664. X
  1665. Xint
  1666. Xlimit_selection(based_on, pattern, additional_criteria)
  1667. Xint based_on, additional_criteria;
  1668. Xchar *pattern;
  1669. X{
  1670. X    /** Given the type of criteria, and the pattern, mark all
  1671. X        non-matching headers as ! VISIBLE.  If additional_criteria,
  1672. X        don't mark as visible something that isn't currently!
  1673. X    **/
  1674. X
  1675. X    register int index, count = 0;
  1676. X
  1677. X    dprint3(2,"\n\n\n**limit on %d - '%s' - (%s) **\n\n",
  1678. X           based_on, pattern, additional_criteria?"add'tl":"base");
  1679. X
  1680. X    if (based_on == SUBJECT) {
  1681. X      for (index = 0; index < message_count; index++)
  1682. X        if (! in_string(shift_lower(header_table[index].subject), pattern))
  1683. X          header_table[index].status &= ~VISIBLE;
  1684. X        else if (additional_criteria &&     
  1685. X             header_table[index].status | VISIBLE)
  1686. X          header_table[index].status &= ~VISIBLE;    /* shut down! */
  1687. X        else { /* mark it as readable */
  1688. X          header_table[index].status |= VISIBLE;
  1689. X          count++;
  1690. X          dprint3(5,"  Message %d (%s from %s) marked as visible\n",
  1691. X            index, header_table[index].subject,
  1692. X            header_table[index].from);
  1693. X        }
  1694. X    }
  1695. X    else if (based_on == FROM) {
  1696. X      for (index = 0; index < message_count; index++)
  1697. X        if (! in_string(shift_lower(header_table[index].from), pattern))
  1698. X          header_table[index].status &= ~VISIBLE;
  1699. X        else if (additional_criteria &&     
  1700. X             header_table[index].status | VISIBLE)
  1701. X          header_table[index].status &= ~VISIBLE;    /* shut down! */
  1702. X        else { /* mark it as readable */
  1703. X          header_table[index].status |= VISIBLE;
  1704. X          count++;
  1705. X          dprint3(5,"  Message %d (%s from %s) marked as visible\n",
  1706. X            index, header_table[index].subject,
  1707. X            header_table[index].from);
  1708. X        }
  1709. X    }
  1710. X    else if (based_on == TO) {
  1711. X      for (index = 0; index < message_count; index++)
  1712. X        if (! in_string(shift_lower(header_table[index].to), pattern))
  1713. X          header_table[index].status &= ~VISIBLE;
  1714. X        else if (additional_criteria &&     
  1715. X             header_table[index].status | VISIBLE)
  1716. X          header_table[index].status &= ~VISIBLE;    /* shut down! */
  1717. X        else { /* mark it as readable */
  1718. X          header_table[index].status |= VISIBLE;
  1719. X          count++;
  1720. X          dprint3(5,"  Message %d (%s from %s) marked as visible\n",
  1721. X            index, header_table[index].subject,
  1722. X            header_table[index].from);
  1723. X        }
  1724. X    }
  1725. X
  1726. X    dprint1(4,"\n** returning %d selected **\n\n\n", count);
  1727. X
  1728. X    return(count);
  1729. X}
  1730. X
  1731. Xint
  1732. Xnext_visible(index)
  1733. Xint index;
  1734. X{
  1735. X    /** Given 'index', this routine will return the actual index into the
  1736. X        array of the NEXT visible message, or '-1' if none are visible 
  1737. X    **/
  1738. X    int remember_for_debug;
  1739. X
  1740. X    remember_for_debug = index;
  1741. X
  1742. X    index--;    /* shift from 'current' to actual index  */
  1743. X    index++;    /* make sure we don't bump into ourself! */
  1744. X
  1745. X    while (index < message_count) {
  1746. X      if (header_table[index].status & VISIBLE) {
  1747. X        dprint2(9,"[Next visible: given %d returning %d]\n", 
  1748. X               remember_for_debug, index+1);
  1749. X        return(index+1);
  1750. X      }
  1751. X      index++;
  1752. X    }
  1753. X
  1754. X    return(-1);
  1755. X}
  1756. X
  1757. Xint
  1758. Xprevious_visible(index)
  1759. Xint index;
  1760. X{
  1761. X    /** Just like 'next-visible', but backwards FIRST... */
  1762. X    
  1763. X    int remember_for_debug;
  1764. X
  1765. X    remember_for_debug = index;
  1766. X
  1767. X    index -= 2;    /* shift from 'current' to actual index, and skip us! */
  1768. X
  1769. X    while (index > -1) {
  1770. X      if (header_table[index].status & VISIBLE) {
  1771. X        dprint2(9,"[previous visible: given %d returning %d]",
  1772. X            remember_for_debug, index+1);
  1773. X        return(index+1);
  1774. X      }
  1775. X      index--;
  1776. X    }
  1777. X
  1778. X    return(-1);
  1779. X}
  1780. X
  1781. Xint
  1782. Xcompute_visible(message)
  1783. Xint message;
  1784. X{
  1785. X    /** return the 'virtual' index of the specified message in the
  1786. X        set of messages - that is, if we have the 25th message as
  1787. X        the current one, but it's #2 based on our limit criteria,
  1788. X        this routine, given 25, will return 2.
  1789. X    **/
  1790. X
  1791. X    register int index, count = 0;
  1792. X
  1793. X    if (! selected) return(message);
  1794. X
  1795. X    if (message < 0) message = 0;    /* normalize */
  1796. X
  1797. X    for (index = 0; index <= message; index++)
  1798. X       if (header_table[index].status & VISIBLE) 
  1799. X         count++;
  1800. X
  1801. X    dprint2(4, "[compute-visible: displayed message %d is actually %d]\n",
  1802. X        count, message);
  1803. X
  1804. X    return(count);
  1805. X}
  1806. X
  1807. Xint
  1808. Xvisible_to_index(message)
  1809. Xint message;
  1810. X{
  1811. X    /** Given a 'virtual' index, return a real one.  This is the
  1812. X        flip-side of the routine above, and returns (message_count+1)
  1813. X        if it cannot map the virtual index requested (too big) 
  1814. X    **/
  1815. X
  1816. X    register int index = 0, count = 0;
  1817. X
  1818. X    for (index = 0; index < message_count; index++) {
  1819. X       if (header_table[index].status & VISIBLE) 
  1820. X         count++;
  1821. X       if (count == message) {
  1822. X         dprint2(4,"visible-to-index: (up) index %d is displayed as %d\n",
  1823. X             message, index);
  1824. X         return(index);
  1825. X       }
  1826. X    }
  1827. X
  1828. X    dprint1(4, "index %d is NOT displayed!\n", message);
  1829. X
  1830. X    return(message_count+1);
  1831. X}
  1832. END_OF_src/limit.c
  1833. if test 6658 -ne `wc -c <src/limit.c`; then
  1834.     echo shar: \"src/limit.c\" unpacked with wrong size!?
  1835. fi
  1836. # end of overwriting check
  1837. fi
  1838. echo shar: End of archive 6 \(of 19\).
  1839. cp /dev/null ark6isdone
  1840. DONE=true
  1841. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1842.     if test ! -f ark${I}isdone ; then
  1843.     echo shar: You still need to run archive ${I}.
  1844.     DONE=false
  1845.     fi
  1846. done
  1847. if test "$DONE" = "true" ; then
  1848.     echo You have unpacked all 19 archives.
  1849.     echo "See the Instructions file"
  1850.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1851. fi
  1852. ##  End of shell archive.
  1853. exit 0
  1854.