edit.c revision 1.2 1 /*
2 * Copyright (c) 1980 Regents of the University of California.
3 * 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[] = "from: @(#)edit.c 5.15 (Berkeley) 6/25/90";*/
36 static char rcsid[] = "$Id: edit.c,v 1.2 1993/08/01 18:13:08 mycroft Exp $";
37 #endif /* not lint */
38
39 #include "rcv.h"
40 #include <sys/stat.h>
41
42 /*
43 * Mail -- a mail program
44 *
45 * Perform message editing functions.
46 */
47
48 /*
49 * Edit a message list.
50 */
51
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
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 edit1(msgvec, type)
76 int *msgvec;
77 char type;
78 {
79 register int c;
80 int i;
81 FILE *fp;
82 register struct message *mp;
83 off_t size;
84
85 /*
86 * Deal with each message to be edited . . .
87 */
88 for (i = 0; msgvec[i] && i < msgCount; i++) {
89 sig_t sigint;
90
91 if (i > 0) {
92 char buf[100];
93 char *p;
94
95 printf("Edit message %d [ynq]? ", msgvec[i]);
96 if (fgets(buf, sizeof buf, stdin) == 0)
97 break;
98 for (p = buf; *p == ' ' || *p == '\t'; p++)
99 ;
100 if (*p == 'q')
101 break;
102 if (*p == 'n')
103 continue;
104 }
105 dot = mp = &message[msgvec[i] - 1];
106 touch(mp);
107 sigint = signal(SIGINT, SIG_IGN);
108 fp = run_editor(setinput(mp), mp->m_size, type, readonly);
109 if (fp != NULL) {
110 (void) fseek(otf, (long) 0, 2);
111 size = ftell(otf);
112 mp->m_block = blockof(size);
113 mp->m_offset = offsetof(size);
114 mp->m_size = fsize(fp);
115 mp->m_lines = 0;
116 mp->m_flag |= MODIFY;
117 rewind(fp);
118 while ((c = getc(fp)) != EOF) {
119 if (c == '\n')
120 mp->m_lines++;
121 if (putc(c, otf) == EOF)
122 break;
123 }
124 if (ferror(otf))
125 perror("/tmp");
126 (void) Fclose(fp);
127 }
128 (void) signal(SIGINT, sigint);
129 }
130 return 0;
131 }
132
133 /*
134 * Run an editor on the file at "fpp" of "size" bytes,
135 * and return a new file pointer.
136 * Signals must be handled by the caller.
137 * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
138 */
139 FILE *
140 run_editor(fp, size, type, readonly)
141 register FILE *fp;
142 off_t size;
143 char type;
144 {
145 register FILE *nf = NULL;
146 register int t;
147 time_t modtime;
148 char *edit;
149 struct stat statb;
150 extern char tempEdit[];
151
152 if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) {
153 perror(tempEdit);
154 goto out;
155 }
156 if ((nf = Fdopen(t, "w")) == NULL) {
157 perror(tempEdit);
158 (void) unlink(tempEdit);
159 goto out;
160 }
161 if (size >= 0)
162 while (--size >= 0 && (t = getc(fp)) != EOF)
163 (void) putc(t, nf);
164 else
165 while ((t = getc(fp)) != EOF)
166 (void) putc(t, nf);
167 (void) fflush(nf);
168 if (fstat(fileno(nf), &statb) < 0)
169 modtime = 0;
170 else
171 modtime = statb.st_mtime;
172 if (ferror(nf)) {
173 (void) Fclose(nf);
174 perror(tempEdit);
175 (void) unlink(tempEdit);
176 nf = NULL;
177 goto out;
178 }
179 if (Fclose(nf) < 0) {
180 perror(tempEdit);
181 (void) unlink(tempEdit);
182 nf = NULL;
183 goto out;
184 }
185 nf = NULL;
186 if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
187 edit = type == 'e' ? _PATH_EX : _PATH_VI;
188 if (run_command(edit, 0, -1, -1, tempEdit, NOSTR) < 0) {
189 (void) unlink(tempEdit);
190 goto out;
191 }
192 /*
193 * If in read only mode or file unchanged, just remove the editor
194 * temporary and return.
195 */
196 if (readonly) {
197 (void) unlink(tempEdit);
198 goto out;
199 }
200 if (stat(tempEdit, &statb) < 0) {
201 perror(tempEdit);
202 goto out;
203 }
204 if (modtime == statb.st_mtime) {
205 (void) unlink(tempEdit);
206 goto out;
207 }
208 /*
209 * Now switch to new file.
210 */
211 if ((nf = Fopen(tempEdit, "a+")) == NULL) {
212 perror(tempEdit);
213 (void) unlink(tempEdit);
214 goto out;
215 }
216 (void) unlink(tempEdit);
217 out:
218 return nf;
219 }
220