now makes the temporary editing file mode 0400 if in readonly
[unix-history] / usr / src / usr.bin / mail / edit.c
CommitLineData
de0c3def
KS
1#
2
3#include "rcv.h"
4#include <stdio.h>
5#include <sys/stat.h>
6
7/*
8 * Mail -- a mail program
9 *
10 * Perform message editing functions.
11 */
12
19f7cf64 13static char *SccsId = "@(#)edit.c 1.2 %G%";
de0c3def
KS
14
15/*
16 * Edit a message list.
17 */
18
19editor(msgvec)
20 int *msgvec;
21{
22 char *edname;
23
24 if ((edname = value("EDITOR")) == NOSTR)
25 edname = EDITOR;
26 return(edit1(msgvec, edname));
27}
28
29/*
30 * Invoke the visual editor on a message list.
31 */
32
33visual(msgvec)
34 int *msgvec;
35{
36 char *edname;
37
38 if ((edname = value("VISUAL")) == NOSTR)
39 edname = VISUAL;
40 return(edit1(msgvec, edname));
41}
42
43/*
44 * Edit a message by writing the message into a funnily-named file
45 * (which should not exist) and forking an editor on it.
46 * We get the editor from the stuff above.
47 */
48
49edit1(msgvec, ed)
50 int *msgvec;
51 char *ed;
52{
53 register char *cp, *cp2;
54 register int c;
55 int *ip, pid, mesg, lines;
56 unsigned int ms;
57 int (*sigint)(), (*sigquit)();
58 FILE *ibuf, *obuf;
59 char edname[15], nbuf[10];
60 struct message *mp;
61 extern char tempEdit[];
62 off_t fsize(), size;
63 struct stat statb;
64 long modtime;
65
66 /*
67 * Set signals; locate editor.
68 */
69
70 sigint = signal(SIGINT, SIG_IGN);
71 sigquit = signal(SIGQUIT, SIG_IGN);
72
73 /*
74 * Deal with each message to be edited . . .
75 */
76
77 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
78 mesg = *ip;
79 mp = &message[mesg-1];
80 mp->m_flag |= MODIFY;
81
82 /*
83 * Make up a name for the edit file of the
84 * form "Message%d" and make sure it doesn't
85 * already exist.
86 */
87
88 cp = &nbuf[10];
89 *--cp = 0;
90 while (mesg) {
91 *--cp = mesg % 10 + '0';
92 mesg /= 10;
93 }
94 cp2 = copy("Message", edname);
95 while (*cp2++ = *cp++)
96 ;
97 if (!access(edname, 2)) {
98 printf("%s: file exists\n", edname);
99 goto out;
100 }
101
102 /*
103 * Copy the message into the edit file.
104 */
105
106 close(creat(edname, 0600));
107 if ((obuf = fopen(edname, "w")) == NULL) {
108 perror(edname);
109 goto out;
110 }
111 if (send(mp, obuf) < 0) {
112 perror(edname);
113 fclose(obuf);
114 remove(edname);
115 goto out;
116 }
117 fflush(obuf);
118 if (ferror(obuf)) {
119 remove(edname);
120 fclose(obuf);
121 goto out;
122 }
123 fclose(obuf);
124
19f7cf64
KS
125 /*
126 * If we are in read only mode, make the
127 * temporary message file readonly as well.
128 */
129
130 if (readonly)
131 chmod(edname, 0400);
132
de0c3def
KS
133 /*
134 * Fork/execl the editor on the edit file.
135 */
136
137 if (stat(edname, &statb) < 0)
138 modtime = 0;
139 modtime = statb.st_mtime;
140 pid = vfork();
141 if (pid == -1) {
142 perror("fork");
143 remove(edname);
144 goto out;
145 }
146 if (pid == 0) {
147 if (sigint != SIG_IGN)
148 signal(SIGINT, SIG_DFL);
149 if (sigquit != SIG_IGN)
150 signal(SIGQUIT, SIG_DFL);
151 execl(ed, ed, edname, 0);
152 perror(ed);
153 _exit(1);
154 }
155 while (wait(&mesg) != pid)
156 ;
157
19f7cf64
KS
158 /*
159 * If in read only mode, just remove the editor
160 * temporary and return.
161 */
162
163 if (readonly) {
164 remove(edname);
165 continue;
166 }
167
de0c3def
KS
168 /*
169 * Now copy the message to the end of the
170 * temp file.
171 */
172
173 if (stat(edname, &statb) < 0) {
174 perror(edname);
175 goto out;
176 }
177 if (modtime == statb.st_mtime) {
178 remove(edname);
179 goto out;
180 }
181 if ((ibuf = fopen(edname, "r")) == NULL) {
182 perror(edname);
183 remove(edname);
184 goto out;
185 }
186 remove(edname);
187 fseek(otf, (long) 0, 2);
188 size = fsize(otf);
189 mp->m_block = blockof(size);
190 mp->m_offset = offsetof(size);
191 ms = 0;
192 lines = 0;
193 while ((c = getc(ibuf)) != EOF) {
194 if (c == '\n')
195 lines++;
196 putc(c, otf);
197 if (ferror(otf))
198 break;
199 ms++;
200 }
201 mp->m_size = ms;
202 mp->m_lines = lines;
203 if (ferror(otf))
204 perror("/tmp");
205 fclose(ibuf);
206 }
207
208 /*
209 * Restore signals and return.
210 */
211
212out:
213 signal(SIGINT, sigint);
214 signal(SIGQUIT, sigquit);
215}