edit.c revision 1.1.1.2 1 /*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37
38 #include "rcv.h"
39 #include <fcntl.h>
40 #include "extern.h"
41
42 /*
43 * Mail -- a mail program
44 *
45 * Perform message editing functions.
46 */
47
48 /*
49 * Edit a message list.
50 */
51 int
52 editor(msgvec)
53 int *msgvec;
54 {
55
56 return edit1(msgvec, 'e');
57 }
58
59 /*
60 * Invoke the visual editor on a message list.
61 */
62 int
63 visual(msgvec)
64 int *msgvec;
65 {
66
67 return edit1(msgvec, 'v');
68 }
69
70 /*
71 * Edit a message by writing the message into a funnily-named file
72 * (which should not exist) and forking an editor on it.
73 * We get the editor from the stuff above.
74 */
75 int
76 edit1(msgvec, type)
77 int *msgvec;
78 int type;
79 {
80 register int c;
81 int i;
82 FILE *fp;
83 register struct message *mp;
84 off_t size;
85
86 /*
87 * Deal with each message to be edited . . .
88 */
89 for (i = 0; msgvec[i] && i < msgCount; i++) {
90 sig_t sigint;
91
92 if (i > 0) {
93 char buf[100];
94 char *p;
95
96 printf("Edit message %d [ynq]? ", msgvec[i]);
97 if (fgets(buf, sizeof buf, stdin) == 0)
98 break;
99 for (p = buf; *p == ' ' || *p == '\t'; p++)
100 ;
101 if (*p == 'q')
102 break;
103 if (*p == 'n')
104 continue;
105 }
106 dot = mp = &message[msgvec[i] - 1];
107 touch(mp);
108 sigint = signal(SIGINT, SIG_IGN);
109 fp = run_editor(setinput(mp), mp->m_size, type, readonly);
110 if (fp != NULL) {
111 (void) fseek(otf, 0L, 2);
112 size = ftell(otf);
113 mp->m_block = blockof(size);
114 mp->m_offset = offsetof(size);
115 mp->m_size = fsize(fp);
116 mp->m_lines = 0;
117 mp->m_flag |= MODIFY;
118 rewind(fp);
119 while ((c = getc(fp)) != EOF) {
120 if (c == '\n')
121 mp->m_lines++;
122 if (putc(c, otf) == EOF)
123 break;
124 }
125 if (ferror(otf))
126 perror("/tmp");
127 (void) Fclose(fp);
128 }
129 (void) signal(SIGINT, sigint);
130 }
131 return 0;
132 }
133
134 /*
135 * Run an editor on the file at "fpp" of "size" bytes,
136 * and return a new file pointer.
137 * Signals must be handled by the caller.
138 * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
139 */
140 FILE *
141 run_editor(fp, size, type, readonly)
142 register FILE *fp;
143 off_t size;
144 int type, readonly;
145 {
146 register FILE *nf = NULL;
147 register int t;
148 time_t modtime;
149 char *edit;
150 struct stat statb;
151 extern char tempEdit[];
152
153 if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
154 perror(tempEdit);
155 goto out;
156 }
157 if ((nf = Fdopen(t, "w")) == NULL) {
158 perror(tempEdit);
159 (void) unlink(tempEdit);
160 goto out;
161 }
162 if (size >= 0)
163 while (--size >= 0 && (t = getc(fp)) != EOF)
164 (void) putc(t, nf);
165 else
166 while ((t = getc(fp)) != EOF)
167 (void) putc(t, nf);
168 (void) fflush(nf);
169 if (fstat(fileno(nf), &statb) < 0)
170 modtime = 0;
171 else
172 modtime = statb.st_mtime;
173 if (ferror(nf)) {
174 (void) Fclose(nf);
175 perror(tempEdit);
176 (void) unlink(tempEdit);
177 nf = NULL;
178 goto out;
179 }
180 if (Fclose(nf) < 0) {
181 perror(tempEdit);
182 (void) unlink(tempEdit);
183 nf = NULL;
184 goto out;
185 }
186 nf = NULL;
187 if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
188 edit = type == 'e' ? _PATH_EX : _PATH_VI;
189 if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) {
190 (void) unlink(tempEdit);
191 goto out;
192 }
193 /*
194 * If in read only mode or file unchanged, just remove the editor
195 * temporary and return.
196 */
197 if (readonly) {
198 (void) unlink(tempEdit);
199 goto out;
200 }
201 if (stat(tempEdit, &statb) < 0) {
202 perror(tempEdit);
203 goto out;
204 }
205 if (modtime == statb.st_mtime) {
206 (void) unlink(tempEdit);
207 goto out;
208 }
209 /*
210 * Now switch to new file.
211 */
212 if ((nf = Fopen(tempEdit, "a+")) == NULL) {
213 perror(tempEdit);
214 (void) unlink(tempEdit);
215 goto out;
216 }
217 (void) unlink(tempEdit);
218 out:
219 return nf;
220 }
221