home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume9 / elm2 / part10 < prev    next >
Text File  |  1987-03-09  |  54KB  |  2,004 lines

  1. Subject:  v09i010:  ELM Mail System, Part10/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 10
  7. Archive-name: elm2/Part10
  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 10 (of 19)."
  14. # Contents:  doc/Form.guide src/alias.c src/date.c test/test.mail
  15. #   utils/from.c
  16. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  17. echo shar: Extracting \"doc/Form.guide\" \(9794 characters\)
  18. if test -f doc/Form.guide ; then 
  19.   echo shar: Will not over-write existing file \"doc/Form.guide\"
  20. else
  21. sed "s/^X//" >doc/Form.guide <<'END_OF_doc/Form.guide'
  22. X.PH ""
  23. X\"
  24. X\"  A guide to using the Elm Forms mode
  25. X\"  format with 'tbl Forms.guide | troff -mm > Forms.format'
  26. X\"  or something similar.
  27. X\"  (C) Copyright 1986 Dave Taylor
  28. X\"
  29. X\"  Last modification: October 9th, 1986
  30. X\"
  31. X.SA 1
  32. X.nr Hy 1
  33. X.nr Pt 1
  34. X.nr Pi 8
  35. X.lg
  36. X.HM 1 1
  37. X.rs
  38. X.ds HF 3  3  
  39. X.ds HP 12 12 10 10 10
  40. X.PF ""
  41. X.de eb
  42. X.sp -1    
  43. X.nf
  44. X\h'-.5n'\L'|\\nau-1'\l'\\n(.lu+1n\(ul'\L'-|\\nau+1'\l'|0u-.5n\(ul'
  45. X.fi
  46. X..
  47. X.ce 99
  48. X.sp 9
  49. X.ps 20
  50. X\fBElm Forms Mode Guide\fR
  51. X.sp 7
  52. X.ps 12
  53. X\fIWhat Forms Mode is, how to use it to create
  54. Xcustom forms, how to reply to forms, and how to
  55. Xuse it for AT&T Mail messages\fR
  56. X.sp 5
  57. XDave Taylor
  58. X.sp
  59. XHewlett-Packard Laboratories
  60. X1501 Page Mill Road
  61. XPalo Alto CA
  62. X94304
  63. X.sp 
  64. Xemail: taylor@hplabs.HP.COM or hplabs!taylor
  65. X.sp 10
  66. X.ps 18
  67. X\fB\(co\fR\s12 Copyright 1986, 1987 by Dave Taylor
  68. X.ps 10
  69. X.SK
  70. X.sp 5
  71. X.ps 14
  72. X\fBElm Forms Mode Guide\fR
  73. X.PH "'Forms Mode Guide''version 1.5'
  74. X.PF "''Page \\\\nP''"
  75. X.nr P 1
  76. X.sp
  77. X.ps 10
  78. X(version 1.5)
  79. X.sp 2
  80. XDave Taylor
  81. X.sp
  82. XHewlett-Packard Laboratories
  83. X1501 Page Mill Road
  84. XPalo Alto CA
  85. X94304
  86. X.sp 
  87. Xemail: taylor@hplabs.HP.COM or hplabs!taylor
  88. X.sp 2
  89. X\*(DT
  90. X.ce 0
  91. X.sp 3
  92. X.P
  93. XWhile there are a lot of mail systems that allow the transmission 
  94. Xof text and primitive pictures, to send and reply to more complex
  95. Xforms is simply not possible.  \fBElm\fR, however, took
  96. Xthe forms mode implemented as part of the AT&T Mail package and has
  97. Xexpanded on it to be a smoothly fit part of the overall mail system.
  98. X.sp
  99. XForms mode gives you the ability to send 'template' files to people 
  100. Xand receive the filled-in replies.  Let's look at an example right
  101. Xoff.
  102. X.sp 2
  103. XSay we were going to use computer mail as a way to file defects with
  104. Xsoftware.  There is a certain amount of information we want to be able
  105. Xto collect when each report is made, and if it is in a specific format
  106. Xwe can use programs to file the defects upon receipt.
  107. X.sp
  108. XThe form we'll try to emulate starts out looking like;
  109. X.DS CB
  110. X.mk a
  111. X.mk a
  112. X.sp
  113. X.tl ''Defect Reporting Form''
  114. X.sp
  115. X.tl 'Program:_________________________'Version:___________________''
  116. X.tl 'Operating System:________________'Version:___________________''
  117. X.sp
  118. X.tl 'Defect Type:_______________________''
  119. X.sp
  120. X.tl 'Date Found:_____________________''By Whom:_____________________'
  121. X.tl 'Date Reported:__________________''Phone:_______________________'
  122. X.sp
  123. X.tl 'Description:______________________________________________________________'
  124. X.tl '__________________________________________________________________________'
  125. X.tl '__________________________________________________________________________'
  126. X.tl '__________________________________________________________________________'
  127. X.tl '__________________________________________________________________________'
  128. X.sp
  129. X.eb
  130. X.DE
  131. X.sp
  132. XThis form can actually be created almost exactly as listed above in 
  133. Xthe \fBElm\fR mail system by using your standard editor and can then
  134. Xbe mailed about as needed.
  135. X.sp
  136. XLet's say that we want a bit more information, however, especially with 
  137. Xfields like ``Defect Type'', we want to list all the recommended answers.
  138. XTo create the actual form, we need merely to replace the underlines in
  139. Xthe above form with spaces.  The multi-line comments can simply be 
  140. Xindicated by a `:' by itself on a line;
  141. X.DS CB
  142. X.mk a
  143. X.sp
  144. X.tl ''Defect Reporting Form''
  145. X.sp
  146. X.tl 'Program:                         'Version:                   ''
  147. X.tl 'Operating System:                'Version:                   ''
  148. X.sp
  149. X.tl '(Valid Defect Types are: user-error, doc-error, fatal, other)'
  150. X.tl 'Defect Type:                       ''
  151. X.sp
  152. X.tl 'Date Found:                     ''By Whom:                     '
  153. X.tl 'Date Reported:                  ''Phone:                       '
  154. X.sp
  155. X.tl 'Description'
  156. X.tl ':'
  157. X.sp
  158. XThank you for filling in this form.
  159. X.sp 4
  160. X.eb
  161. X.DE
  162. X.sp
  163. XAs we can see, it is quite simple to create forms!!  
  164. X.sp 2
  165. XNow that we have an idea what we're talking about, let's actually officially
  166. Xdefine the system...
  167. X.sp 2
  168. X.ne 7
  169. X.ps 12
  170. X\fBForms Mode Specification\fR
  171. X.ps 10
  172. X.sp
  173. X[Note that this is all taken from the document \fIStandard for Exchanging
  174. XForms on AT&T Mail\fR, Version 1.9 of 6/7/86, from AT&T]
  175. X.sp
  176. XThe forms mode is really quite simple.  Simple enough that it is amazing
  177. Xthat it hadn't been implemented before AT&T Mail came along!!
  178. X.sp
  179. XIn a nutshell, each field is delimited by a `:' followed by a number of
  180. Xblank spaces or tabs that represent the valid size for that field.  That
  181. Xis, if we have a line in the form like;
  182. X.nf
  183. X    ``Phone (area-code):     Number:          '' 
  184. X.fi
  185. XThe area-code field will be limited to three characters and the number to nine.
  186. X(this is kind of hard to see with the proportionally spaced formatted copy,
  187. Xalas).
  188. XThe only exception to the rule is that a `:' by itself on a line represents
  189. Xa field that is as large as the user entering the data desires.
  190. X.sp 2
  191. XThe actual form that is transmitted, in AT&T Mail parlance, is a ``SIMPLE''
  192. Xforms handler message (as opposed to the ``ADVANCED'' handler).  This means
  193. Xthat it contains three sections;
  194. X.nf
  195. X
  196. X    The Message Header
  197. X
  198. X    [OPTIONS-SECTION]
  199. X    ***
  200. X    [FORMS-IMAGE]
  201. X    ***
  202. X    [RULES-SECTION]
  203. X
  204. X.fi
  205. X\fBElm\fR generates form messages with the ``options'' section filled out,
  206. Xbut ignores it when receiving mail.  The filled out section is;
  207. X.nf
  208. X
  209. X    WIDTH=80
  210. X    TYPE=SIMPLE
  211. X    OUTPUT=TEXT
  212. X
  213. X.fi
  214. XThe FORMS-IMAGE section is that described above.  The RULES-SECTION can
  215. Xcontain explicit rules about the possible values of each field, but 
  216. Xthis is currently ignored by \fBElm\fR, being a ``SIMPLE'' forms mode
  217. Xmail system.
  218. X.sp
  219. XForms also have the header ``Content-Type: mailform'' to indicate to the
  220. Xmail system (either \fBElm\fR or AT&T Mail) that a form is being sent.
  221. X.sp
  222. X\fBElm\fR further indicates that a form has been received by having an
  223. X``F'' as the status character in the header display section (instead of
  224. X``N'' for new, etc).
  225. X.sp 2
  226. X.ne 5
  227. X.ps 12
  228. X\fBComposing and Sending a Form\fR
  229. X.ps 10
  230. X.sp
  231. XThe first step to enable sending forms is to change the setting of
  232. Xthe variable \fIforms\fR in your \fI.elmrc\fR file to ``ON''.  E.g.;
  233. X.nf
  234. X
  235. X    forms = ON
  236. X
  237. X.fi
  238. XThe next step is to send the message to someone using the `m' (\fImail\fR)
  239. Xcommand.  This then will drop you into an editor.  Type in the form as
  240. Xindicated above, with appropriate colons and comments, and end the entry
  241. Xby leaving the editor.
  242. X.sp
  243. XThe prompt is now;
  244. X.nf
  245. X
  246. X.tl ''Choose: E)dit msg, edit H)eaders, M)ake form, S)end or F)orget : @''
  247. X
  248. X.fi
  249. Xso we choose `m' - \fIMake form\fR.  The program then will either
  250. Xrewrite the prompt without the M)ake form option, indicating that
  251. Xthe form has been accepted, or will indicate the problem and give you
  252. Xa chance to correct it.
  253. X.sp
  254. XOnce it has been accepted, simple use the `s' - \fIsend message\fR -
  255. Xcommand and it's off!
  256. X.sp 
  257. XNote that you cannot reply to a message with a Form.
  258. X.sp 2
  259. X.ne 6
  260. X.ps 12
  261. X\fBReplying to a Form\fR
  262. X.ps 10
  263. X.sp
  264. XLet's reply to the form message we generated now.  The header page of the
  265. X\fBElm\fR mail system will indicate that the message is a form by having
  266. Xan `F' next to it.  So we use `r' to reply and the screen is immediately
  267. Xcleared and we're prompted, field by field, for the data requested.
  268. XEach field has underscores in the input area to indicate the size field that
  269. Xis expected.
  270. X.sp
  271. XAfter answering all the questions we'll have a screen that looks like;
  272. X.DS CB
  273. X.mk a
  274. X.sp
  275. X.tl ''Defect Reporting Form''
  276. X.sp
  277. XProgram: \fBThe Elm Mail System\fR____________
  278. XVersion: \fB1.5\fR_____________________
  279. XOperating System: \fBHP-UX\fR_________________
  280. XVersion: \fB5.141 C\fR__________________
  281. X.sp
  282. X(Valid Defect Types are: user-error, doc-error, fatal, other)
  283. XDefect Type: \fBfatal\fR____________________________________________________
  284. X.sp
  285. XDate Found: \fB10/9/86\fR_____________________
  286. XBy Whom: \fBDave Taylor\fR_______________
  287. XDate Reported: \fB10/9/86\fR__________________
  288. XPhone: \fB(415) 857-6887\fR______________
  289. X.sp
  290. XDescription
  291. X(Enter as many lines as needed, ending with a `.' by itself on a line)
  292. X
  293. X  \fBWhen running it on a CPM system I cannot compile successfully.\fR
  294. X  \fB.\fR
  295. X
  296. XThank you for filling in this form.
  297. X
  298. X.tl ''Choose: E)dit form, edit H)eaders, S)end or F)orget : @''
  299. X.sp 
  300. X.eb
  301. X.DE
  302. X.sp
  303. XQuite simple.  Notice, however, that the order of prompting is left to
  304. Xright on each line, so the fields that on the form are placed in what
  305. Xseems like a logical place, ``By Whom:'' and ``Phone:'' turn out to be
  306. Xconfusing when filling in the actual form since it isn't clear what
  307. X``Phone:'' is being asked for because of the intervention of the
  308. X``Date Reported:'' field.
  309. X.sp 
  310. XThe message that will actually be sent out from this will have the
  311. Xfields in a more acceptable format;
  312. X.DS
  313. X.mk a
  314. X.sp
  315. XWIDTH=80
  316. XTYPE=SIMPLE
  317. XOUTPUT=TEXT
  318. X***
  319. X.tl ''Defect Reporting Form''
  320. X.sp
  321. X.tl 'Program: The Elm Mail System     'Version: 1.5               ''
  322. X.tl 'Operating System: HP-UX          'Version: 5.141 C           ''
  323. X.sp
  324. X.tl '(Valid Defect Types are: user-error, doc-error, fatal, other)'
  325. X.tl 'Defect Type: fatal''
  326. X.sp
  327. X.tl 'Date Found: 10/9/86             ''By Whom: Dave Taylor         '
  328. X.tl 'Date Reported: 10/9/86          ''Phone: (415) 857-6887        '
  329. X.sp
  330. X.tl 'Description'
  331. X.sp
  332. X    When running it on a CPM system I cannot compile successfully.
  333. X.sp 2
  334. XThank you for filling in this form.
  335. X.sp
  336. X***
  337. X.sp
  338. X.eb
  339. X.DE
  340. X.ne 5
  341. X.sp 2
  342. X.ps 12
  343. X\fBComments on Forms Mode\fR
  344. X.ps 10
  345. X.sp
  346. XAs was said at the beginning, this way of sending about forms could
  347. Xprove to be very helpful and useful in a variety of contexts.  On the
  348. Xother hand, until a more sophisticated forms language is used for the
  349. Xforms, this should be sufficient to embody the power of the idea.
  350. X.sp
  351. XI welcome any comments and thoughts on this system and also welcome
  352. Xpossible enhancements.
  353. X.sp
  354. XI also gratefully thank Dale DeJager of AT&T Information Systems 
  355. Xfor sending me more
  356. Xinformation on AT&T Mail than I could possibly digest in any finite
  357. Xamount of time.
  358. END_OF_doc/Form.guide
  359. if test 9794 -ne `wc -c <doc/Form.guide`; then
  360.     echo shar: \"doc/Form.guide\" unpacked with wrong size!?
  361. fi
  362. # end of overwriting check
  363. fi
  364. echo shar: Extracting \"src/alias.c\" \(9636 characters\)
  365. if test -f src/alias.c ; then 
  366.   echo shar: Will not over-write existing file \"src/alias.c\"
  367. else
  368. sed "s/^X//" >src/alias.c <<'END_OF_src/alias.c'
  369. X/**            alias.c            **/
  370. X
  371. X/** This file contains alias stuff
  372. X
  373. X    (C) Copyright 1986 Dave Taylor
  374. X**/
  375. X
  376. X#include "headers.h"
  377. X#include <errno.h>
  378. X
  379. Xchar *expand_group(), *get_alias_address(), *expand_system(), *get_token();
  380. Xchar *error_name(), *error_description();
  381. X
  382. Xunsigned long sleep();
  383. X
  384. Xextern int errno;
  385. X
  386. Xextern int  findnode_has_been_initialized;
  387. X
  388. Xread_alias_files()
  389. X{
  390. X    /** read the system and user alias files, if present.
  391. X        Set the flags 'systemfiles' and 'userfiles' accordingly.
  392. X    **/
  393. X
  394. X    char fname[SLEN];
  395. X    int  hash;
  396. X
  397. X    if ((hash = open(system_hash_file, O_RDONLY)) == -1) {
  398. X     dprint1(1,
  399. X        "Warning: Can't read system hash file %s (read_alias_files)\n",
  400. X        system_hash_file);
  401. X      goto user;
  402. X    }
  403. X
  404. X    read(hash, system_hash_table, sizeof system_hash_table);
  405. X    close(hash);
  406. X
  407. X    /* and data file opened.. */
  408. X
  409. X    if ((system_data = open(system_data_file, O_RDONLY)) == -1) {
  410. X     dprint1(1, 
  411. X             "Warning: Can't read system data file %s (read_alias_files)\n",
  412. X         system_data_file);
  413. X      goto user;
  414. X    }
  415. X
  416. X    system_files++;    /* got the system files! */
  417. X
  418. Xuser:   sprintf(fname,  "%s/.alias_hash", home); 
  419. X
  420. X    if ((hash = open(fname, O_RDONLY)) == -1) {
  421. X     dprint1(1,"Warning: Can't read user hash file %s (read_alias_files)\n",
  422. X          fname);
  423. X      return;
  424. X    }
  425. X
  426. X    read(hash, user_hash_table, sizeof user_hash_table);
  427. X    close(hash);
  428. X
  429. X    sprintf(fname,  "%s/.alias_data", home); 
  430. X
  431. X    if ((user_data = open(fname, O_RDONLY)) == -1) {
  432. X     dprint1(1,
  433. X             "Warning: can't read user data file %s  (read_alias_files)\n",
  434. X         fname);
  435. X      return;
  436. X    }
  437. X
  438. X    user_files++;    /* got user files too! */
  439. X}
  440. X
  441. Xint
  442. Xadd_alias()
  443. X{
  444. X    /** add an alias to the user alias text file.  Return zero 
  445. X        if alias not added in actuality **/
  446. X
  447. X    char name[SLEN], *address, address1[LONG_STRING];
  448. X    char comment[SLEN];
  449. X    char *strcpy();
  450. X
  451. X    PutLine0(LINES-2,0,"Enter alias name: ");
  452. X    CleartoEOLN();
  453. X    Raw(OFF);
  454. X    gets(name);
  455. X    Raw(ON);
  456. X    if (strlen(name) == 0) 
  457. X      return(0);
  458. X    if ((address = get_alias_address(name, 0, 0)) != NULL) {
  459. X      dprint1(2, "Attempt to add a duplicate alias [%s] (add_alias)\n",
  460. X           address); 
  461. X      if (address[0] == '!') {
  462. X        address[0] = ' ';
  463. X        error1("already a group with that name:%s", address);
  464. X      }
  465. X      else
  466. X        error1("already an alias for that: %s", address);
  467. X      return(0);
  468. X    }
  469. X    PutLine1(LINES-2,0,"Full name for %s: ", name);
  470. X    CleartoEOLN();
  471. X    Raw(OFF);
  472. X    gets(comment);
  473. X    Raw(ON);
  474. X    if (strlen(comment) == 0) strcpy(comment, name);  
  475. X    PutLine1(LINES-2,0,"Enter address for %s: ",name);
  476. X    CleartoEOLN();
  477. X    Raw(OFF);
  478. X    gets(address1);
  479. X    Raw(ON);
  480. X    if (strlen(address1) == 0) {
  481. X      error("No address specified!");
  482. X      return(0);
  483. X    }
  484. X    add_to_alias_text(name, comment, address1);
  485. X    return(1);
  486. X}
  487. X
  488. Xint
  489. Xadd_current_alias()
  490. X{
  491. X    /** alias the current message to the specified name and
  492. X        add it to the alias text file, for processing as
  493. X        the user leaves the program.  Returns non-zero iff
  494. X        alias actually added to file **/
  495. X
  496. X    char name[SLEN], address1[LONG_STRING], buffer[LONG_STRING], *address;
  497. X    char comment[SLEN];
  498. X
  499. X    if (current == 0) {
  500. X     dprint0(3,"Add current alias called without any current message!\n");
  501. X     error("No message to alias to!");
  502. X     return(0);
  503. X    }
  504. X    
  505. X    PutLine0(LINES-2,0,"Current message address aliased to: ");
  506. X    CleartoEOLN();
  507. X    Raw(OFF);
  508. X    gets(name);
  509. X    Raw(ON);
  510. X    if (strlen(name) == 0)    /* cancelled... */
  511. X      return(0);
  512. X    if ((address = get_alias_address(name, 0, 0)) != NULL) {
  513. X     dprint1(3,
  514. X             "Attempt to add a duplicate alias [%s] (add_current_alias)\n",
  515. X         address); 
  516. X      if (address[1] == '!') {
  517. X        address[0] = ' ';
  518. X        error1("already a group with that name:%s", address);
  519. X      }
  520. X      else 
  521. X        error1("already an alias for that: %s", address); 
  522. X          return(0);
  523. X    }
  524. X    PutLine1(LINES-2,0,"Full name of %s: ", name);
  525. X    CleartoEOLN();
  526. X    Raw(OFF);
  527. X    gets(comment);
  528. X    Raw(ON);
  529. X    get_return(buffer);    /* grab the return address of this message */
  530. X    strcpy(address1, strip_parens(buffer));    /* remove parens! */
  531. X#ifndef DONT_OPTIMIZE_RETURN
  532. X    optimize_return(address1);
  533. X#endif
  534. X    PutLine3(LINES-2,0,"%s (%s) = %s", comment, name, address1);
  535. X    CleartoEOLN();
  536. X    add_to_alias_text(name, comment, address1);
  537. X    return(1);
  538. X}
  539. X
  540. Xadd_to_alias_text(name, comment, address)
  541. Xchar *name, *comment, *address;
  542. X{
  543. X    /** Add the data to the user alias text file.  Return zero if we
  544. X        succeeded, 1 if not **/
  545. X    
  546. X    FILE *file;
  547. X    char fname[SLEN];
  548. X    
  549. X    sprintf(fname,"%s/.alias_text", home);
  550. X    
  551. X    if ((file = fopen(fname, "a")) == NULL) {
  552. X      dprint2(2, "FILE Failure attempting to add alias to file %s (%s)",
  553. X           fname, "add_to_alias_text");
  554. X      dprint2(2, "** %s - %s **\n", error_name(errno), 
  555. X           error_description(errno));
  556. X      error1("couldn't open %s to add new alias!", fname);
  557. X      return(1);
  558. X    }
  559. X
  560. X    fprintf(file,"%s : %s : %s\n", name, comment, address);
  561. X    fclose(file);
  562. X
  563. X    chown(fname, userid, groupid);
  564. X
  565. X    return(0);
  566. X}
  567. X
  568. Xshow_alias_menu()
  569. X{
  570. X    MoveCursor(LINES-7,0); CleartoEOLN();    
  571. X    MoveCursor(LINES-6,0); CleartoEOLN();    
  572. X    MoveCursor(LINES-5,0); CleartoEOLN();
  573. X    
  574. X    PutLine0(LINES-7,COLUMNS-45, "Alias commands");
  575. X    Centerline(LINES-5,
  576. X"A)lias current msg, Check a P)erson or S)ystem, M)ake new alias, or R)eturn"
  577. X    );
  578. X}
  579. X
  580. Xalias()
  581. X{
  582. X    /** work with alias commands... **/
  583. X    char name[NLEN], *address, ch, buffer[SLEN];
  584. X    int  newaliases = 0;
  585. X
  586. X    if (mini_menu)
  587. X      show_alias_menu();
  588. X
  589. X    /** now let's ensure that we've initialized everything! **/
  590. X
  591. X#ifndef DONT_TOUCH_ADDRESSES
  592. X    
  593. X    if (! findnode_has_been_initialized) {
  594. X      if (! mail_only)
  595. X        error("initializing internal tables...");
  596. X#ifndef USE_DBM
  597. X      get_connections();
  598. X      open_domain_file();
  599. X#endif
  600. X      init_findnode();
  601. X      clear_error();
  602. X          findnode_has_been_initialized = TRUE;
  603. X    }
  604. X
  605. X#endif
  606. X
  607. X    define_softkeys(ALIAS);
  608. X
  609. X    while (1) {
  610. X      prompt("Alias: ");
  611. X      CleartoEOLN();
  612. X      ch = ReadCh();
  613. X      MoveCursor(LINES-1,0); CleartoEOS();
  614. X      
  615. X      dprint1(2,"\n-- Alias command: %c\n\n", ch);
  616. X
  617. X      switch (tolower(ch)) {
  618. X        case '?': alias_help();                break;
  619. X
  620. X        case 'a': newaliases += add_current_alias();    break;
  621. X        case 'm': newaliases += add_alias();         break;
  622. X
  623. X        case RETURN:
  624. X        case LINE_FEED:
  625. X        case 'q':
  626. X        case 'x':
  627. X        case 'r': if (newaliases) install_aliases();
  628. X              return;
  629. X        case 'p': if (newaliases) 
  630. X            error("Warning: new aliases not installed yet!");
  631. X              PutLine0(LINES-2,0,"Check for person: ");
  632. X              CleartoEOLN();
  633. X              Raw(OFF);
  634. X                  gets(name);
  635. X              Raw(ON);
  636. X              if ((address = get_alias_address(name, 0, 0))!=NULL) {
  637. X                    if (address[0] == '!') {
  638. X                      address[0] = ' ';
  639. X                      PutLine1(LINES-1,0,"Group alias:%-60.60s", address);
  640. X                      CleartoEOLN();
  641. X                }
  642. X            else
  643. X              PutLine1(LINES-1,0,"Aliased address: %-60.60s", 
  644. X              address);
  645. X              }
  646. X                  else 
  647. X            error("not found");
  648. X              break;
  649. X
  650. X        case 's': PutLine0(LINES-2,0,"Check for system: ");
  651. X              CleartoEOS();
  652. X              Raw(OFF);
  653. X                  gets(name);
  654. X              Raw(ON);
  655. X              if (talk_to(name)) 
  656. X#ifdef INTERNET_ADDRESS_FORMAT
  657. X            PutLine1(LINES-1,0,
  658. X        "You have a direct connection - the address is (user)@%s", 
  659. X            name);
  660. X#else
  661. X            PutLine1(LINES-1,0,
  662. X        "You have a direct connection - the address is %s!(user)", 
  663. X            name);
  664. X#endif
  665. X              else {
  666. X                sprintf(buffer, "(user)@%s", name);
  667. X#ifdef DONT_TOUCH_ADDRESS
  668. X                 strcpy(address, buffer);
  669. X#else
  670. X                 address = expand_system(buffer, FALSE);
  671. X#endif
  672. X                if (strlen(address) > strlen(name) + 7)
  673. X                  PutLine1(LINES-1,0,"Address is: %.65s", address);
  674. X                else
  675. X                  error1("couldn't expand system '%s'", name);
  676. X              }
  677. X              break;
  678. X
  679. X        case '@': PutLine0(LINES-2,0,"Fully expand alias: ");
  680. X              CleartoEOS();
  681. X              Raw(OFF);
  682. X                  gets(name);
  683. X              Raw(ON);
  684. X              if ((address = get_alias_address(name, 1, 0)) != NULL) {
  685. X                    ClearScreen();
  686. X            PutLine1(3,0,"Aliased address:\n\r%s", address);
  687. X                    PutLine0(LINES-1,0,"Press <return> to continue: ");
  688. X            (void) getchar();
  689. X              }
  690. X                  else 
  691. X            error("not found");
  692. X              if (mini_menu) show_alias_menu();
  693. X              break;
  694. X        default : error("Invalid input!");
  695. X      }
  696. X    }
  697. X}
  698. X
  699. Xinstall_aliases()
  700. X{
  701. X    /** run the 'newalias' program and install the newly
  702. X        added aliases before going back to the main
  703. X        program! 
  704. X    **/
  705. X
  706. X
  707. X    error("Adding new aliases...");
  708. X    sleep(2);
  709. X
  710. X    if (system_call(newalias, SH) == 0) {
  711. X      error("Re-reading the database in...");
  712. X      sleep(2);
  713. X      read_alias_files();
  714. X      set_error("New aliases installed successfully");
  715. X    }
  716. X    else
  717. X      set_error("'newalias' failed.  Please check alias_text");
  718. X}
  719. X
  720. Xalias_help()
  721. X{
  722. X    /** help section for the alias menu... **/
  723. X
  724. X    char ch;
  725. X
  726. X    MoveCursor(LINES-3, 0);    CleartoEOS();
  727. X
  728. X    if (! mini_menu)
  729. X      lower_prompt("Key you want help for : ");
  730. X    else {
  731. X      Centerline(LINES-3, 
  732. X"Enter key you want help for, '?' for list or '.' to leave help");
  733. X      lower_prompt("Key : ");
  734. X    }
  735. X
  736. X    while ((ch = tolower(ReadCh())) != '.') {
  737. X      switch(ch) {
  738. X        case '?' : display_helpfile(ALIAS_HELP);    
  739. X                   if (mini_menu) show_alias_menu();    return;
  740. X        case 'a': error(
  741. X"a = Add return address of current message to alias database");    break;
  742. X        case 'm': error(
  743. X"m = Make new user alias, adding to alias database when done");    break;
  744. X
  745. X        case RETURN:
  746. X        case LINE_FEED:
  747. X        case 'q':
  748. X        case 'x':
  749. X        case 'r': error("return from alias menu");        break;
  750. X              
  751. X        case 'p': error(
  752. X"p = check for a person in the alias database");        break;
  753. X    
  754. X        case 's': error(
  755. X"s = check for a system in the host routing/domain database");    break;
  756. X    
  757. X        default : error("That key isn't used in this section");    break;
  758. X        case '.': return;
  759. X      }
  760. X      if (! mini_menu)
  761. X        lower_prompt("Key you want help for : ");
  762. X      else 
  763. X        lower_prompt("Key : ");
  764. X    }
  765. X}
  766. END_OF_src/alias.c
  767. if test 9636 -ne `wc -c <src/alias.c`; then
  768.     echo shar: \"src/alias.c\" unpacked with wrong size!?
  769. fi
  770. # end of overwriting check
  771. fi
  772. echo shar: Extracting \"src/date.c\" \(10281 characters\)
  773. if test -f src/date.c ; then 
  774.   echo shar: Will not over-write existing file \"src/date.c\"
  775. else
  776. sed "s/^X//" >src/date.c <<'END_OF_src/date.c'
  777. X/**        date.c        **/
  778. X
  779. X/** return the current date and time in a readable format! **/
  780. X/** also returns an ARPA RFC-822 format date...            **/
  781. X
  782. X/** (C) Copyright 1985, Dave Taylor **/
  783. X
  784. X#include "headers.h"
  785. X
  786. X#ifdef BSD
  787. X#  ifndef BSD4.1
  788. X#    include <sys/time.h>
  789. X#  else
  790. X#    include <time.h>
  791. X#    include <sys/types.h>
  792. X#    include <sys/timeb.h>
  793. X#  endif
  794. X#else
  795. X#  include <time.h>
  796. X#endif
  797. X
  798. X#include <ctype.h>
  799. X
  800. X#ifdef BSD
  801. X#undef toupper
  802. X#undef tolower
  803. X#endif
  804. X
  805. X#define MONTHS_IN_YEAR    11    /* 0-11 equals 12 months! */
  806. X#define FEB         1    /* 0 = January           */
  807. X#define DAYS_IN_LEAP_FEB 29    /* leap year only       */
  808. X
  809. X#define ampm(n)        (n > 12? n - 12 : n)
  810. X#define am_or_pm(n)    (n > 11? (n > 23? "am" : "pm") : "am")
  811. X#define leapyear(year)    ((year % 4 == 0) && (year % 100 != 0))
  812. X
  813. Xchar *monname[] = { "January", "February", "March", "April", "May", "June",
  814. X          "July", "August", "September", "October", "November",
  815. X          "December", ""};
  816. X
  817. Xchar *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
  818. X          "Fri", "Sat", "" };
  819. X
  820. Xchar *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  821. X          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
  822. X
  823. Xint  days_in_month[] = { 31,    28,    31,    30,    31,     30, 
  824. X          31,     31,    30,   31,    30,     31,  -1};
  825. X
  826. X#ifdef BSD
  827. X  char *timezone();
  828. X#else
  829. X  extern char *tzname[];
  830. X#endif
  831. X
  832. Xchar *shift_lower(), *strcpy(), *strncpy();
  833. X
  834. Xchar *get_arpa_date()
  835. X{
  836. X    /** returns an ARPA standard date.  The format for the date
  837. X        according to DARPA document RFC-822 is exemplified by;
  838. X
  839. X                     Mon, 12 Aug 85 6:29:08 MST
  840. X
  841. X    **/
  842. X
  843. X    static char buffer[SLEN];    /* static character buffer       */
  844. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  845. X          *localtime();
  846. X    long       junk,        /* time in seconds....         */
  847. X               time();
  848. X
  849. X#ifdef BSD
  850. X# ifdef BSD4.1
  851. X    struct timeb    loc_time;
  852. X
  853. X    junk = time(long *) 0);
  854. X    ftime(&loc_time);
  855. X# else
  856. X    struct  timeval  time_val;        
  857. X    struct  timezone time_zone;
  858. X
  859. X    gettimeofday(&time_val, &time_zone);
  860. X    junk = time_val.tv_sec;
  861. X# endif
  862. X
  863. X#else
  864. X    junk = time((long *) 0);    /* this must be here for it to work! */
  865. X#endif
  866. X
  867. X    the_time = localtime(&junk);
  868. X
  869. X    sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
  870. X      arpa_dayname[the_time->tm_wday],
  871. X      the_time->tm_mday % 32,
  872. X      arpa_monname[the_time->tm_mon],
  873. X      the_time->tm_year % 100,
  874. X      the_time->tm_hour % 24,
  875. X      the_time->tm_min  % 61,
  876. X      the_time->tm_sec  % 61,
  877. X#ifdef BSD
  878. X# ifdef BSD4.1
  879. X      timezone(time_zone.timezone, the_time->tm_isdst));
  880. X# else
  881. X      timezone(time_zone.tz_minuteswest, the_time->tm_isdst));
  882. X# endif
  883. X#else
  884. X      tzname[the_time->tm_isdst]);
  885. X#endif
  886. X    
  887. X    return( (char *) buffer);
  888. X}
  889. X
  890. Xchar *full_month(month)
  891. Xchar *month;
  892. X{
  893. X    /** Given a three letter month abbreviation, return the 
  894. X        full name of the month.   If can't figure it out, just
  895. X        return the given argument. **/
  896. X
  897. X    char   name[4];
  898. X    char   *shift_lower();
  899. X    register int i;
  900. X
  901. X    /** ensure name in correct case... **/
  902. X
  903. X    strncpy(name, shift_lower(month), 3);
  904. X    name[0] = toupper(name[0]);
  905. X
  906. X    /** now simply step through arpa_monname table to find a match **/
  907. X
  908. X    for (i=0; i < 12; i++)
  909. X      if (strncmp(name, arpa_monname[i], 3) == 0)
  910. X        return((char *) monname[i]);
  911. X    
  912. X    dprint1(2, "Warning: Couldn't expand monthname %s (full_month)\n", 
  913. X            month);
  914. X
  915. X    return( (char *) month);
  916. X}
  917. X
  918. Xdays_ahead(days, buffer)
  919. Xint days;
  920. Xchar *buffer;
  921. X{
  922. X    /** return in buffer the date (Day, Mon Day, Year) of the date
  923. X        'days' days after today. **/
  924. X
  925. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  926. X          *localtime();
  927. X    long       junk,        /* time in seconds....         */
  928. X           time();
  929. X
  930. X    junk = time((long *) 0);    /* this must be here for it to work! */
  931. X    the_time = localtime(&junk);
  932. X
  933. X    /* increment the day of the week */
  934. X
  935. X    the_time->tm_wday = (the_time->tm_wday + days) % 7;
  936. X
  937. X    /* the day of the month... */
  938. X    the_time->tm_mday += days;
  939. X    
  940. X    if (the_time->tm_mday > days_in_month[the_time->tm_mon]) {
  941. X      if (the_time->tm_mon == FEB && leapyear(the_time->tm_year)) {
  942. X        if (the_time->tm_mday > DAYS_IN_LEAP_FEB) {
  943. X          the_time->tm_mday -= days_in_month[the_time->tm_mon];
  944. X          the_time->tm_mon += 1;
  945. X        }
  946. X      }
  947. X      else {
  948. X        the_time->tm_mday -= days_in_month[the_time->tm_mon];
  949. X        the_time->tm_mon += 1;
  950. X      }
  951. X    }
  952. X
  953. X    /* check the month of the year */
  954. X    if (the_time->tm_mon > MONTHS_IN_YEAR) {
  955. X      the_time->tm_mon -= MONTHS_IN_YEAR;
  956. X      the_time->tm_year += 1;
  957. X    }
  958. X
  959. X    /* now, finally, build the actual date string */
  960. X
  961. X    sprintf(buffer, "%s, %d %s %d",
  962. X      arpa_dayname[the_time->tm_wday],
  963. X      the_time->tm_mday % 32,
  964. X      arpa_monname[the_time->tm_mon],
  965. X      the_time->tm_year % 100);
  966. X}
  967. X
  968. Xint
  969. Xvalid_date(day, mon, year)
  970. Xchar *day, *mon, *year;
  971. X{
  972. X    /** Validate the given date - returns TRUE iff the date
  973. X        handed is reasonable and valid.  
  974. X        Ignore month param, okay? 
  975. X    **/
  976. X
  977. X    register int daynum, yearnum;
  978. X
  979. X    daynum = atoi(day);
  980. X    yearnum = atoi(year);
  981. X    
  982. X    if (daynum < 1 || daynum > 31) {
  983. X      dprint1(3, "Error: day %d is obviously wrong! (valid_date)\n", 
  984. X              daynum);
  985. X      return(0);
  986. X    }
  987. X    
  988. X    if (yearnum < 1 || (yearnum > 100 && yearnum < 1900) ||
  989. X        yearnum > 2000) {
  990. X      dprint1(3, "Error: year %d is obviously wrong! (valid_date)\n", 
  991. X        yearnum);
  992. X      return(0);
  993. X    }
  994. X    
  995. X    return(1);
  996. X}
  997. X
  998. Xfix_date(entry)
  999. Xstruct header_rec *entry;
  1000. X{
  1001. X    /** This routine will 'fix' the date entry for the specified
  1002. X        message.  This consists of 1) adjusting the year to 0-99
  1003. X        and 2) altering time from HH:MM:SS to HH:MM am|pm **/ 
  1004. X
  1005. X    if (atoi(entry->year) > 99)     
  1006. X      sprintf(entry->year,"%d", atoi(entry->year) - 1900);
  1007. X
  1008. X    fix_time(entry->time);
  1009. X}
  1010. X
  1011. Xfix_time(timestring)
  1012. Xchar *timestring;
  1013. X{
  1014. X    /** Timestring in format HH:MM:SS (24 hour time).  This routine
  1015. X        will fix it to display as: HH:MM [am|pm] **/
  1016. X
  1017. X    int hour, minute;
  1018. X
  1019. X    sscanf(timestring, "%d:%d", &hour, &minute);
  1020. X
  1021. X    if (hour < 1 || hour == 24) 
  1022. X      sprintf(timestring, "12:%2.2d (midnight)", minute);
  1023. X    else if (hour < 12)
  1024. X      sprintf(timestring, "%d:%2.2d am", hour, minute);
  1025. X    else if (hour == 12)
  1026. X      sprintf(timestring, "%d:%2.2d (noon)", hour, minute);
  1027. X    else if (hour < 24)
  1028. X      sprintf(timestring, "%d:%2.2d pm", hour-12, minute);
  1029. X}
  1030. X
  1031. Xint
  1032. Xcompare_dates(rec1, rec2)
  1033. Xstruct header_rec *rec1, *rec2;
  1034. X{
  1035. X    /** This function works similarly to the "strcmp" function, but
  1036. X        has lots of knowledge about the internal date format...
  1037. X        Apologies to those who "know a better way"...
  1038. X    **/
  1039. X
  1040. X    int month1, day1, year1, hour1, minute1,
  1041. X        month2, day2, year2, hour2, minute2;
  1042. X
  1043. X    year1 = atoi(rec1->year);
  1044. X    year2 = atoi(rec2->year);
  1045. X
  1046. X    if (year1 != year2)
  1047. X      return( year1 - year2 );
  1048. X
  1049. X    /* And HERE's where the performance of this sort dies... */
  1050. X
  1051. X    month1 = month_number(rec1->month);    /* retch...  gag....  */
  1052. X    month2 = month_number(rec2->month);    /*    puke...         */
  1053. X
  1054. X    if (month1 == -1) 
  1055. X      dprint1(2,"month_number failed on month '%s'\n", rec1->month);
  1056. X
  1057. X    if (month2 == -1) 
  1058. X      dprint1(2,"month_number failed on month '%s'\n", rec2->month);
  1059. X
  1060. X    if (month1 != month2)
  1061. X      return( month1 - month2 );
  1062. X
  1063. X    /* back and cruisin' now, though... */
  1064. X
  1065. X    day1 = atoi(rec1->day);     /* unfortunately, 2 is greater than 19  */
  1066. X    day2 = atoi(rec2->day);  /* on a dump string-only compare...     */
  1067. X
  1068. X    if (day1 != day2)
  1069. X      return( day1 - day2 );
  1070. X
  1071. X    /* we're really slowing down now... */
  1072. X
  1073. X    minute1 = minute2 = -1;
  1074. X
  1075. X    sscanf(rec1->time, "%d:%d", &hour1, &minute1);
  1076. X    sscanf(rec2->time, "%d:%d", &hour2, &minute2);
  1077. X
  1078. X    /* did we get the time?  If not, try again */
  1079. X
  1080. X    if (minute1 < 0)
  1081. X      sscanf(rec1->time, "%2d%2d", &hour1, &minute1);
  1082. X
  1083. X    if (minute2 < 0)
  1084. X      sscanf(rec2->time, "%2d%2d", &hour2, &minute2);
  1085. X
  1086. X    /** deal with am/pm, if present... **/
  1087. X
  1088. X    if (strlen(rec1->time) > 3)
  1089. X      if (rec1->time[strlen(rec1->time)-2] == 'p')
  1090. X        hour1 += 12;
  1091. X
  1092. X    if (strlen(rec2->time) > 3)
  1093. X      if (rec2->time[strlen(rec2->time)-2] == 'p')
  1094. X        hour2 += 12;
  1095. X
  1096. X    if (hour1 != hour2)
  1097. X      return( hour1 - hour2 );
  1098. X
  1099. X    return( minute1 - minute2 );        /* ignore seconds... */
  1100. X}
  1101. X
  1102. Xint
  1103. Xcompare_parsed_dates(rec1, rec2)
  1104. Xstruct date_rec rec1, rec2;
  1105. X{
  1106. X    /** This function is very similar to the compare_dates
  1107. X        function but assumes that the two record structures
  1108. X        are already parsed and stored in "date_rec" format.
  1109. X    **/
  1110. X
  1111. X    if (rec1.year != rec2.year)
  1112. X      return( rec1.year - rec2.year );
  1113. X    
  1114. X    if (rec1.month != rec2.month)
  1115. X      return( rec1.month - rec2.month );
  1116. X
  1117. X    if (rec1.day != rec2.day)
  1118. X      return( rec1.day - rec2.day );
  1119. X
  1120. X    if (rec1.hour != rec2.hour)
  1121. X      return( rec1.hour - rec2.hour );
  1122. X
  1123. X    return( rec1.minute - rec2.minute );        /* ignore seconds... */
  1124. X}
  1125. X
  1126. Xint
  1127. Xmonth_number(name)
  1128. Xchar *name;
  1129. X{
  1130. X    /** return the month number given the month name... **/
  1131. X
  1132. X    char ch;
  1133. X
  1134. X    switch (tolower(name[0])) {
  1135. X     case 'a' : if ((ch = tolower(name[1])) == 'p')    return(APRIL);
  1136. X            else if (ch == 'u') return(AUGUST);
  1137. X            else return(-1);    /* error! */
  1138. X    
  1139. X     case 'd' : return(DECEMBER);
  1140. X     case 'f' : return(FEBRUARY);
  1141. X     case 'j' : if ((ch = tolower(name[1])) == 'a') return(JANUARY);
  1142. X            else if (ch == 'u') {
  1143. X                  if ((ch = tolower(name[2])) == 'n') return(JUNE);
  1144. X              else if (ch == 'l') return(JULY);
  1145. X              else return(-1);        /* error! */
  1146. X                }
  1147. X            else return(-1);        /* error */
  1148. X     case 'm' : if ((ch = tolower(name[2])) == 'r') return(MARCH);
  1149. X            else if (ch == 'y') return(MAY);
  1150. X            else return(-1);        /* error! */
  1151. X     case 'n' : return(NOVEMBER);
  1152. X     case 'o' : return(OCTOBER);
  1153. X     case 's' : return(SEPTEMBER);
  1154. X     default  : return(-1);
  1155. X    }
  1156. X}
  1157. X
  1158. X#ifdef SITE_HIDING
  1159. X
  1160. Xchar *get_ctime_date()
  1161. X{
  1162. X    /** returns a ctime() format date, but a few minutes in the 
  1163. X        past...(more cunningness to implement hidden sites) **/
  1164. X
  1165. X    static char buffer[SLEN];    /* static character buffer       */
  1166. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  1167. X          *localtime();
  1168. X    long       junk,        /* time in seconds....         */
  1169. X           time();
  1170. X#ifdef BSD
  1171. X    struct  timeval  time_val;        
  1172. X    struct  timezone time_zone;
  1173. X#endif
  1174. X
  1175. X#ifdef BSD
  1176. X    gettimeofday(&time_val, &time_zone);
  1177. X    junk = time_val.tv_sec;
  1178. X#else
  1179. X    junk = time((long *) 0);    /* this must be here for it to work! */
  1180. X#endif
  1181. X    the_time = localtime(&junk);
  1182. X
  1183. X    sprintf(buffer, "%s %s %d %02d:%02d:%02d %d",
  1184. X      arpa_dayname[the_time->tm_wday],
  1185. X      arpa_monname[the_time->tm_mon],
  1186. X      the_time->tm_mday % 32,
  1187. X      min(the_time->tm_hour % 24, (rand() % 24)),
  1188. X      min(abs(the_time->tm_min  % 61 - (rand() % 60)), (rand() % 60)),
  1189. X      min(abs(the_time->tm_sec  % 61 - (rand() % 60)), (rand() % 60)),
  1190. X      the_time->tm_year % 100 + 1900);
  1191. X    
  1192. X    return( (char *) buffer);
  1193. X}
  1194. X
  1195. X#endif
  1196. END_OF_src/date.c
  1197. if test 10281 -ne `wc -c <src/date.c`; then
  1198.     echo shar: \"src/date.c\" unpacked with wrong size!?
  1199. fi
  1200. # end of overwriting check
  1201. fi
  1202. echo shar: Extracting \"test/test.mail\" \(10003 characters\)
  1203. if test -f test/test.mail ; then 
  1204.   echo shar: Will not over-write existing file \"test/test.mail\"
  1205. else
  1206. sed "s/^X//" >test/test.mail <<'END_OF_test/test.mail'
  1207. XFrom root Wed Oct 30 14:03:36 1985
  1208. X>From srmmail Wed Oct 30 14:10:08 1985  remote from veeger
  1209. X>From hplabs Wed Oct 30 14:00:16 1985 remote from hpcnof
  1210. X>From hpl-opus!poulton  Wed Oct 30 02:06:16 1985 remote from hplabs
  1211. XDate: Wed, 30 Oct 85 01:55:05 pst
  1212. XFrom: <hplabs!hpl-opus!poulton>
  1213. XReceived: by HP-VENUS id AA26352; Wed, 30 Oct 85 01:55:05 pst
  1214. XMessage-Id: <8510300955.AA26352@HP-VENUS>
  1215. XTo: hplabs!hpldat!taylor
  1216. XSubject: Re: announce(1)
  1217. X
  1218. XThe announce I got was shar'd July 8.   NLEN was not defined in that
  1219. Xsource, just used.  LONG_SLEN is not defined in the newmail(1)
  1220. Xthat you sent me.  What system are you running on?
  1221. XMy s500 doesn't have these def's.
  1222. X
  1223. X    -> Monday, January 3rd: Call your mother
  1224. X
  1225. XAs to announce --> newmail: why the switch?
  1226. XSeems like both are useful, in different situations.
  1227. X
  1228. XKen Poulton
  1229. XHPL
  1230. X
  1231. X
  1232. X
  1233. X
  1234. XFrom root Wed Oct 30 14:03:39 1985
  1235. X>From srmmail Wed Oct 30 14:10:12 1985  remote from veeger
  1236. X>From hplabs Wed Oct 30 13:59:53 1985 remote from hpcnof
  1237. X>From fowler  Wed Oct 30 12:57:11 1985 remote from hplabs
  1238. XDate: Wed, 30 Oct 85 12:57:11 pst
  1239. XFrom: Greg Fowler <hplabs!fowler>
  1240. XReceived: by HP-VENUS id AA12562; Wed, 30 Oct 85 12:57:11 pst
  1241. XMessage-Id: <8510302057.AA12562@HP-VENUS>
  1242. XTo: mail-men@rochester
  1243. XSubject: Re: Summary of Network Mail Headers
  1244. XReferences: <36700044@hpcnof.UUCP>
  1245. XPriority: Most Urgent
  1246. X
  1247. XI believe your introduction referred to the uucp network.  usenet is the networXk news
  1248. Xsoftware mechanism and isn't a "network".
  1249. X
  1250. X    - > February 19, 1986
  1251. X    -
  1252. X    -    A longer test of the system
  1253. X    -
  1254. X
  1255. X    Greg
  1256. X
  1257. X
  1258. X
  1259. XFrom root Wed Oct 30 14:13:23 1985
  1260. X>From srmmail Wed Oct 30 14:20:08 1985  remote from veeger
  1261. X>From root Wed Oct 30 14:01:57 1985 remote from hpcnof
  1262. XTo: DCC@hplabs
  1263. XSubject: Log of backup tape #1
  1264. X
  1265. XFull Backup starting at Wed Oct 30 12:45:14 MST 1985
  1266. X
  1267. X
  1268. Xbacking up directories: 
  1269. X    ./users/fh ./users/rmd ./users/vince ./users/roberts ./users/row ./users/dt ./Xlost+found ./users/lost+found ./users/scb ./users/kevin ./users/du
  1270. X
  1271. X
  1272. X
  1273. X
  1274. X
  1275. XFrom root Wed Oct 30 15:33:24 1985
  1276. X>From srmmail Wed Oct 30 15:40:26 1985  remote from veeger
  1277. X>From root Wed Oct 30 15:37:17 1985 remote from hpcnof
  1278. XTo: root, uucp, taylor@hplabs.ARPA
  1279. XSubject: Log of backup tape #2
  1280. X
  1281. Xbacking up directories: 
  1282. X    ./users/fh ./users/rmd ./users/vince ./users/roberts ./users/row ./users/dt ./Xlost+found ./users/lost+found ./users/scb ./users/kevin ./users/du
  1283. X
  1284. X
  1285. X
  1286. X
  1287. Xbacking up directories: 
  1288. X    ./users/sbh ./users/ges ./users/cpb ./users/amy ./net ./users/root ./users/balXza ./dev ./users/remple ./users/jr ./users/mwr ./users/larryf
  1289. X
  1290. X
  1291. X
  1292. X
  1293. X
  1294. XFrom root Sun Dec  8 22:50:18 1985
  1295. X>From srmmail Mon Dec  9 00:50:05 1985 remote from veeger
  1296. X>From root Mon Dec  9 00:41:15 1985 remote from hpcnof
  1297. X>From JLarson.pa@Xerox.ARPA  Sun Dec  8 20:45:55 1985 remote from hplabs
  1298. XDate: 8 Dec 85 20:36:36 PST (Sunday)
  1299. XFrom: hplabs!JLarson.pa@Xerox.ARPA
  1300. XSubject: How's it going, anyway?
  1301. XTo: hpcnou!dat@HPLABS.ARPA (Dave Taylor)
  1302. XCc: JLarson.pa@Xerox.ARPA
  1303. X
  1304. XHow are things with you?  Could you send me that paper we were talking
  1305. Xabout?  
  1306. X
  1307. X    Thanks
  1308. X
  1309. XJohn Larson
  1310. XXerox Palo Alto Research Center
  1311. X3333 Coyote Hill Road
  1312. XPalo Alto, Ca  94304
  1313. X
  1314. X
  1315. X
  1316. X
  1317. XFrom root Wed Aug  7 19:58:30 1985
  1318. X>From uucp Wed Aug  7 19:55:12 1985  remote from veeger
  1319. X>From hplabs Wed Aug  7 19:48:10 1985 remote from hpcnof
  1320. X>From RICHER@SUMEX-AIM  Wed Aug  7 09:23:12 1985 remote from hplabs
  1321. XReceived: by HP-VENUS id AA18269; Wed, 7 Aug 85 09:11:48 pdt
  1322. XDate: Tue 6 Aug 85 09:12:37-PDT
  1323. XFrom: Mark Richer <hplabs!RICHER@SUMEX-AIM>
  1324. XReceived: by HP-VENUS via CSNET; 7 Aug 1985 09:11:37-PDT (Wed)
  1325. XReceived: from sumex-aim.arpa by csnet-relay.arpa id a015812; 6 Aug 85 12:14 EDXT
  1326. XTo: hpcnof!veeger!hpcnou!dat%hplabs.csnet@CSNET-RELAY
  1327. XVia:  CSNet; 7 Aug 85 9:11-PDT
  1328. XSubject: Re: AI in Education mailing list...
  1329. XCc: RICHER@SUMEX-AIM
  1330. XIn-Reply-To: <8508030243.AA27641@HP-VENUS>
  1331. XMessage-Id: <12132987812.61.RICHER@SUMEX-AIM.ARPA>
  1332. X
  1333. XI added you to aied.  This message may be of interest to you:
  1334. X
  1335. XArtificial Intelligence in Education Meeting at IJCAI 85
  1336. X---------- ------------ -- --------- ------- -- ----- --
  1337. X
  1338. XPlace: Math Sciences Auditorium (a.k.a. Math 4000A), UCLA campus
  1339. XTime: 6:30 pm, Tuesday, Aug. 20, 1985  (length: 1 - 1 1/4 hr)
  1340. X
  1341. XAgenda:
  1342. X    I have two speakers scheduled to make presentations that
  1343. Xshould stimulate questions and discussions:
  1344. X
  1345. X    (1) Short Announcements
  1346. X
  1347. X    (2) Jeff Bonar, Research Scientist, Learning Research and
  1348. X    Development Center (LRDC), University of Pittsburgh
  1349. X
  1350. X    --- on-going ICAI research projects at LRDC
  1351. X    --- dissemination of ICAI technology in the form of software
  1352. X    tools, workshops, written materials, and video tapes.
  1353. X
  1354. X    (3) Gary Fine, Product Engineering Manager, INTELLICORP,
  1355. X    formerly with a company producing CAI products, also graduate
  1356. X    work in ICAI  
  1357. X
  1358. X    --- bridging the gap between current ICAI technology and the
  1359. X    real world
  1360. X
  1361. X[IJCAI-85, the 9th International Joint Conference on Artificial
  1362. XIntelligence is being held at UCLA Campus, August 18-23, 1985.  This
  1363. Xconference is co-sponsered by the American Association for Artificial
  1364. XIntelligence (AAAI) this year, and I have been told by their office
  1365. Xthat only walk-in registration is available at this time.  For more
  1366. Xinformation, contact AAAI:  AAAI-OFFICE@SUMEX-AIM.ARPA
  1367. X                AAAI, 445 Burgess Drive, Menlo Park, CA 94025
  1368. X                or call (415) 328-3123]
  1369. X
  1370. XDirect questions on the AI in ED meeting (only) to Mark Richer,
  1371. XRICHER@SUMEX-AIM.ARPA
  1372. X-------
  1373. X
  1374. X
  1375. X
  1376. X
  1377. XFrom root Tue Sep 24 09:53:24 1985
  1378. X>From HPMAIL-gateway Tue Sep 24  9:46:47 1985  remote from veeger
  1379. X>From Simon_CINTZ_/_HPD600/TR  Tue Sep 24  9:46:47 1985  remote from hpmail
  1380. XDate:   Tue, 24 Sep 85  9:14:00 MDT
  1381. XFrom:   Simon_CINTZ_/_HPD600/TR  (Simon Cintz)
  1382. XSubject: ITF
  1383. XFrom:   Simon_CINTZ_/_HPD600/TR  (Simon Cintz)
  1384. XTo:     Dave_TAYLOR_/_HPF100/00
  1385. X
  1386. XDave -
  1387. X
  1388. XJust as one programming language doesn't suit the needs of
  1389. Xall programmers, one authoring facility will probably not
  1390. Xsuit the needs of all HP entities that require CBT -- at least
  1391. Xnot in the near future.  Of course, this is my personal opinion
  1392. Xand if I'm wrong, it won't be the first time.
  1393. X
  1394. XGood luck.
  1395. X
  1396. X
  1397. X                                           - Simon
  1398. X
  1399. XFrom root Mon Oct 21 10:43:37 1985
  1400. X>From srmmail Mon Oct 21 10:30:16 1985  remote from veeger
  1401. X>From root Mon Oct 21 10:28:58 1985 remote from hpcnof
  1402. X>From DLS.MDC%office-X.arpa@CSNET-RELAY  Mon Oct 21 01:57:05 1985 remote from hXplabs
  1403. XReceived: by HP-VENUS id AA17376; Mon, 21 Oct 85 01:57:05 pdt
  1404. XDate: 21 Oct 85 01:02 EDT
  1405. XFrom: Duane Stone / McDonnell Douglas / CSC-ASD <hplabs!DLS.MDC%office-1.arpa@CXSNET-RELAY>
  1406. XReceived: by HP-VENUS via CSNET; 21 Oct 1985 01:57:01-PDT (Mon)
  1407. XReceived: from office-1.arpa by CSNET-RELAY.ARPA id a019220; 21 Oct 85 1:18 EDTX
  1408. XTo: Dave Taylor <hpcnou!dat%hplabs.csnet@CSNET-RELAY>
  1409. XVia:  CSNet; 21 Oct 85 1:56-PDT
  1410. XSubject: Re: More Mail Headers...
  1411. XMessage-Id: <MDC-DLS-7W9CS@OFFICE-1>
  1412. XComment: Dave -- this is the body of the message I previously 'sent' to you viaX
  1413. X
  1414. Xa Journal.
  1415. X
  1416. XI might suggest re-wording the para on Author -- my associates might object to X
  1417. X'strange' -- something like:
  1418. X
  1419. X   This is used to credit the original author, or to give credit on article 
  1420. X   excerpts (from Newspapers, magazines, books, etc).
  1421. X
  1422. XOne field which I forgot is:
  1423. X
  1424. X   Length:  This is computed when the message is sent and gives the recipients X
  1425. X   an estimate of the number of pages in the document.
  1426. X
  1427. X   Example:
  1428. X
  1429. X      Length: 6 pages [estimate]
  1430. X
  1431. XAccess:
  1432. X
  1433. X   Used to declare whether a Journal item should be Public or Private (to thoseX
  1434. X   that are on the distribution list or Extended Access list)
  1435. X
  1436. X   Example:
  1437. X
  1438. X      Access: Unrestricted
  1439. X
  1440. XAcknowledge-Delivery:
  1441. X
  1442. X   Used to request the system mailer send back a message when it has 
  1443. X   successfully delivered the item.
  1444. X
  1445. X   Example:
  1446. X
  1447. X      Acknowledge-Delivery: Requested
  1448. X
  1449. XAcknowledge-Receipt:
  1450. X
  1451. X   Used to to ask the recipient to acknowledge receipt of the message.
  1452. X
  1453. X   Example:
  1454. X
  1455. X   Acknowledge-Receipt: Requested
  1456. X
  1457. XAddendum-To:
  1458. X
  1459. X   A pointer to a previously submitted Journal item.
  1460. X
  1461. X   Example:
  1462. X
  1463. X      Addendum-To: <ASD,1234,>
  1464. X
  1465. XDelivery-Timing:
  1466. X
  1467. X   Used by the sender to indicate when the message should be submitted to the 
  1468. X   mailer.
  1469. X
  1470. X      Examples:
  1471. X
  1472. X         Rush:       -   immediate
  1473. X
  1474. X         Soon:       -   as soon as possible
  1475. X
  1476. X         Defer:      -   overnight
  1477. X
  1478. X         Start-Delivery: DATE TIME
  1479. X
  1480. X         Stop-Delivery:  DATE TIME (if not yet delivered)
  1481. X
  1482. XDisposition-Code:
  1483. X
  1484. X   Used by the system to group Journal items into one of several classes for 
  1485. X   eventual archive to tape and as an indicator of how long the archive tapes 
  1486. X   should be retained.
  1487. X
  1488. X   Example:
  1489. X
  1490. X      Disposition-Code: Temporary (2 years)
  1491. X
  1492. XExtended-access:
  1493. X
  1494. X   Used with private Journal items to allow access by other than those on the 
  1495. X   distribution list.
  1496. X
  1497. X   Example:
  1498. X
  1499. X      Extended-access: ASD.MDC
  1500. X
  1501. XLocation:
  1502. X
  1503. X   Used to submit the message to the Journal.  The adressees receive a short 
  1504. X   citation with other header fields and a "Location:" field pointing to a fileX
  1505. X   in an electronic library.
  1506. X
  1507. X   Example:
  1508. X
  1509. X      Location: <MDC,1234,>
  1510. X
  1511. XPart-Of:
  1512. X
  1513. X   A pointer to a previously submitted Journal item.
  1514. X
  1515. X   Example:
  1516. X
  1517. X      Part-Of: <MDC,1234,>
  1518. X
  1519. XRoute-To:
  1520. X
  1521. X   Used to send a message "in-turn" to addressees in the "To:" field -- as 
  1522. X   opposed to the broadcast method of delivery where everyone gets the message X
  1523. X   "simultaneously".  Any addresses in the "Cc:" field receive a copy of the 
  1524. X   message each time it is passed from one adressee to the next in the "To:" 
  1525. X   field.
  1526. X
  1527. X   Example:
  1528. X
  1529. X      Routed-to: {addresses in To field}
  1530. X
  1531. XSigned:
  1532. X
  1533. X   Created when the user employs the Sign command; used to electronically sign X
  1534. X   a message.  It affixes a signature-block to a message.  A "Verify Signature"X
  1535. X   command is available to recipients that lets them find out if anyone has 
  1536. X   changed the body of the message since the message was signed.
  1537. X
  1538. X   Example:
  1539. X
  1540. X          SIGNED
  1541. X      
  1542. X      Duane L. Stone
  1543. X      App. Dev. Mgr.
  1544. X
  1545. XSupersedes:
  1546. X
  1547. X   A pointer to a previously submitted Journal item.
  1548. X
  1549. X   Example:
  1550. X
  1551. X      Supersedes: <MDC,1234,>
  1552. X
  1553. X
  1554. X--- last line of the file --
  1555. END_OF_test/test.mail
  1556. if test 10003 -ne `wc -c <test/test.mail`; then
  1557.     echo shar: \"test/test.mail\" unpacked with wrong size!?
  1558. fi
  1559. # end of overwriting check
  1560. fi
  1561. echo shar: Extracting \"utils/from.c\" \(9633 characters\)
  1562. if test -f utils/from.c ; then 
  1563.   echo shar: Will not over-write existing file \"utils/from.c\"
  1564. else
  1565. sed "s/^X//" >utils/from.c <<'END_OF_utils/from.c'
  1566. X/**        from.c        **/
  1567. X
  1568. X/** print out whom each message is from in the pending mailbox
  1569. X    or specified one, including a subject line if available.. 
  1570. X
  1571. X    Added PREFER_UUCP knowledge 6/86
  1572. X    Added "-n" flag, 9/86
  1573. X
  1574. X    (C) Copyright 1986 Dave Taylor 
  1575. X**/
  1576. X
  1577. X#include <stdio.h>
  1578. X#include "defs.h"
  1579. X
  1580. Xstatic char ident[] = { WHAT_STRING };
  1581. X
  1582. X#define LINEFEED    (char) 10
  1583. X
  1584. X#define metachar(c)    (c == '=' || c == '+' || c == '%')
  1585. X
  1586. XFILE *mailfile;
  1587. X
  1588. Xchar *expand_define();
  1589. Xint   number = 0;    /* should we number the messages?? */
  1590. X
  1591. Xmain(argc, argv)
  1592. Xint argc;
  1593. Xchar *argv[];
  1594. X{
  1595. X    char infile[LONG_SLEN], username[SLEN];
  1596. X
  1597. X    if (argc > 2) {
  1598. X      printf("Usage: %s [-n] {filename | username}\n", argv[0]);
  1599. X      exit(1);
  1600. X    }
  1601. X
  1602. X    if (argc > 1)
  1603. X      if (strcmp(argv[1], "-n") == 0) {
  1604. X        number++;
  1605. X        *argv++;
  1606. X        argc--;
  1607. X      }
  1608. X
  1609. X    if (argc == 2) 
  1610. X      strcpy(infile, argv[1]);
  1611. X    else {
  1612. X      strcpy(username, getlogin());
  1613. X      if (strlen(username) == 0)
  1614. X        cuserid(username);
  1615. X      sprintf(infile,"%s%s",mailhome, username);
  1616. X    }
  1617. X
  1618. X    if (metachar(infile[0])) {
  1619. X      if (expand(infile) == 0) {
  1620. X         fprintf(stderr, "%s: couldn't expand filename %s!\n", 
  1621. X             argv[0], infile);
  1622. X         exit(1);
  1623. X      }
  1624. X    }
  1625. X    else
  1626. X      printf("filename '%s' doesn't have a metacharacter!\n", infile);
  1627. X
  1628. X    if ((mailfile = fopen(infile,"r")) == NULL) {
  1629. X      if (argc == 1)
  1630. X        printf("No mail!\n");
  1631. X      else {
  1632. X        if (argv[1][0] == '/') 
  1633. X          printf("Couldn't open folder/mailfile %s!\n", infile);
  1634. X        else {
  1635. X          sprintf(infile,"%s%s", mailhome, argv[1]);
  1636. X          if ((mailfile = fopen(infile,"r")) == NULL)
  1637. X            printf("Couldn't open folder/mailfile %s!\n", infile);
  1638. X          else if (read_headers()==0)
  1639. X            printf("No messages in mailbox!\n");
  1640. X         }
  1641. X      }
  1642. X    }
  1643. X    else
  1644. X      if (read_headers()==0)
  1645. X        printf("No messages in mailbox!\n");
  1646. X}
  1647. X
  1648. Xint
  1649. Xread_headers()
  1650. X{
  1651. X    /** read the headers, output as found **/
  1652. X
  1653. X    char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
  1654. X    register int subj = 0, in_header = 1, count = 0;
  1655. X
  1656. X    while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
  1657. X      if (first_word(buffer,"From ")) {
  1658. X        if (real_from(buffer, from_whom)) {
  1659. X          subj = 0;
  1660. X          in_header = 1;
  1661. X        }
  1662. X      }
  1663. X      else if (in_header) {
  1664. X        if (first_word(buffer,">From")) 
  1665. X          forwarded(buffer, from_whom); /* return address */
  1666. X        else if (first_word(buffer,"Subject:") ||
  1667. X             first_word(buffer,"Re:")) {
  1668. X          if (! subj++) {
  1669. X            remove_first_word(buffer);
  1670. X        strcpy(subject, buffer);
  1671. X          }
  1672. X        }
  1673. X        else if (first_word(buffer,"From:")) 
  1674. X          parse_arpa_from(buffer, from_whom);
  1675. X        else if (buffer[0] == LINEFEED) {
  1676. X          in_header = 0;    /* in body of message! */
  1677. X          show_header(count+1, from_whom, subject);
  1678. X          from_whom[0] = 0;
  1679. X          subject[0] = 0;
  1680. X          count++;
  1681. X        }
  1682. X      }
  1683. X    }
  1684. X    return(count);
  1685. X}
  1686. X
  1687. Xint
  1688. Xreal_from(buffer, who)
  1689. Xchar *buffer, *who;
  1690. X{
  1691. X    /***** returns true iff 's' has the seven 'from' fields,
  1692. X           initializing the who to the sender *****/
  1693. X
  1694. X    char junk[80];
  1695. X
  1696. X    junk[0] = '\0';
  1697. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  1698. X                who, junk);
  1699. X    return(junk[0] != '\0');
  1700. X}
  1701. X
  1702. Xforwarded(buffer, who)
  1703. Xchar *buffer, *who;
  1704. X{
  1705. X    /** change 'from' and date fields to reflect the ORIGINATOR of 
  1706. X        the message by iteratively parsing the >From fields... **/
  1707. X
  1708. X    char machine[80], buff[80];
  1709. X
  1710. X    machine[0] = '\0';
  1711. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  1712. X                who, machine);
  1713. X
  1714. X    if (machine[0] == '\0') /* try for srm address */
  1715. X      sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  1716. X                who, machine);
  1717. X
  1718. X    if (machine[0] == '\0')
  1719. X      sprintf(buff,"anonymous");
  1720. X    else
  1721. X      sprintf(buff,"%s!%s", machine, who);
  1722. X
  1723. X    strncpy(who, buff, 80);
  1724. X}
  1725. X
  1726. X
  1727. Xremove_first_word(string)
  1728. Xchar *string;
  1729. X{    /** removes first word of string, ie up to first non-white space
  1730. X        following a white space! **/
  1731. X
  1732. X    register int loc;
  1733. X
  1734. X    for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  1735. X        ;
  1736. X
  1737. X    while (string[loc] == ' ' || string[loc] == '\t')
  1738. X      loc++;
  1739. X    
  1740. X    move_left(string, loc);
  1741. X}
  1742. X
  1743. Xmove_left(string, chars)
  1744. Xchar string[];
  1745. Xint  chars;
  1746. X{
  1747. X    /** moves string chars characters to the left DESTRUCTIVELY **/
  1748. X
  1749. X    register int i;
  1750. X
  1751. X    chars--; /* index starting at zero! */
  1752. X
  1753. X    for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  1754. X      string[i-chars] = string[i];
  1755. X
  1756. X    string[i-chars] = '\0';
  1757. X}
  1758. X
  1759. Xshow_header(count, from, subject)
  1760. Xint  count;
  1761. Xchar *from, *subject;
  1762. X{
  1763. X    /** output header in clean format, including abbreviation
  1764. X        of return address if more than one machine name is
  1765. X        contained within it! **/
  1766. X
  1767. X    char buffer[SLEN];
  1768. X    int  loc, i=0, exc=0;
  1769. X
  1770. X#ifdef PREFER_UUCP
  1771. X    
  1772. X    if (chloc(from,'!') != -1 && in_string(from, BOGUS_INTERNET))
  1773. X      from[strlen(from) - strlen(BOGUS_INTERNET)] = '\0';
  1774. X
  1775. X#endif
  1776. X
  1777. X    loc = strlen(from);
  1778. X
  1779. X    while (exc < 2 && loc > 0)
  1780. X      if (from[--loc] == '!')
  1781. X        exc++;
  1782. X
  1783. X    if (exc == 2) { /* lots of machine names!  Get last one */
  1784. X      loc++;
  1785. X      while (loc < strlen(from) && loc < SLEN)
  1786. X        buffer[i++] = from[loc++];
  1787. X      buffer[i] = '\0';
  1788. X      if (number)
  1789. X        printf("%3d: %-20s  %s\n", count, buffer, subject);
  1790. X      else
  1791. X        printf("%-20s  %s\n", buffer, subject);
  1792. X    }
  1793. X    else
  1794. X      if (number)
  1795. X        printf("%3d: %-20s  %s\n", count, from, subject);
  1796. X      else
  1797. X        printf("%-20s  %s\n", from, subject);
  1798. X}    
  1799. X
  1800. Xparse_arpa_from(buffer, newfrom)
  1801. Xchar *buffer, *newfrom;
  1802. X{
  1803. X    /** try to parse the 'From:' line given... It can be in one of
  1804. X        two formats:
  1805. X        From: Dave Taylor <hpcnou!dat>
  1806. X        or  From: hpcnou!dat (Dave Taylor)
  1807. X        Change 'newfrom' ONLY if sucessfully parsed this entry and
  1808. X        the resulting name is non-null! 
  1809. X    **/
  1810. X
  1811. X    char temp_buffer[SLEN], *temp;
  1812. X    register int i, j = 0;
  1813. X
  1814. X    temp = (char *) temp_buffer;
  1815. X    temp[0] = '\0';
  1816. X
  1817. X    no_ret(buffer);        /* blow away '\n' char! */
  1818. X
  1819. X    if (lastch(buffer) == '>') {
  1820. X      for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  1821. X           buffer[i] != '('; i++)
  1822. X        temp[j++] = buffer[i];
  1823. X      temp[j] = '\0';
  1824. X    }
  1825. X    else if (lastch(buffer) == ')') {
  1826. X      for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
  1827. X           buffer[i] != '<'; i--)
  1828. X        temp[j++] = buffer[i];
  1829. X      temp[j] = '\0';
  1830. X      reverse(temp);
  1831. X    }
  1832. X      
  1833. X    if (strlen(temp) > 0) {        /* mess with buffer... */
  1834. X
  1835. X      /* remove leading spaces... */
  1836. X
  1837. X      while (whitespace(temp[0]))
  1838. X        temp = (char *) (temp + 1);        /* increment address! */
  1839. X
  1840. X      /* remove trailing spaces... */
  1841. X
  1842. X      i = strlen(temp) - 1;
  1843. X
  1844. X      while (whitespace(temp[i]))
  1845. X       temp[i--] = '\0';
  1846. X
  1847. X      /* if anything is left, let's change 'from' value! */
  1848. X
  1849. X      if (strlen(temp) > 0)
  1850. X        strcpy(newfrom, temp);
  1851. X    }
  1852. X}
  1853. X
  1854. Xreverse(string)
  1855. Xchar *string;
  1856. X{
  1857. X    /** reverse string... pretty trivial routine, actually! **/
  1858. X
  1859. X    char buffer[SLEN];
  1860. X    register int i, j = 0;
  1861. X
  1862. X    for (i = strlen(string)-1; i >= 0; i--)
  1863. X      buffer[j++] = string[i];
  1864. X
  1865. X    buffer[j] = '\0';
  1866. X
  1867. X    strcpy(string, buffer);
  1868. X}
  1869. X
  1870. Xint
  1871. Xexpand(infile)
  1872. Xchar *infile;
  1873. X{
  1874. X    /** Expand the filename since the first character is a meta-
  1875. X        character that should expand to the "maildir" variable
  1876. X        in the users ".elmrc" file...
  1877. X
  1878. X        Note: this is a brute force way of getting the entry out 
  1879. X        of the .elmrc file, and isn't recommended for the faint 
  1880. X        of heart!
  1881. X    **/
  1882. X
  1883. X    FILE *rcfile;
  1884. X    char  buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr;
  1885. X    int   foundit = 0;
  1886. X
  1887. X    bufptr = (char *) buffer;        /* same address */
  1888. X    
  1889. X    if ((home = getenv("HOME")) == NULL) {
  1890. X      printf(
  1891. X         "Can't expand environment variable $HOME to find .elmrc file!\n");
  1892. X      exit(1);
  1893. X    }
  1894. X
  1895. X    sprintf(buffer, "%s/%s", home, elmrcfile);
  1896. X
  1897. X    if ((rcfile = fopen(buffer, "r")) == NULL) {
  1898. X      printf("Can't open your \".elmrc\" file (%s) for reading!\n",
  1899. X         buffer);
  1900. X      exit(1);
  1901. X    }
  1902. X
  1903. X    while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) {
  1904. X      if (strncmp(buffer, "maildir", 7) == 0 ||
  1905. X          strncmp(buffer, "folders", 7) == 0) {
  1906. X        while (*bufptr != '=' && *bufptr) 
  1907. X          bufptr++;
  1908. X        bufptr++;            /* skip the equals sign */
  1909. X        while (whitespace(*bufptr) && *bufptr)
  1910. X          bufptr++; 
  1911. X        home = bufptr;        /* remember this address */
  1912. X
  1913. X        while (! whitespace(*bufptr) && *bufptr != '\n')
  1914. X          bufptr++;
  1915. X
  1916. X        *bufptr = '\0';        /* remove trailing space */
  1917. X        foundit++;
  1918. X      }
  1919. X    }
  1920. X
  1921. X    fclose(rcfile);            /* be nice... */
  1922. X
  1923. X    if (! foundit) {
  1924. X      printf("Couldn't find \"maildir\" in your .elmrc file!\n");
  1925. X      exit(1);
  1926. X    }
  1927. X
  1928. X    /** Home now points to the string containing your maildir, with
  1929. X        no leading or trailing white space...
  1930. X    **/
  1931. X
  1932. X    expanded_dir = expand_define(home);
  1933. X
  1934. X    sprintf(buffer, "%s%s%s", expanded_dir, 
  1935. X        (expanded_dir[strlen(expanded_dir)-1] == '/' ||
  1936. X        infile[0] == '/') ? "" : "/", (char *) infile+1);
  1937. X
  1938. X    strcpy(infile, buffer);
  1939. X}
  1940. X
  1941. Xchar *expand_define(maildir)
  1942. Xchar *maildir;
  1943. X{
  1944. X    /** This routine expands any occurances of "~" or "$var" in
  1945. X        the users definition of their maildir directory out of
  1946. X        their .elmrc file.
  1947. X
  1948. X        Again, another routine not for the weak of heart or staunch
  1949. X        of will!
  1950. X    **/
  1951. X
  1952. X    static char buffer[SLEN];    /* static buffer AIEE!! */
  1953. X    char   name[SLEN],        /* dynamic buffer!! (?) */
  1954. X           *nameptr,           /*  pointer to name??     */
  1955. X           *value;              /* char pointer for munging */
  1956. X
  1957. X    if (*maildir == '~') 
  1958. X      sprintf(buffer, "%s%s", getenv("HOME"), ++maildir);
  1959. X    else if (*maildir == '$') {     /* shell variable */
  1960. X
  1961. X      /** break it into a single word - the variable name **/
  1962. X
  1963. X      strcpy(name, (char *) maildir + 1);    /* hurl the '$' */
  1964. X      nameptr = (char *) name;
  1965. X      while (*nameptr != '/' && *nameptr) nameptr++;
  1966. X      *nameptr = '\0';    /* null terminate */
  1967. X      
  1968. X      /** got word "name" for expansion **/
  1969. X
  1970. X      if ((value = getenv(name)) == NULL) {
  1971. X        printf("Couldn't expand shell variable $%s in .elmrc!\n", name);
  1972. X        exit(1);
  1973. X      }
  1974. X      sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1);
  1975. X    }
  1976. X    else strcpy(buffer, maildir);
  1977. X
  1978. X    return( ( char *) buffer);
  1979. X}
  1980. END_OF_utils/from.c
  1981. if test 9633 -ne `wc -c <utils/from.c`; then
  1982.     echo shar: \"utils/from.c\" unpacked with wrong size!?
  1983. fi
  1984. # end of overwriting check
  1985. fi
  1986. echo shar: End of archive 10 \(of 19\).
  1987. cp /dev/null ark10isdone
  1988. DONE=true
  1989. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1990.     if test ! -f ark${I}isdone ; then
  1991.     echo shar: You still need to run archive ${I}.
  1992.     DONE=false
  1993.     fi
  1994. done
  1995. if test "$DONE" = "true" ; then
  1996.     echo You have unpacked all 19 archives.
  1997.     echo "See the Instructions file"
  1998.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1999. fi
  2000. ##  End of shell archive.
  2001. exit 0
  2002.