home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1587 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  18.4 KB

  1. From: csu@alembic.acs.com (Dave Mack)
  2. Newsgroups: alt.sources
  3. Subject: Anonymous Contact Service software v1.1, Part08/08
  4. Message-ID: <1990Jul15.171456.7253@alembic.acs.com>
  5. Date: 15 Jul 90 17:14:56 GMT
  6.  
  7. This is the second distribution of the Anonymous Contact Service
  8. software. The distribution consists of 8 shar files. This will
  9. (hopefully) be the last full distribution of the system - all
  10. future versions will be distributed as patches. The patchlevel of
  11. this version is 1.
  12.  
  13. The ACS software provides a mechanism for posting anonymous articles,
  14. for receiving replies to those articles which are also anonymous, and
  15. permits prolonged anonymous conversations in which neither writer knows
  16. the other's actual e-mail address.
  17.  
  18. This software is currently being used to provide an anonymous personals
  19. service in alt.personals.
  20.  
  21. Dave Mack
  22. csu@alembic.ACS.COM
  23.  
  24. #! /bin/sh
  25. # This is a shell archive.  Remove anything before this line, then unpack
  26. # it by saving it into a file and typing "sh file".  To overwrite existing
  27. # files, type "sh file -c".  You can also feed this as standard input via
  28. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  29. # will see the following message at the end:
  30. #        "End of archive 8 (of 8)."
  31. # Contents:  mailer/headers.c
  32. # Wrapped by csu@alembic on Sun Jul 15 12:46:56 1990
  33. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  34. if test -f 'mailer/headers.c' -a "${1}" != "-c" ; then 
  35.   echo shar: Will not clobber existing file \"'mailer/headers.c'\"
  36. else
  37. echo shar: Extracting \"'mailer/headers.c'\" \(15935 characters\)
  38. sed "s/^X//" >'mailer/headers.c' <<'END_OF_FILE'
  39. X/*
  40. X**  message spooing, header and address parsing and completion
  41. X**  functions for smail/rmail
  42. X*/
  43. X
  44. X#ifndef lint
  45. Xstatic char     *sccsid="@(#)headers.c    2.5 (smail) 9/15/87";
  46. X#endif
  47. X
  48. X# include    <stdio.h>
  49. X# include    <sys/types.h>
  50. X# include    <time.h>
  51. X# include    <ctype.h>
  52. X# include    <pwd.h>
  53. X# include    "defs.h"
  54. X
  55. Xextern enum edebug debug;    /* how verbose we are         */ 
  56. Xextern char hostname[];        /* */
  57. Xextern char hostdomain[];    /* */
  58. Xextern char *spoolfile;        /* file name of spooled message */
  59. Xextern FILE *spoolfp;        /* file ptr  to spooled message */
  60. Xextern int spoolmaster;        /* set if creator of spoolfile  */
  61. Xextern time_t now;        /* time                */
  62. Xextern char nows[], arpanows[];    /* time strings            */
  63. Xextern struct tm *gmt, *loc;    /* time structs            */
  64. Xextern char *from_addr;        /* replacement fromaddr with -F */
  65. X
  66. Xstatic char toline[SMLBUF];
  67. Xstatic char fromline[SMLBUF];
  68. Xstatic char dateline[SMLBUF];
  69. Xstatic char midline[SMLBUF];
  70. Xstatic char *ieof = "NOTNULL";
  71. X
  72. Xstruct reqheaders {
  73. X    char *name;
  74. X    char *field;
  75. X    char have;
  76. X};
  77. X
  78. Xstatic struct reqheaders reqtab[] = {
  79. X    "Message-Id:"    ,    midline        ,    'N'    ,
  80. X    "Date:"        ,    dateline    ,    'N'    ,
  81. X    "From:"        ,    fromline    ,    'N'    ,
  82. X    "To:"        ,    toline        ,    'N'    ,
  83. X    NULL         ,    NULL        ,    'N'
  84. X};
  85. X
  86. X
  87. X/*
  88. X**
  89. X** parse(): parse <address> into <domain, user, form>.
  90. X**
  91. X**     input        form
  92. X**    -----        ----
  93. X**    user        LOCAL
  94. X**    domain!user    DOMAIN
  95. X**    user@domain    DOMAIN
  96. X**    @domain,address    LOCAL    (just for sendmail)
  97. X**    host!address    UUCP
  98. X**
  99. X*/
  100. X
  101. Xenum eform
  102. Xparse(address, domain, user)
  103. Xchar *address;        /* input address     */
  104. Xchar *domain;        /* output domain     */
  105. Xchar *user;        /* output user         */
  106. X{
  107. X    int parts;
  108. X    char *partv[MAXPATH];                /* to crack address */
  109. X
  110. X/*
  111. X**  If this is route address form @domain_a,@domain_b:user@domain_c, ...
  112. X*/
  113. X    if(*address == '@')
  114. X#ifdef SENDMAIL
  115. X/*
  116. X**  hand it to sendmail
  117. X*/
  118. X    {
  119. X        goto local;
  120. X    }
  121. X#else
  122. X/*
  123. X**  no sendmail, convert it into a bang path: domain_a!domain_b!domain_c!user
  124. X*/
  125. X    {
  126. X        char buf[SMLBUF], *p;
  127. X        char t_dom[SMLBUF], t_user[SMLBUF];
  128. X
  129. X        (void) strcpy(buf, address+1);        /* elide leading '@' */
  130. X
  131. X        for(p=buf; *p != '\0' ; p++) {    /* search for ',' or ':' */
  132. X            if(*p == ':') {        /* reached end of route */
  133. X                break;
  134. X            }
  135. X            if(*p == ',') {        /* elide ','s */
  136. X                (void) strcpy(p, p+1);
  137. X            }
  138. X            if(*p == '@') {        /* convert '@' to '!' */
  139. X                *p = '!';
  140. X            }
  141. X        }
  142. X
  143. X        if(*p != ':') {    /* bad syntax - punt */
  144. X            goto local;
  145. X        }
  146. X        *p = '\0';
  147. X
  148. X        if(parse(p+1, t_dom, t_user) != LOCAL) {
  149. X            (void) strcat(buf, "!");
  150. X            (void) strcat(buf, t_dom);
  151. X        }
  152. X        (void) strcat(buf, "!");
  153. X        (void) strcat(buf, t_user);
  154. X
  155. X        /* munge the address (yuk)
  156. X        ** it's OK to copy into 'address', because the machinations
  157. X        ** above don't increase the string length of the address.
  158. X        */
  159. X
  160. X        (void) strcpy(address, buf);
  161. X
  162. X        /* re-parse the address */
  163. X        return(parse(address, domain, user));
  164. X    }
  165. X#endif
  166. X/*
  167. X**  Try splitting at @.  If it works, this is user@domain, form DOMAIN.
  168. X**  Prefer the righthand @ in a@b@c.
  169. X*/
  170. X    if ((parts = ssplit(address, '@', partv)) >= 2) {
  171. X        (void) strcpy(domain, partv[parts-1]);
  172. X        (void) strncpy(user, partv[0], partv[parts-1]-partv[0]-1);
  173. X        user[partv[parts-1]-partv[0]-1] = '\0';
  174. X        return (DOMAIN);
  175. X    } 
  176. X/*
  177. X**  Try splitting at !. If it works, see if the piece before the ! has
  178. X**  a . in it (domain!user, form DOMAIN) or not (host!user, form UUCP).
  179. X*/
  180. X    if (ssplit(address, '!', partv) > 1) {
  181. X        (void) strcpy(user, partv[1]);
  182. X        (void) strncpy(domain, partv[0], partv[1]-partv[0]-1);
  183. X        domain[partv[1]-partv[0]-1] = '\0';
  184. X
  185. X        if((parts = ssplit(domain, '.', partv)) < 2) {
  186. X            return(UUCP);
  187. X        }
  188. X
  189. X        if(partv[parts-1][0] == '\0') {
  190. X            partv[parts-1][-1] = '\0'; /* strip trailing . */
  191. X        }
  192. X        return (DOMAIN);
  193. X    }
  194. X/* 
  195. X**  Done trying.  This must be just a user name, form LOCAL.
  196. X*/
  197. Xlocal:
  198. X    (void) strcpy(user, address);
  199. X    (void) strcpy(domain, "");
  200. X    return(LOCAL);                /* user */
  201. X}
  202. X
  203. Xbuild(domain, user, form, result)
  204. Xchar *domain;
  205. Xchar *user;
  206. Xenum eform form;
  207. Xchar *result;
  208. X{
  209. X    switch((int) form) {
  210. X    case LOCAL:
  211. X        (void) sprintf(result, "%s", user); 
  212. X        break;
  213. X    case UUCP:
  214. X        (void) sprintf(result, "%s!%s", domain, user);
  215. X        break;
  216. X    case DOMAIN:
  217. X        (void) sprintf(result, "%s@%s", user, domain);
  218. X        break;
  219. X    }
  220. X}
  221. X
  222. X/*
  223. X**  ssplit(): split a line into array pointers.
  224. X**
  225. X**  Each pointer wordv[i] points to the first character after the i'th 
  226. X**  occurence of c in buf.  Note that each wordv[i] includes wordv[i+1].
  227. X**
  228. X*/
  229. X
  230. Xssplit(buf, c, ptr)
  231. Xregister char *buf;        /* line to split up         */
  232. Xchar c;                /* character to split on    */
  233. Xchar **ptr;            /* the resultant vector        */
  234. X{
  235. X        int count = 0;
  236. X        int wasword = 0;
  237. X
  238. X        for(; *buf; buf++) {
  239. X        if (!wasword) {
  240. X            count++;
  241. X            *ptr++ = buf;
  242. X        }
  243. X        wasword = (c != *buf);
  244. X        }
  245. X    if (!wasword) {
  246. X        count++;
  247. X        *ptr++ = buf;
  248. X    }
  249. X        *ptr = NULL;
  250. X        return(count);
  251. X}
  252. X
  253. X/*
  254. X** Determine whether an address is a local address
  255. X*/
  256. X
  257. Xislocal(addr, domain, user)
  258. Xchar *addr, *domain, *user;
  259. X{
  260. X        enum eform form, parse();
  261. X        extern char hostuucp[];
  262. X
  263. X        /*
  264. X        ** parse the address
  265. X        */
  266. X
  267. X        form = parse(addr, domain, user);
  268. X
  269. X        if((form == LOCAL)            /* user */
  270. X        ||(strcmpic(domain, hostdomain) == 0)    /* user@hostdomain */
  271. X        ||(strcmpic(domain, hostname)   == 0)    /* user@hostname */
  272. X#ifdef DOMGATE
  273. X        ||(strcmpic(domain, &MYDOM[0]) == 0)    /* user@MYDOM w/ dot */
  274. X        ||(strcmpic(domain, &MYDOM[1]) == 0)    /* user@MYDOM no dot */
  275. X#endif
  276. X        ||(strcmpic(domain, hostuucp)   == 0)) {/* user@hostuucp */
  277. X            return(1);
  278. X        }
  279. X        return(0);
  280. X}
  281. X
  282. X/*
  283. X** spool - message spooling module
  284. X**
  285. X** (1) get dates for headers, etc.
  286. X** (2) if the message is on the standard input (no '-f')
  287. X**     (a) create a temp file for spooling the message.
  288. X**     (b) collapse the From_ headers into a path.
  289. X**     (c) if the mail originated locally, then
  290. X**         (i) establish default headers
  291. X**        (ii) scan the message headers for required header fields
  292. X**       (iii) add any required message headers that are absent
  293. X**     (d) copy rest of the message to the spool file
  294. X**     (e) close the spool file
  295. X** (3) open the spool file for reading
  296. X*/
  297. X
  298. Xvoid
  299. Xspool(argc, argv)
  300. Xint argc;
  301. Xchar **argv;
  302. X{
  303. X    static char *tmpf = "/tmp/rmXXXXXX";    /* temp file name */
  304. X    char *mktemp();
  305. X    char buf[SMLBUF];
  306. X    static char splbuf[SMLBUF];
  307. X    char from[SMLBUF], domain[SMLBUF], user[SMLBUF];
  308. X    void rline(), scanheaders(), compheaders();
  309. X
  310. X    /*
  311. X    ** if the mail has already been spooled by
  312. X    ** a previous invocation of smail don't respool.
  313. X    ** check the file name to prevent things like
  314. X    ** rmail -f /etc/passwd badguy@dreadfuldomain
  315. X    */
  316. X
  317. X    if((spoolfile != NULL)
  318. X    && (strncmp(spoolfile, tmpf, strlen(tmpf) - 6) != 0)) {
  319. X        error(EX_TEMPFAIL, "spool: bad file name '%s'\n", spoolfile);
  320. X    }
  321. X
  322. X    /*
  323. X    ** set dates in local, arpa, and gmt forms
  324. X    */
  325. X    setdates();
  326. X
  327. X    /*
  328. X    ** If necessary, copy stdin to a temp file.
  329. X    */
  330. X
  331. X    if(spoolfile == NULL) {
  332. X        spoolfile = strcpy(splbuf, tmpf);
  333. X        (void) mktemp(spoolfile);
  334. X
  335. X        if((spoolfp = fopen(spoolfile, "w")) == NULL) {
  336. X            error(EX_CANTCREAT, "can't create %s.\n", spoolfile);
  337. X        }
  338. X
  339. X        spoolmaster = 1;
  340. X
  341. X        /*
  342. X        ** rline reads the standard input,
  343. X        ** collapsing the From_ and >From_
  344. X        ** lines into a single uucp path.
  345. X        ** first non-from_ line is in buf[];
  346. X        */
  347. X
  348. X        rline(from, buf);
  349. X
  350. X        /*
  351. X        ** if the mail originated here, we parse the header
  352. X        ** and add any required headers that are missing.
  353. X        */
  354. X
  355. X        if(islocal(from, domain, user) || (from_addr != NULL)) {
  356. X            /*
  357. X            ** initialize default headers
  358. X            */
  359. X            def_headers(argc, argv, from);
  360. X
  361. X            /*
  362. X            ** buf has first, non-from_  line
  363. X            */
  364. X            scanheaders(buf);
  365. X            /*
  366. X            ** buf has first, non-header line,
  367. X            */
  368. X
  369. X            compheaders();
  370. X
  371. X            if(buf[0] != '\n') {
  372. X                (void) fputs("\n", spoolfp);
  373. X            }
  374. X        }
  375. X
  376. X        /*
  377. X        ** now, copy the rest of the letter into the spool file
  378. X        ** terminate on either EOF or '^.$'
  379. X        */
  380. X
  381. X        while(ieof != NULL) {
  382. X            (void) fputs(buf, spoolfp);
  383. X            if((fgets(buf, SMLBUF, stdin) == NULL)
  384. X            || (buf[0] == '.' && buf[1] == '\n')) {
  385. X                ieof = NULL;
  386. X            }
  387. X        }
  388. X
  389. X        /*
  390. X        ** close the spool file, and the standard input.
  391. X        */
  392. X
  393. X        (void) fclose(spoolfp);
  394. X        (void) fclose(stdin);    /* you don't see this too often! */
  395. X    }
  396. X
  397. X    if((spoolfp = fopen(spoolfile, "r")) == NULL) {
  398. X        error(EX_TEMPFAIL, "can't open %s.\n", spoolfile);
  399. X    }
  400. X}
  401. X
  402. X/*
  403. X**
  404. X**  rline(): collapse From_ and >From_ lines.
  405. X**
  406. X**  Same idea as the old rmail, but also turns user@domain to domain!user. 
  407. X**
  408. X*/
  409. X
  410. Xvoid
  411. Xrline(from, retbuf)
  412. Xchar *from;
  413. Xchar *retbuf;
  414. X{
  415. X    int parts;            /* for cracking From_ lines ... */
  416. X    char *partv[16];        /* ... apart using ssplit()     */
  417. X    char user[SMLBUF];        /* for rewriting user@host    */
  418. X    char domain[SMLBUF];        /* "   "         "              */
  419. X    char addr[SMLBUF];        /* "   "         "              */
  420. X    enum eform form, parse();    /* "   "         "              */
  421. X    extern build();            /* "   "         "              */
  422. X    char *c;
  423. X    int nhops, i;
  424. X    char buf[SMLBUF], tmp[SMLBUF], *hop[128], *e, *b;
  425. X    char *pwuid();
  426. X
  427. X    if(spoolmaster == 0) return;
  428. X
  429. X    buf[0] = from[0] = addr[0] = '\0';
  430. X/*
  431. X**  Read each line until we hit EOF or a line not beginning with "From "
  432. X**  or ">From " (called From_ lines), accumulating the new path in from
  433. X**  and stuffing the actual sending user (the user name on the last From_ 
  434. X**  line) in addr.
  435. X*/
  436. X    for(;;) {
  437. X        (void) strcpy(retbuf, buf);
  438. X        if(ieof == NULL) {
  439. X            break;
  440. X        }
  441. X        if((fgets(buf, sizeof(buf), stdin) == NULL)
  442. X        || (buf[0] == '.' && buf[1] == '\n')) {
  443. X            ieof = NULL;
  444. X            break;
  445. X        }
  446. X        if (strncmp("From ", buf, 5) 
  447. X            && strncmp(">From ", buf, 6)) {
  448. X            break;
  449. X        }
  450. X/*
  451. X**  Crack the line apart using ssplit.
  452. X*/
  453. X        if(c = index(buf, '\n')) {
  454. X            *c = '\0';
  455. X        }
  456. X        parts = ssplit(buf, ' ', partv);
  457. X/*
  458. X**  Tack host! onto the from argument if "remote from host" is present.
  459. X*/
  460. X
  461. X        if((parts > 3)
  462. X        && (strncmp("remote from ", partv[parts-3], 12) == 0)) {
  463. X            (void) strcat(from, partv[parts-1]);
  464. X            (void) strcat(from, "!");
  465. X        }
  466. X/*
  467. X**  Stuff user name into addr, overwriting the user name from previous 
  468. X**  From_ lines, since only the last one counts.  Then rewrite user@host 
  469. X**  into host!user, since @'s don't belong in the From_ argument.
  470. X*/
  471. X        if(parts < 2) {
  472. X            break;
  473. X        } else {
  474. X            char *x = partv[1];
  475. X            char *q = index(x, ' ');
  476. X            if(q != NULL) {
  477. X                *q = '\0';
  478. X            }
  479. X            (void) strcpy(addr, x);
  480. X        }
  481. X
  482. X        (void) parse(addr, domain, user);
  483. X        if(*domain == '\0') {
  484. X            form = LOCAL;
  485. X        } else {
  486. X            form = UUCP;
  487. X        }
  488. X
  489. X        build(domain, user, form, addr);
  490. X    }
  491. X/*
  492. X**  Now tack the user name onto the from argument.
  493. X*/
  494. X    (void) strcat(from, addr);
  495. X/*
  496. X**  If we still have no from argument, we have junk headers, but we try
  497. X**  to get the user's name using /etc/passwd.
  498. X*/
  499. X
  500. X    if (from[0] == '\0') {
  501. X        char *login;
  502. X        if ((login = pwuid(getuid())) == NULL) {
  503. X            (void) strcpy(from, "nobody");    /* bad news */
  504. X        } else {
  505. X            (void) strcpy(from, login);
  506. X        }
  507. X    }
  508. X
  509. X    /* split the from line on '!'s */
  510. X    nhops = ssplit(from, '!', hop);
  511. X
  512. X    for(i = 0; i < (nhops - 1); i++) {
  513. X        b = hop[i];
  514. X        if(*b == '\0') {
  515. X            continue;
  516. X        }
  517. X        e = hop[i+1];
  518. X        e-- ;
  519. X        *e = '\0';    /* null terminate each path segment */
  520. X        e++;
  521. X
  522. X#ifdef HIDDENHOSTS
  523. X/*
  524. X**  Strip hidden hosts:  anything.hostname.MYDOM -> hostname.MYDOM
  525. X*/
  526. X        for(p = b;(p = index(p, '.')) != NULL; p++) {
  527. X            if(strcmpic(hostdomain, p+1) == 0) {
  528. X                (void) strcpy(b, hostdomain);
  529. X                break;
  530. X            }
  531. X        }
  532. X#endif
  533. X
  534. X/*
  535. X**  Strip useless MYDOM: hostname.MYDOM -> hostname
  536. X*/
  537. X        if(strcmpic(hop[i], hostdomain) == 0) {
  538. X            (void) strcpy(hop[i], hostname);
  539. X        }
  540. X    }
  541. X
  542. X/*
  543. X**  Now strip out any redundant information in the From_ line
  544. X**  a!b!c!c!d    => a!b!c!d
  545. X*/
  546. X
  547. X    for(i = 0; i < (nhops - 2); i++) {
  548. X        b = hop[i];
  549. X        e = hop[i+1];
  550. X        if(strcmpic(b, e) == 0) {
  551. X            *b = '\0';
  552. X        }
  553. X    }
  554. X/*
  555. X**  Reconstruct the From_ line
  556. X*/
  557. X    tmp[0] = '\0';            /* empty the tmp buffer */
  558. X
  559. X    for(i = 0; i < (nhops - 1); i++) {
  560. X        if((hop[i][0] == '\0')    /* deleted this hop */
  561. X         ||((tmp[0] == '\0')    /* first hop == hostname */
  562. X          &&(strcmpic(hop[i], hostname) == 0))) {
  563. X            continue;
  564. X        }
  565. X        (void) strcat(tmp, hop[i]);
  566. X        (void) strcat(tmp, "!");
  567. X    }
  568. X    (void) strcat(tmp, hop[i]);
  569. X    (void) strcpy(from, tmp);
  570. X    (void) strcpy(retbuf, buf);
  571. X    (void) fprintf(spoolfp, "%s\n", from);
  572. X}
  573. X
  574. Xvoid
  575. Xscanheaders(buf)
  576. Xchar *buf;
  577. X{
  578. X    int inheader = 0;
  579. X
  580. X    while(ieof != NULL) {
  581. X        if(buf[0] == '\n') {
  582. X            break; /* end of headers */
  583. X        }
  584. X
  585. X        /*
  586. X        ** header lines which begin with whitespace
  587. X        ** are continuation lines
  588. X        */
  589. X        if((inheader == 0)
  590. X        || ((buf[0] != ' ' && buf[0] != '\t'))) {
  591. X            /* not a continuation line
  592. X            ** check for header
  593. X            */
  594. X            if(isheader(buf) == 0) {
  595. X                /*
  596. X                ** not a header
  597. X                */
  598. X                break;
  599. X            }
  600. X            inheader = 1;
  601. X            haveheaders(buf);
  602. X        }
  603. X        (void) fputs(buf, spoolfp);
  604. X        if((fgets(buf, SMLBUF, stdin) == NULL)
  605. X        || (buf[0] == '.' && buf[1] == '\n')) {
  606. X            ieof = NULL;
  607. X        }
  608. X    }
  609. X
  610. X    if(isheader(buf)) {
  611. X        buf[0] = '\0';
  612. X    }
  613. X}
  614. X
  615. X/*
  616. X** complete headers - add any required headers that are not in the message
  617. X*/
  618. Xvoid
  619. Xcompheaders()
  620. X{
  621. X    struct reqheaders *i;
  622. X
  623. X    /*
  624. X    ** look at the table of required headers and
  625. X    ** add those that are missing to the spooled message.
  626. X    */
  627. X    for(i = reqtab; i->name != NULL; i++) {
  628. X        if(i->have != 'Y') {
  629. X            (void) fprintf(spoolfp, "%s\n", i->field);
  630. X        }
  631. X    }
  632. X}
  633. X
  634. X/*
  635. X** look at a string and determine
  636. X** whether or not it is a valid header.
  637. X*/
  638. Xisheader(s)
  639. Xchar *s;
  640. X{
  641. X    char *p;
  642. X
  643. X    /*
  644. X    ** header field names must terminate with a colon
  645. X    ** and may not be null.
  646. X    */
  647. X    if(((p = index(s, ':')) == NULL) || (s == p)) {
  648. X        return(0);
  649. X
  650. X    }
  651. X    /*
  652. X    ** header field names must consist entirely of
  653. X    ** printable ascii characters.
  654. X    */
  655. X    while(s != p) {
  656. X        if((*s < '!') || (*s > '~')) {
  657. X            return(0);
  658. X        }
  659. X        s++;
  660. X    }
  661. X    /*
  662. X    ** we hit the ':', so the field may be a header
  663. X    */
  664. X    return(1);
  665. X}
  666. X
  667. X/*
  668. X** compare the header field to those in the required header table.
  669. X** if it matches, then mark the required header as being present
  670. X** in the message.
  671. X*/
  672. Xhaveheaders(s)
  673. Xchar *s;
  674. X{
  675. X    struct reqheaders *i;
  676. X
  677. X    for(i = reqtab; i->name != NULL; i++) {
  678. X        if(strncmpic(i->name, s, strlen(i->name)) == 0) {
  679. X            if((strncmpic("From:", s, 5) == 0)
  680. X            && (from_addr != NULL)) {
  681. X                (void) sprintf(s, "From: %s\n", from_addr);
  682. X            }
  683. X            i->have = 'Y';
  684. X            break;
  685. X        }
  686. X    }
  687. X}
  688. X
  689. X/*
  690. X** create default headers for the message.
  691. X*/
  692. Xdef_headers(argc, argv, from)
  693. Xint argc;
  694. Xchar **argv;
  695. Xchar *from;
  696. X{
  697. X    def_to(argc, argv);    /* default To:        */
  698. X    def_date();        /* default Date:    */
  699. X    def_from(from);        /* default From:     */
  700. X    def_mid();        /* default Message-Id:    */
  701. X}
  702. X
  703. X/*
  704. X** default Date: in arpa format
  705. X*/
  706. Xdef_date()
  707. X{
  708. X    (void) strcpy(dateline, "Date: ");
  709. X    (void) strcat(dateline, arpanows);
  710. X}
  711. X
  712. X/*
  713. X** default Message-Id
  714. X**  Message-Id: <yymmddhhmm.AAppppp@hostdomain>
  715. X**
  716. X**    yy     year
  717. X**    mm     month
  718. X**    dd     day
  719. X**    hh     hour
  720. X**    mm     minute
  721. X**    ppppp    process-id
  722. X**
  723. X** date and time are set by GMT
  724. X*/
  725. Xdef_mid()
  726. X{
  727. X    (void) sprintf(midline, "Message-Id: <%02d%02d%02d%02d%02d.AA%05d@%s>",
  728. X        gmt->tm_year,
  729. X        gmt->tm_mon+1,
  730. X        gmt->tm_mday,
  731. X        gmt->tm_hour,
  732. X        gmt->tm_min,
  733. X        getpid(),
  734. X        hostdomain);
  735. X}
  736. X
  737. X/*
  738. X** default From:
  739. X**  From: user@hostdomain (Full Name)
  740. X*/
  741. Xdef_from(from)
  742. Xchar *from;
  743. X{
  744. X
  745. X    char *nameptr;
  746. X    char name[SMLBUF];
  747. X    char *getenv(), *login;
  748. X    char *pwfnam(), *pwuid();
  749. X
  750. X    if (from_addr != NULL) {
  751. X        (void) sprintf(fromline, "From: %s", from_addr);
  752. X        return;
  753. X    }
  754. X
  755. X    name[0] = '\0';
  756. X    if((nameptr = getenv("NAME")) != NULL) {
  757. X        (void) strcpy(name, nameptr);
  758. X    } else if((login = pwuid(getuid())) != NULL) {
  759. X        if((nameptr = pwfnam(login)) != NULL) {
  760. X            (void) strcpy(name, nameptr);
  761. X        }
  762. X    }
  763. X    if(name[0] != '\0') {
  764. X        (void) sprintf(fromline,
  765. X            "From: %s@%s (%s)", from, hostdomain, name);
  766. X    } else {
  767. X        (void) sprintf(fromline,
  768. X            "From: %s@%s", from, hostdomain);
  769. X    }
  770. X}
  771. X
  772. X/*
  773. X** default To:
  774. X**  To: recip1, recip2, ...
  775. X**
  776. X** lines longer than 50 chars are continued on another line.
  777. X*/
  778. Xdef_to(argc, argv)
  779. Xint argc;
  780. Xchar **argv;
  781. X{
  782. X    int i, n;
  783. X    char *bol;
  784. X
  785. X    bol = toline;
  786. X    (void) strcpy(bol, "To: ");
  787. X    for(n = i = 0; i < argc; i++) {
  788. X        (void) strcat(bol, argv[i]);
  789. X
  790. X        if((index(argv[i], '!') == NULL)
  791. X        && (index(argv[i], '@') == NULL)) {
  792. X            (void) strcat(bol, "@");
  793. X            (void) strcat(bol, hostdomain);
  794. X        }
  795. X        if(i+1 < argc) {
  796. X            n = strlen(bol);
  797. X            if(n > 50) {
  798. X                (void) strcat(bol, ",\n\t");
  799. X                bol = bol + strlen(bol);
  800. X                *bol = '\0';
  801. X                n = 8;
  802. X            } else {
  803. X                (void) strcat(bol, ", ");
  804. X            }
  805. X        }
  806. X    }
  807. X}
  808. END_OF_FILE
  809. if test 15935 -ne `wc -c <'mailer/headers.c'`; then
  810.     echo shar: \"'mailer/headers.c'\" unpacked with wrong size!
  811. fi
  812. # end of 'mailer/headers.c'
  813. fi
  814. echo shar: End of archive 8 \(of 8\).
  815. cp /dev/null ark8isdone
  816. MISSING=""
  817. for I in 1 2 3 4 5 6 7 8 ; do
  818.     if test ! -f ark${I}isdone ; then
  819.     MISSING="${MISSING} ${I}"
  820.     fi
  821. done
  822. if test "${MISSING}" = "" ; then
  823.     echo You have unpacked all 8 archives.
  824.     rm -f ark[1-9]isdone
  825. else
  826.     echo You still need to unpack the following archives:
  827.     echo "        " ${MISSING}
  828. fi
  829. ##  End of shell archive.
  830. exit 0
  831.