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