diff options
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/movemail.c | 239 |
1 files changed, 169 insertions, 70 deletions
diff --git a/lib-src/movemail.c b/lib-src/movemail.c index 79ea6dcabab..add3ab7e11d 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c | |||
| @@ -121,6 +121,17 @@ Boston, MA 02111-1307, USA. */ | |||
| 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 |
| @@ -166,12 +177,16 @@ main (argc, argv) | |||
| 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]; |
| @@ -223,80 +238,89 @@ main (argc, argv) | |||
| 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 | |||
| 231 | On systems that use a lock file, extracting the mail without locking | ||
| 232 | WILL occasionally cause loss of mail due to timing errors! | ||
| 233 | |||
| 234 | So, if creation of the lock file fails | ||
| 235 | due to access permission on the mail spool directory, | ||
| 236 | you simply MUST change the permission | ||
| 237 | and/or make movemail a setgid program | ||
| 238 | so it can create lock files properly. | ||
| 239 | |||
| 240 | You might also wish to verify that your system is one | ||
| 241 | which uses lock files for this purpose. Some systems use other methods. | ||
| 242 | |||
| 243 | If your system uses the `flock' system call for mail locking, | ||
| 244 | define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file | ||
| 245 | and recompile movemail. If the s- file for your system | ||
| 246 | should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report | ||
| 247 | to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */ | ||
| 248 | |||
| 249 | lockname = concat (inname, ".lock", ""); | ||
| 250 | tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1); | ||
| 251 | strcpy (tempname, inname); | ||
| 252 | p = tempname + strlen (tempname); | ||
| 253 | while (p != tempname && !IS_DIRECTORY_SEP (p[-1])) | ||
| 254 | p--; | ||
| 255 | *p = 0; | ||
| 256 | strcpy (p, "EXXXXXX"); | ||
| 257 | mktemp (tempname); | ||
| 258 | unlink (tempname); | ||
| 259 | |||
| 260 | while (1) | ||
| 261 | { | 245 | { |
| 262 | /* Create the lock file, but not under the lock file name. */ | 246 | /* Use a lock file named after our first argument with .lock appended: |
| 263 | /* Give up if cannot do that. */ | 247 | If it exists, the mail file is locked. */ |
| 264 | desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666); | 248 | /* Note: this locking mechanism is *required* by the mailer |
| 265 | if (desc < 0) | 249 | (on systems which use it) to prevent loss of mail. |
| 266 | { | 250 | |
| 267 | char *message = (char *) xmalloc (strlen (tempname) + 50); | 251 | On systems that use a lock file, extracting the mail without locking |
| 268 | sprintf (message, "%s--see source file lib-src/movemail.c", | 252 | WILL occasionally cause loss of mail due to timing errors! |
| 269 | tempname); | 253 | |
| 270 | pfatal_with_name (message); | 254 | So, if creation of the lock file fails |
| 271 | } | 255 | due to access permission on the mail spool directory, |
| 272 | close (desc); | 256 | you simply MUST change the permission |
| 273 | 257 | and/or make movemail a setgid program | |
| 274 | tem = link (tempname, lockname); | 258 | so it can create lock files properly. |
| 259 | |||
| 260 | You might also wish to verify that your system is one | ||
| 261 | which uses lock files for this purpose. Some systems use other methods. | ||
| 262 | |||
| 263 | If your system uses the `flock' system call for mail locking, | ||
| 264 | define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file | ||
| 265 | and recompile movemail. If the s- file for your system | ||
| 266 | should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report | ||
| 267 | to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */ | ||
| 268 | |||
| 269 | lockname = concat (inname, ".lock", ""); | ||
| 270 | tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1); | ||
| 271 | strcpy (tempname, inname); | ||
| 272 | p = tempname + strlen (tempname); | ||
| 273 | while (p != tempname && !IS_DIRECTORY_SEP (p[-1])) | ||
| 274 | p--; | ||
| 275 | *p = 0; | ||
| 276 | strcpy (p, "EXXXXXX"); | ||
| 277 | mktemp (tempname); | ||
| 275 | unlink (tempname); | 278 | unlink (tempname); |
| 276 | if (tem >= 0) | ||
| 277 | break; | ||
| 278 | sleep (1); | ||
| 279 | 279 | ||
| 280 | /* If lock file is five minutes old, unlock it. | 280 | while (1) |
| 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 | { | 281 | { |
| 286 | now = time (0); | 282 | /* Create the lock file, but not under the lock file name. */ |
| 287 | if (st.st_ctime < now - 300) | 283 | /* Give up if cannot do that. */ |
| 288 | unlink (lockname); | 284 | desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666); |
| 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 | } | ||
| 289 | } | 310 | } |
| 290 | } | ||
| 291 | 311 | ||
| 292 | delete_lockname = lockname; | 312 | delete_lockname = lockname; |
| 313 | } | ||
| 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 | ||
| @@ -329,21 +353,36 @@ main (argc, argv) | |||
| 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. */ |
| @@ -385,6 +424,17 @@ main (argc, argv) | |||
| 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 | ||
| @@ -423,6 +473,12 @@ main (argc, argv) | |||
| 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 | ||
| @@ -433,13 +489,57 @@ main (argc, argv) | |||
| 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 | ||
| @@ -522,7 +622,6 @@ xmalloc (size) | |||
| 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 |
| @@ -657,7 +756,7 @@ popmail (user, outfile, password) | |||
| 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; |