aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1997-01-20 07:30:40 +0000
committerRichard M. Stallman1997-01-20 07:30:40 +0000
commita4deff3cac769334e3ccaa316a7fc321e528688f (patch)
tree7b7e1f2a5fe984f4010c60772ddb5cd3ffb0affc
parent1559a86dabb6f2f1123fe3692704438661363f95 (diff)
downloademacs-a4deff3cac769334e3ccaa316a7fc321e528688f.tar.gz
emacs-a4deff3cac769334e3ccaa316a7fc321e528688f.zip
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.
-rw-r--r--lib-src/movemail.c239
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. */
121extern int lk_open (), lk_close (); 121extern 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
131static 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. */
508static char *
509mail_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
658pop_retr (server, msgno, action, arg) 757pop_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;