home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume22 / elm2.3 / part20 < prev    next >
Text File  |  1990-06-07  |  50KB  |  1,653 lines

  1. Subject:  v22i079:  ELM mail syste, release 2.3, Part20/26
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 0c97a24b 2f9763ff a2721b13 d88922bd
  5.  
  6. Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
  7. Posting-number: Volume 22, Issue 79
  8. Archive-name: elm2.3/part20
  9.  
  10. #!/bin/sh
  11. # this is part 20 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file src/read_rc.c continued
  14. #
  15. CurArch=20
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file src/read_rc.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> src/read_rc.c
  27. X\n\rdirectory to store your elmrc and alias files. Shall I create the\
  28. X\n\rdirectory .elm for you and set it up (y/n)? y%c",BACKSPACE);
  29. X
  30. X      fflush(stdout);
  31. X      ch=getchar();
  32. X      if (ch == 'n' || ch == 'N') {
  33. X        printf("No.\n\rVery well. I won't create it.\
  34. X        \n\rBut, you may run into difficulties later.\n\r");
  35. X        sleep(4);
  36. X      }
  37. X      else {
  38. X        printf("Yes.\n\rGreat! I'll do it now.\n\r");
  39. X        create_new_elmdir();
  40. X      }
  41. X    }
  42. X
  43. X    /* Look for the elmrc file */
  44. X    sprintf(filename,"%s/%s", home, elmrcfile);
  45. X    if ((file = fopen(filename, "r")) == NULL) {
  46. X      dprint(2,(debugfile,"Warning:User has no \".elm/elmrc\" file\n\n"));
  47. X
  48. X      /* look for old-style .elmrc file in $HOME */
  49. X      sprintf(filename, "%s/.elmrc", home);
  50. X      if (access(filename, 00) != -1) {
  51. X        move_old_files_to_new();
  52. X
  53. X        /* try to open elmrc file again */
  54. X        sprintf(filename,"%s/%s", home, elmrcfile);
  55. X        if((file = fopen(filename, "r")) == NULL) {
  56. X          dprint(2, (debugfile,
  57. X        "Warning: could not open new \".elm/elmrc\" file.\n"));
  58. X          dprint(2, (debugfile, "** %s - %s **\n", error_name(errno), 
  59. X           error_description(errno)));
  60. X          printf("Warning: could not open new \".elm/elmrc\" file!");
  61. X          printf(" Using default parameters.\n\r");
  62. X          sleep(4);
  63. X        }
  64. X      }
  65. X    }
  66. X
  67. X    if(file) {
  68. X      int   last = ASSIGNMENT, this;
  69. X
  70. X      while (fgets(buffer, SLEN, file) != NULL) {
  71. X        lineno++;
  72. X        no_ret(buffer);         /* remove return */
  73. X        if (buffer[0] == '#'        /* comment       */
  74. X         || strlen(buffer) < 2)     /* empty line    */
  75. X          continue;
  76. X
  77. X        this = ASSIGNMENT;
  78. X
  79. X        if(breakup(buffer, word1, word2) == -1)
  80. X          continue;        /* word2 is null - let default value stand */
  81. X
  82. X        strcpy(word1, shift_lower(word1));    /* to lower case */
  83. X
  84. X        if (equal(word1,"maildir") || equal(word1,"folders")) {
  85. X          strcpy(raw_folders, word2);
  86. X          expand_env(folders, word2);
  87. X        }
  88. X        else if (equal(word1,"tmpdir")) {
  89. X          expand_env(temp_dir, word2);
  90. X          if (temp_dir[strlen (temp_dir)-1] != '/')
  91. X                strcat(temp_dir, "/");
  92. X        }
  93. X        else if (equal(word1, "fullname") || equal(word1,"username") ||
  94. X             equal(word1, "name")) {
  95. X          strcpy(full_username, word2);
  96. X        }
  97. X        else if (equal(word1, "prefix")) {
  98. X          for (i=0, len = strlen(word2); i < len; i++)
  99. X        prefixchars[i] = (word2[i] == '_' ? ' ' : word2[i]);
  100. X          prefixchars[i] = '\0';
  101. X        }
  102. X        else if (equal(word1, "shell")) {
  103. X          strcpy(raw_shell, word2);
  104. X          expand_env(shell, word2);
  105. X        }
  106. X        else if (equal(word1, "sort") || equal(word1, "sortby")) {
  107. X          strcpy(word2, shift_lower(word2));
  108. X          if (equal(word2, "sent"))
  109. X         sortby = SENT_DATE;
  110. X          else if (equal(word2, "received") || equal(word2,"recieved"))
  111. X         sortby = RECEIVED_DATE;
  112. X          else if (equal(word2, "from") || equal(word2, "sender"))
  113. X         sortby = SENDER;
  114. X          else if (equal(word2, "size") || equal(word2, "lines"))
  115. X        sortby = SIZE;
  116. X          else if (equal(word2, "subject"))
  117. X        sortby = SUBJECT;
  118. X          else if (equal(word2, "mailbox") || equal(word2, "folder"))
  119. X        sortby = MAILBOX_ORDER;
  120. X          else if (equal(word2, "status"))
  121. X        sortby = STATUS;
  122. X          else if (equal(word2, "reverse-sent") || equal(word2,"rev-sent"))
  123. X         sortby = - SENT_DATE;
  124. X          else if (strncmp(word2, "reverse-rec",11) == 0 || 
  125. X               strncmp(word2,"rev-rec",7) == 0)
  126. X         sortby = - RECEIVED_DATE;
  127. X          else if (equal(word2, "reverse-from") || equal(word2, "rev-from")
  128. X            || equal(word2,"reverse-sender")||equal(word2,"rev-sender"))
  129. X         sortby = - SENDER;
  130. X          else if (equal(word2, "reverse-size") || equal(word2, "rev-size")
  131. X            || equal(word2, "reverse-lines")|| equal(word2,"rev-lines"))
  132. X        sortby = - SIZE;
  133. X          else if (equal(word2, "reverse-subject") || 
  134. X               equal(word2, "rev-subject"))
  135. X        sortby = - SUBJECT;
  136. X          else if (equal(word2, "reverse-mailbox") || 
  137. X               equal(word2, "rev-mailbox") ||
  138. X               equal(word2, "reverse-folder") || 
  139. X               equal(word2, "rev-folder"))
  140. X        sortby = - MAILBOX_ORDER;
  141. X          else if (equal(word2, "reverse-status") || 
  142. X               equal(word2, "rev-status"))
  143. X        sortby = - STATUS;
  144. X          else {
  145. X        errors++;
  146. X        printf(
  147. X      "I can't understand sort key %s in line %d in your \".elm/elmrc\" file\n",
  148. X             word2, lineno);
  149. X            continue;
  150. X          }
  151. X        }
  152. X        else if (equal (word1, "receivedmail") || equal(word1, "mailbox")) {
  153. X          /* the last is an old name of this option - here for
  154. X           * compatibility in case the user has never written out
  155. X           * a new elmrc while in elm since the name change.
  156. X           */
  157. X          rc_has_recvdmail = TRUE;
  158. X          strcpy(raw_recvdmail, word2);
  159. X          expand_env(recvd_mail, word2);
  160. X        }
  161. X        else if (equal(word1, "editor") || equal(word1,"mailedit")) {
  162. X          strcpy(raw_editor, word2);
  163. X          expand_env(editor, word2);
  164. X        }
  165. X        else if (equal(word1, "sentmail") ||
  166. X        equal(word1, "savemail") || equal(word1, "saveto")) {
  167. X          /* the last two were old names of this option - here for
  168. X           * compatibility in case the user has never written out
  169. X           * a new elmrc while in elm since the name change.
  170. X           */
  171. X          rc_has_sentmail = TRUE;
  172. X          strcpy(raw_sentmail, word2);
  173. X          expand_env(sent_mail, word2);
  174. X        }
  175. X        else if (equal(word1, "calendar")) {
  176. X          strcpy(raw_calendar_file, word2);
  177. X          expand_env(calendar_file, word2);
  178. X        }
  179. X        else if (equal(word1, "print") || equal(word1, "printmail")) {
  180. X          strcpy(raw_printout, word2);
  181. X          expand_env(printout, word2);
  182. X        }
  183. X        else if (equal(word1, "pager") || equal(word1, "page")) {
  184. X          strcpy(raw_pager, word2);
  185. X          expand_env(pager, word2);
  186. X          if (equal(pager,"builtin+") || equal(pager,"internal+"))
  187. X        clear_pages++;
  188. X        }
  189. X        else if (equal(word1, "signature")) {
  190. X          if (equal(shift_lower(word2), "on") ||
  191. X          equal(shift_lower(word2), "off")) {
  192. X        errors++;
  193. X        printf(
  194. X    "\"signature\" used in obsolete way in .elm/elmrc file. Ignored!\n\r");
  195. X        printf(
  196. X "\t(Signature should specify the filename to use rather than on/off.)\n\r\n");
  197. X          }
  198. X          else {
  199. X        strcpy(raw_local_signature, word2);
  200. X        strcpy(raw_remote_signature, raw_local_signature);
  201. X        expand_env(local_signature, word2);
  202. X        strcpy(remote_signature, local_signature);
  203. X          }
  204. X        }
  205. X        else if (equal(word1, "localsignature")) {
  206. X          strcpy(raw_local_signature, word2);
  207. X          expand_env(local_signature, word2);
  208. X        }
  209. X        else if (equal(word1, "remotesignature")) {
  210. X          strcpy(raw_remote_signature, word2);
  211. X          expand_env(remote_signature, word2);
  212. X        }
  213. X        else if (equal(word1, "sigdashes")) {
  214. X          sig_dashes = is_it_on(word2);
  215. X        }
  216. X        else if (equal(word1, "escape")) {
  217. X          escape_char = word2[0];
  218. X        }
  219. X        else if (equal(word1, "attribution")) {
  220. X          strcpy(attribution, word2);
  221. X        }
  222. X        else if (equal(word1, "autocopy")) {
  223. X          auto_copy = is_it_on(word2);
  224. X        }
  225. X        else if (equal(word1, "copy") || equal(word1, "auto_cc")) {
  226. X          auto_cc = is_it_on(word2);
  227. X        }
  228. X        else if (equal(word1, "names")) {
  229. X          names_only = is_it_on(word2);
  230. X        }
  231. X        else if (equal(word1, "resolve")) {
  232. X          resolve_mode = is_it_on(word2);
  233. X        }
  234. X        else if (equal(word1, "weed")) {
  235. X          filter = is_it_on(word2);
  236. X        }
  237. X        else if (equal(word1, "noheader")) {
  238. X          noheader = is_it_on(word2);
  239. X        }
  240. X        else if (equal(word1, "titles")) {
  241. X          title_messages = is_it_on(word2);
  242. X        }
  243. X        else if (equal(word1, "savebyname") || equal(word1, "savename")) {
  244. X          save_by_name = is_it_on(word2);
  245. X        }
  246. X        else if (equal(word1, "forcename")) {
  247. X          force_name = is_it_on(word2);
  248. X        }
  249. X        else if (equal(word1, "movepage") || equal(word1, "page") ||
  250. X             equal(word1, "movewhenpaged")) {
  251. X          move_when_paged = is_it_on(word2);
  252. X        }
  253. X        else if (equal(word1, "pointnew") || equal(word1, "pointtonew")) {
  254. X          point_to_new = is_it_on(word2);
  255. X        }
  256. X        else if (equal(word1, "keypad") || equal(word1, "hpkeypad")) {
  257. X          hp_terminal = is_it_on(word2);
  258. X        }
  259. X        else if (equal(word1, "softkeys") || equal(word1, "hpsoftkeys")) {
  260. X          if (hp_softkeys = is_it_on(word2))
  261. X        hp_terminal = TRUE;    /* must be set also! */
  262. X        }
  263. X        else if (equal(word1, "arrow")) {
  264. X          arrow_cursor += is_it_on(word2);    /* may have been set already */
  265. X        }
  266. X        else if (strncmp(word1, "form", 4) == 0) {
  267. X          allow_forms = (is_it_on(word2)? MAYBE : NO);
  268. X        }
  269. X        else if (equal(word1, "promptafter")) {
  270. X          prompt_after_pager = is_it_on(word2);
  271. X        }
  272. X        else if (strncmp(word1, "menu", 4) == 0) {
  273. X          /* if not turned off by -m cmd line arg,
  274. X           * obey elmrc file setting */
  275. X          if(mini_menu)
  276. X        mini_menu = is_it_on(word2);
  277. X        }
  278. X        else if (strncmp(word1, "warning", 7) == 0) {
  279. X          warnings = is_it_on(word2);
  280. X        }
  281. X        else if (equal(word1, "alwaysleave")) {
  282. X          /* this is an old option - here for
  283. X           * compatibility in case the user has never written out
  284. X           * a new elmrc while in elm since the split of
  285. X           * alwaysleave into alwayskeep and alwaysstore
  286. X           */
  287. X          always_keep = is_it_on(word2);
  288. X          always_store = !is_it_on(word2);
  289. X        }
  290. X        else if (equal(word1, "alwayskeep")) {
  291. X          always_keep = is_it_on(word2);
  292. X        }
  293. X        else if (equal(word1, "alwaysstore") || equal(word1, "store")) {
  294. X          always_store = is_it_on(word2);
  295. X        }
  296. X        else if (equal(word1, "alwaysdelete") || equal(word1, "delete")) {
  297. X          always_del = is_it_on(word2);
  298. X        }
  299. X        else if (equal(word1, "askcc") || equal(word1, "cc")) {
  300. X          prompt_for_cc = is_it_on(word2);
  301. X        }
  302. X        else if (equal(word1, "ask") || equal(word1, "question")) {
  303. X          question_me = is_it_on(word2);
  304. X        }
  305. X        else if (equal(word1, "keep") || equal(word1, "keepempty")) {
  306. X          keep_empty_files = is_it_on(word2);
  307. X        }
  308. X        else if (equal(word1, "bounce") || equal(word1, "bounceback")) {
  309. X          bounceback = atoi(word2);
  310. X          if (bounceback > MAX_HOPS) {
  311. X        errors++;
  312. X        printf(
  313. X    "Warning: bounceback is set to greater than %d (max-hops). Ignored.\n",
  314. X             MAX_HOPS);
  315. X        bounceback = 0;
  316. X          }
  317. X        }
  318. X        else if (equal(word1, "userlevel")) {
  319. X          user_level = atoi(word2);
  320. X        }
  321. X        else if (equal(word1, "timeout")) {
  322. X          timeout = atoi(word2);
  323. X          if (timeout < 10) {
  324. X        errors++;
  325. X        printf(
  326. X         "Warning: timeout is set to less than 10 seconds. Ignored.\n");
  327. X        timeout = 0;
  328. X          }
  329. X        }
  330. X        else if (equal(word1, "weedout")) {
  331. X          weedout(word2);
  332. X          this = WEEDOUT;
  333. X        }
  334. X        else if (equal(word1, "alternatives")) {
  335. X          alternatives(word2);
  336. X          this = ALTERNATIVES;
  337. X        }
  338. X        else if (last == WEEDOUT) {
  339. X          weedout(buffer);
  340. X          this = WEEDOUT;
  341. X        }
  342. X        else if (last == ALTERNATIVES) {
  343. X          alternatives(buffer);
  344. X          this = ALTERNATIVES;
  345. X        }
  346. X        else {
  347. X          errors++;
  348. X          printf(
  349. X         "I can't understand line %d in your \".elm/elmrc\" file:\n> %s\n", 
  350. X             lineno, buffer);
  351. X        }
  352. X        last = this;
  353. X      }
  354. X      /* sleep two seconds for each error and then some so user
  355. X       * can read them before screen is cleared */
  356. X      if(errors)
  357. X        sleep((errors * 2) + 2);
  358. X    }
  359. X
  360. X    /* see if the user has a folders directory */
  361. X    if (access(folders, 00) == -1) {
  362. X      if(batch_only)  {
  363. X        printf("\n\rNotice:\
  364. X\n\rELM requires the use of a folders directory to store your mail folders in.\
  365. X\n\rI'd like to create the directory %s for you,\
  366. X\n\rbut I can't in \"batch mode\". Please run ELM in \"normal mode\" first.\
  367. X\n\r", folders);
  368. X        exit(0);
  369. X      }
  370. X
  371. X      printf("\n\rNotice:\
  372. X\n\rELM requires the use of a folders directory to store your mail folders in.\
  373. X\n\rShall I create the directory %s for you (y/n)? y%c", folders, BACKSPACE);
  374. X
  375. X      fflush(stdout);
  376. X      ch=getchar();
  377. X      if (ch == 'n' || ch == 'N') {
  378. X        printf("No.\n\rVery well. I won't create it.\
  379. X        \n\rBut, you may run into difficulties later.\n\r");
  380. X        sleep(4);
  381. X      }
  382. X      else {
  383. X        printf("Yes.\n\rGreat! I'll do it now.\n\r");
  384. X        create_new_folders();
  385. X      }
  386. X    }
  387. X
  388. X    /* If recvd_mail or sent_mail havent't yet been established in
  389. X     * the elmrc, establish them from their defaults.
  390. X     * Then if they begin with a metacharacter, replace it with the
  391. X     * folders directory name.
  392. X     */
  393. X    if(!rc_has_recvdmail) {
  394. X      strcpy(raw_recvdmail, default_recvdmail);
  395. X      strcpy(recvd_mail, raw_recvdmail);
  396. X    }
  397. X    if(metachar(recvd_mail[0])) {
  398. X      strcpy(buffer, &recvd_mail[1]);
  399. X      sprintf(recvd_mail, "%s/%s", folders, buffer);
  400. X    }
  401. X
  402. X    if(!rc_has_sentmail) {
  403. X      sprintf(raw_sentmail, default_sentmail);
  404. X      sprintf(sent_mail, default_sentmail);
  405. X    }
  406. X    if(metachar(sent_mail[0])) {
  407. X      strcpy(buffer, &sent_mail[1]);
  408. X      sprintf(sent_mail, "%s/%s", folders, buffer);
  409. X    }
  410. X
  411. X    if (debug > 10)     /** only do this if we REALLY want debug! **/
  412. X      dump_rc_results();
  413. X
  414. X}
  415. X    
  416. Xweedout(string)
  417. Xchar *string;
  418. X{
  419. X    /** This routine is called with a list of headers to weed out.   **/
  420. X
  421. X    char *strptr, *header;
  422. X    register int i, len;
  423. X
  424. X    strptr = string;
  425. X
  426. X    while ((header = strtok(strptr, "\t ,\"'")) != NULL) {
  427. X      if (strlen(header) > 0) {
  428. X        if (! strcmp(header, "*end-of-user-headers*")) break;
  429. X        if (weedcount > MAX_IN_WEEDLIST) {
  430. X          printf("Too many weed headers!  Leaving...\n");
  431. X          exit(1);
  432. X        }
  433. X        if ((weedlist[weedcount] = pmalloc(strlen(header) + 1)) 
  434. X        == NULL) {
  435. X          printf("Too many weed headers! Out of memory!  Leaving...\n");
  436. X          exit(1);
  437. X        }
  438. X
  439. X        for (i=0, len = strlen(header); i< len; i++)
  440. X          if (header[i] == '_') header[i] = ' ';
  441. X
  442. X        strcpy(weedlist[weedcount], header);
  443. X        weedcount++;
  444. X      }
  445. X      strptr = NULL;
  446. X    }
  447. X}
  448. X
  449. Xalternatives(string)
  450. Xchar *string;
  451. X{
  452. X    /** This routine is called with a list of alternative addresses
  453. X        that you may receive mail from (forwarded) **/
  454. X
  455. X    char *strptr, *address;
  456. X    struct addr_rec *current_record, *previous_record;
  457. X
  458. X    previous_record = alternative_addresses;    /* start 'er up! */
  459. X    /* move to the END of the alternative addresses list */
  460. X
  461. X    if (previous_record != NULL)
  462. X      while (previous_record->next != NULL)
  463. X        previous_record = previous_record->next;
  464. X
  465. X    strptr = (char *) string;
  466. X
  467. X    while ((address = strtok(strptr, "\t ,\"'")) != NULL) {
  468. X      if (previous_record == NULL) {
  469. X        previous_record = (struct addr_rec *) pmalloc(sizeof 
  470. X        *alternative_addresses);
  471. X
  472. X        strcpy(previous_record->address, address);
  473. X        previous_record->next = NULL;
  474. X        alternative_addresses = previous_record;
  475. X      }
  476. X      else {
  477. X        current_record = (struct addr_rec *) pmalloc(sizeof 
  478. X        *alternative_addresses);
  479. X      
  480. X        strcpy(current_record->address, address);
  481. X        current_record->next = NULL;
  482. X        previous_record->next = current_record;
  483. X        previous_record = current_record;
  484. X      }
  485. X      strptr = (char *) NULL;
  486. X    }
  487. X}
  488. X
  489. Xdefault_weedlist()
  490. X{
  491. X    /** Install the default headers to weed out!  Many gracious 
  492. X        thanks to John Lebovitz for this dynamic method of 
  493. X        allocation!
  494. X    **/
  495. X
  496. X    static char *default_list[] = { ">From", "In-Reply-To:",
  497. X               "References:", "Newsgroups:", "Received:",
  498. X               "Apparently-To:", "Message-Id:", "Content-Type:",
  499. X               "From", "X-Mailer:", "Status:",
  500. X               "*end-of-defaults*", NULL
  501. X             };
  502. X
  503. X    for (weedcount = 0; default_list[weedcount] != (char *) 0;weedcount++){
  504. X      if ((weedlist[weedcount] = 
  505. X          pmalloc(strlen(default_list[weedcount]) + 1)) == NULL) {
  506. X        printf("\n\rNot enough memory for default weedlist. Leaving.\n\r");
  507. X        leave(1);
  508. X      }
  509. X      strcpy(weedlist[weedcount], default_list[weedcount]);
  510. X    }
  511. X}
  512. X
  513. Xint
  514. Xmatches_weedlist(buffer)
  515. Xchar *buffer;
  516. X{
  517. X    /** returns true iff the first 'n' characters of 'buffer' 
  518. X        match an entry of the weedlist **/
  519. X    
  520. X    register int i;
  521. X
  522. X    for (i=0;i < weedcount; i++)
  523. X      if (strncmp(buffer, weedlist[i], strlen(weedlist[i])) == 0) 
  524. X        return(1);
  525. X
  526. X    return(0);
  527. X}
  528. X
  529. Xint
  530. Xbreakup(buffer, word1, word2)
  531. Xchar *buffer, *word1, *word2;
  532. X{
  533. X    /** This routine breaks buffer down into word1, word2 where 
  534. X        word1 is alpha characters only, and there is an equal
  535. X        sign delimiting the two...
  536. X        alpha = beta
  537. X        For lines with more than one 'rhs', word2 is set to the
  538. X        entire string.
  539. X        Return -1 if word 2 is of zero length, else 0.
  540. X    **/
  541. X
  542. X    register int i;
  543. X    
  544. X    for (i=0;buffer[i] != '\0' && ok_rc_char(buffer[i]); i++)
  545. X      if (buffer[i] == '_')
  546. X        word1[i] = '-';
  547. X      else if (isupper(buffer[i]))
  548. X        word1[i] = tolower(buffer[i]);
  549. X      else
  550. X        word1[i] = buffer[i];
  551. X
  552. X    word1[i++] = '\0';    /* that's the first word! */
  553. X
  554. X    /** spaces before equal sign? **/
  555. X
  556. X    while (whitespace(buffer[i])) i++;
  557. X    if (buffer[i] == '=') i++;
  558. X
  559. X    /** spaces after equal sign? **/
  560. X
  561. X    while (whitespace(buffer[i])) i++;
  562. X
  563. X    if (buffer[i] != '\0')
  564. X      strcpy(word2, (char *) (buffer + i));
  565. X    else
  566. X      word2[0] = '\0';
  567. X
  568. X    /* remove trailing spaces from word2! */
  569. X    i = strlen(word2) - 1;
  570. X    while(i && (whitespace(word2[i]) || word2[i] == '\n'))
  571. X      word2[i--] = '\0';
  572. X
  573. X    return(*word2 == '\0' ? -1 : 0 );
  574. X
  575. X}
  576. X
  577. Xexpand_env(dest, buffer)
  578. Xchar *dest, *buffer;
  579. X{
  580. X    /** expand possible metacharacters in buffer and then copy
  581. X        to dest... 
  582. X
  583. X        BEWARE!! Because strtok() is used on buffer, buffer may be changed.
  584. X
  585. X        This routine knows about "~" being the home directory,
  586. X        and "$xxx" being an environment variable.
  587. X    **/
  588. X
  589. X    char  *word, *string, next_word[SLEN];
  590. X    
  591. X    if (buffer[0] == '/') {
  592. X      dest[0] = '/';
  593. X      dest[1] = '\0';
  594. X    }
  595. X    else
  596. X      dest[0] = '\0';
  597. X
  598. X    string = (char *) buffer;
  599. X
  600. X    while ((word = strtok(string, "/")) != NULL) {
  601. X      if (word[0] == '$') {
  602. X        next_word[0] = '\0';
  603. X        if (getenv((char *) (word + 1)) != NULL)
  604. X        strcpy(next_word, getenv((char *) (word + 1)));
  605. X        if (strlen(next_word) == 0)
  606. X          leave(printf("\n\rCan't expand environment variable '%s'.\n\r",
  607. X            word));
  608. X      }
  609. X      else if (word[0] == '~' && word[1] == '\0')
  610. X        strcpy(next_word, home);
  611. X      else
  612. X        strcpy(next_word, word);
  613. X
  614. X      sprintf(dest, "%s%s%s", dest, 
  615. X         (strlen(dest) > 0 && lastch(dest) != '/' ? "/":""),
  616. X         next_word);
  617. X
  618. X      string = (char *) NULL;
  619. X    }
  620. X}
  621. X
  622. X#define on_off(s)    (s == 1? "ON " : "OFF")
  623. Xdump_rc_results()
  624. X{
  625. X
  626. X    register int i, len;
  627. X
  628. X    fprintf(debugfile, "folders = %s ", folders);
  629. X    fprintf(debugfile, "temp_dir = %s ", temp_dir);
  630. X    fprintf(debugfile, "recvd_mail = %s ", recvd_mail);
  631. X    fprintf(debugfile, "editor = %s\n", editor);
  632. X    fprintf(debugfile, "printout = %s ", printout);
  633. X    fprintf(debugfile, "sent_mail = %s ", sent_mail);
  634. X    fprintf(debugfile, "calendar_file = %s\n", calendar_file);
  635. X    fprintf(debugfile, "prefixchars = %s ", prefixchars);
  636. X    fprintf(debugfile, "shell = %s ", shell);
  637. X    fprintf(debugfile, "pager = %s\n", pager);
  638. X    fprintf(debugfile, "\n");
  639. X    fprintf(debugfile, "escape = %c\n", escape_char);
  640. X    fprintf(debugfile, "\n");
  641. X
  642. X    fprintf(debugfile, "mini_menu    = %s ", on_off(mini_menu));
  643. X    fprintf(debugfile, "filter_hdrs  = %s ", on_off(filter));
  644. X    fprintf(debugfile, "auto_copy      = %s\n", on_off(auto_copy));
  645. X
  646. X    fprintf(debugfile, "resolve_mode   = %s ", on_off(resolve_mode));
  647. X    fprintf(debugfile, "auto_save_copy = %s ", on_off(auto_cc));
  648. X    fprintf(debugfile, "noheader     = %s\n", on_off(noheader));
  649. X
  650. X    fprintf(debugfile, "title_msgs   = %s ", on_off(title_messages));
  651. X    fprintf(debugfile, "hp_terminal    = %s ", on_off(hp_terminal));
  652. X    fprintf(debugfile, "hp_softkeys    = %s\n", on_off(hp_softkeys));
  653. X
  654. X    fprintf(debugfile, "save_by_name = %s ", on_off(save_by_name));
  655. X    fprintf(debugfile, "force_name = %s\n", on_off(force_name));
  656. X
  657. X    fprintf(debugfile, "move_paged   = %s ", on_off(move_when_paged));
  658. X    fprintf(debugfile, "point_to_new   = %s ", on_off(point_to_new));
  659. X    fprintf(debugfile, "prompt_after_pager   = %s ",
  660. X        on_off(prompt_after_pager));
  661. X    fprintf(debugfile, "bounceback     = %s\n", on_off(bounceback));
  662. X
  663. X    fprintf(debugfile, "always_keep = %s ", on_off(always_keep));
  664. X    fprintf(debugfile, "always_store = %s ", on_off(always_store));
  665. X    fprintf(debugfile, "always_delete  = %s ", on_off(always_del));
  666. X    fprintf(debugfile, "arrow_cursor   = %s ", on_off(arrow_cursor));
  667. X    fprintf(debugfile, "names        = %s\n", on_off(names_only));
  668. X
  669. X    fprintf(debugfile, "warnings     = %s ", on_off(warnings));
  670. X    fprintf(debugfile, "question_me    = %s ", on_off(question_me));
  671. X    fprintf(debugfile, "keep_nil_files = %s\n\n", 
  672. X               on_off(keep_empty_files));
  673. X
  674. X    fprintf(debugfile, "local_signature  = %s\n", local_signature);
  675. X    fprintf(debugfile, "remote_signature = %s\n", remote_signature);
  676. X    fprintf(debugfile, "sig_dashes = %s\n", on_off(sig_dashes));
  677. X
  678. X    fprintf(debugfile, "Userlevel is set to %s user: %d\n", 
  679. X        user_level == 0 ? "beginning" : 
  680. X         user_level > 1 ? "expert" : "intermediate", user_level);
  681. X
  682. X    fprintf(debugfile, "\nAnd we're skipping the following headers:\n\t");
  683. X
  684. X    for (len=8, i=0; i < weedcount; i++) {
  685. X      if (weedlist[i][0] == '*') continue;    /* skip '*end-of-defaults*' */
  686. X      if (len + strlen(weedlist[i]) > 80) {
  687. X        fprintf(debugfile, " \n\t");
  688. X        len = 8;
  689. X      }
  690. X      fprintf(debugfile, "%s  ", weedlist[i]);
  691. X      len += strlen(weedlist[i]) + 3;
  692. X    }
  693. X    
  694. X    fprintf(debugfile, "\n\n");
  695. X}
  696. X
  697. Xis_it_on(word)
  698. Xchar *word;
  699. X{
  700. X    /** Returns TRUE if the specified word is either 'ON', 'YES'
  701. X        or 'TRUE', and FALSE otherwise.   We explicitly translate
  702. X        to lowercase here to ensure that we have the fastest
  703. X        routine possible - we really DON'T want to have this take
  704. X        a long time or our startup will be major pain each time.
  705. X    **/
  706. X
  707. X    static char mybuffer[NLEN];
  708. X    register int i, j;
  709. X
  710. X    for (i=0, j=0; word[i] != '\0'; i++)
  711. X      mybuffer[j++] = isupper(word[i]) ? tolower(word[i]) : word[i];
  712. X    mybuffer[j] = '\0';
  713. X
  714. X    return(  (strncmp(mybuffer, "on",   2) == 0) ||
  715. X         (strncmp(mybuffer, "yes",  3) == 0) ||
  716. X         (strncmp(mybuffer, "true", 4) == 0)
  717. X          );
  718. X}
  719. SHAR_EOF
  720. echo "File src/read_rc.c is complete"
  721. chmod 0444 src/read_rc.c || echo "restore of src/read_rc.c fails"
  722. echo "x - extracting src/remail.c (Text)"
  723. sed 's/^X//' << 'SHAR_EOF' > src/remail.c &&
  724. X
  725. Xstatic char rcsid[] = "@(#)$Id: remail.c,v 4.1 90/04/28 22:43:50 syd Exp $";
  726. X
  727. X/*******************************************************************************
  728. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  729. X *
  730. X *             Copyright (c) 1986, 1987 Dave Taylor
  731. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  732. X *******************************************************************************
  733. X * Bug reports, patches, comments, suggestions should be sent to:
  734. X *
  735. X *    Syd Weinstein, Elm Coordinator
  736. X *    elm@DSI.COM            dsinc!elm
  737. X *
  738. X *******************************************************************************
  739. X * $Log:    remail.c,v $
  740. X * Revision 4.1  90/04/28  22:43:50  syd
  741. X * checkin of Elm 2.3 as of Release PL0
  742. X * 
  743. X *
  744. X ******************************************************************************/
  745. X
  746. X/** For those cases when you want to have a message continue along
  747. X    to another person in such a way as they end up receiving it with
  748. X    the return address the person YOU received the mail from (does
  749. X    this comment make any sense yet??)...
  750. X
  751. X**/
  752. X
  753. X#include "headers.h"
  754. X#include <errno.h>
  755. X
  756. Xextern int errno;
  757. X
  758. Xchar *error_name(), *error_description();
  759. X
  760. Xint
  761. Xremail()
  762. X{
  763. X    /** remail a message... returns TRUE if new foot needed ... **/
  764. X    
  765. X    FILE *mailfd;
  766. X    char entered[VERY_LONG_STRING], expanded[VERY_LONG_STRING];
  767. X    char *filename, buffer[VERY_LONG_STRING], ch;
  768. X    extern char *tempnam();
  769. X
  770. X    entered[0] = '\0';
  771. X
  772. X    get_to(entered, expanded);
  773. X    if (strlen(entered) == 0)
  774. X      return(0);
  775. X
  776. X    display_to(expanded);
  777. X
  778. X    if((filename=tempnam(temp_dir, "snd.")) == NULL) {
  779. X      dprint(1, (debugfile, "couldn't make temp file nam! (remail)\n"));
  780. X      sprintf(buffer, "Sorry - couldn't make file temp file name.");
  781. X      set_error(buffer);
  782. X      return(1);
  783. X    }
  784. X
  785. X    if ((mailfd = fopen(filename, "w")) == NULL) {
  786. X      dprint(1, (debugfile, "couldn't open temp file %s! (remail)\n", 
  787. X          filename));
  788. X      dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
  789. X          error_description(errno)));
  790. X      sprintf(buffer, "Sorry - couldn't open file %s for writing (%s).",
  791. X          error_name(errno));
  792. X      set_error(buffer);
  793. X      return(1);
  794. X    }
  795. X
  796. X    /** now let's copy the message into the newly opened
  797. X        buffer... **/
  798. X
  799. X    chown (filename, userid, groupid);
  800. X
  801. X    copy_message("", mailfd, FALSE, TRUE, FALSE, TRUE);  
  802. X
  803. X    fclose(mailfd);
  804. X
  805. X    /** Got the messsage, now let's ensure the person really wants to 
  806. X        remail it... **/
  807. X
  808. X    ClearLine(LINES-1);
  809. X    ClearLine(LINES);
  810. X    PutLine1(LINES-1,0,
  811. X        "Are you sure you want to remail this message (y/n)? y%c",
  812. X        BACKSPACE);
  813. X    fflush(stdin);
  814. X    fflush(stdout);
  815. X    ch = ReadCh();
  816. X    if (tolower(ch) == 'n') { /* another day, another No... */
  817. X      Write_to_screen("No.", 0);
  818. X      set_error("Bounce of message cancelled.");
  819. X      (void) unlink(filename);
  820. X      return(1);
  821. X    }
  822. X    Write_to_screen("Yes.", 0);
  823. X
  824. X    sprintf(buffer,"( (%s %s ; %s %s) & ) < %s", 
  825. X          mailer, strip_parens(strip_commas(expanded)), 
  826. X          remove_cmd, filename, filename);
  827. X
  828. X    PutLine0(LINES,0,"Resending mail...");
  829. X    system_call(buffer, SH, FALSE, FALSE);
  830. X    set_error("Mail resent.");
  831. X
  832. X    return(1);
  833. X}
  834. SHAR_EOF
  835. chmod 0444 src/remail.c || echo "restore of src/remail.c fails"
  836. echo "x - extracting src/reply.c (Text)"
  837. sed 's/^X//' << 'SHAR_EOF' > src/reply.c &&
  838. X
  839. Xstatic char rcsid[] = "@(#)$Id: reply.c,v 4.1 90/04/28 22:43:51 syd Exp $";
  840. X
  841. X/*******************************************************************************
  842. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  843. X *
  844. X *             Copyright (c) 1986, 1987 Dave Taylor
  845. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  846. X *******************************************************************************
  847. X * Bug reports, patches, comments, suggestions should be sent to:
  848. X *
  849. X *    Syd Weinstein, Elm Coordinator
  850. X *    elm@DSI.COM            dsinc!elm
  851. X *
  852. X *******************************************************************************
  853. X * $Log:    reply.c,v $
  854. X * Revision 4.1  90/04/28  22:43:51  syd
  855. X * checkin of Elm 2.3 as of Release PL0
  856. X * 
  857. X *
  858. X ******************************************************************************/
  859. X
  860. X/*** routine allows replying to the sender of the current message 
  861. X
  862. X***/
  863. X
  864. X#include "headers.h"
  865. X#include <errno.h>
  866. X
  867. X#ifndef BSD
  868. X#  include <sys/types.h>
  869. X# ifndef VMS
  870. X#  include <sys/utsname.h>
  871. X# endif
  872. X#endif
  873. X
  874. X/** Note that this routine generates automatic header information
  875. X    for the subject and (obviously) to lines, but that these can
  876. X    be altered while in the editor composing the reply message! 
  877. X**/
  878. X
  879. Xchar *strip_parens(), *get_token();
  880. X
  881. Xextern int errno;
  882. X
  883. Xchar *error_name(), *strcat(), *strcpy();
  884. X
  885. Xint
  886. Xreply()
  887. X{
  888. X    /** Reply to the current message.  Returns non-zero iff
  889. X        the screen has to be rewritten. **/
  890. X
  891. X    char return_address[SLEN], subject[SLEN];
  892. X    int  return_value, form_letter;
  893. X
  894. X    form_letter = (headers[current-1]->status & FORM_LETTER);
  895. X
  896. X    if (get_return(return_address, current-1)) {
  897. X      strcpy(subject, headers[current-1]->subject);
  898. X      if (form_letter)
  899. X        return_value = mail_filled_in_form(return_address, subject);
  900. X      else
  901. X        return_value = sendmsg(return_address, "", subject, TRUE, NO, TRUE);
  902. X    }
  903. X    else if (headers[current-1]->subject[0] != '\0') {
  904. X      if ((strncmp("Re:", headers[current-1]->subject, 3) == 0) ||
  905. X          (strncmp("RE:", headers[current-1]->subject, 3) == 0) ||
  906. X          (strncmp("re:", headers[current-1]->subject, 3) == 0)) 
  907. X        strcpy(subject, headers[current-1]->subject);
  908. X      else {
  909. X        strcpy(subject,"Re: ");
  910. X        strcat(subject,headers[current-1]->subject); 
  911. X      }
  912. X      if (form_letter)
  913. X        return_value = mail_filled_in_form(return_address, subject);
  914. X      else
  915. X        return_value = sendmsg(return_address, "", subject, TRUE, NO, TRUE);
  916. X    }
  917. X    else
  918. X      if (form_letter)
  919. X        return_value = mail_filled_in_form(return_address, 
  920. X                        "Filled in Form");
  921. X      else
  922. X        return_value = sendmsg(return_address, "", "Re: your mail", 
  923. X                TRUE, NO, TRUE);
  924. X
  925. X    return(return_value);
  926. X}
  927. X
  928. Xint
  929. Xreply_to_everyone()
  930. X{
  931. X    /** Reply to everyone who received the current message.  
  932. X        This includes other people in the 'To:' line and people
  933. X        in the 'Cc:' line too.  Returns non-zero iff the screen 
  934. X            has to be rewritten. **/
  935. X
  936. X    char return_address[SLEN], subject[SLEN];
  937. X    char full_address[VERY_LONG_STRING];
  938. X    int  return_value;
  939. X
  940. X    get_return(return_address, current-1);
  941. X
  942. X    full_address[0] = '\0';            /* no copies yet    */
  943. X    get_and_expand_everyone(return_address, full_address);
  944. X
  945. X    if (headers[current-1]->subject[0] != '\0') {
  946. X      if ((strncmp("Re:", headers[current-1]->subject, 3) == 0) ||
  947. X          (strncmp("RE:", headers[current-1]->subject, 3) == 0) ||
  948. X          (strncmp("re:", headers[current-1]->subject, 3) == 0)) 
  949. X        strcpy(subject, headers[current-1]->subject);
  950. X      else {
  951. X        strcpy(subject,"Re: ");
  952. X        strcat(subject,headers[current-1]->subject); 
  953. X      }
  954. X      return_value = sendmsg(return_address, full_address, subject, 
  955. X                 TRUE, NO, TRUE);
  956. X    }
  957. X    else
  958. X      return_value = sendmsg(return_address, full_address, 
  959. X                  "Re: your mail", TRUE, NO, TRUE);
  960. X
  961. X    return(return_value);
  962. X
  963. X}
  964. X
  965. Xint
  966. Xforward()
  967. X{
  968. X    /** Forward the current message.  What this actually does is
  969. X        to temporarily set forwarding to true, then call 'send' to
  970. X        get the address and route the mail.   Modified to also set
  971. X        'noheader' to FALSE also, so that the original headers
  972. X        of the message sent are included in the message body also.
  973. X        Return TRUE if the main part of the screen has been changed
  974. X        (useful for knowing whether a redraw is needed.
  975. X    **/
  976. X
  977. X    char subject[SLEN], address[VERY_LONG_STRING];
  978. X    int  results, edit_msg = FALSE;
  979. X
  980. X    forwarding = TRUE;
  981. X
  982. X    address[0] = '\0';
  983. X
  984. X    if (headers[current-1]->status & FORM_LETTER)
  985. X      PutLine0(LINES-3,COLUMNS-40,"<No editing allowed.>");
  986. X    else {
  987. X      edit_msg = (want_to("Edit outgoing message? (y/n) ",'y') != 'n');
  988. X    }
  989. X
  990. X    if (strlen(headers[current-1]->subject) > 0) {
  991. X
  992. X      strcpy(subject, headers[current-1]->subject); 
  993. X
  994. X      /* this next strange compare is to see if the last few chars are
  995. X         already '(fwd)' before we tack another on */
  996. X
  997. X      if (strlen(subject) < 6 || (strcmp((char *) subject+strlen(subject)-5,
  998. X                         "(fwd)") != 0))
  999. X        strcat(subject, " (fwd)");
  1000. X
  1001. X      results = sendmsg(address, "", subject, edit_msg,
  1002. X        headers[current-1]->status & FORM_LETTER? 
  1003. X        PREFORMATTED : allow_forms, FALSE);
  1004. X    }
  1005. X    else
  1006. X      results = sendmsg(address, "", "Forwarded mail...", edit_msg, 
  1007. X        headers[current-1]->status & FORM_LETTER? 
  1008. X        PREFORMATTED : allow_forms, FALSE);
  1009. X    
  1010. X    forwarding = FALSE;
  1011. X
  1012. X    return(results);
  1013. X}
  1014. X
  1015. Xget_and_expand_everyone(return_address, full_address)
  1016. Xchar *return_address, *full_address;
  1017. X{
  1018. X    /** Read the current message, extracting addresses from the 'To:'
  1019. X        and 'Cc:' lines.   As each address is taken, ensure that it
  1020. X        isn't to the author of the message NOR to us.  If neither,
  1021. X        prepend with current return address and append to the 
  1022. X        'full_address' string.
  1023. X    **/
  1024. X
  1025. X    char ret_address[SLEN], buf[SLEN], new_address[SLEN],
  1026. X     address[SLEN], comment[SLEN];
  1027. X    int  in_message = 1, first_pass = 0, iindex, line_pending = 0;
  1028. X
  1029. X    /** First off, get to the first line of the message desired **/
  1030. X
  1031. X    if (fseek(mailfile, headers[current-1]->offset, 0) == -1) {
  1032. X    dprint(1,(debugfile,"Error: seek %ld resulted in errno %s (%s)\n", 
  1033. X         headers[current-1]->offset, error_name(errno), 
  1034. X         "get_and_expand_everyone"));
  1035. X    error2("ELM [seek] couldn't read %d bytes into file (%s).",
  1036. X           headers[current-1]->offset, error_name(errno));
  1037. X    return;
  1038. X    }
  1039. X    /** okay!  Now we're there!  **/
  1040. X
  1041. X    /** let's fix the ret_address to reflect the return address of this
  1042. X    message with '%s' instead of the persons login name... **/
  1043. X
  1044. X    translate_return(return_address, ret_address);
  1045. X
  1046. X    /** now let's parse the actual message! **/
  1047. X
  1048. X    while (in_message) {
  1049. X      if (! line_pending)
  1050. X        in_message = (int) (fgets(buf, SLEN, mailfile) != NULL);
  1051. X      line_pending = 0;
  1052. X      if (first_word(buf, "From ") && first_pass++ != 0) 
  1053. X    in_message = FALSE;
  1054. X      else if (first_word(buf, "To:") || first_word(buf, "Cc:") ||
  1055. X           first_word(buf, "CC:") || first_word(buf, "cc:")) {
  1056. X    do {
  1057. X      no_ret(buf);
  1058. X
  1059. X      /** we have a buffer with a list of addresses, each of either the
  1060. X          form "address (name)" or "name <address>".  Our mission, should
  1061. X          we decide not to be too lazy, is to break it into the two parts.
  1062. X      **/
  1063. X          
  1064. X      if (!whitespace(buf[0]))
  1065. X        iindex = chloc(buf, ':')+1;        /* skip header field */
  1066. X      else
  1067. X        iindex = 0;                /* skip whitespace   */
  1068. X
  1069. X      while (break_down_tolist(buf, &iindex, address, comment)) {
  1070. X
  1071. X        if (okay_address(address, return_address)) {
  1072. X          sprintf(new_address, ret_address, address);
  1073. X          optimize_and_add(new_address, full_address);
  1074. X        }
  1075. X      }
  1076. X
  1077. X          in_message = (int) (fgets(buf, SLEN, mailfile) != NULL);
  1078. X
  1079. X      if (in_message) dprint(2, (debugfile, "> %s", buf));
  1080. X    
  1081. X    } while (in_message && whitespace(buf[0]));
  1082. X    line_pending++;
  1083. X      }
  1084. X      else if (strlen(buf) < 2)    /* done with header */
  1085. X     in_message = FALSE;
  1086. X    }
  1087. X}
  1088. X
  1089. Xint
  1090. Xokay_address(address, return_address)
  1091. Xchar *address, *return_address;
  1092. X{
  1093. X    /** This routine checks to ensure that the address we just got
  1094. X        from the "To:" or "Cc:" line isn't us AND isn't the person    
  1095. X        who sent the message.  Returns true iff neither is the case **/
  1096. X
  1097. X    char our_address[SLEN];
  1098. X    struct addr_rec  *alternatives;
  1099. X
  1100. X    if (in_list(address, return_address))
  1101. X      return(FALSE);
  1102. X
  1103. X    if(in_list(address, username))
  1104. X      return(FALSE);
  1105. X
  1106. X    sprintf(our_address, "%s!%s", hostname, username);
  1107. X    if (in_list(address, our_address))
  1108. X      return(FALSE);
  1109. X
  1110. X    sprintf(our_address, "%s!%s", hostfullname, username);
  1111. X    if (in_list(address, our_address))
  1112. X      return(FALSE);
  1113. X
  1114. X    sprintf(our_address, "%s@%s", username, hostname);
  1115. X    if (in_list(address, our_address))
  1116. X      return(FALSE);
  1117. X
  1118. X    sprintf(our_address, "%s@%s", username, hostfullname);
  1119. X    if (in_list(address, our_address))
  1120. X      return(FALSE);
  1121. X
  1122. X    alternatives = alternative_addresses;
  1123. X
  1124. X    while (alternatives != NULL) {
  1125. X      if (in_list(address, alternatives->address))
  1126. X        return(FALSE);
  1127. X      alternatives = alternatives->next;
  1128. X    }
  1129. X
  1130. X    return(TRUE);
  1131. X}
  1132. X        
  1133. Xoptimize_and_add(new_address, full_address)
  1134. Xchar *new_address, *full_address;
  1135. X{
  1136. X    /** This routine will add the new address to the list of addresses
  1137. X        in the full address buffer IFF it doesn't already occur.  It
  1138. X        will also try to fix dumb hops if possible, specifically hops
  1139. X        of the form ...a!b...!a... and hops of the form a@b@b etc 
  1140. X    **/
  1141. X
  1142. X    register int len, host_count = 0, i;
  1143. X    char     hosts[MAX_HOPS][SLEN];    /* array of machine names */
  1144. X    char     *host, *addrptr;
  1145. X
  1146. X    if (in_list(full_address, new_address))
  1147. X      return(1);    /* duplicate address */
  1148. X
  1149. X    /** optimize **/
  1150. X    /*  break down into a list of machine names, checking as we go along */
  1151. X    
  1152. X    addrptr = (char *) new_address;
  1153. X
  1154. X    while ((host = get_token(addrptr, "!", 1)) != NULL) {
  1155. X      for (i = 0; i < host_count && ! equal(hosts[i], host); i++)
  1156. X          ;
  1157. X
  1158. X      if (i == host_count) {
  1159. X        strcpy(hosts[host_count++], host);
  1160. X        if (host_count == MAX_HOPS) {
  1161. X           dprint(2, (debugfile,
  1162. X              "Error: hit max_hops limit trying to build return address (%s)\n",
  1163. X              "optimize_and_add"));
  1164. X           error("Can't build return address. Hit MAX_HOPS limit!");
  1165. X           return(1);
  1166. X        }
  1167. X      }
  1168. X      else 
  1169. X        host_count = i + 1;
  1170. X      addrptr = NULL;
  1171. X    }
  1172. X
  1173. X    /** fix the ARPA addresses, if needed **/
  1174. X    
  1175. X    if (chloc(hosts[host_count-1], '@') > -1)
  1176. X      fix_arpa_address(hosts[host_count-1]);
  1177. X      
  1178. X    /** rebuild the address.. **/
  1179. X
  1180. X    new_address[0] = '\0';
  1181. X
  1182. X    for (i = 0; i < host_count; i++)
  1183. X      sprintf(new_address, "%s%s%s", new_address, 
  1184. X              new_address[0] == '\0'? "" : "!",
  1185. X              hosts[i]);
  1186. X
  1187. X    if (full_address[0] == '\0')
  1188. X      strcpy(full_address, new_address);
  1189. X    else {
  1190. X      len = strlen(full_address);
  1191. X      full_address[len  ] = ',';
  1192. X      full_address[len+1] = ' ';
  1193. X      full_address[len+2] = '\0';
  1194. X      strcat(full_address, new_address);
  1195. X    }
  1196. X
  1197. X    return(0);
  1198. X}
  1199. X
  1200. Xget_return_name(address, name, trans_to_lowercase)
  1201. Xchar *address, *name;
  1202. Xint   trans_to_lowercase;
  1203. X{
  1204. X    /** Given the address (either a single address or a combined list 
  1205. X        of addresses) extract the login name of the first person on
  1206. X        the list and return it as 'name'.  Modified to stop at
  1207. X        any non-alphanumeric character. **/
  1208. X
  1209. X    /** An important note to remember is that it isn't vital that this
  1210. X        always returns just the login name, but rather that it always
  1211. X        returns the SAME name.  If the persons' login happens to be,
  1212. X        for example, joe.richards, then it's arguable if the name 
  1213. X        should be joe, or the full login.  It's really immaterial, as
  1214. X        indicated before, so long as we ALWAYS return the same name! **/
  1215. X
  1216. X    /** Another note: modified to return the argument as all lowercase
  1217. X        always, unless trans_to_lowercase is FALSE... **/
  1218. X
  1219. X    char single_address[SLEN];
  1220. X    register int i, loc, iindex = 0;
  1221. X
  1222. X    dprint(6, (debugfile,"get_return_name called with (%s, <>, shift=%s)\n",
  1223. X           address, onoff(trans_to_lowercase)));
  1224. X
  1225. X    /* First step - copy address up to a comma, space, or EOLN */
  1226. X
  1227. X    for (i=0; address[i] != ',' && ! whitespace(address[i]) && 
  1228. X         address[i] != '\0'; i++)
  1229. X      single_address[i] = address[i];
  1230. X    single_address[i] = '\0';
  1231. X
  1232. X    /* Now is it an ARPA address?? */
  1233. X
  1234. X    if ((loc = chloc(single_address, '@')) != -1) {      /* Yes */
  1235. X
  1236. X      /* At this point the algorithm is to keep shifting our copy 
  1237. X         window left until we hit a '!'.  The login name is then
  1238. X             located between the '!' and the first metacharacter to 
  1239. X         it's right (ie '%', ':' or '@'). */
  1240. X
  1241. X      for (i=loc; single_address[i] != '!' && i > -1; i--)
  1242. X          if (single_address[i] == '%' || 
  1243. X              single_address[i] == ':' ||
  1244. X          single_address[i] == '@') loc = i-1;
  1245. X    
  1246. X      if (i < 0 || single_address[i] == '!') i++;
  1247. X
  1248. X      for (iindex = 0; iindex < loc - i + 1; iindex++)
  1249. X        if (trans_to_lowercase)
  1250. X          name[iindex] = tolower(single_address[iindex+i]);
  1251. X        else
  1252. X          name[iindex] = single_address[iindex+i];
  1253. X      name[iindex] = '\0';
  1254. X    }
  1255. X    else {    /* easier - standard USENET address */
  1256. X
  1257. X      /* This really is easier - we just cruise left from the end of
  1258. X         the string until we hit either a '!' or the beginning of the
  1259. X             line.  No sweat. */
  1260. X
  1261. X      loc = strlen(single_address)-1;     /* last char */
  1262. X
  1263. X      for (i = loc; single_address[i] != '!' && single_address[i] != '.' 
  1264. X           && i > -1; i--)
  1265. X         if (trans_to_lowercase)
  1266. X           name[iindex++] = tolower(single_address[i]);
  1267. X         else
  1268. X           name[iindex++] = single_address[i];
  1269. X      name[iindex] = '\0';
  1270. X      reverse(name);
  1271. X    }
  1272. X}
  1273. X
  1274. Xint
  1275. Xbreak_down_tolist(buf, iindex, address, comment)
  1276. Xchar *buf, *address, *comment;
  1277. Xint  *iindex;
  1278. X{
  1279. X    /** This routine steps through "buf" and extracts a single address
  1280. X        entry.  This entry can be of any of the following forms;
  1281. X
  1282. X        address (name)
  1283. X        name <address>
  1284. X        address
  1285. X    
  1286. X        Once it's extracted a single entry, it will then return it as
  1287. X        two tokens, with 'name' (e.g. comment) surrounded by parens.
  1288. X        Returns ZERO if done with the string...
  1289. X    **/
  1290. X
  1291. X    char buffer[LONG_STRING];
  1292. X    register int i, loc = 0, hold_index, len;
  1293. X
  1294. X    if (*iindex > strlen(buf)) return(FALSE);
  1295. X
  1296. X    while (whitespace(buf[*iindex])) (*iindex)++;
  1297. X
  1298. X    if (*iindex > strlen(buf)) return(FALSE);
  1299. X
  1300. X    /** Now we're pointing at the first character of the token! **/
  1301. X
  1302. X    hold_index = *iindex;
  1303. X
  1304. X    while (buf[*iindex] != ',' && buf[*iindex] != '\0')
  1305. X      buffer[loc++] = buf[(*iindex)++];
  1306. X
  1307. X    (*iindex)++;
  1308. X    buffer[loc] = '\0';
  1309. X
  1310. X    while (whitespace(buffer[loc]))     /* remove trailing whitespace */
  1311. X      buffer[--loc] = '\0';
  1312. X
  1313. X    if (strlen(buffer) == 0) return(FALSE);
  1314. X
  1315. X    dprint(5, (debugfile, "\n* got \"%s\"\n", buffer));
  1316. X
  1317. X    if (buffer[loc-1] == ')') {    /*   address (name)  format */
  1318. X      for (loc = 0, len = strlen(buffer);buffer[loc] != '(' && loc < len; loc++)
  1319. X        /* get to the opening comment character... */ ;
  1320. X
  1321. X      loc--;    /* back up to just before the paren */
  1322. X      while (whitespace(buffer[loc])) loc--;    /* back up */
  1323. X
  1324. X      /** get the address field... **/
  1325. X
  1326. X      for (i=0; i <= loc; i++)
  1327. X        address[i] = buffer[i];
  1328. X      address[i] = '\0';
  1329. X
  1330. X      /** now get the comment field, en toto! **/
  1331. X
  1332. X      loc = 0;
  1333. X
  1334. X      for (i = chloc(buffer, '('), len = strlen(buffer); i < len; i++)
  1335. X        comment[loc++] = buffer[i];
  1336. X      comment[loc] = '\0';
  1337. X    }
  1338. X    else if (buffer[loc-1] == '>') {    /*   name <address>  format */
  1339. X      dprint(7, (debugfile, "\tcomment <address>\n"));
  1340. X      for (loc = 0, len = strlen(buffer);buffer[loc] != '<' && loc < len; loc++)
  1341. X        /* get to the opening comment character... */ ;
  1342. X      while (whitespace(buffer[loc])) loc--;    /* back up */
  1343. X
  1344. X      /** get the comment field... **/
  1345. X
  1346. X      comment[0] = '(';
  1347. X      for (i=1; i < loc; i++)
  1348. X        comment[i] = buffer[i-1];
  1349. X      comment[i++] = ')';
  1350. X      comment[i] = '\0';
  1351. X
  1352. X      /** now get the address field, en toto! **/
  1353. X
  1354. X      loc = 0;
  1355. X
  1356. X      for (i = chloc(buffer,'<') + 1, len = strlen(buffer); i < len - 1; i++)
  1357. X        address[loc++] = buffer[i];
  1358. X    
  1359. X      address[loc] = '\0';
  1360. X    }
  1361. X    else {
  1362. X      /** the next section is added so that all To: lines have commas
  1363. X          in them accordingly **/
  1364. X
  1365. X      for (i=0; buffer[i] != '\0'; i++)
  1366. X        if (whitespace(buffer[i])) break;
  1367. X      if (i < strlen(buffer)) {    /* shouldn't be whitespace */
  1368. X        buffer[i] = '\0';
  1369. X        *iindex = hold_index + strlen(buffer) + 1;
  1370. X      }
  1371. X      strcpy(address, buffer);
  1372. X      comment[0] = '\0';
  1373. X    }
  1374. X
  1375. X    dprint(5, (debugfile, "-- returning '%s' '%s'\n", address, comment));
  1376. X
  1377. X    return(TRUE);
  1378. X}
  1379. SHAR_EOF
  1380. chmod 0444 src/reply.c || echo "restore of src/reply.c fails"
  1381. echo "x - extracting src/returnadd.c (Text)"
  1382. sed 's/^X//' << 'SHAR_EOF' > src/returnadd.c &&
  1383. X
  1384. Xstatic char rcsid[] = "@(#)$Id: returnadd.c,v 4.1 90/04/28 22:43:54 syd Exp $";
  1385. X
  1386. X/*******************************************************************************
  1387. X *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  1388. X *
  1389. X *             Copyright (c) 1986, 1987 Dave Taylor
  1390. X *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  1391. X *******************************************************************************
  1392. X * Bug reports, patches, comments, suggestions should be sent to:
  1393. X *
  1394. X *    Syd Weinstein, Elm Coordinator
  1395. X *    elm@DSI.COM            dsinc!elm
  1396. X *
  1397. X *******************************************************************************
  1398. X * $Log:    returnadd.c,v $
  1399. X * Revision 4.1  90/04/28  22:43:54  syd
  1400. X * checkin of Elm 2.3 as of Release PL0
  1401. X * 
  1402. X * 
  1403. X ******************************************************************************/
  1404. X
  1405. X/** This set of routines is used to generate real return addresses
  1406. X    and also return addresses suitable for inclusion in a users
  1407. X    alias files (ie optimized based on the pathalias database).
  1408. X
  1409. X**/
  1410. X
  1411. X#include "headers.h"
  1412. X
  1413. X#include <errno.h>
  1414. X
  1415. X#include <sys/types.h>
  1416. X#include <sys/stat.h>
  1417. X
  1418. Xchar *shift_lower();
  1419. X
  1420. Xextern int errno;
  1421. X
  1422. Xchar *error_name(), *strcat(), *strcpy();
  1423. X
  1424. X#ifdef OPTIMIZE_RETURN
  1425. X
  1426. Xoptimize_return(address)
  1427. Xchar *address;
  1428. X{
  1429. X    /** This routine tries to create an optimized address, that is,
  1430. X        an address that has the minimal information needed to 
  1431. X        route a message to this person given the current path
  1432. X        database...
  1433. X    **/
  1434. X
  1435. X#ifndef INTERNET
  1436. X    char    bogus_internet[SLEN];
  1437. X
  1438. X    sprintf(bogus_internet, "@%s", hostfullname);
  1439. X
  1440. X    /** first off, let's see if we need to strip off the localhost
  1441. X        address crap... **/
  1442. X
  1443. X    /** if we have a uucp part (e.g.a!b) AND the bogus address...**/
  1444. X
  1445. X    if (chloc(address,'!') != -1 && in_string(address, bogus_internet))
  1446. X      address[strlen(address)-strlen(bogus_internet)] = '\0';
  1447. X#endif
  1448. X
  1449. X    /** next step is to figure out what sort of address we have... **/
  1450. X
  1451. X    if (chloc(address, '%') != -1)
  1452. X      optimize_cmplx_arpa(address);
  1453. X    else if (chloc(address, '@') != -1)
  1454. X      optimize_arpa(address);
  1455. X    else
  1456. X      optimize_usenet(address);
  1457. X}
  1458. X
  1459. Xoptimize_cmplx_arpa(address)
  1460. Xchar *address;
  1461. X{
  1462. X    /** Try to optimize a complex ARPA address.  A Complex address is one 
  1463. X        that contains '%' (deferred '@').  For example:  
  1464. X        veeger!hpcnof!hplabs!joe%sytech@syte  
  1465. X        is a complex address (no kidding, right?).  The algorithm for 
  1466. X        trying to resolve it is to move all the way to the right, then 
  1467. X        back up left until the first '!' then from there to the SECOND 
  1468. X        metacharacter on the right is the name@host address...(in this 
  1469. X            example, it would be "joe%sytech").  Check this in the routing
  1470. X        table.  If not present, keep backing out to the right until we
  1471. X        find a host that is present, or we hit the '@' sign.  Once we
  1472. X        have a 'normal' ARPA address, hand it to optimize_arpa().
  1473. X    **/
  1474. X
  1475. X    char name[NLEN], buffer[SLEN], junk[SLEN];
  1476. X    char host[NLEN], old_host[NLEN];
  1477. X    register int i, loc, nloc = 0, hloc = 0, passes = 1;
  1478. X
  1479. X    /** first off, get the name%host... **/
  1480. X
  1481. X    for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--)
  1482. X       ;
  1483. X
  1484. X    while (address[loc] != '\0') {
  1485. X
  1486. X      if (passes == 1) {
  1487. X        loc++;
  1488. X
  1489. X        while (address[loc] != '%' && address[loc] != '@')
  1490. X          name[nloc++] = address[loc++];
  1491. X      }
  1492. X      else {
  1493. X        for (i=0; old_host[i] != '\0'; i++)
  1494. X          name[nloc++] = old_host[i];
  1495. X      }
  1496. X
  1497. X      loc++;
  1498. X  
  1499. X      while (address[loc] != '%' && address[loc] != '@')
  1500. X        host[hloc++] = address[loc++];
  1501. X  
  1502. X      host[hloc] = name[nloc] = '\0';
  1503. X
  1504. X      strcpy(old_host, host);
  1505. X
  1506. X      sprintf(buffer, "%s@%s", name, shift_lower(host));
  1507. X
  1508. X      if (expand_site(buffer, junk) == 0) {
  1509. X        strcpy(address, buffer);
  1510. X        return;
  1511. X      }
  1512. X      else if (address[loc] == '@') {
  1513. X        optimize_arpa(address);
  1514. X        return;
  1515. X      }
  1516. X      else
  1517. X        name[nloc++] = '%';    /* for next pass through */
  1518. X
  1519. X    }
  1520. X}
  1521. X
  1522. Xoptimize_arpa(address)
  1523. Xchar *address;
  1524. X{
  1525. X    /** Get an arpa address and simplify it to the minimal
  1526. X        route needed to get mail to this person... **/
  1527. X
  1528. X    char name[NLEN], buffer[SLEN], junk[SLEN];
  1529. X    char host[NLEN];
  1530. X    register int loc, nloc = 0, hloc = 0, at_sign = 0;
  1531. X
  1532. X    for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--) {
  1533. X      if (address[loc] == '@')
  1534. X         at_sign++;    /* remember this spot! */
  1535. X      else if (at_sign)
  1536. X        name[nloc++] = address[loc];
  1537. X      else
  1538. X        host[hloc++] = address[loc];
  1539. X    }
  1540. X
  1541. X    name[nloc] = host[hloc] = '\0';
  1542. X
  1543. X    reverse(name);
  1544. X    reverse(host);
  1545. X
  1546. X    sprintf(buffer,"%s@%s", name, shift_lower(host));
  1547. X
  1548. X    if (expand_site(buffer, junk) == 0) {
  1549. X      strcpy(address, buffer);
  1550. X      return;
  1551. X    }
  1552. X
  1553. X    optimize_usenet(address);    /* that didn't work... */
  1554. X}
  1555. X    
  1556. Xoptimize_usenet(address)
  1557. Xchar *address;
  1558. X{
  1559. X    /** optimize the return address IFF it's a standard usenet
  1560. X        address...
  1561. X    **/
  1562. X
  1563. X    char name[NLEN],  new_address[SLEN], buffer[SLEN], junk[SLEN];
  1564. X    register int loc, nloc = 0, aloc = 0, passes = 1;
  1565. X
  1566. X    for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--) 
  1567. X      name[nloc++] = address[loc];
  1568. X    name[nloc] = '\0';
  1569. X
  1570. X    reverse(name);
  1571. X
  1572. X    new_address[0] = '\0';    
  1573. X
  1574. X    /* got name, now get machine until we can get outta here */
  1575. X
  1576. X    while (loc > -1) {
  1577. X
  1578. X      new_address[aloc++] = address[loc--];    /* the '!' char */
  1579. X
  1580. X      while (address[loc] != '!' && loc > -1)
  1581. X        new_address[aloc++] = address[loc--];
  1582. X
  1583. X      new_address[aloc] = '\0';
  1584. X
  1585. X      strcpy(buffer, new_address);
  1586. X      reverse(buffer);
  1587. X    
  1588. X      if (expand_site(buffer, junk) == 0) {
  1589. X        if (passes == 1 && chloc(name, '@') == -1) {
  1590. X          buffer[strlen(buffer) - 1] = '\0';    /* remove '!' */
  1591. X          sprintf(address, "%s@%s", name, buffer);
  1592. X        }
  1593. X        else 
  1594. X          sprintf(address, "%s%s", buffer, name);
  1595. X        return;        /* success! */
  1596. X      }
  1597. X      passes++;
  1598. X    }
  1599. X
  1600. X    return;        /* nothing to do! */
  1601. X}
  1602. X
  1603. X#endif    /* OPTIMIZE_RETURN */
  1604. X
  1605. Xint
  1606. Xget_return(buffer, msgnum)
  1607. Xchar *buffer;
  1608. Xint msgnum;
  1609. X{
  1610. X    /** reads msgnum message again, building up the full return 
  1611. X        address including all machines that might have forwarded 
  1612. X        the message.  Returns whether it is using the To line **/
  1613. X
  1614. X    char buf[SLEN], name1[SLEN], name2[SLEN], lastname[SLEN];
  1615. X    char hold_return[SLEN], alt_name2[SLEN], buf2[SLEN];
  1616. X    int ok = 1, lines;
  1617. X    int using_to = FALSE;
  1618. X
  1619. X    /* now initialize all the char buffers [thanks Keith!] */
  1620. X
  1621. X    buf[0] = name1[0] = name2[0] = lastname[0] = '\0';
  1622. X    hold_return[0] = alt_name2[0] = buf2[0] = '\0';
  1623. X
  1624. X    /** get to the first line of the message desired **/
  1625. X
  1626. X    if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  1627. X      dprint(1, (debugfile,
  1628. X        "Error: %d not a valid message number message_count = %d (%s)",
  1629. X        msgnum, message_count, "get_return"));
  1630. X      error1("%d not a valid message number!");
  1631. X      return(using_to);
  1632. X    }
  1633. X
  1634. X    if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  1635. X      dprint(1, (debugfile,
  1636. X        "Error: seek %ld bytes into file hit errno %s (%s)", 
  1637. X        headers[msgnum]->offset, error_name(errno), 
  1638. X            "get_return"));
  1639. X      error2("Couldn't seek %d bytes into file (%s).",
  1640. X           headers[msgnum]->offset, error_name(errno));
  1641. X      return(using_to);
  1642. X    }
  1643. X    /** okay!  Now we're there!  **/
  1644. X
  1645. X    lines = headers[msgnum]->lines;
  1646. SHAR_EOF
  1647. echo "End of part 20"
  1648. echo "File src/returnadd.c is continued in part 21"
  1649. echo "21" > s2_seq_.tmp
  1650. exit 0
  1651.