1 /*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 #include "rcv.h"
13 #include <fcntl.h>
14 #include "extern.h"
15
16 /*
17 * Mail -- a mail program
18 *
19 * Perform message editing functions.
20 */
21
22 /*
23 * Edit a message list.
24 */
25 int
editor(msgvec)26 editor(msgvec)
27 int *msgvec;
28 {
29
30 return edit1(msgvec, 'e');
31 }
32
33 /*
34 * Invoke the visual editor on a message list.
35 */
36 int
visual(msgvec)37 visual(msgvec)
38 int *msgvec;
39 {
40
41 return edit1(msgvec, 'v');
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 */
49 int
edit1(msgvec,type)50 edit1(msgvec, type)
51 int *msgvec;
52 int type;
53 {
54 register int c;
55 int i;
56 FILE *fp;
57 register struct message *mp;
58 off_t size;
59
60 /*
61 * Deal with each message to be edited . . .
62 */
63 for (i = 0; msgvec[i] && i < msgCount; i++) {
64 sig_t sigint;
65
66 if (i > 0) {
67 char buf[100];
68 char *p;
69
70 printf("Edit message %d [ynq]? ", msgvec[i]);
71 if (fgets(buf, sizeof buf, stdin) == 0)
72 break;
73 for (p = buf; *p == ' ' || *p == '\t'; p++)
74 ;
75 if (*p == 'q')
76 break;
77 if (*p == 'n')
78 continue;
79 }
80 dot = mp = &message[msgvec[i] - 1];
81 touch(mp);
82 sigint = signal(SIGINT, SIG_IGN);
83 fp = run_editor(setinput(mp), mp->m_size, type, readonly);
84 if (fp != NULL) {
85 (void) fseek(otf, 0L, 2);
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 }
99 if (ferror(otf))
100 perror("/tmp");
101 (void) Fclose(fp);
102 }
103 (void) signal(SIGINT, sigint);
104 }
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.
112 * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
113 */
114 FILE *
run_editor(fp,size,type,readonly)115 run_editor(fp, size, type, readonly)
116 register FILE *fp;
117 off_t size;
118 int type, readonly;
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 }
131 if ((nf = Fdopen(t, "w")) == NULL) {
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;
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) {
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)
162 edit = type == 'e' ? _PATH_EX : _PATH_VI;
163 if (run_command(edit, 0, -1, -1, tempEdit, NOSTR, NOSTR) < 0) {
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;
182 }
183 /*
184 * Now switch to new file.
185 */
186 if ((nf = Fopen(tempEdit, "a+")) == NULL) {
187 perror(tempEdit);
188 (void) unlink(tempEdit);
189 goto out;
190 }
191 (void) unlink(tempEdit);
192 out:
193 return nf;
194 }
195