122451Sdist /*
2*62083Sbostic * Copyright (c) 1980, 1993
3*62083Sbostic * The Regents of the University of California. All rights reserved.
433499Sbostic *
542741Sbostic * %sccs.include.redist.c%
622451Sdist */
722451Sdist
834905Sbostic #ifndef lint
9*62083Sbostic static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 06/06/93";
1034905Sbostic #endif /* not lint */
111228Skas
121228Skas #include "rcv.h"
1354505Sbostic #include <fcntl.h>
1454505Sbostic #include "extern.h"
151228Skas
161228Skas /*
171228Skas * Mail -- a mail program
181228Skas *
191228Skas * Perform message editing functions.
201228Skas */
211228Skas
221228Skas /*
231228Skas * Edit a message list.
241228Skas */
2554505Sbostic int
editor(msgvec)261228Skas editor(msgvec)
271228Skas int *msgvec;
281228Skas {
291228Skas
3034963Sedward return edit1(msgvec, 'e');
311228Skas }
321228Skas
331228Skas /*
341228Skas * Invoke the visual editor on a message list.
351228Skas */
3654505Sbostic int
visual(msgvec)371228Skas visual(msgvec)
381228Skas int *msgvec;
391228Skas {
401228Skas
4134963Sedward return edit1(msgvec, 'v');
421228Skas }
431228Skas
441228Skas /*
451228Skas * Edit a message by writing the message into a funnily-named file
461228Skas * (which should not exist) and forking an editor on it.
471228Skas * We get the editor from the stuff above.
481228Skas */
4954505Sbostic int
edit1(msgvec,type)5034963Sedward edit1(msgvec, type)
511228Skas int *msgvec;
5254505Sbostic int type;
531228Skas {
541228Skas register int c;
5534963Sedward int i;
5634879Sedward FILE *fp;
5731142Sedward register struct message *mp;
5834963Sedward off_t size;
591228Skas
601228Skas /*
611228Skas * Deal with each message to be edited . . .
621228Skas */
6334879Sedward for (i = 0; msgvec[i] && i < msgCount; i++) {
6439612Sedward sig_t sigint;
6534963Sedward
6634963Sedward if (i > 0) {
6734963Sedward char buf[100];
6834963Sedward char *p;
6934963Sedward
7034987Sedward printf("Edit message %d [ynq]? ", msgvec[i]);
7134963Sedward if (fgets(buf, sizeof buf, stdin) == 0)
7234963Sedward break;
7334987Sedward for (p = buf; *p == ' ' || *p == '\t'; p++)
7434963Sedward ;
7534963Sedward if (*p == 'q')
7634963Sedward break;
7734963Sedward if (*p == 'n')
7834963Sedward continue;
791228Skas }
8034987Sedward dot = mp = &message[msgvec[i] - 1];
8134987Sedward touch(mp);
8234963Sedward sigint = signal(SIGINT, SIG_IGN);
8334963Sedward fp = run_editor(setinput(mp), mp->m_size, type, readonly);
8434963Sedward if (fp != NULL) {
8554505Sbostic (void) fseek(otf, 0L, 2);
8634963Sedward size = ftell(otf);
8734963Sedward mp->m_block = blockof(size);
8834963Sedward mp->m_offset = offsetof(size);
8934963Sedward mp->m_size = fsize(fp);
9034963Sedward mp->m_lines = 0;
9134963Sedward mp->m_flag |= MODIFY;
9234963Sedward rewind(fp);
9334963Sedward while ((c = getc(fp)) != EOF) {
9434963Sedward if (c == '\n')
9534963Sedward mp->m_lines++;
9634963Sedward if (putc(c, otf) == EOF)
9734963Sedward break;
9834963Sedward }
9934963Sedward if (ferror(otf))
10034963Sedward perror("/tmp");
10143865Sedward (void) Fclose(fp);
1021228Skas }
10334963Sedward (void) signal(SIGINT, sigint);
1041228Skas }
10534963Sedward return 0;
10634963Sedward }
10734963Sedward
10834963Sedward /*
10934963Sedward * Run an editor on the file at "fpp" of "size" bytes,
11034963Sedward * and return a new file pointer.
11134963Sedward * Signals must be handled by the caller.
11237870Sbostic * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
11334963Sedward */
11434963Sedward FILE *
run_editor(fp,size,type,readonly)11534963Sedward run_editor(fp, size, type, readonly)
11634963Sedward register FILE *fp;
11734963Sedward off_t size;
11854505Sbostic int type, readonly;
11934963Sedward {
12034963Sedward register FILE *nf = NULL;
12134963Sedward register int t;
12234963Sedward time_t modtime;
12334963Sedward char *edit;
12434963Sedward struct stat statb;
12534963Sedward extern char tempEdit[];
12634963Sedward
12734963Sedward if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
12834963Sedward perror(tempEdit);
12934963Sedward goto out;
13034963Sedward }
13143865Sedward if ((nf = Fdopen(t, "w")) == NULL) {
13234963Sedward perror(tempEdit);
13334963Sedward (void) unlink(tempEdit);
13434963Sedward goto out;
13534963Sedward }
13634963Sedward if (size >= 0)
13734963Sedward while (--size >= 0 && (t = getc(fp)) != EOF)
13834963Sedward (void) putc(t, nf);
13934963Sedward else
14034963Sedward while ((t = getc(fp)) != EOF)
14134963Sedward (void) putc(t, nf);
14234963Sedward (void) fflush(nf);
14334963Sedward if (fstat(fileno(nf), &statb) < 0)
14434963Sedward modtime = 0;
14534963Sedward else
14634963Sedward modtime = statb.st_mtime;
14743865Sedward if (ferror(nf)) {
14843865Sedward (void) Fclose(nf);
14934963Sedward perror(tempEdit);
15034963Sedward (void) unlink(tempEdit);
15134963Sedward nf = NULL;
15234963Sedward goto out;
15334963Sedward }
15443865Sedward if (Fclose(nf) < 0) {
15543865Sedward perror(tempEdit);
15643865Sedward (void) unlink(tempEdit);
15743865Sedward nf = NULL;
15843865Sedward goto out;
15943865Sedward }
16034963Sedward nf = NULL;
16134963Sedward if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
16237870Sbostic edit = type == 'e' ? _PATH_EX : _PATH_VI;
16354505Sbostic if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) {
16434963Sedward (void) unlink(tempEdit);
16534963Sedward goto out;
16634963Sedward }
1671228Skas /*
16834963Sedward * If in read only mode or file unchanged, just remove the editor
16934963Sedward * temporary and return.
1701228Skas */
17134963Sedward if (readonly) {
17234963Sedward (void) unlink(tempEdit);
17334963Sedward goto out;
17434963Sedward }
17534963Sedward if (stat(tempEdit, &statb) < 0) {
17634963Sedward perror(tempEdit);
17734963Sedward goto out;
17834963Sedward }
17934963Sedward if (modtime == statb.st_mtime) {
18034963Sedward (void) unlink(tempEdit);
18134963Sedward goto out;
18234963Sedward }
18334963Sedward /*
18434963Sedward * Now switch to new file.
18534963Sedward */
18643865Sedward if ((nf = Fopen(tempEdit, "a+")) == NULL) {
18734963Sedward perror(tempEdit);
18834963Sedward (void) unlink(tempEdit);
18934963Sedward goto out;
19034963Sedward }
19134963Sedward (void) unlink(tempEdit);
1921228Skas out:
19334963Sedward return nf;
1941228Skas }
195