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