Commit 293e836d 293e836dad9f9d522e72f562ce6efa987d09f6c4 by Sergey Poznyakoff

Handle keyboard interrupts. Use util_tempfile().

1 parent 34ffae30
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 }
......