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