Handle keyboard interrupts. Use util_tempfile().
Showing
1 changed file
with
110 additions
and
174 deletions
... | @@ -31,33 +31,52 @@ | ... | @@ -31,33 +31,52 @@ |
31 | int | 31 | int |
32 | mail_send (int argc, char **argv) | 32 | mail_send (int argc, char **argv) |
33 | { | 33 | { |
34 | char *to = NULL, *cc = NULL, *bcc = NULL, *subj = NULL; | 34 | struct send_environ env; |
35 | int status; | ||
35 | 36 | ||
37 | env.to = env.cc = env.bcc = env.subj = NULL; | ||
38 | |||
36 | if (argc < 2) | 39 | if (argc < 2) |
37 | to = readline ("To: "); | 40 | env.to = readline ("To: "); |
38 | else | 41 | else |
39 | { | 42 | { |
40 | while (--argc) | 43 | while (--argc) |
41 | { | 44 | { |
42 | char *p = alias_expand (*++argv); | 45 | char *p = alias_expand (*++argv); |
43 | if (to) | 46 | if (env.to) |
44 | util_strcat(&to, ","); | 47 | util_strcat(&env.to, ","); |
45 | util_strcat(&to, p); | 48 | util_strcat(&env.to, p); |
46 | free (p); | 49 | free (p); |
47 | } | 50 | } |
48 | } | 51 | } |
49 | 52 | ||
50 | if ((util_find_env ("askcc"))->set) | 53 | if ((util_find_env ("askcc"))->set) |
51 | cc = readline ("Cc: "); | 54 | env.cc = readline ("Cc: "); |
52 | if ((util_find_env ("askbcc"))->set) | 55 | if ((util_find_env ("askbcc"))->set) |
53 | bcc = readline ("Bcc: "); | 56 | env.bcc = readline ("Bcc: "); |
54 | 57 | ||
55 | if ((util_find_env ("asksub"))->set) | 58 | if ((util_find_env ("asksub"))->set) |
56 | subj = readline ("Subject: "); | 59 | env.subj = readline ("Subject: "); |
57 | else | 60 | else |
58 | subj = (util_find_env ("subject"))->value; | 61 | env.subj = (util_find_env ("subject"))->value; |
62 | |||
63 | status = mail_send0 (&env, isupper(argv[0][0])); | ||
64 | free_env_headers (&env); | ||
65 | return status; | ||
66 | } | ||
67 | |||
59 | 68 | ||
60 | return mail_send0 (to, cc, bcc, subj, isupper(argv[0][0])); | 69 | void |
70 | free_env_headers (struct send_environ *env) | ||
71 | { | ||
72 | if (env->to) | ||
73 | free (env->to); | ||
74 | if (env->cc) | ||
75 | free (env->cc); | ||
76 | if (env->bcc) | ||
77 | free (env->bcc); | ||
78 | if (env->subj) | ||
79 | free (env->subj); | ||
61 | } | 80 | } |
62 | 81 | ||
63 | /* mail_send0(): shared between mail_send() and mail_reply(); | 82 | /* mail_send0(): shared between mail_send() and mail_reply(); |
... | @@ -65,12 +84,10 @@ mail_send (int argc, char **argv) | ... | @@ -65,12 +84,10 @@ mail_send (int argc, char **argv) |
65 | If the variable "record" is set, the outgoing message is | 84 | If the variable "record" is set, the outgoing message is |
66 | saved after being sent. If "save_to" argument is non-zero, | 85 | saved after being sent. If "save_to" argument is non-zero, |
67 | the name of the save file is derived from "to" argument. Otherwise, | 86 | the name of the save file is derived from "to" argument. Otherwise, |
68 | it is taken from the value of "record" variable. | 87 | it is taken from the value of "record" variable. */ |
69 | 88 | ||
70 | NOTE: arguments must be allocated dynamically. They will be freed | ||
71 | before exit */ | ||
72 | int | 89 | int |
73 | mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | 90 | mail_send0 (struct send_environ *env, int save_to) |
74 | { | 91 | { |
75 | char *buf = NULL; | 92 | char *buf = NULL; |
76 | size_t n = 0; | 93 | size_t n = 0; |
... | @@ -78,168 +95,81 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | ... | @@ -78,168 +95,81 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) |
78 | int fd; | 95 | int fd; |
79 | char *filename; | 96 | char *filename; |
80 | FILE *file; | 97 | FILE *file; |
81 | const char *tmpdir; | ||
82 | char *savefile = NULL; | 98 | char *savefile = NULL; |
83 | 99 | int int_cnt; | |
84 | /* We have to be extra careful about opening temporary files, since we | 100 | |
85 | may be running with extra privilege i.e setgid(). */ | 101 | fd = util_tempfile(&filename); |
86 | tmpdir = (getenv ("TMPDIR")) ? getenv ("TMPDIR") : "/tmp"; | ||
87 | filename = alloca (strlen (tmpdir) + /*'/'*/1 + /* "muXXXXXX" */8 + 1); | ||
88 | sprintf (filename, "%s/muXXXXXX", tmpdir); | ||
89 | #ifdef HAVE_MKSTEMP | ||
90 | { | ||
91 | int save_mask = umask(077); | ||
92 | fd = mkstemp (filename); | ||
93 | umask(save_mask); | ||
94 | } | ||
95 | #else | ||
96 | if (mktemp (filename)) | ||
97 | fd = open(filename, O_CREAT|O_EXCL|O_RDWR, 0600); | ||
98 | else | ||
99 | fd = -1; | ||
100 | #endif | ||
101 | 102 | ||
102 | if (fd == -1) | 103 | if (fd == -1) |
103 | { | 104 | { |
104 | fprintf (stderr, "Can not open temporary file"); | 105 | util_error("Can not open temporary file"); |
105 | return 1; | 106 | return 1; |
106 | } | 107 | } |
107 | 108 | ||
108 | file = fdopen (fd, "w+"); | 109 | /* Prepare environment */ |
109 | 110 | env = env; | |
110 | while (getline (&buf, &n, stdin) >= 0 && !done) | 111 | env->filename = filename; |
112 | env->file = fdopen (fd, "w+"); | ||
113 | env->ofile = ofile; | ||
114 | |||
115 | ml_clear_interrupt(); | ||
116 | int_cnt = 0; | ||
117 | while (!done) | ||
111 | { | 118 | { |
119 | buf = readline(NULL); | ||
120 | |||
121 | if (ml_got_interrupt()) | ||
122 | { | ||
123 | if (++int_cnt == 2) | ||
124 | break; | ||
125 | util_error("(Interrupt -- one more to kill letter)"); | ||
126 | if (buf) | ||
127 | free (buf); | ||
128 | continue; | ||
129 | } | ||
130 | |||
131 | if (!buf) | ||
132 | break; | ||
133 | int_cnt = 0; | ||
134 | |||
112 | if (buf[0] == (util_find_env("escape"))->value[0]) | 135 | if (buf[0] == (util_find_env("escape"))->value[0]) |
113 | { | 136 | { |
114 | FILE *ostdout = ofile; | 137 | int argc; |
115 | ofile = file; | 138 | char **argv; |
116 | buf[strlen(buf)-1] = '\0'; | 139 | int status; |
117 | switch (buf[1]) | 140 | |
141 | ofile = env->file; | ||
142 | |||
143 | if (argcv_get (buf+1, "", &argc, &argv) == 0) | ||
118 | { | 144 | { |
119 | case '!': | 145 | struct mail_command_entry entry; |
120 | util_do_command ("!%s", &buf[2]); | 146 | entry = util_find_entry (mail_escape_table, argv[0]); |
121 | break; | 147 | |
122 | case '.': | 148 | if (entry.func) |
123 | done = 1; | 149 | status = (*entry.func)(argc, argv, env); |
124 | break; | ||
125 | case ':': | ||
126 | case '-': | ||
127 | util_do_command ("%s", &buf[2]); | ||
128 | break; | ||
129 | case '?': | ||
130 | /* escape help */ | ||
131 | break; | ||
132 | case 'A': | ||
133 | fprintf (ofile, "%s", (util_find_env("Sign"))->value); | ||
134 | break; | ||
135 | case 'a': | ||
136 | fprintf (ofile, "%s", (util_find_env("sign"))->value); | ||
137 | break; | ||
138 | case 'b': | ||
139 | bcc = realloc (bcc, (strlen(bcc) + strlen(buf) - 1) * | ||
140 | sizeof(char)); | ||
141 | strcat (bcc, ", "); | ||
142 | strcat (bcc, &buf[3]); | ||
143 | break; | ||
144 | case 'c': | ||
145 | cc = realloc (cc, (strlen(cc) + strlen(buf) - 1) * | ||
146 | sizeof (char)); | ||
147 | strcat (cc, ", "); | ||
148 | strcat (cc, &buf[3]); | ||
149 | break; | ||
150 | case 'd': | ||
151 | { | ||
152 | FILE *dead = fopen (getenv("DEAD"), "r"); | ||
153 | char c; | ||
154 | while ((c = fgetc(dead))) | ||
155 | fputc (c, file); | ||
156 | fclose (dead); | ||
157 | } | ||
158 | break; | ||
159 | case 'e': | ||
160 | fclose (file); | ||
161 | ofile = ostdout; | ||
162 | util_do_command ("!%s %s", getenv("EDITOR"), filename); | ||
163 | file = fopen (filename, "a"); | ||
164 | ofile = file; | ||
165 | break; | ||
166 | case 'f': | ||
167 | util_do_command ("print %s", &buf[3]); | ||
168 | break; | ||
169 | case 'F': | ||
170 | util_do_command ("Print %s", &buf[3]); | ||
171 | break; | ||
172 | case 'h': | ||
173 | /* reget Bcc, Cc, To, and Subject */ | ||
174 | break; | ||
175 | case 'i': | ||
176 | fprintf (file, "%s", (util_find_env(&buf[3]))->value); | ||
177 | break; | ||
178 | case 'm': | ||
179 | /* quote messages */ | ||
180 | break; | ||
181 | case 'M': | ||
182 | /* same as m with no headers ignored */ | ||
183 | break; | ||
184 | case 'p': | ||
185 | fclose (file); | ||
186 | ofile = ostdout; | ||
187 | if (/* numlines (filename) > */ util_getlines()) | ||
188 | util_do_command ("!%s %s", getenv("PAGER"), filename); | ||
189 | else | 150 | else |
190 | /* dump filename */; | 151 | util_error("Unknown escape %s", argv[0]); |
191 | file = fopen (filename, "a"); | ||
192 | ofile = file; | ||
193 | break; | ||
194 | case 'q': | ||
195 | fclose (file); | ||
196 | rename (filename, getenv("DEAD")); | ||
197 | util_do_command ("quit"); | ||
198 | break; | ||
199 | case 'r': | ||
200 | case '<': | ||
201 | /* read in a file */ | ||
202 | break; | ||
203 | case 's': | ||
204 | free (subj); | ||
205 | subj = strdup (&buf[3]); | ||
206 | break; | ||
207 | case 't': | ||
208 | to = realloc (to, (strlen(to) + strlen(buf) - 1) * | ||
209 | sizeof (char)); | ||
210 | strcat (to, ", "); | ||
211 | strcat (to, &buf[3]); | ||
212 | break; | ||
213 | case 'v': | ||
214 | fclose (file); | ||
215 | ofile = ostdout; | ||
216 | util_do_command ("!%s %s", getenv("VISUAL"), filename); | ||
217 | file = fopen (filename, "a"); | ||
218 | ofile = file; | ||
219 | break; | ||
220 | case 'w': | ||
221 | { | ||
222 | FILE *f2 = fopen (&buf[3], "a"); | ||
223 | /* read this file and output to f2 */ | ||
224 | fclose (f2); | ||
225 | } | ||
226 | break; | ||
227 | case 'x': | ||
228 | util_do_command ("quit"); | ||
229 | break; | ||
230 | case '|': | ||
231 | /* pipe to &buf[3] */ | ||
232 | break; | ||
233 | default: | ||
234 | fprintf (stderr, "Unknown escape %c\n", buf[0]); | ||
235 | break; | ||
236 | } | 152 | } |
237 | ofile = ostdout; | 153 | else |
154 | { | ||
155 | util_error("can't parse escape sequence"); | ||
156 | } | ||
157 | argcv_free (argc, argv); | ||
158 | |||
159 | ofile = env->ofile; | ||
238 | } | 160 | } |
239 | else | 161 | else |
240 | fprintf (file, "%s", buf); | 162 | fprintf (env->file, "%s", buf); |
241 | fflush (file); | 163 | fflush (env->file); |
242 | /* free (buf); */ | 164 | free (buf); |
165 | } | ||
166 | |||
167 | fclose (env->file); | ||
168 | if (int_cnt) | ||
169 | { | ||
170 | remove (filename); | ||
171 | free (filename); | ||
172 | return 1; | ||
243 | } | 173 | } |
244 | 174 | ||
245 | file = fopen (filename, "r"); | 175 | file = fopen (filename, "r"); |
... | @@ -254,8 +184,9 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | ... | @@ -254,8 +184,9 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) |
254 | if ((status = mailer_create (&mailer, mailer_name)) != 0 | 184 | if ((status = mailer_create (&mailer, mailer_name)) != 0 |
255 | || (status = mailer_open (mailer, MU_STREAM_RDWR)) != 0) | 185 | || (status = mailer_open (mailer, MU_STREAM_RDWR)) != 0) |
256 | { | 186 | { |
257 | fprintf (stderr, "%s: %s\n", mailer_name, strerror (status)); | 187 | util_error("%s: %s", mailer_name, strerror (status)); |
258 | remove (filename); | 188 | remove (filename); |
189 | free (filename); | ||
259 | return 1; | 190 | return 1; |
260 | } | 191 | } |
261 | message_create (&msg, NULL); | 192 | message_create (&msg, NULL); |
... | @@ -264,14 +195,14 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | ... | @@ -264,14 +195,14 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) |
264 | { | 195 | { |
265 | header_t header = NULL; | 196 | header_t header = NULL; |
266 | message_get_header (msg, &header); | 197 | message_get_header (msg, &header); |
267 | if (to && *to != '\0') | 198 | if (env->to && *env->to != '\0') |
268 | header_set_value (header, MU_HEADER_TO, to, 0); | 199 | header_set_value (header, MU_HEADER_TO, strdup (env->to), 0); |
269 | if (cc && *cc != '\0') | 200 | if (env->cc && *env->cc != '\0') |
270 | header_set_value (header, MU_HEADER_CC, cc, 0); | 201 | header_set_value (header, MU_HEADER_CC, strdup (env->cc), 0); |
271 | if (bcc && *bcc != '\0') | 202 | if (env->bcc && *env->bcc != '\0') |
272 | header_set_value (header, MU_HEADER_BCC , bcc, 0); | 203 | header_set_value (header, MU_HEADER_BCC , strdup (env->bcc), 0); |
273 | if (subj && *subj != '\0') | 204 | if (env->subj && *env->subj != '\0') |
274 | header_set_value (header, MU_HEADER_SUBJECT, subj, 1); | 205 | header_set_value (header, MU_HEADER_SUBJECT, strdup (env->subj), 1); |
275 | } | 206 | } |
276 | 207 | ||
277 | /* Fill the body. */ | 208 | /* Fill the body. */ |
... | @@ -286,9 +217,12 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | ... | @@ -286,9 +217,12 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) |
286 | size_t len = strlen (buf); | 217 | size_t len = strlen (buf); |
287 | stream_write (stream, buf, len, offset, &n); | 218 | stream_write (stream, buf, len, offset, &n); |
288 | offset += len; | 219 | offset += len; |
289 | free (buf); | ||
290 | buf = NULL; | ||
291 | } | 220 | } |
221 | |||
222 | if (offset == 0) | ||
223 | util_error("Null message body; hope that's ok\n"); | ||
224 | if (buf) | ||
225 | free (buf); | ||
292 | } | 226 | } |
293 | 227 | ||
294 | fclose (file); | 228 | fclose (file); |
... | @@ -296,7 +230,7 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | ... | @@ -296,7 +230,7 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) |
296 | /* Save outgoing message */ | 230 | /* Save outgoing message */ |
297 | if (save_to) | 231 | if (save_to) |
298 | { | 232 | { |
299 | savefile = strdup (to); | 233 | savefile = strdup (env->to); |
300 | if (savefile) | 234 | if (savefile) |
301 | { | 235 | { |
302 | char *p = strchr(savefile, '@'); | 236 | char *p = strchr(savefile, '@'); |
... | @@ -313,9 +247,11 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) | ... | @@ -313,9 +247,11 @@ mail_send0 (char *to, char *cc, char *bcc, char *subj, int save_to) |
313 | message_destroy (&msg, NULL); | 247 | message_destroy (&msg, NULL); |
314 | mailer_destroy (&mailer); | 248 | mailer_destroy (&mailer); |
315 | remove (filename); | 249 | remove (filename); |
250 | free (filename); | ||
316 | return 0; | 251 | return 0; |
317 | } | 252 | } |
318 | 253 | ||
319 | remove (filename); | 254 | remove (filename); |
255 | free (filename); | ||
320 | return 1; | 256 | return 1; |
321 | } | 257 | } | ... | ... |
-
Please register or sign in to post a comment