4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / mail / edit.c
CommitLineData
9552e6b8 1/*
a12ff486
KB
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
0c5f72fb 4 *
f15db449 5 * %sccs.include.redist.c%
9552e6b8
DF
6 */
7
acfc7e9b 8#ifndef lint
a12ff486 9static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) %G%";
acfc7e9b 10#endif /* not lint */
de0c3def
KS
11
12#include "rcv.h"
a0d23834
KB
13#include <fcntl.h>
14#include "extern.h"
de0c3def
KS
15
16/*
17 * Mail -- a mail program
18 *
19 * Perform message editing functions.
20 */
21
de0c3def
KS
22/*
23 * Edit a message list.
24 */
a0d23834 25int
de0c3def
KS
26editor(msgvec)
27 int *msgvec;
28{
de0c3def 29
d33aa50d 30 return edit1(msgvec, 'e');
de0c3def
KS
31}
32
33/*
34 * Invoke the visual editor on a message list.
35 */
a0d23834 36int
de0c3def
KS
37visual(msgvec)
38 int *msgvec;
39{
de0c3def 40
d33aa50d 41 return edit1(msgvec, 'v');
de0c3def
KS
42}
43
44/*
45 * Edit a message by writing the message into a funnily-named file
46 * (which should not exist) and forking an editor on it.
47 * We get the editor from the stuff above.
48 */
a0d23834 49int
d33aa50d 50edit1(msgvec, type)
de0c3def 51 int *msgvec;
a0d23834 52 int type;
de0c3def 53{
de0c3def 54 register int c;
d33aa50d 55 int i;
064d7d97 56 FILE *fp;
064d7d97 57 register struct message *mp;
d33aa50d 58 off_t size;
de0c3def 59
de0c3def
KS
60 /*
61 * Deal with each message to be edited . . .
62 */
064d7d97 63 for (i = 0; msgvec[i] && i < msgCount; i++) {
e62a1467 64 sig_t sigint;
d33aa50d
EW
65
66 if (i > 0) {
67 char buf[100];
68 char *p;
69
470c33f3 70 printf("Edit message %d [ynq]? ", msgvec[i]);
d33aa50d
EW
71 if (fgets(buf, sizeof buf, stdin) == 0)
72 break;
470c33f3 73 for (p = buf; *p == ' ' || *p == '\t'; p++)
d33aa50d
EW
74 ;
75 if (*p == 'q')
76 break;
77 if (*p == 'n')
78 continue;
de0c3def 79 }
470c33f3
EW
80 dot = mp = &message[msgvec[i] - 1];
81 touch(mp);
d33aa50d
EW
82 sigint = signal(SIGINT, SIG_IGN);
83 fp = run_editor(setinput(mp), mp->m_size, type, readonly);
84 if (fp != NULL) {
a0d23834 85 (void) fseek(otf, 0L, 2);
d33aa50d
EW
86 size = ftell(otf);
87 mp->m_block = blockof(size);
88 mp->m_offset = offsetof(size);
89 mp->m_size = fsize(fp);
90 mp->m_lines = 0;
91 mp->m_flag |= MODIFY;
92 rewind(fp);
93 while ((c = getc(fp)) != EOF) {
94 if (c == '\n')
95 mp->m_lines++;
96 if (putc(c, otf) == EOF)
97 break;
98 }
de0c3def 99 if (ferror(otf))
d33aa50d 100 perror("/tmp");
07b0d286 101 (void) Fclose(fp);
de0c3def 102 }
d33aa50d
EW
103 (void) signal(SIGINT, sigint);
104 }
d33aa50d
EW
105 return 0;
106}
107
108/*
109 * Run an editor on the file at "fpp" of "size" bytes,
110 * and return a new file pointer.
111 * Signals must be handled by the caller.
435e8dff 112 * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
d33aa50d
EW
113 */
114FILE *
115run_editor(fp, size, type, readonly)
116 register FILE *fp;
117 off_t size;
a0d23834 118 int type, readonly;
d33aa50d
EW
119{
120 register FILE *nf = NULL;
121 register int t;
122 time_t modtime;
123 char *edit;
124 struct stat statb;
125 extern char tempEdit[];
126
127 if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
128 perror(tempEdit);
129 goto out;
130 }
07b0d286 131 if ((nf = Fdopen(t, "w")) == NULL) {
d33aa50d
EW
132 perror(tempEdit);
133 (void) unlink(tempEdit);
134 goto out;
135 }
136 if (size >= 0)
137 while (--size >= 0 && (t = getc(fp)) != EOF)
138 (void) putc(t, nf);
139 else
140 while ((t = getc(fp)) != EOF)
141 (void) putc(t, nf);
142 (void) fflush(nf);
143 if (fstat(fileno(nf), &statb) < 0)
144 modtime = 0;
145 else
146 modtime = statb.st_mtime;
07b0d286
EW
147 if (ferror(nf)) {
148 (void) Fclose(nf);
149 perror(tempEdit);
150 (void) unlink(tempEdit);
151 nf = NULL;
152 goto out;
153 }
154 if (Fclose(nf) < 0) {
d33aa50d
EW
155 perror(tempEdit);
156 (void) unlink(tempEdit);
157 nf = NULL;
158 goto out;
159 }
160 nf = NULL;
161 if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
435e8dff 162 edit = type == 'e' ? _PATH_EX : _PATH_VI;
a0d23834 163 if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) {
d33aa50d
EW
164 (void) unlink(tempEdit);
165 goto out;
166 }
167 /*
168 * If in read only mode or file unchanged, just remove the editor
169 * temporary and return.
170 */
171 if (readonly) {
172 (void) unlink(tempEdit);
173 goto out;
174 }
175 if (stat(tempEdit, &statb) < 0) {
176 perror(tempEdit);
177 goto out;
178 }
179 if (modtime == statb.st_mtime) {
180 (void) unlink(tempEdit);
181 goto out;
de0c3def 182 }
de0c3def 183 /*
d33aa50d 184 * Now switch to new file.
de0c3def 185 */
07b0d286 186 if ((nf = Fopen(tempEdit, "a+")) == NULL) {
d33aa50d
EW
187 perror(tempEdit);
188 (void) unlink(tempEdit);
189 goto out;
190 }
191 (void) unlink(tempEdit);
de0c3def 192out:
d33aa50d 193 return nf;
de0c3def 194}