home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / vmail / part02 < prev    next >
Encoding:
Text File  |  1988-03-13  |  34.2 KB  |  1,417 lines

  1. Article 999 of comp.sources.unix:
  2. Path: s.cc.purdue.edu!h.cc.purdue.edu!j.cc.purdue.edu!pur-ee!iuvax!inuxc!ihnp4!ptsfa!ames!amdcad!sun!pitstop!sundc!seismo!uunet!munnari!jz
  3. From: jz@mulga.oz.au (Justin Zobel)
  4. Newsgroups: comp.sources.unix
  5. Subject: v12i005:  vmail - screen-based mail handler, Part02/03
  6. Message-ID: <1855@munnari.oz>
  7. Date: 13 Oct 87 21:15:31 GMT
  8. Sender: kre@munnari.oz
  9. Lines: 1403
  10. Approved: kre@munnari.oz.au
  11.  
  12. Submitted by: jz@mulga.oz.au
  13. Posting-number: Volume 12, Issue 5
  14. Archive-name: vmail/Part02
  15.  
  16. This is the second of three parts of vmail, an interactive mail handler
  17. that sits on top of MH.
  18.     vmail has a number of advantages over raw MH.  It is screen-based and
  19. faster (and more convenient) than the MH show-scan-rmm refile cycle.
  20. vmail makes it feasible for users to organise and keep track of moderate
  21. volumes of mail without wasting too much time, and is very simple to use.
  22. It has been in use at Melbourne University Computer Science Department
  23. for about six months without any problems, and has become the interface of
  24. choice for many users.
  25.  
  26. : ---------------------------------------- cut here
  27.  
  28. echo x - "call.c" 2>&1
  29. sed "s/^X//" >"call.c" <<'!The!End!'
  30. X/* --------------------
  31. X    vmail -- call.c
  32. X
  33. X    Routines that call MH equivalents, editor, shell.
  34. X
  35. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  36. X-------------------- */
  37. X
  38. X#include "defs.h"
  39. X#include <signal.h>
  40. X
  41. X#define WARNING    "Warning -- mail headers may be out of date"
  42. X
  43. Xunion wait status;
  44. X
  45. X/* --------------------
  46. X    Fork a call to `comp'.
  47. X    Terminal type must be reset before call.
  48. X-------------------- */
  49. Xvoid
  50. Xcomp()
  51. X{
  52. X    char    *tmp, *argv[20], str[LEN], s1[LEN], *next_token();
  53. X    int        i, (*oldint)(), (*oldquit)(), (*signal())();
  54. X
  55. X    *s1 = '\0';
  56. X    if(comp_args) {
  57. X        sprintf(str, "(give options to)   comp ");
  58. X        get_string(str, s1);
  59. X    }
  60. X    clear();
  61. X    addstatus("composing mail ...", false);
  62. X    move(STATUS+1, 0);
  63. X    refresh();
  64. X    top_level = false;            /* used by tstp() so that right thing is done
  65. X                                   when process is restarted */
  66. X    if(! vfork()) {
  67. X        argv[0] = COMP;
  68. X        for(i=1, tmp=s1 ; *tmp != '\0' ; i++) {
  69. X            argv[i] = tmp;
  70. X            tmp = next_token(tmp);
  71. X        }
  72. X        argv[i] = 0;
  73. X        no_control();
  74. X        execv(COMP, argv);
  75. X        printf("Warning: can't execute %s\n", COMP);
  76. X        exit(0);
  77. X    }
  78. X    oldint = signal(SIGINT, SIG_IGN);
  79. X    oldquit = signal(SIGQUIT, SIG_IGN);
  80. X    wait(&status);
  81. X    signal(SIGINT, oldint);
  82. X    signal(SIGQUIT, oldquit);
  83. X    top_level = true;
  84. X    to_control();
  85. X    hold_end();                    /* wait for user to want to continue - may wish
  86. X                                   to read error messages */
  87. X    display_page();
  88. X    addstatus(WARNING, true);    /* vmail's data structures not updated */
  89. X}
  90. X
  91. X
  92. X/* --------------------
  93. X    Fork a call to `forw'.
  94. X    Terminal type must be reset before call.
  95. X-------------------- */
  96. Xvoid
  97. Xforw()
  98. X{
  99. X    char    *tmp, *argv[20], str[LEN], s1[LEN], s2[10], *next_token();
  100. X    int        i, (*oldint)(), (*oldquit)(), (*signal())();
  101. X
  102. X    sprintf(s2, "%d", curmail->number);
  103. X    *s1 = '\0';
  104. X    if(forw_args) {
  105. X        sprintf(str, "(give options to)   forw +%s %s ", curflr->name, s2);
  106. X        get_string(str, s1);
  107. X    }
  108. X    clear();
  109. X    addstatus("forwarding mail ...", false);
  110. X    move(STATUS+1, 0);
  111. X    refresh();
  112. X    top_level = false;            /* used by tstp() so that right thing is done
  113. X                                   when process is restarted */
  114. X    if(! vfork()) {
  115. X        sprintf(str, "+%s", curflr->name);
  116. X        argv[0] = FORW; argv[1] = str; argv[2] = s2;
  117. X        for(i=3, tmp=s1 ; *tmp != '\0' ; i++) {
  118. X            argv[i] = tmp;
  119. X            tmp = next_token(tmp);
  120. X        }
  121. X        argv[i] = 0;
  122. X        no_control();
  123. X        execv(FORW, argv);
  124. X        printf("Warning: can't execute %s\n", FORW);
  125. X        exit(0);
  126. X    }
  127. X    oldint = signal(SIGINT, SIG_IGN);
  128. X    oldquit = signal(SIGQUIT, SIG_IGN);
  129. X    wait(&status);
  130. X    signal(SIGINT, oldint);
  131. X    signal(SIGQUIT, oldquit);
  132. X    top_level = true;
  133. X    to_control();
  134. X    hold_end();                    /* wait for user to want to continue - may wish
  135. X                                   to read error messages */
  136. X    display_page();
  137. X    addstatus(WARNING, true);    /* vmail's data structures not updated */
  138. X}
  139. X
  140. X
  141. X/* --------------------
  142. X    Fork a call to `repl'.
  143. X    Terminal type must be reset before call.
  144. X-------------------- */
  145. Xvoid
  146. Xrepl()
  147. X{
  148. X    char    *tmp, *argv[20], str[LEN], s1[LEN], s2[10], *next_token();
  149. X    int        i, (*oldint)(), (*oldquit)(), (*signal())();
  150. X
  151. X    sprintf(s2, "%d", curmail->number);
  152. X    *s1 = '\0';
  153. X    if(repl_args) {
  154. X        sprintf(str, "(give options to)   repl +%s %s ", curflr->name, s2);
  155. X        get_string(str, s1);
  156. X    }
  157. X    clear();
  158. X    addstatus("answering mail ...", false);
  159. X    move(STATUS+1, 0);
  160. X    refresh();
  161. X    top_level = false;            /* used by tstp() so that right thing is done
  162. X                                   when process is restarted */
  163. X    if(! vfork()) {
  164. X        sprintf(str, "+%s", curflr->name);
  165. X        argv[0] = REPL; argv[1] = str; argv[2] = s2;
  166. X        for(i=3, tmp=s1 ; *tmp != '\0' ; i++) {
  167. X            argv[i] = tmp;
  168. X            tmp = next_token(tmp);
  169. X        }
  170. X        argv[i] = 0;
  171. X        no_control();
  172. X        execv(REPL, argv);
  173. X        printf("Warning: can't execute %s\n", REPL);
  174. X        exit(0);
  175. X    }
  176. X    oldint = signal(SIGINT, SIG_IGN);
  177. X    oldquit = signal(SIGQUIT, SIG_IGN);
  178. X    wait(&status);
  179. X    signal(SIGINT, oldint);
  180. X    signal(SIGQUIT, oldquit);
  181. X    top_level = true;
  182. X    to_control();
  183. X    hold_end();                    /* wait for user to want to continue - may wish
  184. X                                   to read error messages */
  185. X    display_page();
  186. X    addstatus(WARNING, true);    /* vmail's data structures not updated */
  187. X}
  188. X
  189. X
  190. X/* --------------------
  191. X    Fork a call to editor.
  192. X    Terminal type must be reset before call.
  193. X-------------------- */
  194. Xvoid
  195. Xedit()
  196. X{
  197. X    char    str[LEN];
  198. X    int        (*oldint)(), (*oldquit)(), (*signal())();
  199. X
  200. X    clear();
  201. X    mvaddstr(TITLE, 0, "editing mail ...");
  202. X    move(STATUS, 0);
  203. X    refresh();
  204. X    top_level = false;            /* used by tstp() so that right thing is done
  205. X                                   when process is restarted */
  206. X    if(! vfork()) {
  207. X        no_control();
  208. X        sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
  209. X        execlp(editor, editor, str, 0);
  210. X        printf("Warning: can't execute %s\n", editor);
  211. X        exit(0);
  212. X    }
  213. X    oldint = signal(SIGINT, SIG_IGN);
  214. X    oldquit = signal(SIGQUIT, SIG_IGN);
  215. X    wait(&status);
  216. X    signal(SIGINT, oldint);
  217. X    signal(SIGQUIT, oldquit);
  218. X    top_level = true;
  219. X    to_control();
  220. X    hold_end();                    /* wait for user to want to continue - may wish
  221. X                                   to read error messages */
  222. X    display_page();
  223. X}
  224. X
  225. X
  226. X/* --------------------
  227. X    Fork a call to shell.
  228. X    Terminal type must be reset before call.
  229. X
  230. X    This should perhaps be modified so that only a single command can be
  231. X    issued, as in vi ... but this was simpler to do.
  232. X-------------------- */
  233. Xvoid
  234. Xcall_shell()
  235. X{
  236. X    int        (*oldint)(), (*oldquit)(), (*signal())();
  237. X
  238. X    clear();
  239. X    mvaddstr(TITLE, 0, "calling shell ...");
  240. X    move(STATUS, 0);
  241. X    refresh();
  242. X    top_level = false;            /* used by tstp() so that right thing is done
  243. X                                   when process is restarted */
  244. X    if(! vfork()) {
  245. X        no_control();
  246. X        fix_mh();
  247. X        execlp(shell, shell, "-i", 0);
  248. X        printf("Warning: can't execute %s\n", shell);
  249. X        exit(0);
  250. X    }
  251. X    oldint = signal(SIGINT, SIG_IGN);
  252. X    oldquit = signal(SIGQUIT, SIG_IGN);
  253. X    wait(&status);
  254. X    signal(SIGINT, oldint);
  255. X    signal(SIGQUIT, oldquit);
  256. X    top_level = true;
  257. X    to_control();
  258. X    hold_end();                    /* wait for user to want to continue - may wish
  259. X                                   to read error messages */
  260. X    display_page();
  261. X}
  262. X
  263. X
  264. X/* --------------------
  265. X    Pipe current mail item into given command.
  266. X-------------------- */
  267. Xvoid
  268. Xdo_pipe()
  269. X{
  270. X    char    str[LEN], s1[LEN];
  271. X    int        (*oldint)(), (*oldquit)(), (*signal())();
  272. X
  273. X    *s1 = '\0';
  274. X    sprintf(str, "(give command to)   show +%s %d | ", curflr->name,
  275. X                                                        curmail->number);
  276. X    get_string(str, s1);
  277. X    clear();
  278. X    addstatus("piping mail ...", false);
  279. X    move(STATUS+1, 0);
  280. X    refresh();
  281. X    sprintf(str, "%s %s/%s/%d | %s", CAT, mail_dir, curflr->name,
  282. X                                                        curmail->number, s1);
  283. X    top_level = false;            /* used by tstp() so that right thing is done
  284. X                                   when process is restarted */
  285. X    no_control();
  286. X    oldint = signal(SIGINT, SIG_IGN);
  287. X    oldquit = signal(SIGQUIT, SIG_IGN);
  288. X    system(str);            /* exec needs full path of command => use system */
  289. X    signal(SIGINT, oldint);
  290. X    signal(SIGQUIT, oldquit);
  291. X    top_level = true;
  292. X    to_control();
  293. X    hold_end();                    /* wait for user to want to continue - may wish
  294. X                                   to read error messages */
  295. X    display_page();
  296. X}
  297. !The!End!
  298.  
  299. echo x - "choose.c" 2>&1
  300. sed "s/^X//" >"choose.c" <<'!The!End!'
  301. X/* --------------------
  302. X    vmail -- choose.c
  303. X
  304. X    Tty-based folder selection.
  305. X
  306. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  307. X-------------------- */
  308. X
  309. X#include "defs.h"
  310. X
  311. X#define START            10                /* offset from margin of screen */
  312. X#define RESET()            toggle=false,    /* left- or right- hand indicator */ \
  313. X                        i=FIRST+1,        /* initial row */                     \
  314. X                        j=START,        /* initial column */                 \
  315. X                        f=first            /* first folder */
  316. X
  317. XWINDOW    *chooser = (WINDOW *) NULL;
  318. X
  319. X/* --------------------
  320. X    Display folder selection page, read commands to move around page and
  321. X    select folders.
  322. X-------------------- */
  323. Xvoid
  324. Xchoose()
  325. X{
  326. X    int        n, i, j;
  327. X    bool    toggle;
  328. X    folder    next, f, showing(),
  329. X            first = folders,    /* first folder on screen */
  330. X            last;                /* folder after last folder on screen */
  331. X    char    c, str[LEN], flushin();
  332. X
  333. X    RESET();
  334. X    if(chooser == (WINDOW *) NULL)
  335. X        chooser = newwin(0, 0, 0, 0);
  336. X    last = showing(first);
  337. Xrestart:
  338. X    while((c = flushin()) != ' ' && c != 'q') switch(c) {
  339. X        case '\r':        /* go to next screen of folder names */
  340. X        case '\n':
  341. X            if(last == (folder) NULL)
  342. X                beep();
  343. X            else {
  344. X                first = last;
  345. X                last = showing(first);
  346. X                RESET();
  347. X            }
  348. X            break;
  349. X        case '\b':        /* go back one page of folders */
  350. X            if(first == folders)
  351. X                beep();
  352. X            else {
  353. X                for(i=(lines-FIRST)*2 ; i > FIRST && first->prev != (folder) NULL ; i--, first=first->prev)
  354. X                    ;
  355. X                last = showing(first);
  356. X                RESET();
  357. X            }
  358. X            break;
  359. X        case CTRL_L:    /* redraw */
  360. X            last = showing(first);
  361. X            break;
  362. X        case 'h':        /* move left */
  363. X            if(! toggle)    /* already at left */
  364. X                beep();
  365. X            else {
  366. X                next = f;
  367. X                FRST_OF_NAME(next);
  368. X                next = next->prev;
  369. X                if(next == (folder) NULL)
  370. X                    beep();
  371. X                else {
  372. X                    f = next; j = START; toggle = false;
  373. X                    wmove(chooser, i, j);
  374. X                    wrefresh(chooser);
  375. X                }
  376. X            }
  377. X            break;
  378. X        case 'j':        /* move down */
  379. X            if(i+1 >= lines)    /* at bottom */
  380. X                beep();
  381. X            else {
  382. X                next = f;
  383. X                for(n=0 ; n < 2 && next != (folder) NULL ; n++) {
  384. X                    LAST_OF_NAME(next);
  385. X                    next = next->next;
  386. X                }
  387. X                if(next == (folder) NULL)
  388. X                    beep();
  389. X                else {
  390. X                    i++; f = next;
  391. X                    wmove(chooser, i, j);
  392. X                    wrefresh(chooser);
  393. X                }
  394. X            }
  395. X            break;
  396. X        case 'k':        /* move up */
  397. X            if(i <= FIRST+1)    /* at top */
  398. X                beep();
  399. X            else {
  400. X                next = f;
  401. X                for(n=0 ; n < 2 && next != (folder) NULL ; n++) {
  402. X                    FRST_OF_NAME(next);
  403. X                    next = next->prev;
  404. X                }
  405. X                if(next == (folder) NULL)
  406. X                    beep();
  407. X                else {
  408. X                    i--; f = next;
  409. X                    wmove(chooser, i, j);
  410. X                    wrefresh(chooser);
  411. X                }
  412. X            }
  413. X            break;
  414. X        case 'l':        /* move right */
  415. X            if(toggle)        /* at right */
  416. X                beep();
  417. X            else {
  418. X                next = f;
  419. X                LAST_OF_NAME(next);
  420. X                next = next->next;
  421. X                if(next == (folder) NULL)
  422. X                    beep();
  423. X                else {
  424. X                    f = next; j = cols/2; toggle = true;
  425. X                    wmove(chooser, i, j);
  426. X                    wrefresh(chooser);
  427. X                }
  428. X            }
  429. X            break;
  430. X        default:
  431. X            beep();
  432. X            break;
  433. X    }
  434. X    if(c == ' ') {        /* attempt to go to folder */
  435. X        if(! f->valid) {    /* load folder */
  436. X            mvwaddstr(chooser, FIRST, 0, "Reading mail headers ...");
  437. X            wmove(chooser, i, j);
  438. X            wrefresh(chooser);
  439. X            f->valid = true;
  440. X            find_mail(f, false);
  441. X        }
  442. X        if(f->valid == EMPTY) {        /* folder is empty */
  443. X                /* Go back to chooser, display "empty" message */
  444. X            sprintf(str, "%s -- folder empty", f->name);
  445. X            if(first == f)        /* find new first folder for page */
  446. X                if(f->next != (folder) NULL)
  447. X                    first = f->next;
  448. X                else
  449. X                    first = folders;
  450. X            last = showing(first);
  451. X            RESET();
  452. X            mvwaddstr(chooser, FIRST, 0, str);
  453. X            wmove(chooser, i, j);
  454. X            wrefresh(chooser);
  455. X            goto restart;
  456. X        } 
  457. X        curflr = f;
  458. X        curmail = f->mail;
  459. X        y = FIRST;
  460. X    }
  461. X    display_page();
  462. X}
  463. X
  464. X
  465. X/* --------------------
  466. X    Show all folder names starting with "start" ending with last folder or
  467. X    when page is full.
  468. X-------------------- */
  469. Xfolder
  470. Xshowing(start)
  471. X    folder    start;
  472. X{
  473. X    int        count, i = FIRST+1, j = START;
  474. X    bool    toggle = false;
  475. X    folder    p, f;
  476. X    item    m;
  477. X    char    str[LEN];
  478. X
  479. X    wclear(chooser);
  480. X    mvwaddstr(chooser, TITLE, 0,
  481. X"h,j,k,l -- left,down,up,right        <return>,<bs> -- next/prev page of folders");
  482. X    mvwaddstr(chooser, STATUS, 0,
  483. X"<space> -- select folder             q -- quit, no change         ^L -- refresh");
  484. X    for(p=f=start ; i < lines && f != (folder) NULL ; p=f=p->next) {
  485. X        if(f->valid) {
  486. X                /* find last page of folder, count items in folders */
  487. X            for(count=0, p=f ; p->next != (folder) NULL &&
  488. X                                        p->next->name == f->name ; p=p->next)
  489. X                for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  490. X                    ;
  491. X            for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  492. X                ;
  493. X            if(count == 1)
  494. X                sprintf(str, "%s: %d, 1 item", f->name, f->mail->number);
  495. X            else
  496. X                sprintf(str, "%s: %d-%d, %d items", f->name, f->mail->number,
  497. X                                                    p->last->number, count);
  498. X        } else
  499. X            sprintf(str, "%-15s(inactive)", f->name);
  500. X        if(f == curflr) standout();
  501. X        mvwaddstr(chooser, i, j, str);
  502. X        if(f == curflr) standend();
  503. X        if(toggle)
  504. X            j = START, i++;
  505. X        else
  506. X            j = cols/2;
  507. X        toggle = ! toggle;
  508. X    }
  509. X    wmove(chooser, FIRST+1, START);
  510. X    wrefresh(chooser);
  511. X    return(f);
  512. X}
  513. X
  514. X
  515. XWINDOW *folwin = (WINDOW *) NULL;
  516. X
  517. X/* --------------------
  518. X    List all folders, active or otherwise.
  519. X-------------------- */
  520. Xvoid
  521. Xlist_folders()
  522. X{
  523. X    folder    f = folders, p;
  524. X    int        count, i = FIRST, half = cols/2;
  525. X    bool    toggle = false;
  526. X    char    str[LEN];
  527. X    WINDOW    *newwin();
  528. X    item    m;
  529. X
  530. X    if(folwin == (WINDOW *) NULL)
  531. X        folwin = newwin(0, 0, 0, 0);
  532. X    wclear(folwin);
  533. X    for(p=f ; ; p=f=p->next) {
  534. X        if((i+2) % lines == 0) {
  535. X            if(use_prompt(folwin) == 'q')
  536. X                break;
  537. X            i = FIRST;
  538. X            wclear(folwin);
  539. X        }
  540. X        if(f == (folder) NULL) {
  541. X            use_prompt(folwin);
  542. X            break;
  543. X        }
  544. X        if(f->valid) {
  545. X                /* find last page of folder, count items in folders */
  546. X            for(count=0, p=f ; p->next != (folder) NULL &&
  547. X                                        p->next->name == f->name ; p=p->next)
  548. X                for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  549. X                    ;
  550. X            for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  551. X                ;
  552. X            if(count == 1)
  553. X                sprintf(str, "%s: %d, 1 item", f->name, f->mail->number);
  554. X            else
  555. X                sprintf(str, "%s: %d-%d, %d items", f->name, f->mail->number,
  556. X                                                    p->last->number, count);
  557. X        } else
  558. X            sprintf(str, "%-15s(inactive)", f->name);
  559. X        if(f == curflr)
  560. X            wstandout(folwin);
  561. X        if(toggle) {
  562. X            mvwaddstr(folwin, i, half, str);
  563. X            i++;
  564. X        } else
  565. X            mvwaddstr(folwin, i, 10, str);
  566. X        if(f == curflr)
  567. X            wstandend(folwin);
  568. X        toggle = !toggle;
  569. X    }
  570. X    display_page();
  571. X}
  572. !The!End!
  573.  
  574. echo x - "cmds.c" 2>&1
  575. sed "s/^X//" >"cmds.c" <<'!The!End!'
  576. X/* --------------------
  577. X    vmail -- cmds.c
  578. X
  579. X    Commands not included in page.c or move.c.
  580. X
  581. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  582. X-------------------- */
  583. X
  584. X#include "defs.h"
  585. X#include <signal.h>
  586. X
  587. X/* --------------------
  588. X    Print the name of the alternate folder.
  589. X-------------------- */
  590. Xvoid
  591. Xshow_folder()
  592. X{
  593. X    char    str[LEN];
  594. X
  595. X    if(alternate == (folder) NULL)
  596. X        addstatus("No alternate folder", false);
  597. X    else {
  598. X        sprintf(str, "alternate folder is %s\n", alternate->name);
  599. X        addstatus(str, false);
  600. X    }
  601. X}
  602. X
  603. X
  604. X/* --------------------
  605. X    Make current folder inactive - remove list of mail headers, set valid
  606. X    to false.
  607. X-------------------- */
  608. Xvoid
  609. Xinactive()
  610. X{
  611. X    folder    f, p;
  612. X
  613. X        /* find first page of folder */
  614. X    p = curflr; FRST_OF_NAME(p);
  615. X        /* find last page of folder */
  616. X    f = curflr; LAST_OF_NAME(f);
  617. X    p->next = f->next;
  618. X    p->valid = false;
  619. X/* should free records */
  620. X    p->mail = p->last = (item) NULL;
  621. X    p->pagenum = p->pages = 1;
  622. X    if(p->next != (folder) NULL)
  623. X        p->next->prev = p;
  624. X    curflr = p;
  625. X    NEXT_VALID(curflr);
  626. X    if(curflr == (folder) NULL) {
  627. X        curflr = p;
  628. X        PREV_VALID(curflr);
  629. X    }
  630. X    if(curflr == (folder) NULL) {
  631. X        addstatus("Making last active folder inactive", true);
  632. X        to_normal();
  633. X        exit(0);
  634. X    } else {
  635. X        curmail = curflr->mail;
  636. X        y = FIRST;
  637. X        display_page();
  638. X    }
  639. X}
  640. X
  641. X
  642. X/* --------------------
  643. X    Show current mail item with fork to pager.
  644. X-------------------- */
  645. Xvoid
  646. Xshow_mail()
  647. X{
  648. X    int        (*oldint)(), (*oldquit)(), (*signal())();
  649. X    char    str[LEN];
  650. X    union wait status;
  651. X
  652. X    clear();
  653. X    refresh();
  654. X    top_level = false;            /* used by tstp() so that right thing is done
  655. X                                   when process is restarted */
  656. X    if(! vfork()) {
  657. X        no_control();
  658. X        sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
  659. X        execlp(pager, pager, str, 0);
  660. X        printf("Warning: can't execute %s\n", pager);
  661. X        exit(0);
  662. X    }
  663. X    oldint = signal(SIGINT, SIG_IGN);
  664. X    oldquit = signal(SIGQUIT, SIG_IGN);
  665. X    wait(&status);
  666. X    signal(SIGINT, oldint);
  667. X    signal(SIGQUIT, oldquit);
  668. X    top_level = true;
  669. X    to_control();
  670. X    hold_end();                    /* wait for user to want to continue - may wish
  671. X                                   to read error messages */
  672. X    display_page();
  673. X}
  674. X
  675. X
  676. X/* --------------------
  677. X    Save current mail item to named file.  If first non-space character
  678. X    is ~, expand it.
  679. X-------------------- */
  680. Xvoid
  681. Xsave_item()
  682. X{
  683. X    struct passwd *pwent, *getpwnam();
  684. X    char    *tmp, buf[LEN], *str = buf, save[LEN];
  685. X    FILE    *fi, *fo, *fopen();
  686. X
  687. X    sprintf(save, "%s.%d", curflr->name, curmail->number);
  688. X    sprintf(str, "file (%s)? ", save);
  689. X    get_string(str, str);
  690. X    for(; *str == ' ' ; str++)
  691. X        ;
  692. X    for(tmp=str ; *tmp != '\0' && *tmp != ' ' ; tmp++)
  693. X        ;
  694. X    *tmp = '\0';
  695. X    if(*str != '\0')        /* don't take default */
  696. X        if(*str == '~')    {    /* expand home directory name */
  697. X            tmp = str + 2;
  698. X            if(*(str+1) == '/')
  699. X                pwent = getpwnam(user);
  700. X            else {    
  701. X                for( ; *tmp != '\0' && *tmp != '/' ; tmp++)
  702. X                    ;
  703. X                *(tmp++) = '\0';
  704. X                if((pwent = getpwnam(str+1)) == (struct passwd *) NULL) {
  705. X                    sprintf(save, "%s: no such user", str+1);
  706. X                    addstatus(save, true);
  707. X                    return;
  708. X                }
  709. X            }
  710. X            sprintf(save, "%s/%s", pwent->pw_dir, tmp);
  711. X        } else                /* take str as given */
  712. X            strcpy(save, str);
  713. X    if((fo = fopen(save, "w")) == (FILE *) NULL) {
  714. X        sprintf(str, "%s: no write permission", save);
  715. X        addstatus(str, true);
  716. X        return;
  717. X    }
  718. X    addstatus("saving ...", false);
  719. X    sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
  720. X    fi = fopen(str, "r");
  721. X    while(fgets(str, LEN, fi) != (char *) NULL)
  722. X        fprintf(fo, "%s", str);
  723. X    fclose(fi); fclose(fo);
  724. X    addstatus("saved", false);
  725. X}
  726. !The!End!
  727.  
  728. echo x - "find.c" 2>&1
  729. sed "s/^X//" >"find.c" <<'!The!End!'
  730. X/* --------------------
  731. X    vmail -- find.c
  732. X
  733. X    Searching titles for strings.
  734. X
  735. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  736. X-------------------- */
  737. X
  738. X#include "defs.h"
  739. X
  740. Xstatic char str[LEN] = "^.*";
  741. X
  742. X/* --------------------
  743. X    Get string for searching, either forwards (forwards = true) or backwards
  744. X    (forwards = false).  Then scan mail headers using regex().
  745. X-------------------- */
  746. Xvoid
  747. Xsearch(forwards)
  748. X    int        forwards;
  749. X{
  750. X    char    s1[LEN], *s2, *re_comp();
  751. X    int        i;
  752. X    bool    found = false;
  753. X    folder    f;
  754. X    item    m;
  755. X
  756. X    get_string((forwards) ? "/" : "?", s1);
  757. X    if((i = strlen(s1)) > 0) {
  758. X            /* new search string */
  759. X        strcpy(str+3, s1);
  760. X        str[i+=3] = '.', str[++i] = '*', str[++i] = '\0';
  761. X    } else if(strlen(str+3) == 0) {
  762. X        addstatus("", false);
  763. X        return;
  764. X    }
  765. X    if((s2 = re_comp(str)) != (char *) NULL) {
  766. X        addstatus(s2, false);
  767. X        return;
  768. X    }
  769. X    addstatus("searching ...", false);
  770. X    if(forwards)
  771. X        for(i=y+1, f=curflr, m=curmail->next ; ! found && m != curmail ; ) {
  772. X            if(m == (item) NULL) {
  773. X                f = f->next; NEXT_VALID(f);
  774. X                if(f == (folder) NULL) {
  775. X                    f = folders;
  776. X                    NEXT_VALID(f);
  777. X                }
  778. X                m = f->mail;
  779. X                i = FIRST;
  780. X            }
  781. X            if(! (found = re_exec(m->title)))
  782. X                m = m->next, i++;
  783. X        }
  784. X    else
  785. X        for(i=y-1, f=curflr, m=curmail->prev ; ! found && m != curmail ; ) {
  786. X            if(m == (item) NULL) {
  787. X                f = f->prev; PREV_VALID(f);
  788. X                if(f == (folder) NULL) {
  789. X                        /* find last folder */
  790. X                    for(f=folders ; f->next != (folder) NULL ; f=f->next)
  791. X                        ;
  792. X                    PREV_VALID(f);
  793. X                }
  794. X                    /* find last mail item with count */
  795. X                for(i=FIRST, m=f->mail ; m->next != (item) NULL ; i++,m=m->next)
  796. X                    ;
  797. X            }
  798. X            if(! (found = re_exec(m->title)))
  799. X                m = m->prev, i--;
  800. X        }
  801. X    curmail = m, y = i;
  802. X    if(f != curflr) {
  803. X        curflr = f;
  804. X        display_page();
  805. X    } else if(! found)    /* come back to current folder (known to be valid) */
  806. X        addstatus("pattern not found", true);
  807. X    else
  808. X        addstatus("", false);
  809. X}
  810. !The!End!
  811.  
  812. echo x - "inc.c" 2>&1
  813. sed "s/^X//" >"inc.c" <<'!The!End!'
  814. X/* --------------------
  815. X    vmail -- inc.c
  816. X
  817. X    Incorporate new mail with "inc", parse output and update appropriate
  818. X    folder-pages.
  819. X
  820. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  821. X-------------------- */
  822. X
  823. X#include "defs.h"
  824. X
  825. X#define INCORP        "Incorporating new mail into "
  826. X#define TAIL        "...\n"
  827. X
  828. Xstatic folder isfol;        /* folder into which mail is being incorporated */
  829. Xstatic item ismail;            /* last item of mail on isfol page */
  830. Xstatic int count;            /* number of items on isfol page */
  831. X
  832. X/* --------------------
  833. X    Call, inc, parse output to work out what items have been read and into
  834. X    what folders.
  835. X-------------------- */
  836. Xvoid
  837. Xinc()
  838. X{
  839. X    char    str[LEN], line[LEN], *tmp, *fgets();
  840. X    FILE    *pp, *fdopen();
  841. X    int        num, pd[2], len = strlen(INCORP), numbers();
  842. X    bool    redraw = true;
  843. X    union wait status;
  844. X
  845. X    addstatus("incorporating mail ... ", true);
  846. X    pipe(pd);
  847. X    if(! vfork()) {
  848. X        close(pd[0]);
  849. X        dup2(pd[1], 1);
  850. X        close(pd[1]);
  851. X        dup2(1, 2);
  852. X        execl(INC, "inc", 0);
  853. X    }
  854. X    close(pd[1]);
  855. X    if((pp = fdopen(pd[0], "r")) == (FILE *) NULL) {
  856. X        addstatus("panic, can't incorporate mail", true);
  857. X        return;
  858. X    }
  859. X    while((tmp = fgets(str, LEN, pp)) != (char *) NULL)    /* read "inc" output */
  860. X        if(strncmp(tmp, INCORP, len) == 0) {    /* reading into new folder */
  861. X            tmp += len;
  862. X            tmp[strlen(tmp)-strlen(TAIL)] = '\0';
  863. X            goto_incorp_folder(tmp);
  864. X            if(isfol == (folder) NULL) {
  865. X                sprintf(line, "can't go to folder %s", tmp);
  866. X                addstatus(line, true);
  867. X                redraw = false;
  868. X                break;
  869. X            } else {
  870. X                sprintf(line, "incorporating mail into folder %s", tmp);
  871. X                addstatus(line, true);
  872. X            }
  873. X        } else if(num = numbers(tmp))    /* continuing to read into folder */
  874. X            create_mail_record(num);
  875. X        else if(strlen(str) > 2) {        /* vmail is confused - break */
  876. X            str[strlen(str)-1] = '\0';
  877. X            addstatus(str, true);
  878. X            redraw = false;
  879. X            break;
  880. X        }
  881. X    if(redraw) {
  882. X        if(isfol != curflr)
  883. X            alternate = curflr;
  884. X        curflr = isfol;
  885. X        curmail = ismail;
  886. X        y = count;
  887. X        display_page();
  888. X    }
  889. X    fclose(pp);
  890. X    wait(&status);
  891. X}
  892. X
  893. X
  894. X/* --------------------
  895. X    Extract the first number from str.
  896. X-------------------- */
  897. Xint
  898. Xnumbers(str)
  899. X    char    *str;
  900. X{
  901. X    char    save, *tmp;
  902. X    int        i;
  903. X
  904. X    for(; *str == ' ' ; str++)
  905. X        ;
  906. X    for(tmp=str ; *str >= '0' && *str <= '9' ; str++)
  907. X        ;
  908. X    save = *str, *str = '\0', i = atoi(tmp), *str = save;
  909. X    return(i);
  910. X}
  911. X
  912. X
  913. X/* --------------------
  914. X    Find the folder into which mail is being incorporated, set isfol,
  915. X    ismail, count.
  916. X-------------------- */
  917. Xvoid
  918. Xgoto_incorp_folder(str)
  919. X    char    *str;
  920. X{
  921. X    folder    create_folder();
  922. X
  923. X    GOTO_NAME(isfol, str);
  924. X    if(isfol == (folder) NULL) {    /* new folder */
  925. X        isfol = create_folder(str);
  926. X        isfol->valid = true;
  927. X        ismail = (item) NULL;
  928. X        count = FIRST-1;
  929. X    } else {
  930. X        if(! isfol->valid) {
  931. X            isfol->valid = true;
  932. X            find_mail(isfol, false);
  933. X        }
  934. X            /* find last appropriate folder record */
  935. X        LAST_OF_NAME(isfol);
  936. X        for(count=FIRST, ismail=isfol->mail ; ismail->next != (item) NULL ;
  937. X                                                count++, ismail=ismail->next)
  938. X            ;
  939. X    }
  940. X}
  941. X
  942. X
  943. X/* --------------------
  944. X    Create and insert new item record into isfol, may need to create new page.
  945. X-------------------- */
  946. Xvoid
  947. Xcreate_mail_record(num)
  948. X    int        num;
  949. X{
  950. X    item    m;
  951. X    folder    new_folder();
  952. X
  953. X    m = NEW(mail_item);
  954. X    get_title(isfol, m, num);
  955. X    m->next = (item) NULL;
  956. X    if(count > lines) {
  957. X            /* create new folder record */
  958. X        isfol = new_folder(isfol);
  959. X        ismail = (item) NULL;
  960. X        count = FIRST;
  961. X    } else
  962. X        count++;
  963. X    if(ismail == (item) NULL) {
  964. X            /* new record, possibly new folder */
  965. X        m->prev = (item) NULL;
  966. X        isfol->mail = isfol->last = m;
  967. X    } else {
  968. X            /* insert at end of list of mail items */
  969. X        m->prev = ismail;
  970. X        ismail->next = isfol->last = m;
  971. X    }
  972. X    ismail = m;
  973. X}
  974. !The!End!
  975.  
  976. echo x - "init.c" 2>&1
  977. sed "s/^X//" >"init.c" <<'!The!End!'
  978. X/* --------------------
  979. X    vmail -- init.c
  980. X
  981. X    Initialisation routines - setting ttystate, finding valid folders,
  982. X    trapping signals.
  983. X
  984. X    Ttystate is controlled by a mix of curses and ioctl.  For simplicity,
  985. X    initial setups are done with curses.  Curses is also used for basic
  986. X    screen manipulation.  However, for speed ioctl is used in switching
  987. X    in and out of normal terminal state.
  988. X
  989. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  990. X-------------------- */
  991. X
  992. X#include "defs.h"
  993. X#include <signal.h>
  994. X
  995. Xstatic struct sgttyb tty, t_tty;        /* for holding tty state */
  996. Xstatic struct tchars chrs, t_chrs;
  997. Xstatic struct ltchars lchrs, t_lchrs;
  998. X
  999. Xstatic char    termcap[1024],                /* termcap entry */
  1000. X            *cur_folder;                /* initial current folder */
  1001. X
  1002. X/* --------------------
  1003. X    Start-up routine - set terminal control, signals, etc.
  1004. X-------------------- */
  1005. Xvoid
  1006. Xinit(argc, argv)
  1007. X    int        argc;
  1008. X    char    **argv;
  1009. X{
  1010. X    folder    ftmp, find_mail();
  1011. X    char    *pargv[20],                    /* argv from profile */
  1012. X            *profile = (char *) NULL,    /* location of MH profile */
  1013. X            *home = (char *) NULL,        /* home directory */
  1014. X            *term = (char *) NULL;        /* terminal type */
  1015. X    int        pargc = 0;                    /* argc from profile */
  1016. X
  1017. X    get_home(&home);
  1018. X    get_env(&term, &profile, home);
  1019. X    tgetent(termcap, term);
  1020. X    cols = tgetnum("co");
  1021. X        /* lines holds no. of lines for headers, ie "li" less STATUS, TITLE */
  1022. X    lines = tgetnum("li") - 2;
  1023. X    ioctl(0, TIOCGETP, &tty);
  1024. X    ioctl(0, TIOCGETP, &chrs);
  1025. X    ioctl(0, TIOCGETP, &lchrs);
  1026. X
  1027. X    read_profile(&pargc, pargv, profile, home);
  1028. X    process_args(pargc, pargv);
  1029. X    find_folders();
  1030. X    mark_valid_folders(pargc, pargv);
  1031. X        /* give precedence to command line args => process second */
  1032. X    mark_valid_folders(argc, argv);
  1033. X    for(ftmp=folders ; ftmp != (folder) NULL ;)
  1034. X        if(ftmp->valid)
  1035. X            ftmp = find_mail(ftmp, true);
  1036. X        else
  1037. X            ftmp = ftmp->next;
  1038. X    if(curflr->valid == EMPTY) {
  1039. X        printf("%s: folder empty.\n", curflr->name);
  1040. X        exit(1);
  1041. X    }
  1042. X        /* find last instance of initial folder */
  1043. X    LAST_OF_NAME(curflr);
  1044. X    curmail = curflr->mail;
  1045. X
  1046. X    initscr();
  1047. X    crmode();
  1048. X    noecho();
  1049. X    nonl();
  1050. X
  1051. X    signal(SIGTSTP, tstp);
  1052. X    signal(SIGINT, tint);
  1053. X
  1054. X    ioctl(0, TIOCGETP, &t_tty);
  1055. X    ioctl(0, TIOCGETP, &t_chrs);
  1056. X    ioctl(0, TIOCGETP, &t_lchrs);
  1057. X
  1058. X    y = FIRST;
  1059. X    display_page();
  1060. X}
  1061. X
  1062. X
  1063. X/* --------------------
  1064. X    Find user name, home directory.
  1065. X-------------------- */
  1066. Xvoid
  1067. Xget_home(home)
  1068. X    char **home;
  1069. X{
  1070. X    struct passwd *pwent, *getpwuid();
  1071. X
  1072. X    pwent = getpwuid(getuid());
  1073. X    *home = NEWSTR(strlen(pwent->pw_dir)+1);
  1074. X    strcpy(*home, pwent->pw_dir);
  1075. X    if(access(*home, R_OK | W_OK | X_OK)) {
  1076. X        printf("%s: no permissions.\n", *home);
  1077. X        exit(1);
  1078. X    }
  1079. X    user = NEWSTR(strlen(pwent->pw_name)+1);
  1080. X    strcpy(user, pwent->pw_name);
  1081. X}
  1082. X
  1083. X
  1084. X/* --------------------
  1085. X    Find pager, editor, shell, terminal type, MH profile - defaults are PAGER,
  1086. X    EDITOR, SHELL, none, PROFILE.  Set by PAGER, EDITOR, SHELL, TERM, MH
  1087. X    environment variables.
  1088. X-------------------- */
  1089. Xvoid
  1090. Xget_env(term, profile, home)
  1091. X    char **term, **profile, *home;
  1092. X{
  1093. X    char    **tmp;
  1094. X
  1095. X    for(tmp = environ ; *tmp != (char *) NULL ; tmp++)
  1096. X        if(!strncmp("PAGER=", *tmp, 6)) {
  1097. X            pager = NEWSTR(strlen(*tmp)-4);
  1098. X            strcpy(pager, *tmp+6);
  1099. X        } else if(!strncmp("EDITOR=", *tmp, 7)) {
  1100. X            editor = NEWSTR(strlen(*tmp)-5);
  1101. X            strcpy(editor, *tmp+7);
  1102. X        } else if(!strncmp("SHELL=", *tmp, 6)) {
  1103. X            shell = NEWSTR(strlen(*tmp)-4);
  1104. X            strcpy(shell, *tmp+6);
  1105. X        } else if(!strncmp("TERM=", *tmp, 5)) {
  1106. X            *term = NEWSTR(strlen(*tmp)-3);
  1107. X            strcpy(*term, *tmp+5);
  1108. X        } else if(!strncmp("MH=", *tmp, 3)) {
  1109. X            *profile = NEWSTR(strlen(*tmp)-1);
  1110. X            strcpy(*profile, *tmp+3);
  1111. X        }
  1112. X    if(*term == (char *) NULL) {
  1113. X        printf("Terminal type unknown\n");
  1114. X        exit(1);
  1115. X    }
  1116. X    if(*profile == (char *) NULL) {
  1117. X        *profile = NEWSTR(strlen(home)+strlen(PROFILE)+2);
  1118. X        sprintf(*profile, "%s/%s", home, PROFILE);
  1119. X    }
  1120. X    if(pager == (char *) NULL) {
  1121. X        pager = NEWSTR(strlen(PAGER)+1);
  1122. X        strcpy(pager, PAGER);
  1123. X    }
  1124. X    if(shell == (char *) NULL) {
  1125. X        shell = NEWSTR(strlen(SHELL)+1);
  1126. X        strcpy(shell, SHELL);
  1127. X    }
  1128. X    if(editor == (char *) NULL) {
  1129. X        editor = NEWSTR(strlen(EDITOR)+1);
  1130. X        strcpy(editor, EDITOR);
  1131. X    }
  1132. X}
  1133. X
  1134. X
  1135. Xstatic char argkeep[LEN];            /* storage for args from profile */
  1136. X
  1137. X/* --------------------
  1138. X    Find mail directory, current-folder, context, default options.
  1139. X-------------------- */
  1140. Xvoid
  1141. Xread_profile(pargc, pargv, profile, home)
  1142. X    int *pargc;
  1143. X    char **pargv, *profile, *home;
  1144. X{
  1145. X    FILE    *fp, *fopen();
  1146. X    char    str[LEN], *ptr, iscontext[LEN], *index(), *next_token();
  1147. X
  1148. X    if((fp = fopen(profile, "r")) == (FILE *) NULL) {
  1149. X        printf("Profile: %s: cannot open.\n", profile);
  1150. X        exit(1);
  1151. X    }
  1152. X    *iscontext = '\0';
  1153. X    while(fgets(str, LEN, fp) != (char *) NULL) {
  1154. X            /* get entries from profile */
  1155. X        if(lstrncmp("context:", str, 8) == 0 && *(ptr=str+8) != '\0') {
  1156. X            squash(str);
  1157. X            strcpy(iscontext, str+8);
  1158. X        } else if(lstrncmp("vmail:", str, 6) == 0 && *(ptr=str+6) != '\0') {
  1159. X            for( ; *ptr == ' ' || *ptr == '\t' ; ptr++)
  1160. X                ;
  1161. X            *index(ptr, '\n') = '\0';
  1162. X            strcpy(argkeep, ptr);
  1163. X            for(ptr=argkeep ; *ptr != '\0' ; ) {
  1164. X                pargv[(*pargc)++] = ptr;
  1165. X                ptr = next_token(ptr);
  1166. X            }
  1167. X        } else if(lstrncmp("path:", str, 5) == 0 && *(ptr=str+5) != '\0') {
  1168. X            squash(str);
  1169. X            if(*ptr == '/') {        /* full pathname */
  1170. X                mail_dir = NEWSTR(strlen(ptr)+1);
  1171. X                strcpy(mail_dir, ptr);
  1172. X            } else {
  1173. X                mail_dir = NEWSTR(strlen(home)+strlen(ptr)+1);
  1174. X                sprintf(mail_dir, "%s/%s", home, ptr);
  1175. X            }
  1176. X        } else if(lstrncmp("folder-protect:", str, 15) == 0 &&
  1177. X                                                        *(str+15) != '\0') {
  1178. X            squash(str);
  1179. X            folder_protect = atoo(str+15);
  1180. X        } else if(lstrncmp("current-folder:", str, 15) == 0 &&
  1181. X                                                        *(str+15) != '\0') {
  1182. X            squash(str);
  1183. X            cur_folder = NEWSTR(strlen(str+15)+1);
  1184. X            strcpy(cur_folder, str);
  1185. X        }
  1186. X    }
  1187. X    fclose(fp);
  1188. X    if(mail_dir == (char *) NULL) {
  1189. X        mail_dir = NEWSTR(strlen(home)+strlen(MAILDIR)+2);
  1190. X        sprintf(mail_dir, "%s/%s", home, str+6);
  1191. X    }
  1192. X    if(access(mail_dir, R_OK | W_OK | X_OK)) {
  1193. X        printf("%s: no permissions.\n", mail_dir);
  1194. X        exit(1);
  1195. X    }
  1196. X    if(*iscontext == '\0')
  1197. X        strcpy(iscontext, CONTEXT);
  1198. X    context = NEWSTR(strlen(mail_dir)+strlen(iscontext)+2);
  1199. X    sprintf(context, "%s/%s", mail_dir, iscontext);
  1200. X    if(access(context, R_OK | W_OK)) {
  1201. X        printf("%s: no permissions.\n", context);
  1202. X        exit(1);
  1203. X    }
  1204. X    if(cur_folder == (char *) NULL)
  1205. X        cur_folder = CURFOL;
  1206. X}
  1207. X
  1208. X
  1209. X/* --------------------
  1210. X    Squash spaces, tabs, newlines out of given string.
  1211. X-------------------- */
  1212. Xvoid
  1213. Xsquash(str)
  1214. X    char    *str;
  1215. X{
  1216. X    int        i, j;
  1217. X
  1218. X    for(i=0, j=0 ; (str[j] = str[i]) != '\0' ; i++)
  1219. X        if(str[j] != ' ' && str[j] != '\t' && str[j] != '\n')
  1220. X            j++;
  1221. X}
  1222. X
  1223. X
  1224. X/* --------------------
  1225. X    Mark folders as specified by setenv, command line.  At startup, default
  1226. X    is for only active folder to be cur_folder.
  1227. X-------------------- */
  1228. Xvoid
  1229. Xmark_valid_folders(argc, argv)
  1230. X    int        argc;
  1231. X    char    **argv;
  1232. X{
  1233. X    char    *name;
  1234. X    folder    f;
  1235. X
  1236. X    name = cur_folder;
  1237. X        /* find valid folders - mark all folders from argv as valid */
  1238. X    for(; argc > 0 ; argc--, argv++)
  1239. X        if(**argv == '+')                /* startup folder */
  1240. X            name = (*argv) + 1;
  1241. X        else if(**argv != '-') {        /* not a flag */
  1242. X            GOTO_NAME(f, *argv);
  1243. X            if(f == (folder) NULL)
  1244. X                printf("Warning: no such folder as %s\n", *argv);
  1245. X            else
  1246. X                f->valid = true;
  1247. X        }
  1248. X    GOTO_NAME(f, name);
  1249. X    if(f == (folder) NULL) {
  1250. X        printf("%s does not exist\n", name);
  1251. X        exit(1);
  1252. X    }
  1253. X    f->valid = true;
  1254. X    curflr = f;
  1255. X}
  1256. X
  1257. X
  1258. X/* --------------------
  1259. X    Reset terminal, clean up.
  1260. X-------------------- */
  1261. Xvoid
  1262. Xto_normal()
  1263. X{
  1264. X    move(lines+FIRST-1, 0);
  1265. X    refresh();
  1266. X    no_control();
  1267. X    printf("\n");
  1268. X}
  1269. X
  1270. X
  1271. X/* --------------------
  1272. X    Reset terminal.
  1273. X-------------------- */
  1274. Xvoid
  1275. Xno_control()
  1276. X{
  1277. X    ioctl(0, TIOCSETP, &tty);
  1278. X    ioctl(0, TIOCSETP, &chrs);
  1279. X    ioctl(0, TIOCSETP, &lchrs);
  1280. X}
  1281. X
  1282. X
  1283. X/* --------------------
  1284. X    Set terminal.
  1285. X-------------------- */
  1286. Xvoid
  1287. Xto_control()
  1288. X{
  1289. X    ioctl(0, TIOCSETP, &t_tty);
  1290. X    ioctl(0, TIOCSETP, &t_chrs);
  1291. X    ioctl(0, TIOCSETP, &t_lchrs);
  1292. X}
  1293. X
  1294. X
  1295. X#define    mask(s)    (1 << ((s)-1))
  1296. X
  1297. X/* --------------------
  1298. X    Trap for ^Z.
  1299. X-------------------- */
  1300. Xvoid
  1301. Xtstp()
  1302. X{
  1303. X    int        x, y;
  1304. X
  1305. X    getyx(curscr, y, x);
  1306. X    to_normal();
  1307. X    fix_mh();
  1308. X
  1309. X    signal(SIGTSTP, SIG_DFL);
  1310. X    sigsetmask(sigblock(0) &~ mask(SIGTSTP));
  1311. X    kill(0, SIGTSTP);
  1312. X    sigblock(mask(SIGTSTP));
  1313. X    signal(SIGTSTP, tstp);
  1314. X
  1315. X    if(top_level) {
  1316. X        to_control();
  1317. X        touchwin(curscr);
  1318. X        wmove(curscr, y, x);
  1319. X        wrefresh(curscr);
  1320. X    }
  1321. X}
  1322. X
  1323. X
  1324. X/* --------------------
  1325. X    Trap for ^?.
  1326. X-------------------- */
  1327. Xvoid
  1328. Xtint()
  1329. X{
  1330. X    touchwin(stdscr);
  1331. X    addstatus("-- interrupt --", true);
  1332. X    longjmp(env, 0);    /* jump to main */
  1333. X}
  1334. X
  1335. X
  1336. X/* --------------------
  1337. X    Convert an ascii string to octal.
  1338. X-------------------- */
  1339. Xint
  1340. Xatoo(str)
  1341. X    char *str;
  1342. X{
  1343. X    int        i;
  1344. X
  1345. X    for(; *str < '0' && *str > '7' ; str++)
  1346. X        ;
  1347. X    for(i=0 ; *str >= '0' && *str <= '7' ; str++)
  1348. X        i = i*8 + *str - '0';
  1349. X    return(i);
  1350. X}
  1351. X
  1352. X
  1353. X/* --------------------
  1354. X    Update MH environment - context and current mail item of current folder.
  1355. X-------------------- */
  1356. Xfix_mh()
  1357. X{
  1358. X    char str[LEN], buf[20];
  1359. X
  1360. X    update(context, "Current-Folder:", curflr->name, 15);
  1361. X    sprintf(str, "%s/%s/%s", mail_dir, curflr->name, SEQU);
  1362. X    sprintf(buf, "%d", curmail->number);
  1363. X    update(str, "cur:", buf, 4);
  1364. X}
  1365. X
  1366. X
  1367. X/* --------------------
  1368. X    Update file, replacing line beginning with match of len by "match new".
  1369. X-------------------- */
  1370. Xupdate(file, match, new, len)
  1371. X    char    *file, *match, *new;
  1372. X    int        len;
  1373. X{
  1374. X    FILE    *fp, *tmp, *fopen();
  1375. X    bool    change = false;
  1376. X    char    *mktemp(), *fgets();
  1377. X    char    str[LEN], *name = mktemp("/tmp/vmail.XXXXXX");
  1378. X
  1379. X    if((fp = fopen(file, "r")) == (FILE *) NULL) {
  1380. X        if((fp = fopen(file, "w+")) == (FILE *) NULL)
  1381. X            printf("Can't open %s for writing\n", file);
  1382. X        else {
  1383. X            fprintf(fp, "%s %s\n", match, new);
  1384. X            close(fp);
  1385. X        }
  1386. X    } else {
  1387. X        if((tmp = fopen(name, "w+")) == (FILE *) NULL)
  1388. X            printf("Can't open %s\n", file);
  1389. X        else {
  1390. X            while(fgets(str, LEN, fp) != (char *) NULL)
  1391. X                if(lstrncmp(str, match, len) == 0) {
  1392. X                    change = true;
  1393. X                    fprintf(tmp, "%s %s\n", match, new);
  1394. X                } else
  1395. X                    fprintf(tmp, "%s", str);
  1396. X            if(! change)
  1397. X                fprintf(tmp, "%s %s\n", match, new);
  1398. X            fclose(fp);
  1399. X            fclose(tmp);
  1400. X            if((fp = fopen(file, "w+")) == (FILE *) NULL)
  1401. X                printf("Can't open %s for writing\n", file);
  1402. X            else {
  1403. X                tmp = fopen(name, "r");
  1404. X                while(fgets(str, LEN, tmp) != (char *) NULL)
  1405. X                    fprintf(fp, "%s", str);
  1406. X                fclose(fp);
  1407. X                fclose(tmp);
  1408. X                unlink(name);
  1409. X            }
  1410. X        }
  1411. X    }
  1412. X}
  1413. !The!End!
  1414. exit
  1415.  
  1416.  
  1417.