home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / mush / part05 < prev    next >
Internet Message Format  |  1991-04-21  |  51KB

  1. From: argv@zipcode.com (Dan Heller)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i062:  mush - Mail User's Shell, Part05/22
  4. Message-ID: <1991Apr21.024943.11261@sparky.IMD.Sterling.COM>
  5. Date: 21 Apr 91 02:49:43 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 1f170650 7e363deb 1e0a40bc 2d27dcec
  8.  
  9. Submitted-by: Dan Heller <argv@zipcode.com>
  10. Posting-number: Volume 18, Issue 62
  11. Archive-name: mush/part05
  12. Supersedes: mush: Volume 12, Issue 28-47
  13.  
  14. #!/bin/sh
  15. # do not concatenate these parts, unpack them in order with /bin/sh
  16. # file command2.c continued
  17. #
  18. if test ! -r _shar_seq_.tmp; then
  19.     echo 'Please unpack part 1 first!'
  20.     exit 1
  21. fi
  22. (read Scheck
  23.  if test "$Scheck" != 5; then
  24.     echo Please unpack part "$Scheck" next!
  25.     exit 1
  26.  else
  27.     exit 0
  28.  fi
  29. ) < _shar_seq_.tmp || exit 1
  30. if test ! -f _shar_wnt_.tmp; then
  31.     echo 'x - still skipping command2.c'
  32. else
  33. echo 'x - continuing file command2.c'
  34. sed 's/^X//' << 'SHAR_EOF' >> 'command2.c' &&
  35. X    return -1;
  36. X    }
  37. X
  38. X    (void) Unsetenv(2, argv);
  39. X
  40. X    for (i = 0; environ[i]; i++);
  41. X    if (!spaces) {
  42. X    char **new_environ =
  43. X            (char **)malloc((unsigned) ((i+2) * sizeof(char *)));
  44. X    /* add 1 for the new item, and 1 for null-termination */
  45. X    if (!new_environ) {
  46. X        xfree(newstr);
  47. X        return -1;
  48. X    }
  49. X    spaces = 1;
  50. X    for (i = 0; new_environ[i] = environ[i]; i++);
  51. X    xfree((char *) environ);
  52. X    environ = new_environ;
  53. X    }
  54. X    environ[i] = newstr;
  55. X    environ[i+1] = NULL;
  56. X    spaces--;
  57. X    return 0;
  58. }
  59. X
  60. Unsetenv(n, argv)
  61. int n;
  62. char **argv;
  63. {
  64. X    char **envp, **last;
  65. X
  66. X    if (n != 2 || !strcmp(argv[1], "-?"))
  67. X    return help(0, "unsetenv", cmd_help);
  68. X
  69. X    n = strlen(argv[1]);
  70. X    for (last = environ; *last; last++);
  71. X    last--;
  72. X
  73. X    for (envp = environ; envp <= last; envp++) {
  74. X    if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
  75. X        xfree(*envp);
  76. X        *envp = *last;
  77. X        *last-- = NULL;
  78. X        spaces++;
  79. X    }
  80. X    }
  81. X    return 0;
  82. }
  83. X
  84. Printenv(argc, argv)
  85. int argc;
  86. char **argv;
  87. {
  88. X    char **e;
  89. X
  90. X    if (argv && argv[1] && !strcmp(argv[1], "-?"))
  91. X    return help(0, "printenv", cmd_help);
  92. X    for (e = environ; *e; e++)
  93. X    if (argc < 2 || !strncmp(*e, argv[1], strlen(argv[1])))
  94. X        wprint("%s\n", *e);
  95. X    return 0;
  96. }
  97. X
  98. /*
  99. X * internal stty call to allow the user to change his tty character
  100. X * settings.  sorry, no way to change cbreak/echo modes.  Save echo_flg
  101. X * so that execute() won't reset it.
  102. X */
  103. /*ARGSUSED*/
  104. my_stty(un_used, argv)
  105. int un_used;
  106. char **argv;
  107. {
  108. X    u_long save_echo = ison(glob_flags, ECHO_FLAG);
  109. X
  110. X    if (istool)
  111. X    return 0;
  112. X
  113. X    if (argv && argv[1] && !strcmp(argv[1], "-?"))
  114. X    return help(0, "stty", cmd_help);
  115. X    turnon(glob_flags, ECHO_FLAG);
  116. X    execute(argv);
  117. X    if (save_echo)
  118. X    turnon(glob_flags, ECHO_FLAG);
  119. X    else
  120. X    turnoff(glob_flags, ECHO_FLAG);
  121. X
  122. X    savetty();
  123. #ifdef TIOCGLTC
  124. X    if (ioctl(0, TIOCGLTC, <chars))
  125. X    error("TIOCGLTC");
  126. #endif /* TIOCGLTC */
  127. X    echo_off();
  128. X    return 0;
  129. }
  130. X
  131. /*
  132. X * Edit a message...
  133. X */
  134. edit_msg(i, argv, list)
  135. int i;
  136. char *argv[], list[];
  137. {
  138. X    int edited = 0;
  139. X    char buf[MAXPATHLEN], *b, *dir, **edit_cmd, *editor, *mktemp();
  140. X    u_long flags = 0L;
  141. X    char *cmd = *argv;
  142. X    FILE *fp;
  143. X
  144. X    if (istool)
  145. X    return 0;
  146. X
  147. X    if (*++argv && !strcmp(*argv, "-?"))
  148. X    return help(0, "edit_msg", cmd_help);
  149. X
  150. X    if (ison(glob_flags, READ_ONLY)) {
  151. X    print("\"%s\" is read-only.\n", mailfile);
  152. X    return -1;
  153. X    }
  154. X
  155. X    if (get_msg_list(argv, list) == -1)
  156. X    return -1;
  157. X
  158. X    if (!(editor = do_set(set_options,
  159. X    (*cmd == 'v')? "visual" : "editor")) || !*editor)
  160. X    editor = DEF_EDITOR;
  161. X
  162. X    for (i = 0; i < msg_cnt; i++) {
  163. X    if (!msg_bit(list, i))
  164. X        continue;
  165. X
  166. X    if (edited) {
  167. X        print("Edit message %d [y/n/q]? ", i+1);
  168. X        if (Getstr(buf, sizeof (buf), 0) < 0 || lower(buf[0]) == 'q')
  169. X        return 0;
  170. X        if (buf[0] && buf[0] != 'y')
  171. X        continue;
  172. X    }
  173. X
  174. X    b = buf + Strcpy(buf, editor);
  175. X    *b++ = ' ';
  176. X
  177. X    /* getdir() uses the home directory if no tmpdir */
  178. X    if (!(dir = getdir(do_set(set_options, "tmpdir"))))
  179. alted:
  180. X        dir = ALTERNATE_HOME;
  181. X    (void) mktemp(sprintf(b, "%s/.msgXXXXXXX", dir));
  182. X    if (!(fp = mask_fopen(b, "w+"))) {
  183. X        if (strcmp(dir, ALTERNATE_HOME))
  184. X        goto alted;
  185. X        error("can't create %s", b);
  186. X        return -1;
  187. X    }
  188. X    wprint("editing message %d ...", i+1);
  189. X    /* copy message into file making sure all headers exist. */
  190. X    turnon(flags, UPDATE_STATUS);
  191. #ifdef MMDF
  192. X    turnon(flags, NO_SEPARATOR);
  193. #endif /* MMDF */
  194. X    wprint("(%d lines)\n", copy_msg(i, fp, flags, NULL));
  195. X
  196. X    if (edit_cmd = mk_argv(buf, &edited, FALSE)) {
  197. X        print("Starting \"%s\"...\n", buf);
  198. X        (void) fclose(fp);
  199. X        turnon(glob_flags, IS_GETTING);
  200. X        execute(edit_cmd);
  201. X        turnoff(glob_flags, IS_GETTING);
  202. X        free_vec(edit_cmd);
  203. X        if (load_folder(b, FALSE, (char *)i) > 0) {
  204. X        (void) unlink(b);
  205. X        edited = 1;
  206. X        }
  207. X        set_isread(i); /* if you edit it, you read it, right? */
  208. X    }
  209. X    }
  210. X    return 0;
  211. }
  212. X
  213. /*
  214. X * Pipe a message list to a unix command.  This function is hacked together
  215. X * from bits of readmsg, above, and other bits of display_msg (misc.c).
  216. X */
  217. pipe_msg(x, argv, list)
  218. int x;
  219. char **argv, list[];
  220. {
  221. X    char *p = x ? *argv : NULL;
  222. X    char buf[256], *pattern = NULL;
  223. X    u_long flg = 0L;
  224. X    extern FILE *ed_fp;
  225. X    int show_deleted = !!do_set(set_options, "show_deleted");
  226. X
  227. X    /* Increment argv only if argv[0] is the mush command "pipe" */
  228. X    if (x && p && (!strcmp(p, "pipe") || !strcmp(p, "Pipe"))) {
  229. X    if (p && *p == 'P')
  230. X        turnon(flg, NO_HEADER);
  231. X    while (x && *++argv && **argv == '-')
  232. X        if (!strcmp(*argv, "-?"))
  233. X        return help(0, "pipe_msg", cmd_help);
  234. X        else if (!strcmp(*argv, "-p") && !(pattern = *++argv)) {
  235. X        print("Specify a pattern with -p\n");
  236. X        return -1;
  237. X        }
  238. X    }
  239. X    if (!msg_cnt) {
  240. X    print("No messages.\n");
  241. X    return -1;
  242. X    }
  243. X
  244. X    if (x && (x = get_msg_list(argv, list)) == -1)
  245. X    return -1;
  246. X    argv += x;
  247. X    if (!*argv) {
  248. X    turnon(flg, NO_HEADER);
  249. X    /* The constant strings must be constants because user's
  250. X     * $SHELL might not be appropriate since "sh" scripts are
  251. X     * usually sent.  User can always (easily) override.
  252. X     */
  253. X    (void) strcpy(buf, "/bin/sh");
  254. X    if (!pattern)
  255. X        pattern = "#!";
  256. X    } else
  257. X    (void) argv_to_string(buf, argv);
  258. X    if (!buf[0]) {
  259. X    print("Must specify a legitimate command or shell.\n");
  260. X    return -1;
  261. X    }
  262. X    current_msg = 0;
  263. X    if (!chk_option("alwaysignore", "pipe"))
  264. X    turnon(flg, NO_IGNORE);
  265. #ifdef MMDF
  266. X    turnon(flg, NO_SEPARATOR);
  267. #endif /* MMDF */
  268. X    (void) do_pager(buf, -1); /* start pager -- see do_pager() about "-1" */
  269. X    turnoff(glob_flags, WAS_INTR); /* if command interrupts, mush gets it */
  270. X
  271. X    for (x = 0; x < msg_cnt && isoff(glob_flags, WAS_INTR); x++)
  272. X    if (msg_bit(list, x)) {
  273. X        current_msg = x;
  274. X        if (!show_deleted && ison(msg[x].m_flags, DELETE)) {
  275. X        print("Message %d deleted; ", x+1);
  276. X        if (iscurses)
  277. X            print_more("skipping it.");
  278. X        else
  279. X            print("skipping it.\n");
  280. X        continue;
  281. X        }
  282. X        set_isread(x);
  283. X        if (copy_msg(x, NULL_FILE, flg, pattern) == 0)
  284. X        print("No lines sent to %s!\n", buf);
  285. X    }
  286. X    (void) do_pager(NULL, FALSE); /* end pager */
  287. X    return 0;
  288. }
  289. X
  290. /* echo the arguments.  return 0 or -1 if -h given and there are no msgs. */
  291. do_echo(n, argv)
  292. int n;
  293. char **argv;
  294. {
  295. X    char buf[BUFSIZ], c;
  296. X    int no_return = 0, comp_hdr = 0, as_prompt = 0;
  297. X
  298. X    while (n >= 0 && argv && *++argv && **argv == '-') {
  299. X    n = 1;
  300. X    while (n > 0 && (c = argv[0][n++]))
  301. X        switch(c) {
  302. X        case 'n': no_return++;
  303. X        when 'h': comp_hdr++;
  304. X        when 'p': as_prompt++;
  305. X        when '?': return help(0, "echo", cmd_help);
  306. X        otherwise: n = -1; break; /* Just echo whatever it was */
  307. X        }
  308. X    }
  309. X    if (comp_hdr && as_prompt) {
  310. X    print("-h and -p cannot be used together.\n");
  311. X    return -1;
  312. X    }
  313. X
  314. X    (void) argv_to_string(buf, argv);
  315. X    if (comp_hdr) {
  316. X    if (!msg_cnt) {
  317. X        print("No messages.\n");
  318. X        return -1;
  319. X    }
  320. X    /* there may be a %-sign, so use %s to print */
  321. X    print("%s", format_hdr(current_msg, buf, FALSE)+9);
  322. X    } else if (as_prompt) {
  323. X    print("%s", format_prompt(current_msg, buf)); /* may be a %-sign */
  324. X    } else
  325. X    print("%s", buf); /* there may be a %-sign in "buf" */
  326. X    if (!no_return)
  327. X    print_more("\n");
  328. X    return 0;
  329. }
  330. X
  331. eval_cmd (argc, argv, list)
  332. int argc;
  333. char *argv[], list[];
  334. {
  335. X    int status = -1;
  336. X    u_long save_is_pipe;
  337. X    char **newav, buf[BUFSIZ];
  338. X    int comp_hdr = 0, as_prompt = 0, as_macro = 0;
  339. X
  340. X    while (argv && *++argv && **argv == '-') {
  341. X    int c, n = 1;
  342. X    while (c = argv[0][n++])
  343. X        switch(c) {
  344. X        case 'h': comp_hdr++;
  345. X        when 'p': as_prompt++;
  346. X        when 'm': as_macro++;
  347. X        otherwise: return help(0, "eval", cmd_help);
  348. X        }
  349. X    }
  350. X    if (comp_hdr && as_prompt) {
  351. X    print("-h and -p cannot be used together.\n");
  352. X    return -1;
  353. X    }
  354. X
  355. X    (void) argv_to_string(buf, argv);
  356. X    if (as_macro) {
  357. X    m_xlate(buf);
  358. X    mac_queue(buf);
  359. X    return 0;
  360. X    }
  361. X    newav = make_command(buf, TRPL_NULL, &argc);
  362. X    if (comp_hdr) {
  363. X    if (!msg_cnt) {
  364. X        print("No messages.\n");
  365. X        return -1;
  366. X    }
  367. X    /* This is inefficient, but the only way to preserve
  368. X     * imbedded quotes, tabs, etc. in format expansions.
  369. X     */
  370. X    for (argv = newav; argv && *argv; argv++) {
  371. X        /* Don't mess with one-character strings */
  372. X        if (argv[0][1]) {
  373. X        char *format = *argv;
  374. X        *argv = savestr(format_hdr(current_msg, format, FALSE)+9);
  375. X        Debug("expanding (%s) to (%s)\n", format, *argv);
  376. X        xfree(format);
  377. X        }
  378. X    }
  379. X    } else if (as_prompt) {
  380. X    for (argv = newav; argv && *argv; argv++) {
  381. X        /* Don't mess with one-character strings */
  382. X        if (argv[0][1]) {
  383. X        char *tmp = *argv;
  384. X        *argv = savestr(format_prompt(current_msg, tmp));
  385. X        Debug("expanding (%s) to (%s)\n", tmp, *argv);
  386. X        xfree(tmp);
  387. X        }
  388. X    }
  389. X    }
  390. X    /* Can't use cmd_line() because we want DO_PIPE and IS_PIPE
  391. X     * to remain on -- cmd_line() turns both of them off
  392. X     */
  393. X    if (newav) {
  394. X    save_is_pipe = ison(glob_flags, IS_PIPE);
  395. X    status = do_command(argc, newav, list);
  396. X    if (save_is_pipe)
  397. X        turnon(glob_flags, IS_PIPE);
  398. X    }
  399. X    return status;
  400. }
  401. X
  402. await(argc, argv, list)
  403. int argc;
  404. char *argv[], list[];
  405. {
  406. X    int done = 0, snooze = 30, last_cnt = msg_cnt;
  407. X
  408. X    if (argc && *++argv) {
  409. X    if (!strcmp(*argv, "-?"))
  410. X        return help(0, "await", cmd_help);
  411. X    else if (!strcmp(*argv, "-T")) {
  412. X        if (*++argv && isdigit(**argv) && **argv > '0') {
  413. X        snooze = atoi(*argv);
  414. X        } else {
  415. X        print("await: integer greater than 0 required for -T\n");
  416. X        return -1;
  417. X        }
  418. X    }
  419. X    }
  420. X    Debug("snoozing %d\n", snooze);
  421. X
  422. X    do {
  423. X    if (!(done = check_new_mail()))
  424. X        sleep((unsigned) snooze);
  425. X    } while (!done);
  426. X    /* Known to be safe to pass NULL to chk_two_lists() */
  427. X    if (!chk_option("quiet", "await"))
  428. X    bell();
  429. X
  430. X    while (last_cnt < msg_cnt) {
  431. X    set_msg_bit(list, last_cnt);
  432. X    ++last_cnt;
  433. X    }
  434. X
  435. X    return 0;
  436. }
  437. X
  438. mark_msg(x, argv, list)
  439. int x;
  440. char **argv, list[];
  441. {
  442. X    int i, set_priority = 0;
  443. X    int unmark = argv && argv[0] && argv[0][0] == 'u';
  444. X
  445. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  446. X    return help(0, "mark", cmd_help);
  447. X
  448. X    /* command must be "mark [ -[A|B|C|D|E] ] [msg_list]" */
  449. X    if (!unmark && argv && *argv && **argv == '-') {
  450. X    if (!argv[0][1])
  451. X        set_priority = -1; /* special case for clearing priority */
  452. X    else if ((set_priority = (upper(argv[0][1]) - 'A' + 1)) < 1 ||
  453. X          set_priority > MAX_PRIORITY) {
  454. X        print("mark: priority -A through -%c required (- to clear)\n",
  455. X        MAX_PRIORITY + 'A');
  456. X        return -1;
  457. X    }
  458. X    ++argv;
  459. X    }
  460. X    if (x && (x = get_msg_list(argv, list)) == -1)
  461. X    return -1;
  462. X    argv += x;
  463. X    /* if extraneous args exist or the priority was misspecified... */
  464. X    if (argv[0]) {
  465. X    print("Unknown arg: %s.  mark -? for help.\n", *argv);
  466. X    return -1;
  467. X    }
  468. X    for (x = 0; x < msg_cnt; x++)
  469. X    if (msg_bit(list, x)) {
  470. X        if (set_priority)
  471. X        /* could be setting priority or clearing all priorities */
  472. X        for (i = 1; i <= MAX_PRIORITY; i++)
  473. X            turnoff(msg[x].m_flags, M_PRIORITY(i));
  474. X        if (unmark)
  475. X        turnoff(msg[x].m_flags, M_PRIORITY(0));
  476. X        else if (set_priority > 0) {
  477. X        turnon(msg[x].m_flags, M_PRIORITY(set_priority)|DO_UPDATE);
  478. X        turnon(glob_flags, DO_UPDATE);
  479. X        } else if (set_priority == 0)
  480. X        turnon(msg[x].m_flags, M_PRIORITY(0));
  481. X    }
  482. X    if (istool > 1)
  483. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  484. X    return 0;
  485. }
  486. SHAR_EOF
  487. echo 'File command2.c is complete' &&
  488. chmod 0644 command2.c ||
  489. echo 'restore of command2.c failed'
  490. Wc_c="`wc -c < 'command2.c'`"
  491. test 13555 -eq "$Wc_c" ||
  492.     echo 'command2.c: original size 13555, current size' "$Wc_c"
  493. rm -f _shar_wnt_.tmp
  494. fi
  495. # ============= commands.c ==============
  496. if test -f 'commands.c' -a X"$1" != X"-c"; then
  497.     echo 'x - skipping commands.c (File already exists)'
  498.     rm -f _shar_wnt_.tmp
  499. else
  500. > _shar_wnt_.tmp
  501. echo 'x - extracting commands.c (Text)'
  502. sed 's/^X//' << 'SHAR_EOF' > 'commands.c' &&
  503. /* @(#)commands.c    (c) copyright 10/18/86 (Dan Heller) */
  504. X
  505. #include "mush.h"
  506. X
  507. /*
  508. X * Note that all of the routines in here act upon and return 0 or -1.
  509. X * if -1, then the main loop will clear message lists.
  510. X */
  511. X
  512. struct cmd cmds[] = {
  513. #ifdef SIGSTOP
  514. X    { "stop", stop },
  515. #endif /* SIGSTOP */
  516. X    { "?",       question_mark },{ "sh", sh },
  517. X    { "alias",       do_alias    },  { "unalias",    do_alias   },
  518. X    { "expand",      do_alias    },  { "cmd",     do_alias   },
  519. X    { "uncmd",       do_alias    },  { "from",    do_from    },
  520. X    { "un_hdr",      do_alias    },  { "my_hdr",      do_alias   },
  521. X    { "fkey",       do_alias    },  { "unfkey",     do_alias   },
  522. X    { "set",       set         },  { "unset",     set        },
  523. X    { "ignore",      set         },  { "unignore", set        },
  524. X    { "version",  do_version  },  { "help",    print_help },
  525. X    { "pick",       do_pick     },  { "sort",     sort        },
  526. X    { "next",      readmsg     },  { "previous", readmsg    },
  527. X    { "type",     readmsg     },  { "print",    readmsg    },
  528. X    { "history",  disp_hist   },  { "top",    readmsg       },
  529. X    { "saveopts", save_opts   },  { "source",   source        },
  530. X    { "headers",  do_hdrs     },  { "ls",    ls       },
  531. X    { "folder",   folder      },  { "update",   folder     },
  532. X    { "cd",       cd          },  { "pwd",    cd        },
  533. X    { "exit",      mush_quit   },  { "quit",     mush_quit  },
  534. X    { "write",       save_msg    },  { "save",     save_msg   },
  535. X    { "copy",       save_msg    },  { "folders",  folders    },
  536. X    { "merge",      merge_folders },
  537. X    { "mark",      mark_msg    },  { "unmark",    mark_msg   },
  538. #ifdef CURSES
  539. X    { "curses",   curses_init },  { "bind",    bind_it    },
  540. X    { "unbind",   bind_it     },  { "bind-macro", bind_it  },
  541. X    { "unbind-macro", bind_it  },
  542. #endif /* CURSES */
  543. X    { "map",      bind_it     },  { "unmap",       bind_it    },
  544. X    { "map!",     bind_it     },  { "unmap!",      bind_it    },
  545. X    { "preserve", preserve    },  { "unpreserve",  preserve   },
  546. X    { "replyall", respond     },  { "replysender", respond    },
  547. X    { "delete",      delete      },  { "undelete",    delete     },
  548. X    { "mail",       do_mail     },  { "echo",       do_echo    },
  549. X    { "lpr",      lpr          },  { "alternates",  alts       },
  550. X    { "edit",      edit_msg    },  { "flags",       msg_flags  },
  551. X    { "pipe",     pipe_msg    },  { "eval",       eval_cmd   },
  552. X    { "undigest", do_undigest },  { "await",       await      },
  553. X    { NULL, mush_quit }
  554. };
  555. X
  556. struct cmd ucb_cmds[] = {
  557. X    { "t",   readmsg   }, { "n",  readmsg  }, { "p", readmsg  },
  558. X    { "+",   readmsg   }, { "-",  readmsg  }, { "P", readmsg  },
  559. X    { "Print", readmsg }, { "T",  readmsg  }, { "Type", readmsg },
  560. X    { "x",   mush_quit }, { "q", mush_quit }, { "xit", mush_quit },
  561. X    { ":a",  do_hdrs   }, { ":d", do_hdrs  }, { ":r", do_hdrs },
  562. X    { ":o",  do_hdrs   }, { ":u", do_hdrs  }, { ":n", do_hdrs },
  563. X    { ":s",  do_hdrs   }, { ":p", do_hdrs  }, { ":m", do_hdrs },
  564. X    { "z",   do_hdrs   }, { "z-", do_hdrs  }, { "z+", do_hdrs },
  565. X    { "h",   do_hdrs   }, { "H",  do_hdrs  },
  566. X    { "f",   do_from   }, { "m",  do_mail  }, { "alts", alts  },
  567. X    { "d",   delete    }, { "dt", delete   }, { "dp", delete  },
  568. X    { "u",   delete    }, { "fo", folder   },
  569. X    { "s",   save_msg  }, { "co", save_msg }, { "w", save_msg },
  570. X    { "pre", preserve  }, { "unpre", preserve },
  571. X    { "R",   respond   }, { "r",   respond },
  572. X    { "reply", respond }, { "respond", respond },
  573. X    { "v",   edit_msg  }, { "e",   edit_msg },
  574. X    { NULL, mush_quit }
  575. };
  576. X
  577. struct cmd hidden_cmds[] = {
  578. X    { "about",    print_help  },
  579. X    { "debug", toggle_debug }, { "open",     nopenfiles },
  580. X    { "stty",    my_stty     },
  581. X    { "setenv",    Setenv      }, { "unsetenv",     Unsetenv   },
  582. X    { "printenv", Printenv  }, { "Pipe",    pipe_msg   },
  583. X    { NULL, mush_quit }
  584. };
  585. X
  586. toggle_debug(argc, argv)
  587. int argc;
  588. char **argv;
  589. {
  590. X    if (argc < 2) /* no value -- toggle "debug" (off/on) */
  591. X    debug = !debug;
  592. X    else
  593. X    debug = atoi(*++argv);
  594. X    print("debugging value: %d\n", debug);
  595. X    return 0;
  596. }
  597. X
  598. /* if + was specified, then print messages without headers.
  599. X * n or \n (which will be NULL) will print next unread or undeleted message.
  600. X */
  601. readmsg(x, argv, list)
  602. int x;
  603. char **argv, list[];
  604. {
  605. X    register char *p = x? *argv : NULL;
  606. X    register long flg = 0;
  607. X    extern FILE *ed_fp;
  608. X
  609. X    if (x && *++argv && !strcmp(*argv, "-?"))
  610. X    return help(0, "readmsg", cmd_help);
  611. X    /* View a message as long as user isn't in the editor.
  612. X     * If ed_fp is not null, then we've got the
  613. X     * file open for typing.  If it's NULL, then an editor is going.
  614. X     */
  615. X    if (ison(glob_flags, IS_GETTING) && !ed_fp) {
  616. X    print("Not while you're in the editor, you don't.\n");
  617. X    return -1;
  618. X    }
  619. X    if (!msg_cnt) {
  620. X    print("No messages.\n");
  621. X    return -1;
  622. X    }
  623. X    if (x)
  624. X    if (!strcmp(p, "top"))
  625. X        turnon(flg, M_TOP);
  626. X    else if (*p == '+') {
  627. X        turnon(flg, NO_PAGE);
  628. X        turnon(flg, NO_HEADER);
  629. X    } else if (isupper(*p))
  630. X        turnon(flg, NO_IGNORE);
  631. X
  632. X    if (x && (x = get_msg_list(argv, list)) == -1)
  633. X    return -1;
  634. X    else if (x == 0) {  /* no arguments were parsed (or given) */
  635. X    /* get_msg_list sets current msg on */
  636. X    if (isoff(glob_flags, IS_PIPE))
  637. X        unset_msg_bit(list, current_msg);
  638. X    /* most commands move to the "next" message. type and print don't */
  639. X    if ((!p || !*p || *p == 'n' || *p == '+') && current_msg < msg_cnt &&
  640. X                    isoff(msg[current_msg].m_flags, UNREAD))
  641. X        current_msg++;
  642. X    if (p && (*p == '-' || !strcmp(p, "previous"))) {
  643. X        while (--current_msg >= 0 &&
  644. X        (ison(msg[current_msg].m_flags, DELETE) ||
  645. X         ison(msg[current_msg].m_flags, SAVED)))
  646. X        ;
  647. X        if (current_msg < 0) {
  648. X        print("No previous message.\n");
  649. X        current_msg = 0;
  650. X        return -1;
  651. X        }
  652. X    } else {
  653. X        /*
  654. X         * To be compatible with ucb-mail, find the next available unread
  655. X         * message.  If at the end, only wrap around if "wrap" is set.
  656. X         */
  657. X        if (current_msg == msg_cnt && do_set(set_options, "wrap"))
  658. X        current_msg = 0;
  659. X        /* "type" or "print" prints the current only -- "next" goes on.. */
  660. X        if (!p || !*p || *p == 'n')
  661. X        while (current_msg < msg_cnt &&
  662. X            (ison(msg[current_msg].m_flags, DELETE) ||
  663. X             ison(msg[current_msg].m_flags, SAVED)))
  664. X            current_msg++;
  665. X        if (current_msg >= msg_cnt) {
  666. X        print("No more messages.\n");
  667. X        current_msg = msg_cnt - 1;
  668. X        return -1;
  669. X        }
  670. X    }
  671. X    if (isoff(glob_flags, IS_PIPE))
  672. X        set_msg_bit(list, current_msg);
  673. X    }
  674. X    current_msg = 0;
  675. X    for (x = 0; x < msg_cnt; x++)
  676. X    if (msg_bit(list, x)) {
  677. X        current_msg = x;
  678. #ifdef SUNTOOL
  679. X        if (istool > 1) {
  680. X        read_mail(NO_ITEM, 0, NO_EVENT);
  681. X        return 0;
  682. X        }
  683. #endif /* SUNTOOL */
  684. X        display_msg(x, flg);
  685. X    }
  686. X    return 0;
  687. }
  688. X
  689. preserve(n, argv, list)
  690. int n;        /* no use for argc, so use space for a local variable */
  691. char **argv, list[];
  692. {
  693. X    register int unpre;
  694. X
  695. X    unpre = !strncmp(*argv, "un", 2);
  696. X    if (*++argv && !strcmp(*argv, "-?"))
  697. X    return help(0, "preserve", cmd_help);
  698. X    if (get_msg_list(argv, list) == -1)
  699. X    return -1;
  700. X    for (n = 0; n < msg_cnt; n++)
  701. X    if (msg_bit(list, n))
  702. X        if (unpre) {
  703. X        if (ison(msg[n].m_flags, PRESERVE)) {
  704. X            turnoff(msg[n].m_flags, PRESERVE);
  705. X            turnon(glob_flags, DO_UPDATE);
  706. X        }
  707. X        } else {
  708. X        if (isoff(msg[n].m_flags, PRESERVE)) {
  709. X            turnon(msg[n].m_flags, PRESERVE);
  710. X            turnon(glob_flags, DO_UPDATE);
  711. X        }
  712. X        }
  713. X    if (istool)
  714. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  715. X    return 0;
  716. }
  717. X
  718. lpr(n, argv, list)
  719. int n;  /* no use for argc, so use its address space for a variable */
  720. char **argv, list[];
  721. {
  722. X    register FILE    *pp;
  723. X    register long     flags = 0;
  724. X    char        print_cmd[128], *printer, c, *cmd;
  725. X    int            total = 0;
  726. X    SIGRET        (*oldint)(), (*oldquit)();
  727. X
  728. #ifdef PRINTER_OPT
  729. X    char *opt = PRINTER_OPT;
  730. #else
  731. X    char opt[2];
  732. #ifdef SYSV
  733. X    opt[0] = 'd';
  734. #else
  735. X    opt[0] = 'P';
  736. #endif /* SYSV */
  737. X    opt[1] = 0;
  738. #endif /* PRINTER_OPT */
  739. X
  740. X    if (!chk_option("alwaysignore", "printer"))
  741. X    turnon(flags, NO_IGNORE);
  742. #ifdef MSG_SEPARATOR
  743. X    turnon(flags, NO_SEPARATOR);
  744. #endif /* MMDF */
  745. X    if (!(printer = do_set(set_options, "printer")) || !*printer)
  746. X    printer = DEF_PRINTER;
  747. X    while (argv && *++argv && **argv == '-') {
  748. X    n = 1;
  749. X    while (c = argv[0][n++])
  750. X        switch(c) {
  751. X        case 'n': turnon(flags, NO_HEADER);
  752. X        when 'h': turnoff(flags, NO_IGNORE);
  753. X        when 'P': case 'd':
  754. #ifndef PRINTER_OPT
  755. X            opt[0] = argv[0][n-1];
  756. #endif /* PRINTER_OPT */
  757. X            if (!argv[0][n] && !(n = 0, *++argv)) {
  758. X                print("specify printer!\n");
  759. X                return -1;
  760. X            }
  761. X            printer = argv[0] + n;
  762. X            n += strlen(printer);
  763. X        otherwise: return help(0, "lpr", cmd_help);
  764. X        }
  765. X    }
  766. X    if (get_msg_list(argv, list) == -1)
  767. X    return -1;
  768. X
  769. X    if (cmd = do_set(set_options, "print_cmd"))
  770. X    (void) strcpy(print_cmd, cmd);
  771. X    else
  772. X    (void) sprintf(print_cmd, "%s %s%s", LPR, opt, printer);
  773. X    Debug("print command: %s\n", print_cmd);
  774. X    if (!(pp = popen(print_cmd, "w"))) {
  775. X    error("cannot print");
  776. X    return -1;
  777. X    }
  778. X    on_intr();
  779. X    for (n = 0; isoff(glob_flags, WAS_INTR) && n < msg_cnt; n++) {
  780. X    if (msg_bit(list, n)) {
  781. X        if (total++)
  782. X        (void) fputc('\f', pp); /* send a formfeed for multiple copies */
  783. X        print("printing message %d...", n+1);
  784. X        print_more("(%d lines)\n", copy_msg(n, pp, (u_long) flags, NULL));
  785. X        turnon(msg[n].m_flags, PRINTED|DO_UPDATE);
  786. X        turnon(glob_flags, DO_UPDATE);
  787. X    }
  788. X    }
  789. X    off_intr();
  790. X    (void) pclose(pp);
  791. X    print_more("%d message%s printed ", total, (total==1)? "": "s");
  792. X    if (cmd)
  793. X    print_more("through \"%s\".\n", cmd);
  794. X    else
  795. X    print_more("at \"%s\".\n", printer);
  796. X    return 0;
  797. }
  798. X
  799. /* save [msg_list] [file] */
  800. save_msg(n, argv, list)   /* argc isn't used, so use space for variable 'n' */
  801. int n;
  802. char **argv, list[];
  803. {
  804. X    register FILE    *mail_fp = NULL_FILE;
  805. X    register char     *file = NULL, *mode, firstchar = **argv, *tmp = ".";
  806. X    int         msg_number, force = 0, by_subj = 0, by_author = 0;
  807. X    char        buf[MAXPATHLEN];
  808. X    long         flg = 0;
  809. X
  810. X    while (*++argv)
  811. X    if (*argv[0] != '-')
  812. X        break;
  813. X    else
  814. X        switch (argv[0][1]) {
  815. X        case 'S' :
  816. X            by_subj = 2;
  817. X        when 's' :
  818. X            by_subj = 1;
  819. X        when 'A' :
  820. X            by_author = 2;
  821. X        when 'a' :
  822. X            by_author = 1;
  823. X        when 'f' :
  824. X            force = 1;
  825. X        otherwise :
  826. X            return help(0, "save", cmd_help);
  827. X        }
  828. X    if (!force && (force = (*argv && !strcmp(*argv, "!"))))
  829. X    argv++;
  830. X    if ((n = get_msg_list(argv, list)) == -1)
  831. X    return -1;
  832. X    argv += n;
  833. X    if (*argv && *(file = *argv) == '\\')
  834. X    file++;
  835. X    else if (!file && !by_subj && !by_author) {
  836. X    /* if no filename specified, save in ~/mbox */
  837. X    if (firstchar == 'w') {
  838. X        /* mbox should have headers. If he really wants it, specify it */
  839. X        print("Must specify file name for 'w'\n");
  840. X        return -1;
  841. X    }
  842. X    if (!(file = do_set(set_options, "mbox")) || !*file)
  843. X        file = DEF_MBOX;
  844. X    }
  845. X    n = 1; /* tell getpath to ignore no such file or directory */
  846. X    if (file)
  847. X    tmp = getpath(file, &n);
  848. X    if (n < 0) {
  849. X    print("%s: %s\n", file, tmp);
  850. X    return -1;
  851. X    } else if (n && !by_subj && !by_author) {
  852. X    print("%s is a directory\n", file);
  853. X    return -1;
  854. X    }
  855. X    file = tmp;
  856. X    if (force || Access(file, F_OK))
  857. X    mode = "w", force = 0;
  858. X    else
  859. X    mode = "a";
  860. X    if (firstchar != 'w' && *mode == 'a' && !by_author && !by_subj &&
  861. X        !test_folder(file, "not a folder, save anyway?"))
  862. X    return 0;
  863. X    /*
  864. X     * open the file for writing (appending) unless we're saving by subject
  865. X     * or author name in which case we'll determine the filename later
  866. X     */
  867. X    if (!by_author && !by_subj && !(mail_fp = lock_fopen(file, mode))) {
  868. X    error("cannot save in \"%s\"", file);
  869. X    return -1;
  870. X    }
  871. X
  872. #ifdef SUNTOOL
  873. X    if (istool)
  874. X    timeout_cursors(TRUE);
  875. #endif /* SUNTOOL */
  876. X    if (!chk_option("alwaysignore", "save"))
  877. X    turnon(flg, NO_IGNORE);    /* presently overridden by UPDATE_STATUS */
  878. X    if (firstchar == 'w') {
  879. X    turnon(flg, NO_HEADER);
  880. #ifdef MMDF
  881. X    turnon(flg, NO_SEPARATOR);
  882. #endif /* MMDF */
  883. X    } else
  884. X    turnon(flg, UPDATE_STATUS);
  885. X
  886. X    for (n = msg_number = 0; msg_number < msg_cnt; msg_number++)
  887. X    if (msg_bit(list, msg_number)) {
  888. X        if ((by_author || by_subj) && !mail_fp) {
  889. X        char buf2[256], addr[256];
  890. X        register char *p, *p2;
  891. X        if (by_subj) {
  892. X            if (p = header_field(msg_number, "subject")) {
  893. X            /* convert spaces and non-alpha-numerics to '_' */
  894. X            if (!lcase_strncmp(p, "re:", 3)) {
  895. X                p += 3;
  896. X                skipspaces(0);
  897. X            }
  898. X            for (p2 = p; *p2; p2++)
  899. X                if (!isalnum(*p2) && !index(".,@#$%-+=", *p2))
  900. X                *p2 = '_';
  901. X            } else
  902. X            p = "mbox";
  903. X        } else {
  904. X            (void) reply_to(msg_number, FALSE, buf2);
  905. X            (void) get_name_n_addr(buf2, NULL, addr);
  906. X            if (p = rindex(addr, '!'))
  907. X            p++;
  908. X            else
  909. X            p = addr;
  910. X            if (p2 = any(p, "@%"))
  911. X            *p2 = 0;
  912. X        }
  913. X        if (!p || !*p)
  914. X            p = "tmp";
  915. X        (void) sprintf(buf, "%s/%s", file, p);
  916. X        if (force || Access(buf, F_OK))
  917. X            mode = "w";
  918. X        else
  919. X            mode = "a";
  920. X        if (firstchar != 'w' && *mode == 'a' &&
  921. X            !test_folder(buf, "not a folder, save anyway?")) {
  922. X            if (by_author == 2 || by_subj == 2)
  923. X            break;
  924. X            continue;
  925. X        }
  926. X        if (!(mail_fp = lock_fopen(buf, mode))) {
  927. X            error("cannot save in \"%s\"", buf);
  928. X            if (by_author == 2 || by_subj == 2)
  929. X            break;
  930. X            continue;
  931. X        }
  932. X        }
  933. X        print("%sing msg %d ... ",
  934. X        (firstchar == 's')? "Sav" : "Writ", msg_number+1);
  935. X        print_more("(%d lines)",
  936. X        copy_msg(msg_number, mail_fp, (u_long) flg, NULL));
  937. X        if (by_author == 1 || by_subj == 1) {
  938. X        print_more(" in \"%s\"", buf);
  939. X        (void) close_lock(buf, mail_fp), mail_fp = NULL_FILE;
  940. X        }
  941. X        print_more("\n");
  942. X        n++;
  943. X        if (isoff(msg[msg_number].m_flags, SAVED) && firstchar != 'c') {
  944. X        turnon(glob_flags, DO_UPDATE);
  945. X        turnon(msg[msg_number].m_flags, SAVED|DO_UPDATE);
  946. X        }
  947. X    }
  948. X    if (mail_fp) {
  949. X    (void) close_lock(file, mail_fp);
  950. X    if (!file)
  951. X        file = buf;
  952. X    print_more("%s %d msg%s to %s\n",
  953. X        (*mode == 'a')? "Appended" : "Saved", n, (n != 1)? "s": "", file);
  954. X    }
  955. #ifdef SUNTOOL
  956. X    if (istool) {
  957. X    extern Panel_item folder_item, save_item;
  958. X    timeout_cursors(FALSE);
  959. X    if (firstchar != 'c' && n > 0)
  960. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  961. X    if (*mode == 'w' && n > 0) {
  962. #ifndef NO_WALK_MENUS
  963. X        create_folder_menus();
  964. #else /* NO_WALK_MENUS */
  965. X        add_folder_to_menu(folder_item, 3);
  966. X        add_folder_to_menu(save_item, 1);
  967. #endif /* NO_WALK_MENUS */
  968. X    }
  969. X    }
  970. #endif /* SUNTOOL */
  971. X    return 0;
  972. }
  973. X
  974. respond(n, argv, list)
  975. int n;  /* no use for argc, so use its address space for a variable */
  976. char **argv, *list;
  977. {
  978. X    register char *cmd = *argv;
  979. X    char list1[MAXMSGS_BITS];
  980. X    int cur_msg = current_msg, save_cnt = msg_cnt;
  981. X
  982. X    if (*++argv && !strcmp(*argv, "-?"))
  983. X    return help(0, "respond", cmd_help);
  984. X    if ((n = get_msg_list(argv, list)) == -1)
  985. X    return -1;
  986. X
  987. X    /* make into our own list so ~: commands don't overwrite this list */
  988. X    bitput(list, list1, MAXMSGS, =);
  989. X
  990. X    /* back up one arg to replace "cmd" in the new argv[0] */
  991. X    argv += (n-1);
  992. X    if (!strcmp(cmd, "replyall"))
  993. X    Upper(*cmd);
  994. X    if (n > 0)
  995. X    strdup(argv[0], cmd);
  996. X
  997. X    /* make sure the *current* message is the one being replied to */
  998. X    for (current_msg = -1, n = 0; n < msg_cnt && current_msg == -1; n++)
  999. X    if (msg_bit(list1, n) && current_msg == -1)
  1000. X        current_msg = n;
  1001. X    if (current_msg == -1) { /* "reply -" can cause this to happen */
  1002. X    current_msg = cur_msg;
  1003. X    return -1;
  1004. X    }
  1005. X    if (do_mail(1 /* ignored */, argv, list) == -1)
  1006. X    return -1;
  1007. X    /* New mail may have arrived during do_mail(), which will change
  1008. X     * the msg_cnt.  Use the old count when examining the list of bits
  1009. X     * to set the replied flag, or the wrong messages can be marked.
  1010. X     */
  1011. X    for (n = 0; n < save_cnt; n++)
  1012. X    if (msg_bit(list1, n)) {
  1013. X        /* set_isread(n); */
  1014. X        set_replied(n); /* only if mail got delivered */
  1015. X    }
  1016. X    if (istool)
  1017. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  1018. X    /* copy the specified list back into msg_list */
  1019. X    bitput(list1, list, MAXMSGS, =);
  1020. X    return 0;
  1021. }
  1022. X
  1023. /* cd to a particular directory specified by "p" */
  1024. cd(x, argv) /* argc, unused -- use space for a non-register variable */
  1025. int x;
  1026. char **argv;
  1027. {
  1028. X    char *cwd, buf[MAXPATHLEN];
  1029. X    register char *path, *p = argv[1], *cdpath = NULL, *p2;
  1030. X    int err = 0;
  1031. X
  1032. X    if (argv && argv[1] && !strcmp(argv[1], "-?"))
  1033. X    return help(0, argv[0], cmd_help);
  1034. X
  1035. X    if (!strcmp(*argv, "pwd")) {
  1036. X    set_cwd(); /* reset in case some dummy changed $cwd */
  1037. X        if ((p = do_set(set_options, "cwd")) && *p) {
  1038. X        print("%s\n", p);
  1039. X        return 0;
  1040. X    }
  1041. X    return -1;
  1042. X    }
  1043. X    if (!p || !*p) /* if no args, pwd = ".", cd = ~ */
  1044. X    p = (**argv == 'p')? "." : "~";
  1045. X    /* if a full path was not specified, loop through cdpath */
  1046. X    if (**argv != 'p' && *p != '/' && *p != '~' && *p != '+')
  1047. X    cdpath = do_set(set_options, "cdpath");
  1048. X    (void) strcpy(buf, p);
  1049. X    do  {
  1050. X    err = x = 0;
  1051. X    path = getpath(buf, &x);
  1052. X    if (x != 1 || chdir(path) == -1) {
  1053. X        err = errno;
  1054. X        if (cdpath) {
  1055. X        char c;
  1056. X        if (p2 = any(cdpath, " \t:"))
  1057. X            c = *p2, *p2 = 0;
  1058. X        (void) sprintf(buf, "%s/%s", cdpath, p);
  1059. X        if (cdpath = p2) /* assign and compare to NULL */
  1060. X            *p2 = c;
  1061. X        while (cdpath && (isspace(*cdpath) || *cdpath == ':'))
  1062. X            cdpath++;
  1063. X        }
  1064. X    }
  1065. X    } while (err && cdpath && *cdpath);
  1066. X    if (err)
  1067. X    error(p);
  1068. X    set_cwd();
  1069. X    if ((istool || iscurses || err) && (cwd = do_set(set_options, "cwd"))) {
  1070. X    if (err)
  1071. X        turnon(glob_flags, CONT_PRNT);
  1072. X    if (iscurses || istool || ison(glob_flags, WARNING))
  1073. X        print("Working dir: %s\n", cwd);
  1074. X    }
  1075. X    return 0;
  1076. }
  1077. X
  1078. mush_quit(argc, argv)
  1079. int argc;
  1080. char **argv;
  1081. {
  1082. X    u_long updated = ison(glob_flags, DO_UPDATE);
  1083. X
  1084. X    if (argc > 1) {
  1085. X    if (!strcmp(argv[1], "-?"))
  1086. X        return help(0, "quit", cmd_help);
  1087. X    else {
  1088. X        print("%s: too many arguments\n", argv[0]);
  1089. X        return -1;
  1090. X    }
  1091. X    }
  1092. X    if ((!argc || (*argv && **argv == 'q')) && !copyback("Really Quit? ",TRUE))
  1093. X    return -1;
  1094. #ifdef CURSES
  1095. X    if (iscurses) {
  1096. X    /* we may already be on the bottom line; some cases won't be */
  1097. X    move(LINES-1, 0), refresh();
  1098. X    if (updated)
  1099. X        putchar('\n');
  1100. X    }
  1101. #endif /* CURSES */
  1102. X    cleanup(0);
  1103. #ifdef lint
  1104. X    return 0;
  1105. #endif /* lint */
  1106. }
  1107. X
  1108. delete(argc, argv, list)
  1109. int argc;
  1110. char **argv, list[];
  1111. {
  1112. X    register int prnt_next, undel = argc && **argv == 'u';
  1113. X    int old_msg = current_msg;
  1114. X
  1115. X    prnt_next = (argv && (!strcmp(*argv, "dt") || !strcmp(*argv, "dp")));
  1116. X
  1117. X    if (argc && *++argv && !strcmp(*argv, "-?"))
  1118. X    return help(0, "delete", cmd_help);
  1119. X
  1120. X    if (ison(glob_flags, READ_ONLY)) {
  1121. X    print("Folder is read-only\n");
  1122. X    return -1;
  1123. X    }
  1124. X
  1125. X    if (get_msg_list(argv, list) == -1)
  1126. X    return -1;
  1127. X    for (argc = 0; argc < msg_cnt; argc++)
  1128. X    if (msg_bit(list, argc))
  1129. X        if (undel)
  1130. X        turnoff(msg[argc].m_flags, DELETE);
  1131. X        else
  1132. X        turnon(msg[argc].m_flags, DELETE|DO_UPDATE);
  1133. X
  1134. X    /* only if current_msg has been affected && not in curses mode */
  1135. X    if (prnt_next == 0 && !iscurses && msg_bit(list, current_msg))
  1136. X    prnt_next = !!do_set(set_options, "autoprint"); /* change to boolean */
  1137. X
  1138. X    turnon(glob_flags, DO_UPDATE);
  1139. X
  1140. X    /* goto next available message if current was just deleted.
  1141. X     * If there are no more messages, turnoff prnt_next.
  1142. X     */
  1143. X    if (!iscurses && !undel && msg_bit(list, current_msg))
  1144. X    (void) next_msg();
  1145. X    else
  1146. X    prnt_next = 0;
  1147. X
  1148. X    if (prnt_next && !undel && !iscurses && isoff(glob_flags, DO_PIPE))
  1149. X    if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
  1150. X        display_msg(current_msg, (long)0);
  1151. X    else {
  1152. X        if (ison(msg[current_msg].m_flags, DELETE))
  1153. X        print("No more messages.\n");
  1154. X        current_msg = old_msg;
  1155. X    }
  1156. #ifdef SUNTOOL
  1157. X    if (istool && isoff(glob_flags, IS_PIPE)) {
  1158. X    /* If deleted messages are to be shown and the current message
  1159. X     * has moved off the screen, or if all messages are deleted,
  1160. X     * redraw the whole display.
  1161. X     * Otherwise, redraw the display starting at the current
  1162. X     * topmost message, to bring the new current message on.
  1163. X     */
  1164. X    if (current_msg != old_msg && do_set(set_options, "show_deleted") ||
  1165. X        n_array[0] > msg_cnt)
  1166. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  1167. X    else {
  1168. X        char *av[3], buf[8];
  1169. X        /* do_hdrs(0, ...) repositions the display, so pass an arg */
  1170. X        av[0] = "h";
  1171. X        av[1] = sprintf(buf, "%d", n_array[0] + 1);
  1172. X        av[2] = NULL;
  1173. X        (void) do_hdrs(2, av, NULL);
  1174. X    }
  1175. X    }
  1176. #endif /* SUNTOOL */
  1177. X    return 0;
  1178. }
  1179. X
  1180. /*
  1181. X * historically from the "from" command in ucb-mail, this just prints
  1182. X * the composed header of the messages set in list or in pipe.
  1183. X */
  1184. do_from(n, argv, list)
  1185. int n;
  1186. char **argv, list[];
  1187. {
  1188. X    int inc_cur_msg = 0;
  1189. X
  1190. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  1191. X    return help(0, "from", cmd_help);
  1192. X    if (argv && *argv && (!strcmp(*argv, "+") || !strcmp(*argv, "-")))
  1193. X    if (!strcmp(*argv, "+")) {
  1194. X        if (!*++argv && current_msg < msg_cnt-1)
  1195. X        current_msg++;
  1196. X        inc_cur_msg = 1;
  1197. X    } else if (!strcmp(*argv, "-")) {
  1198. X        if (!*++argv && current_msg > 0)
  1199. X        current_msg--;
  1200. X        inc_cur_msg = -1;
  1201. X    }
  1202. X    if ((n = get_msg_list(argv, list)) == -1)
  1203. X    return -1;
  1204. X    else if (argv && argv[n]) {
  1205. X    u_long save_flags = glob_flags;
  1206. X    char *newargv[6], buf[BUFSIZ];
  1207. X    (void) argv_to_string(buf, &argv[n]);
  1208. X    newargv[0] = "pick";
  1209. X    if (n == 0) {
  1210. X        newargv[++n] = "-r";
  1211. X        newargv[++n] = "*";
  1212. X        turnoff(glob_flags, IS_PIPE);
  1213. X    } else {
  1214. X        n = 0;
  1215. X        turnon(glob_flags, IS_PIPE);
  1216. X    }
  1217. X    newargv[++n] = "-f";
  1218. X    newargv[++n] = buf;
  1219. X    newargv[++n] = NULL;
  1220. X    Debug("calling: "), print_argv(newargv);
  1221. X    turnon(glob_flags, DO_PIPE);
  1222. X    (void) do_pick(n, newargv, list);
  1223. X    glob_flags = save_flags;
  1224. X    }
  1225. X    for (n = 0; n < msg_cnt; n++)
  1226. X    if (msg_bit(list, n)) {
  1227. X        wprint("%s\n", compose_hdr(n));
  1228. X        /* if -/+ given, set current message pointer to this message */
  1229. X        if (inc_cur_msg) {
  1230. X        current_msg = n;
  1231. X        /* if - was given, then set to first listed message.
  1232. X         * otherwise, + means last listed message -- let it go...
  1233. X         */
  1234. X        if (inc_cur_msg < 0)
  1235. X            inc_cur_msg = 0;
  1236. X        }
  1237. X    }
  1238. X    return 0;
  1239. }
  1240. X
  1241. static
  1242. sorter(cmd1, cmd2)
  1243. register struct cmd *cmd1, *cmd2;
  1244. {
  1245. X    return strcmp(cmd1->command, cmd2->command);
  1246. }
  1247. X
  1248. question_mark(x, argv)
  1249. int x;
  1250. char **argv;
  1251. {
  1252. X    int n = 0, N = sizeof cmds / sizeof (struct cmd);
  1253. X    char *Cmds[sizeof cmds/sizeof(struct cmd)], *p, buf[30];
  1254. X
  1255. X    if (!*++argv) {
  1256. X    if (N % 5)
  1257. X        N = N / 5 + 1;
  1258. X    else
  1259. X        N = N / 5;
  1260. X
  1261. X    qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
  1262. X                sizeof(struct cmd), sorter);
  1263. X
  1264. X    for (x = 0; x < N * 5; x++) {
  1265. X        if (!(x % 5))
  1266. X        if (!(p = Cmds[n++] = malloc(80))) {
  1267. X            error("malloc in question_mark()");
  1268. X            free_vec(Cmds);
  1269. X            return -1;
  1270. X        }
  1271. X        if (x%5*N+n < sizeof cmds / sizeof (struct cmd))
  1272. X        p += strlen(sprintf(p, "%-14.14s ", cmds[x%5*N+n-1].command));
  1273. X    }
  1274. X    Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
  1275. X    Cmds[n] = NULL;
  1276. X    (void) help(0, (char *) Cmds, NULL);
  1277. X    free_vec(Cmds);
  1278. X    } else if (!strcmp(*argv, "-?"))
  1279. X    return help(0, "?", cmd_help);
  1280. X    else {
  1281. X    for (x = 0; cmds[x].command; x++)
  1282. X        if (!strcmp(*argv, cmds[x].command))
  1283. X        return cmd_line(sprintf(buf, "\\%s -?", *argv), msg_list);
  1284. X    print("Unknown command: %s\n", *argv);
  1285. X    }
  1286. X    return 0 - in_pipe();
  1287. }
  1288. SHAR_EOF
  1289. chmod 0644 commands.c ||
  1290. echo 'restore of commands.c failed'
  1291. Wc_c="`wc -c < 'commands.c'`"
  1292. test 22758 -eq "$Wc_c" ||
  1293.     echo 'commands.c: original size 22758, current size' "$Wc_c"
  1294. rm -f _shar_wnt_.tmp
  1295. fi
  1296. # ============= compose.icon ==============
  1297. if test -f 'compose.icon' -a X"$1" != X"-c"; then
  1298.     echo 'x - skipping compose.icon (File already exists)'
  1299.     rm -f _shar_wnt_.tmp
  1300. else
  1301. > _shar_wnt_.tmp
  1302. echo 'x - extracting compose.icon (Text)'
  1303. sed 's/^X//' << 'SHAR_EOF' > 'compose.icon' &&
  1304. /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
  1305. X */
  1306. X    0xFFFF,0xFFFF,0xFFFF,0xF89C,0xFFFF,0xFFFF,0xFFFF,0xF8A2,
  1307. X    0xC000,0x0000,0x0000,0x1A61,0xC000,0x0000,0x0000,0x1A91,
  1308. X    0xC000,0x0000,0x0000,0x1989,0xC000,0x0000,0x0000,0x1A46,
  1309. X    0xC000,0x0000,0x0000,0x1E26,0xC000,0x0000,0x0000,0x1B1A,
  1310. X    0xC003,0x0FDE,0x0000,0x1498,0xC003,0x8FFF,0x0000,0x2968,
  1311. X    0xC000,0x0000,0x0000,0x5262,0xC000,0x0000,0x0000,0xA4A2,
  1312. X    0xC000,0x0000,0x0001,0x4988,0xC000,0x0000,0x0002,0x9288,
  1313. X    0xC000,0x0000,0x0005,0x2622,0xC0E6,0xEFCF,0x79FA,0x4A22,
  1314. X    0xC0F7,0xEFEF,0xFDF4,0x9888,0xC000,0x0000,0x0029,0x3888,
  1315. X    0xC000,0x0000,0x0052,0x5A22,0xC7B9,0xEF9D,0x9DA4,0x9A22,
  1316. X    0xC7FD,0xFFDF,0xDF49,0x1888,0xC000,0x0000,0x0292,0x1888,
  1317. X    0xC000,0x0000,0x0524,0x1A22,0xC73F,0x3CEC,0xFA48,0x1A22,
  1318. X    0xC7BF,0xBEFE,0xF490,0x1888,0xC000,0x0000,0x2920,0x1888,
  1319. X    0xC000,0x0000,0x5240,0x1A22,0xC6E7,0x67E7,0xA4E0,0x1A22,
  1320. X    0xC7F7,0xF7F7,0x49F0,0x1888,0xC000,0x0002,0x9200,0x1888,
  1321. X    0xC000,0x0005,0x2400,0x1A22,0xC79D,0x99EA,0x4F00,0x1A22,
  1322. X    0xC7DF,0xDDF4,0x9F80,0x1888,0xC000,0x0029,0x2000,0x1888,
  1323. X    0xC000,0x0052,0x4000,0x1A22,0xC738,0x00E4,0x8000,0x1A22,
  1324. X    0xC7BC,0x0129,0x0000,0x1888,0xC000,0x0112,0x0000,0x1888,
  1325. X    0xC000,0x020C,0x0000,0x1A22,0xC000,0x0218,0x0000,0x1A22,
  1326. X    0xC000,0x0660,0x0000,0x1888,0xC000,0x0780,0x0000,0x1888,
  1327. X    0xC000,0x0E00,0x0000,0x1A22,0xC000,0x0800,0x0000,0x1A22,
  1328. X    0xC000,0x0000,0x0000,0x1888,0xC000,0x0000,0x0000,0x1888,
  1329. X    0xC000,0x0000,0x0000,0x1A22,0xC000,0x0000,0x0000,0x1A22,
  1330. X    0xC000,0x0000,0x2000,0x1888,0xC000,0x0000,0x2000,0x1888,
  1331. X    0xC006,0x888E,0x2C00,0x1A22,0xC005,0x4891,0x3200,0x1A22,
  1332. X    0xC005,0x4890,0x2200,0x1888,0xC005,0x488E,0x2200,0x1888,
  1333. X    0xC005,0x4881,0x2200,0x1A22,0xC005,0x4991,0x2200,0x1A22,
  1334. X    0xC005,0x468E,0x2200,0x1888,0xC000,0x0000,0x0000,0x1888,
  1335. X    0xC000,0x0000,0x0000,0x1A22,0xC000,0x0000,0x0000,0x1A22,
  1336. X    0xC000,0x0000,0x0000,0x1888,0xC000,0x0000,0x0000,0x1888,
  1337. X    0xFFFF,0xFFFF,0xFFFF,0xFA22,0xFFFF,0xFFFF,0xFFFF,0xFA22
  1338. SHAR_EOF
  1339. chmod 0644 compose.icon ||
  1340. echo 'restore of compose.icon failed'
  1341. Wc_c="`wc -c < 'compose.icon'`"
  1342. test 1933 -eq "$Wc_c" ||
  1343.     echo 'compose.icon: original size 1933, current size' "$Wc_c"
  1344. rm -f _shar_wnt_.tmp
  1345. fi
  1346. # ============= config.h-dist ==============
  1347. if test -f 'config.h-dist' -a X"$1" != X"-c"; then
  1348.     echo 'x - skipping config.h-dist (File already exists)'
  1349.     rm -f _shar_wnt_.tmp
  1350. else
  1351. > _shar_wnt_.tmp
  1352. echo 'x - extracting config.h-dist (Text)'
  1353. sed 's/^X//' << 'SHAR_EOF' > 'config.h-dist' &&
  1354. /* config.h 1.1    (c) copyright 1986 (Dan Heller) */
  1355. X
  1356. /* Default names and locations for files */
  1357. #define MAILRC        ".mushrc"
  1358. #define ALTERNATE_RC    ".mailrc"
  1359. #define DEFAULT_RC    "/usr/lib/Mushrc"
  1360. #define ALT_DEF_RC    "/usr/lib/Mail.rc"
  1361. #define SIGNATURE    ".signature"
  1362. #define FORTUNE        "/usr/games/fortune"
  1363. #define COMMAND_HELP    "/usr/lib/cmd_help"
  1364. #ifdef SUNTOOL
  1365. #    define TOOL_HELP    "/usr/lib/tool_help"
  1366. #endif /* SUNTOOL */
  1367. #define ALTERNATE_HOME    "/tmp"       /* Path must be read/write to EVERYONE */
  1368. #define EDFILE      ".edXXXXXX"  /* file/pathname added to user's "home" */
  1369. X
  1370. #define LS_COMMAND    "ls"
  1371. #define LPR        "lpr"
  1372. #define DEF_PRINTER    "lp"
  1373. /* If your lpr command understands only -P or -d (or some other flag) then
  1374. X * define PRINTER_OPT to the appropriate value.  If you want to be able to
  1375. X * use either one, don't define this at all.  The defaults (when neither
  1376. X * -P nor -d is used on the mush "lpr" command line) are as noted here.
  1377. X * If your lpr requires that the option and the printer name be separate
  1378. X * arguments, include a trailing space in this definition.
  1379. X */
  1380. #ifdef SYSV
  1381. #define PRINTER_OPT    "-d"
  1382. #endif /* SYSV */
  1383. #ifdef BSD
  1384. #define PRINTER_OPT    "-P"
  1385. #endif /* BSD */
  1386. X
  1387. /* default settings for some variable strings */
  1388. #define DEF_PROMPT    "Msg %m of %t: "
  1389. #define DEF_PAGER    "more" /* set to "internal" to use internal pager */
  1390. #define DEF_SHELL    "csh"
  1391. #define DEF_EDITOR    "vi"
  1392. #define DEF_FOLDER    "~/Mail"        /* default Mail folder */
  1393. #define DEF_MBOX    "~/mbox"    /* default mbox */
  1394. #define DEF_INDENT_STR    "> "        /* indent included mail */
  1395. #define DEF_ESCAPE    "~"
  1396. #define DEF_HDR_FMT    "%25f %7d (%l/%c) \"%s\"" /* default hdr_format */
  1397. #define DEF_CURSES_HELP    \
  1398. X    "display save mail reply next-msg back-msg screen-next screen-back"
  1399. X
  1400. /* Headers that will NOT be included when forwarding mail */
  1401. #define IGNORE_ON_FWD    "status,priority,return-receipt-to"
  1402. X
  1403. #define    MAXMSGS    1000        /* Maximum number of messages we can read */
  1404. #define HDRSIZ    (2*BUFSIZ)    /* This should not be < BUFSIZ! */
  1405. X
  1406. /*
  1407. X * Define INTERNAL_MALLOC and recompile if you have trouble with mush
  1408. X * core-dumping due to malloc/free errors.  Also, if you run a System 5
  1409. X * variant, you might notice a performance improvement if you define this
  1410. X * variable.  It uses the malloc distributed by Larry Wall for perl v2.
  1411. X */
  1412. /* #define INTERNAL_MALLOC /**/
  1413. X
  1414. /*
  1415. X * Define TIMEZONE if your system has neither the SysV external variable
  1416. X * tzname nor the BSD timezone() function.  The example below is for
  1417. X * Gould BSD4.3 systems; others should define it as a string, e.g. "PST"
  1418. X * If TIMEZONE is defined, DAYLITETZ can also be defined, e.g. "PDT"
  1419. X *
  1420. X * Define USA if you are using US/NorthAmerican time zone abbreviations.
  1421. X * If USA is not defined, dates in outgoing mail will include timezones
  1422. X * specified as offsets from GMT, e.g. Pacific Standard Time is -0800.
  1423. X */
  1424. /* #define TIMEZONE T->tm_zone /**/
  1425. /* #define USA /**/
  1426. X
  1427. /* mail delivery system macros and defines... */
  1428. X
  1429. /*
  1430. X * If you are using MMDF, define MMDF here.
  1431. X */
  1432. /* #define MMDF /**/
  1433. #ifdef MMDF
  1434. /*
  1435. X * If MMDF delivers mail the user's home directory, define HOMEMAIL.
  1436. X * Also check the definition of the delivery file name MAILFILE, below.
  1437. X */
  1438. /* #define HOMEMAIL /**/
  1439. #define MAIL_DELIVERY    "exec /usr/mmdf/bin/submit -mlnr"
  1440. #define VERBOSE_ARG    "Ww"
  1441. #define MTA_EXIT    9    /* exit status for successful submit */
  1442. #else /* MMDF */
  1443. /*
  1444. X * If you are not using MMDF, check these definitions.
  1445. X */
  1446. #define MAIL_DELIVERY    "/usr/lib/sendmail -i" /* "-i" works like "-oi" */
  1447. #define VERBOSE_ARG    "-v"    /* undef if none exists */
  1448. #define METOO_ARG    "-m"    /* man sendmail for more info. */
  1449. #define MTA_EXIT    0    /* exit status for successful mail delivery */
  1450. #endif /* MMDF */
  1451. X
  1452. /* If your mail transfer agent uses something *besides* "From " to separate
  1453. X * adjacent messages in a folder, define MSG_SEPARATOR to be this string.
  1454. X * If that string is 4 ^A's, then the string would be "\001\001\001\001".
  1455. X * With the exception of MMDF, below, you should OMIT a trailing newline
  1456. X * from the setting of MSG_SEPARATOR.
  1457. X * If you don't know what any of this means, leave it alone.
  1458. X */
  1459. /* #define MSG_SEPARATOR "From " /**/
  1460. #ifdef MMDF
  1461. /*
  1462. X * These values should be identical (respectively) to the contents of
  1463. X * delim1 and delim2 in MMDFSRC/conf/yoursite/conf.c (sans newline).
  1464. X */
  1465. #define MSG_SEPARATOR    "\001\001\001\001\n"
  1466. #define END_MSG_SEP    "\001\001\001\001\n"
  1467. /*
  1468. X * You only need to define LCKDFLDIR if you have MMDF configured to use the
  1469. X * locking routines in lib/util/lk_lock.c (ie., link(2)-based locking).
  1470. X * Most of you WILL NOT need this, since you probably use one of the more
  1471. X * sophisticated locking modules provided with MMDF.  Remember to alter the
  1472. X * Makefile so as to access the MMDF library at the link step.
  1473. X */
  1474. /* #define LCKDFLDIR    "/usr/spool/mmdf/lockfiles" /* (for example) */
  1475. #else /* !MMDF */
  1476. #ifdef M_XENIX
  1477. #define DOT_LOCK    /* DOT_LOCK should be used for SCO Xenix */
  1478. #endif /* M_XENIX */
  1479. #endif /* MMDF */
  1480. X
  1481. /* If your mailer does not understand commas between addresses, you should
  1482. X * define NO_COMMAS.  This includes pre-3.0 smail and default MTAs used on
  1483. X * xenix, and sys-v systems.
  1484. X * This does NOT apply to MMDF or sendmail, in most cases.
  1485. X */
  1486. #ifdef SUN_4_1        /* SunOS 4.1 has warped sendmail.cf */
  1487. #define NO_COMMAS /**/
  1488. #endif /* SUN_4_1
  1489. X
  1490. /*
  1491. X * Most RFC822 compliant mailers (sendmail) will add the headers From:
  1492. X * and Date: on outgoing mail.  If the user or UA sends these headers,
  1493. X * most MTAs will not append them automatically.  However, there are
  1494. X * certain MTAs which will not allow this -- these "picky mailers" will
  1495. X * precede such headers with a '>' and make the headers very ugly and
  1496. X * somewhat redundant or contradictory.  It is advisable to set this
  1497. X * *UNLESS* your MTA is not RFC822 compiant -- therefore you should NOT
  1498. X * set this (xenix, sys-v).
  1499. X */
  1500. /* #define PICKY_MAILER /**/
  1501. X
  1502. /* If your system supports the vprintf() functions, True for sys-v and
  1503. X * later sun versions (3.0+ ?).  Typically not true for BSD systems, but
  1504. X * that will probably change in the future.
  1505. X */
  1506. #if defined(SYSV) || defined(sun)
  1507. #define VPRINTF
  1508. #endif /* SYSV || sun */
  1509. X
  1510. /* If your system uses the getwd() system call (as opposed to getcwd()),
  1511. X * and your system is not a BSD system (e.g. MIPS), define GETWD below.
  1512. X */
  1513. /* #define GETWD    /**/
  1514. X
  1515. #ifdef HOMEMAIL
  1516. #define MAILFILE    "Mailbox"    /* or whatever */
  1517. #else /* HOMEMAIL */
  1518. #define MAILDIR        "/usr/spool/mail"
  1519. #endif /* HOMEMAIL */
  1520. SHAR_EOF
  1521. chmod 0644 config.h-dist ||
  1522. echo 'restore of config.h-dist failed'
  1523. Wc_c="`wc -c < 'config.h-dist'`"
  1524. test 6407 -eq "$Wc_c" ||
  1525.     echo 'config.h-dist: original size 6407, current size' "$Wc_c"
  1526. rm -f _shar_wnt_.tmp
  1527. fi
  1528. # ============= curs_io.c ==============
  1529. if test -f 'curs_io.c' -a X"$1" != X"-c"; then
  1530.     echo 'x - skipping curs_io.c (File already exists)'
  1531.     rm -f _shar_wnt_.tmp
  1532. else
  1533. > _shar_wnt_.tmp
  1534. echo 'x - extracting curs_io.c (Text)'
  1535. sed 's/^X//' << 'SHAR_EOF' > 'curs_io.c' &&
  1536. /* @(#)curs_io.c    (c) copyright 3/18/87 (Dan Heller) */
  1537. X
  1538. /* curs_io.c -- curses based I/O */
  1539. #include "mush.h"
  1540. #include "bindings.h"
  1541. #include "glob.h"
  1542. X
  1543. static backspace();
  1544. X
  1545. #if !defined(M_XENIX) || (defined(M_XENIX) && !defined(CURSES))
  1546. char *_unctrl[] = {
  1547. X    "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
  1548. X    "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
  1549. X    "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
  1550. X    " ", "!", "\"", "#", "$",  "%", "&", "'", "(", ")", "*", "+", ",", "-",
  1551. X    ".", "/", "0",  "1", "2",  "3", "4", "5", "6", "7", "8", "9", ":", ";",
  1552. X    "<", "=", ">",  "?", "@",  "A", "B", "C", "D", "E", "F", "G", "H", "I",
  1553. X    "J", "K", "L",  "M", "N",  "O", "P", "Q", "R", "S", "T", "U", "V", "W",
  1554. X    "X", "Y", "Z",  "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
  1555. X    "f", "g", "h",  "i", "j",  "k", "l", "m", "n", "o", "p", "q", "r", "s",
  1556. X    "t", "u", "v",  "w", "x",  "y", "z", "{", "|", "}", "~", "^?"
  1557. };
  1558. #endif /* !M_XENIX || (M_XENIX && !CURSES) */
  1559. X
  1560. char    del_line;    /* tty delete line character */
  1561. char    del_word;    /* tty delete word character */
  1562. char    del_char;    /* backspace */
  1563. char    reprint_line;    /* usually ^R */
  1564. char    eofc;        /* usually ^D */
  1565. char    lit_next;    /* usually ^V */
  1566. char    complete;    /* word completion, usually ESC */
  1567. char    complist;    /* completion listing, usually ^D */
  1568. X
  1569. tty_settings()
  1570. {
  1571. X    savetty();
  1572. X
  1573. #ifdef SYSV
  1574. X    eofc = _tty.c_cc[VEOF];
  1575. #else
  1576. #ifdef BSD
  1577. X    if (ioctl(0, TIOCGETC, &tchars) != -1)
  1578. X    eofc = tchars.t_eofc;
  1579. X    else
  1580. #endif /* BSD */
  1581. X    eofc = CTRL('D');
  1582. #endif /* SYSV */
  1583. X
  1584. X    if (!isatty(0)) {
  1585. X    del_line = CTRL('U');
  1586. X    del_char = CTRL('H');
  1587. X    } else {
  1588. X    del_line = _tty.sg_kill;
  1589. X    del_char = _tty.sg_erase;
  1590. X    }
  1591. X
  1592. #ifdef TIOCGLTC
  1593. #ifndef AUX    /* AUX defines TIOCGLTC but doesn't use it */
  1594. X    if (ioctl(0, TIOCGLTC, <chars) != -1) {
  1595. X    del_word = ltchars.t_werasc;
  1596. X    reprint_line = ltchars.t_rprntc;
  1597. X    lit_next = ltchars.t_lnextc;
  1598. X    } else
  1599. #endif /* AUX */
  1600. #endif /* TIOCGLTC */
  1601. X    {
  1602. X    del_word = CTRL('W');
  1603. X    reprint_line = CTRL('R');
  1604. X    lit_next = CTRL('V');
  1605. X    }
  1606. }
  1607. X
  1608. #ifdef Addch
  1609. #undef Addch
  1610. #endif /* Addch */
  1611. X
  1612. #ifndef CURSES
  1613. X
  1614. /* Make sure all ifs have matching elses! */
  1615. X
  1616. #define Addch(c) \
  1617. X    if (ison(glob_flags, ECHO_FLAG)) \
  1618. X    {;} \
  1619. X    else \
  1620. X    (void) fputc(c, stdout), (void) fflush(stdout)
  1621. X
  1622. #else
  1623. X
  1624. /* see end of Getstr */
  1625. #define Addch(c)  \
  1626. X    if (iscurses) \
  1627. X    addch(c), refresh(); \
  1628. X    else if (ison(glob_flags, ECHO_FLAG)) \
  1629. X    {;} \
  1630. X    else \
  1631. X    (void) fputc(c, stdout), (void) fflush(stdout)
  1632. #endif /* CURSES */
  1633. X
  1634. /*
  1635. X * get a string of at most 'length' chars.
  1636. X * allow backspace-space-backspace, kill word and kill line
  1637. X * (options set by user in stty).
  1638. X * length is the max length this string can get. offset is from beginning
  1639. X * of string.
  1640. X * input of ^D returns -1; otherwise, return the number of chars in string.
  1641. X */
  1642. Getstr(String, length, offset)
  1643. char String[];
  1644. register int length;
  1645. {
  1646. X    register int c, literal_next = FALSE, lit_bs = FALSE;
  1647. X    struct cmd_map *curr_map;
  1648. X    int count = offset, save_wc = wrapcolumn;
  1649. X
  1650. X    (void) fflush(stdout); /* make sure everything is flushed before getting input */
  1651. X
  1652. X    if (mac_hide) {
  1653. X    curr_map = NULL_MAP;
  1654. X    wrapcolumn = 0;
  1655. X    } else if (ison(glob_flags, IS_GETTING))
  1656. X    curr_map = bang_map;
  1657. X    else if (iscurses)
  1658. X    curr_map = NULL_MAP;
  1659. X    else
  1660. X    curr_map = line_map;
  1661. X
  1662. X    while ((c = m_getchar()) != '\n' && c != '\r' && c != EOF &&
  1663. X        isoff(glob_flags, WAS_INTR)) {
  1664. X    /* echo isn't set, so whatever the character, enter it */
  1665. X    if (ison(glob_flags, QUOTE_MACRO) || ison(glob_flags, ECHO_FLAG)) {
  1666. X        if (count < length) {
  1667. X        String[count++] = c;
  1668. X        /* Note: Addch includes ECHO_FLAG test */
  1669. X        if (iscntrl(c)) {
  1670. X            Addch('^');
  1671. X            Addch(_unctrl[c][1]);
  1672. X        } else
  1673. X            Addch(c);
  1674. X        } else {
  1675. X        print("\nWarning: string too long. Truncated at %d chars.",
  1676. X            length);
  1677. X        if (ison(glob_flags, QUOTE_MACRO)) {
  1678. X            mac_flush();
  1679. X            m_ungetc(reprint_line);
  1680. X            continue;
  1681. X        } else
  1682. X            break;
  1683. X        }
  1684. X    }
  1685. X    /* ^D as the first char on a line or two ^D's in a row is EOF */
  1686. X    else if (c == eofc && !count)
  1687. X        break;
  1688. X    else if (c == '\\' && count < length) {
  1689. X        literal_next = TRUE, lit_bs = FALSE;
  1690. X        Addch(String[count++] = '\\');
  1691. X        } else if (c == lit_next && count < length) {
  1692. X        literal_next = lit_bs = TRUE;
  1693. X        String[count++] = '\\';
  1694. X        if (!in_macro()) {
  1695. X        /* if (iscntrl(c)) */
  1696. X            Addch('^');
  1697. X        /* Addch(_unctrl[c][1]); */
  1698. X        }
  1699. X    } else if (literal_next) {
  1700. SHAR_EOF
  1701. true || echo 'restore of curs_io.c failed'
  1702. fi
  1703. echo 'End of  part 5'
  1704. echo 'File curs_io.c is continued in part 6'
  1705. echo 6 > _shar_seq_.tmp
  1706. exit 0
  1707. exit 0 # Just in case...
  1708. -- 
  1709. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1710. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1711. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1712. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1713.