Mercurial > emacs
comparison lib-src/movemail.c @ 16897:523d5c54a3f5
Include maillock.h (conditionally).
Remove a redundant inclusion of <stdio.h>.
(MAIL_USE_MAILLOCK): New macro, conditionally defined.
(main): Add variable spool_name.
Support the usage of maillock and mailunlock to
lock and unlock mailboxes.
(mail_spool_name): New function.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Mon, 20 Jan 1997 07:30:40 +0000 |
parents | ed13d19dbce5 |
children | d878e23bbfa6 |
comparison
equal
deleted
inserted
replaced
16896:b2c51d6de440 | 16897:523d5c54a3f5 |
---|---|
119 | 119 |
120 #ifdef MAIL_USE_MMDF | 120 #ifdef MAIL_USE_MMDF |
121 extern int lk_open (), lk_close (); | 121 extern int lk_open (), lk_close (); |
122 #endif | 122 #endif |
123 | 123 |
124 #if !defined (MAIL_USE_SYSTEM_LOCK) && !defined (MAIL_USE_MMDF) && \ | |
125 defined (HAVE_LIBMAIL) && defined (HAVE_MAILLOCK_H) | |
126 #include <maillock.h> | |
127 /* We can't use maillock unless we know what directory system mail | |
128 files appear in. */ | |
129 #ifdef MAILDIR | |
130 #define MAIL_USE_MAILLOCK | |
131 static char *mail_spool_name (); | |
132 #endif | |
133 #endif | |
134 | |
124 /* Cancel substitutions made by config.h for Emacs. */ | 135 /* Cancel substitutions made by config.h for Emacs. */ |
125 #undef open | 136 #undef open |
126 #undef read | 137 #undef read |
127 #undef write | 138 #undef write |
128 #undef close | 139 #undef close |
164 char *lockname, *p; | 175 char *lockname, *p; |
165 char *tempname; | 176 char *tempname; |
166 int desc; | 177 int desc; |
167 #endif /* not MAIL_USE_SYSTEM_LOCK */ | 178 #endif /* not MAIL_USE_SYSTEM_LOCK */ |
168 | 179 |
180 #ifdef MAIL_USE_MAILLOCK | |
181 char *spool_name; | |
182 #endif | |
183 | |
169 delete_lockname = 0; | 184 delete_lockname = 0; |
170 | 185 |
171 if (argc < 3) | 186 if (argc < 3) |
172 { | 187 { |
173 fprintf (stderr, "Usage: movemail inbox destfile [POP-password]\n"); | 188 fprintf (stderr, "Usage: movemail inbox destfile [POP-password]\n"); |
174 exit(1); | 189 exit (1); |
175 } | 190 } |
176 | 191 |
177 inname = argv[1]; | 192 inname = argv[1]; |
178 outname = argv[2]; | 193 outname = argv[2]; |
179 | 194 |
221 if (access (inname, R_OK | W_OK) != 0) | 236 if (access (inname, R_OK | W_OK) != 0) |
222 pfatal_with_name (inname); | 237 pfatal_with_name (inname); |
223 | 238 |
224 #ifndef MAIL_USE_MMDF | 239 #ifndef MAIL_USE_MMDF |
225 #ifndef MAIL_USE_SYSTEM_LOCK | 240 #ifndef MAIL_USE_SYSTEM_LOCK |
226 /* Use a lock file named after our first argument with .lock appended: | 241 #ifdef MAIL_USE_MAILLOCK |
227 If it exists, the mail file is locked. */ | 242 spool_name = mail_spool_name (inname); |
228 /* Note: this locking mechanism is *required* by the mailer | 243 if (! spool_name) |
229 (on systems which use it) to prevent loss of mail. | 244 #endif |
230 | 245 { |
231 On systems that use a lock file, extracting the mail without locking | 246 /* Use a lock file named after our first argument with .lock appended: |
232 WILL occasionally cause loss of mail due to timing errors! | 247 If it exists, the mail file is locked. */ |
233 | 248 /* Note: this locking mechanism is *required* by the mailer |
234 So, if creation of the lock file fails | 249 (on systems which use it) to prevent loss of mail. |
235 due to access permission on the mail spool directory, | 250 |
236 you simply MUST change the permission | 251 On systems that use a lock file, extracting the mail without locking |
237 and/or make movemail a setgid program | 252 WILL occasionally cause loss of mail due to timing errors! |
238 so it can create lock files properly. | 253 |
239 | 254 So, if creation of the lock file fails |
240 You might also wish to verify that your system is one | 255 due to access permission on the mail spool directory, |
241 which uses lock files for this purpose. Some systems use other methods. | 256 you simply MUST change the permission |
242 | 257 and/or make movemail a setgid program |
243 If your system uses the `flock' system call for mail locking, | 258 so it can create lock files properly. |
244 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file | 259 |
245 and recompile movemail. If the s- file for your system | 260 You might also wish to verify that your system is one |
246 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report | 261 which uses lock files for this purpose. Some systems use other methods. |
247 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */ | 262 |
248 | 263 If your system uses the `flock' system call for mail locking, |
249 lockname = concat (inname, ".lock", ""); | 264 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file |
250 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1); | 265 and recompile movemail. If the s- file for your system |
251 strcpy (tempname, inname); | 266 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report |
252 p = tempname + strlen (tempname); | 267 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */ |
253 while (p != tempname && !IS_DIRECTORY_SEP (p[-1])) | 268 |
254 p--; | 269 lockname = concat (inname, ".lock", ""); |
255 *p = 0; | 270 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1); |
256 strcpy (p, "EXXXXXX"); | 271 strcpy (tempname, inname); |
257 mktemp (tempname); | 272 p = tempname + strlen (tempname); |
258 unlink (tempname); | 273 while (p != tempname && !IS_DIRECTORY_SEP (p[-1])) |
259 | 274 p--; |
260 while (1) | 275 *p = 0; |
261 { | 276 strcpy (p, "EXXXXXX"); |
262 /* Create the lock file, but not under the lock file name. */ | 277 mktemp (tempname); |
263 /* Give up if cannot do that. */ | 278 unlink (tempname); |
264 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666); | 279 |
265 if (desc < 0) | 280 while (1) |
266 { | 281 { |
267 char *message = (char *) xmalloc (strlen (tempname) + 50); | 282 /* Create the lock file, but not under the lock file name. */ |
268 sprintf (message, "%s--see source file lib-src/movemail.c", | 283 /* Give up if cannot do that. */ |
269 tempname); | 284 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666); |
270 pfatal_with_name (message); | 285 if (desc < 0) |
286 { | |
287 char *message = (char *) xmalloc (strlen (tempname) + 50); | |
288 sprintf (message, "%s--see source file lib-src/movemail.c", | |
289 tempname); | |
290 pfatal_with_name (message); | |
291 } | |
292 close (desc); | |
293 | |
294 tem = link (tempname, lockname); | |
295 unlink (tempname); | |
296 if (tem >= 0) | |
297 break; | |
298 sleep (1); | |
299 | |
300 /* If lock file is five minutes old, unlock it. | |
301 Five minutes should be good enough to cope with crashes | |
302 and wedgitude, and long enough to avoid being fooled | |
303 by time differences between machines. */ | |
304 if (stat (lockname, &st) >= 0) | |
305 { | |
306 now = time (0); | |
307 if (st.st_ctime < now - 300) | |
308 unlink (lockname); | |
309 } | |
271 } | 310 } |
272 close (desc); | 311 |
273 | 312 delete_lockname = lockname; |
274 tem = link (tempname, lockname); | 313 } |
275 unlink (tempname); | |
276 if (tem >= 0) | |
277 break; | |
278 sleep (1); | |
279 | |
280 /* If lock file is five minutes old, unlock it. | |
281 Five minutes should be good enough to cope with crashes | |
282 and wedgitude, and long enough to avoid being fooled | |
283 by time differences between machines. */ | |
284 if (stat (lockname, &st) >= 0) | |
285 { | |
286 now = time (0); | |
287 if (st.st_ctime < now - 300) | |
288 unlink (lockname); | |
289 } | |
290 } | |
291 | |
292 delete_lockname = lockname; | |
293 #endif /* not MAIL_USE_SYSTEM_LOCK */ | 314 #endif /* not MAIL_USE_SYSTEM_LOCK */ |
294 #endif /* not MAIL_USE_MMDF */ | 315 #endif /* not MAIL_USE_MMDF */ |
295 | 316 |
296 if (fork () == 0) | 317 if (fork () == 0) |
297 { | 318 { |
298 int lockcount = 0; | 319 int lockcount = 0; |
299 int status; | 320 int status = 0; |
321 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK) | |
322 long touched_lock, now; | |
323 #endif | |
300 | 324 |
301 setuid (getuid ()); | 325 setuid (getuid ()); |
302 | 326 |
303 #ifndef MAIL_USE_MMDF | 327 #ifndef MAIL_USE_MMDF |
304 #ifdef MAIL_USE_SYSTEM_LOCK | 328 #ifdef MAIL_USE_SYSTEM_LOCK |
327 /* This label exists so we can retry locking | 351 /* This label exists so we can retry locking |
328 after a delay, if it got EAGAIN or EBUSY. */ | 352 after a delay, if it got EAGAIN or EBUSY. */ |
329 retry_lock: | 353 retry_lock: |
330 | 354 |
331 /* Try to lock it. */ | 355 /* Try to lock it. */ |
356 #ifdef MAIL_USE_MAILLOCK | |
357 if (spool_name) | |
358 { | |
359 /* The "0 - " is to make it a negative number if maillock returns | |
360 non-zero. */ | |
361 status = 0 - maillock (spool_name, 1); | |
362 #ifdef HAVE_TOUCHLOCK | |
363 touched_lock = time (0); | |
364 #endif | |
365 lockcount = 5; | |
366 } | |
367 else | |
368 #endif /* MAIL_USE_MAILLOCK */ | |
369 { | |
332 #ifdef MAIL_USE_SYSTEM_LOCK | 370 #ifdef MAIL_USE_SYSTEM_LOCK |
333 #ifdef MAIL_USE_LOCKF | 371 #ifdef MAIL_USE_LOCKF |
334 status = lockf (indesc, F_LOCK, 0); | 372 status = lockf (indesc, F_LOCK, 0); |
335 #else /* not MAIL_USE_LOCKF */ | 373 #else /* not MAIL_USE_LOCKF */ |
336 #ifdef XENIX | 374 #ifdef XENIX |
337 status = locking (indesc, LK_RLCK, 0L); | 375 status = locking (indesc, LK_RLCK, 0L); |
338 #else | 376 #else |
339 #ifdef WINDOWSNT | 377 #ifdef WINDOWSNT |
340 status = locking (indesc, LK_RLCK, -1L); | 378 status = locking (indesc, LK_RLCK, -1L); |
341 #else | 379 #else |
342 status = flock (indesc, LOCK_EX); | 380 status = flock (indesc, LOCK_EX); |
343 #endif | 381 #endif |
344 #endif | 382 #endif |
345 #endif /* not MAIL_USE_LOCKF */ | 383 #endif /* not MAIL_USE_LOCKF */ |
346 #endif /* MAIL_USE_SYSTEM_LOCK */ | 384 #endif /* MAIL_USE_SYSTEM_LOCK */ |
385 } | |
347 | 386 |
348 /* If it fails, retry up to 5 times | 387 /* If it fails, retry up to 5 times |
349 for certain failure codes. */ | 388 for certain failure codes. */ |
350 if (status < 0) | 389 if (status < 0) |
351 { | 390 { |
383 errno = saved_errno; | 422 errno = saved_errno; |
384 pfatal_with_name (outname); | 423 pfatal_with_name (outname); |
385 } | 424 } |
386 if (nread < sizeof buf) | 425 if (nread < sizeof buf) |
387 break; | 426 break; |
427 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK) | |
428 if (spool_name) | |
429 { | |
430 now = time (0); | |
431 if (now - touched_lock > 60) | |
432 { | |
433 touchlock (); | |
434 touched_lock = now; | |
435 } | |
436 } | |
437 #endif /* MAIL_USE_MAILLOCK */ | |
388 } | 438 } |
389 } | 439 } |
390 | 440 |
391 #ifdef BSD_SYSTEM | 441 #ifdef BSD_SYSTEM |
392 if (fsync (outdesc) < 0) | 442 if (fsync (outdesc) < 0) |
421 if (unlink (inname) < 0 && errno != ENOENT) | 471 if (unlink (inname) < 0 && errno != ENOENT) |
422 #endif /* MAIL_UNLINK_SPOOL */ | 472 #endif /* MAIL_UNLINK_SPOOL */ |
423 creat (inname, 0600); | 473 creat (inname, 0600); |
424 #endif /* not MAIL_USE_SYSTEM_LOCK */ | 474 #endif /* not MAIL_USE_SYSTEM_LOCK */ |
425 | 475 |
476 #ifdef MAIL_USE_MAILLOCK | |
477 /* This has to occur in the child, i.e., in the process that | |
478 acquired the lock! */ | |
479 if (spool_name) | |
480 mailunlock (); | |
481 #endif | |
426 exit (0); | 482 exit (0); |
427 } | 483 } |
428 | 484 |
429 wait (&status); | 485 wait (&status); |
430 if (!WIFEXITED (status)) | 486 if (!WIFEXITED (status)) |
431 exit (1); | 487 exit (1); |
432 else if (WRETCODE (status) != 0) | 488 else if (WRETCODE (status) != 0) |
433 exit (WRETCODE (status)); | 489 exit (WRETCODE (status)); |
434 | 490 |
435 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK) | 491 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK) |
436 unlink (lockname); | 492 #ifdef MAIL_USE_MAILLOCK |
493 if (! spool_name) | |
494 #endif /* MAIL_USE_MAILLOCK */ | |
495 unlink (lockname); | |
437 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */ | 496 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */ |
438 | 497 |
439 #endif /* ! DISABLE_DIRECT_ACCESS */ | 498 #endif /* ! DISABLE_DIRECT_ACCESS */ |
440 | 499 |
441 return 0; | 500 return 0; |
442 } | 501 } |
502 | |
503 #ifdef MAIL_USE_MAILLOCK | |
504 /* This function uses stat to confirm that the mail directory is | |
505 identical to the directory of the input file, rather than just | |
506 string-comparing the two paths, because one or both of them might | |
507 be symbolic links pointing to some other directory. */ | |
508 static char * | |
509 mail_spool_name (inname) | |
510 char *inname; | |
511 { | |
512 struct stat stat1, stat2; | |
513 char *indir, *fname; | |
514 int status; | |
515 | |
516 if (! (fname = rindex (inname, '/'))) | |
517 return NULL; | |
518 | |
519 fname++; | |
520 | |
521 if (stat (MAILDIR, &stat1) < 0) | |
522 return NULL; | |
523 | |
524 indir = (char *) xmalloc (fname - inname + 1); | |
525 strncpy (indir, inname, fname - inname); | |
526 indir[fname-inname] = '\0'; | |
527 | |
528 | |
529 status = stat (indir, &stat2); | |
530 | |
531 free (indir); | |
532 | |
533 if (status < 0) | |
534 return NULL; | |
535 | |
536 if ((stat1.st_dev == stat2.st_dev) && | |
537 (stat1.st_ino == stat2.st_ino)) | |
538 return fname; | |
539 | |
540 return NULL; | |
541 } | |
542 #endif /* MAIL_USE_MAILLOCK */ | |
443 | 543 |
444 /* Print error message and exit. */ | 544 /* Print error message and exit. */ |
445 | 545 |
446 void | 546 void |
447 fatal (s1, s2) | 547 fatal (s1, s2) |
520 #include <netdb.h> | 620 #include <netdb.h> |
521 #else | 621 #else |
522 #undef _WINSOCKAPI_ | 622 #undef _WINSOCKAPI_ |
523 #include <winsock.h> | 623 #include <winsock.h> |
524 #endif | 624 #endif |
525 #include <stdio.h> | |
526 #include <pwd.h> | 625 #include <pwd.h> |
527 | 626 |
528 #ifdef USG | 627 #ifdef USG |
529 #include <fcntl.h> | 628 #include <fcntl.h> |
530 /* Cancel substitutions made by config.h for Emacs. */ | 629 /* Cancel substitutions made by config.h for Emacs. */ |
655 return (0); | 754 return (0); |
656 } | 755 } |
657 | 756 |
658 pop_retr (server, msgno, action, arg) | 757 pop_retr (server, msgno, action, arg) |
659 popserver server; | 758 popserver server; |
660 int (*action)(); | 759 int (*action) (); |
661 { | 760 { |
662 extern char *strerror (); | 761 extern char *strerror (); |
663 char *line; | 762 char *line; |
664 int ret; | 763 int ret; |
665 | 764 |