Mercurial > hg > xemacs-beta
comparison lib-src/movemail.c @ 398:74fd4e045ea6 r21-2-29
Import from CVS: tag r21-2-29
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:13:30 +0200 |
parents | aabb7f5b1c81 |
children | a86b2b5e0111 |
comparison
equal
deleted
inserted
replaced
397:f4aeb21a5bad | 398:74fd4e045ea6 |
---|---|
1 /* movemail foo bar -- move file foo to file bar, | 1 /* movemail foo bar -- move file foo to file bar, |
2 locking file foo the way /bin/mail respects. | 2 locking file foo. |
3 Copyright (C) 1986, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. | 3 Copyright (C) 1986, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GNU Emacs. | 5 This file is part of XEmacs. |
6 | 6 |
7 GNU Emacs is free software; you can redistribute it and/or modify | 7 XEmacs is free software; you can redistribute it and/or modify it |
8 it under the terms of the GNU General Public License as published by | 8 under the terms of the GNU General Public License as published by the |
9 the Free Software Foundation; either version 2, or (at your option) | 9 Free Software Foundation; either version 2, or (at your option) any |
10 any later version. | 10 later version. |
11 | 11 |
12 GNU Emacs is distributed in the hope that it will be useful, | 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 GNU General Public License for more details. | 15 for more details. |
16 | 16 |
17 You should have received a copy of the GNU General Public License | 17 You should have received a copy of the GNU General Public License |
18 along with GNU Emacs; see the file COPYING. If not, write to | 18 along with XEmacs; see the file COPYING. If not, write to |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 Boston, MA 02111-1307, USA. */ | 20 Boston, MA 02111-1307, USA. |
21 | 21 |
22 /* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *will | 22 Please mail bugs and suggestions to the XEmacs maintainer. |
23 cause loss of mail* if you do it on a system that does not normally | 23 */ |
24 use flock as its way of interlocking access to inbox files. The | 24 |
25 setting of MAIL_USE_FLOCK and MAIL_USE_LOCKF *must agree* with the | 25 /* Important notice: |
26 system's own conventions. It is not a choice that is up to you. | 26 * |
27 | 27 * You *must* coordinate the locking method used by movemail with that |
28 So, if your system uses lock files rather than flock, then the only way | 28 * used by your mail delivery agent, as well as that of the other mail |
29 you can get proper operation is to enable movemail to write lockfiles there. | 29 * user agents on your system. movemail allows you to do this at run |
30 This means you must either give that directory access modes | 30 * time via the -m flag. Moreover, it uses a default determined by |
31 that permit everyone to write lockfiles in it, or you must make movemail | 31 * the MAIL_LOCK_DOT, MAIL_LOCK_LOCKF, MAIL_LOCK_FLOCK, |
32 a setuid or setgid program. */ | 32 * MAIL_LOCK_LOCKING, and MAIL_LOCK_MMDF preprocessor settings. |
33 */ | |
34 | |
35 /* | |
36 * Mike Sperber <sperber@informatik.uni-tuebingen.de> reorganized | |
37 * everything that has to with locking in December 1999. | |
38 */ | |
33 | 39 |
34 /* | 40 /* |
35 * Modified January, 1986 by Michael R. Gretzinger (Project Athena) | 41 * Modified January, 1986 by Michael R. Gretzinger (Project Athena) |
36 * | 42 * |
37 * Added POP (Post Office Protocol) service. When compiled -DMAIL_USE_POP | 43 * Added POP (Post Office Protocol) service. When compiled -DMAIL_USE_POP |
54 * | 60 * |
55 */ | 61 */ |
56 | 62 |
57 #define NO_SHORTNAMES /* Tell config not to load remap.h */ | 63 #define NO_SHORTNAMES /* Tell config not to load remap.h */ |
58 #define DONT_ENCAPSULATE | 64 #define DONT_ENCAPSULATE |
59 #include <../src/config.h> | 65 #include <config.h> |
60 #include <sys/types.h> | 66 #include <sys/types.h> |
61 #include <sys/stat.h> | 67 #include <sys/stat.h> |
62 #include <sys/file.h> | |
63 #include <stdio.h> | 68 #include <stdio.h> |
64 #include <errno.h> | 69 #include <errno.h> |
65 #include "../src/sysfile.h" | 70 #include "../src/sysfile.h" |
66 #include "../src/syswait.h" | 71 #include "../src/syswait.h" |
67 #ifndef WINDOWSNT | 72 #ifndef WINDOWSNT |
105 properly - make sure it does before you enable this! */ | 110 properly - make sure it does before you enable this! */ |
106 #define DISABLE_DIRECT_ACCESS | 111 #define DISABLE_DIRECT_ACCESS |
107 #include <io.h> | 112 #include <io.h> |
108 #endif /* WINDOWSNT */ | 113 #endif /* WINDOWSNT */ |
109 | 114 |
110 #if defined (HAVE_UNISTD_H) || defined (USG) | 115 #if defined (HAVE_UNISTD_H) |
111 #include <unistd.h> | 116 #include <unistd.h> |
112 #endif /* unistd.h */ | 117 #endif /* unistd.h */ |
113 #ifndef F_OK | 118 #ifndef F_OK |
114 #define F_OK 0 | 119 #define F_OK 0 |
115 #define X_OK 1 | 120 #define X_OK 1 |
116 #define W_OK 2 | 121 #define W_OK 2 |
117 #define R_OK 4 | 122 #define R_OK 4 |
118 #endif /* No F_OK */ | 123 #endif /* No F_OK */ |
119 | 124 |
120 #if defined (HAVE_FCNTL_H) || defined (USG) | 125 #if defined (HAVE_FCNTL_H) |
121 #include <fcntl.h> | 126 #include <fcntl.h> |
122 #endif /* fcntl.h */ | 127 #endif /* fcntl.h */ |
123 | 128 |
124 #if defined (XENIX) || defined (WINDOWSNT) | 129 #ifdef HAVE_LOCKING |
125 #include <sys/locking.h> | 130 #include <sys/locking.h> |
126 #endif | 131 #endif |
127 | 132 |
128 #ifdef MAIL_USE_LOCKF | 133 #ifdef HAVE_MMDF |
129 #define MAIL_USE_SYSTEM_LOCK | |
130 #endif | |
131 | |
132 #ifdef MAIL_USE_FLOCK | |
133 #define MAIL_USE_SYSTEM_LOCK | |
134 #endif | |
135 | |
136 #ifdef MAIL_USE_MMDF | |
137 extern int lk_open (), lk_close (); | 134 extern int lk_open (), lk_close (); |
138 #endif | 135 #endif |
139 | 136 |
140 /* Cancel substitutions made by config.h for Emacs. */ | 137 /* Cancel substitutions made by config.h for Emacs. */ |
141 #undef open | 138 #undef open |
143 #undef write | 140 #undef write |
144 #undef close | 141 #undef close |
145 | 142 |
146 static void fatal (char *, char*); | 143 static void fatal (char *, char*); |
147 static void error (char *, char *, char *); | 144 static void error (char *, char *, char *); |
145 static void usage(int); | |
148 static void pfatal_with_name (char *); | 146 static void pfatal_with_name (char *); |
149 static void pfatal_and_delete (char *); | 147 static void pfatal_and_delete (char *); |
150 static char *concat (char *, char *, char *); | 148 static char *concat (char *, char *, char *); |
151 static long *xmalloc (unsigned int); | 149 static long *xmalloc (unsigned int); |
152 #ifdef MAIL_USE_POP | 150 #ifdef MAIL_USE_POP |
153 static int popmail (char *, char *, char *); | 151 static int popmail (char *, char *, char *); |
154 static int pop_retr (popserver server, int msgno, int (*action)(), void *arg); | 152 static int pop_retr (popserver server, int msgno, |
153 int (*action)(char *, FILE *), FILE *arg); | |
155 static int mbx_write (char *, FILE *); | 154 static int mbx_write (char *, FILE *); |
156 static int mbx_delimit_begin (FILE *); | 155 static int mbx_delimit_begin (FILE *); |
157 static int mbx_delimit_end (FILE *); | 156 static int mbx_delimit_end (FILE *); |
158 static struct re_pattern_buffer* compile_regex (char* regexp_pattern); | 157 static struct re_pattern_buffer* compile_regex (char* regexp_pattern); |
159 static int pop_search_top (popserver server, int msgno, int lines, | 158 static int pop_search_top (popserver server, int msgno, int lines, |
160 struct re_pattern_buffer* regexp); | 159 struct re_pattern_buffer* regexp); |
161 #endif | 160 #endif |
162 | |
163 /* Nonzero means this is name of a lock file to delete on fatal error. */ | |
164 char *delete_lockname; | |
165 | 161 |
166 int verbose=0; | 162 int verbose=0; |
167 #ifdef MAIL_USE_POP | 163 #ifdef MAIL_USE_POP |
168 int reverse=0; | 164 int reverse=0; |
169 int keep_messages=0; | 165 int keep_messages=0; |
182 { "reverse-pop-order", no_argument, NULL, 'x' }, | 178 { "reverse-pop-order", no_argument, NULL, 'x' }, |
183 { "keep-messages", no_argument, NULL, 'k' }, | 179 { "keep-messages", no_argument, NULL, 'k' }, |
184 { "regex", required_argument, NULL, 'r' }, | 180 { "regex", required_argument, NULL, 'r' }, |
185 { "match-lines", required_argument, NULL, 'l' }, | 181 { "match-lines", required_argument, NULL, 'l' }, |
186 #endif | 182 #endif |
183 { "lock-method", required_argument, NULL, 'm' }, | |
184 { "help", no_argument, NULL, 'h' }, | |
187 { "verbose", no_argument, NULL, 'v' }, | 185 { "verbose", no_argument, NULL, 'v' }, |
188 { 0 } | 186 { 0 } |
189 }; | 187 }; |
188 | |
189 #define DOTLOCKING 0 | |
190 #define FLOCKING 1 | |
191 #define LOCKFING 2 | |
192 #define MMDF 3 | |
193 #define LOCKING 4 | |
194 | |
195 #if defined(MAIL_LOCK_FLOCK) && defined(HAVE_FLOCK) | |
196 #define DEFAULT_LOCKING FLOCKING | |
197 #elif defined(MAIL_LOCK_LOCKF) && defined(HAVE_LOCKF) | |
198 #define DEFAULT_LOCKING LOCKFING | |
199 #elif defined(MAIL_LOCK_MMDF) && defined(HAVE_MMDF) | |
200 #define DEFAULT_LOCKING MMDF | |
201 #elif defined(MAIL_LOCK_LOCKING) && defined(HAVE_LOCKING) | |
202 #define DEFAULT_LOCKING LOCKING | |
203 #else | |
204 #define DEFAULT_LOCKING DOTLOCKING | |
205 #endif | |
206 | |
207 static void lock_dot(char *); | |
208 static void unlock_dot(char *); | |
209 static int parse_lock_method(char *); | |
210 static char *unparse_lock_method(int); | |
190 | 211 |
191 int | 212 int |
192 main (int argc, char *argv[]) | 213 main (int argc, char *argv[]) |
193 { | 214 { |
194 char *inname=0, *outname=0, *poppass=0; | 215 char *inname=0, *outname=0, *poppass=0; |
196 int indesc, outdesc; | 217 int indesc, outdesc; |
197 int nread; | 218 int nread; |
198 int status; | 219 int status; |
199 #endif | 220 #endif |
200 | 221 |
201 #ifndef MAIL_USE_SYSTEM_LOCK | 222 int lock_method = DEFAULT_LOCKING; |
202 struct stat st; | 223 |
203 long now; | 224 char *maybe_lock_env; |
204 int tem; | 225 |
205 char *lockname, *p; | 226 maybe_lock_env = getenv("EMACSLOCKMETHOD"); |
206 char *tempname; | 227 if (maybe_lock_env) |
207 int desc; | 228 { |
208 #endif /* not MAIL_USE_SYSTEM_LOCK */ | 229 printf("maybe-lock_env: %s\n", maybe_lock_env); |
209 | 230 lock_method = parse_lock_method(maybe_lock_env); |
210 delete_lockname = 0; | 231 } |
211 | 232 |
212 while (1) | 233 for (;;) |
213 { | 234 { |
214 #ifdef MAIL_USE_POP | 235 #ifdef MAIL_USE_POP |
215 char* optstring = "i:o:p:l:r:xvk"; | 236 char* optstring = "i:o:m:p:l:r:xvhk"; |
216 #else | 237 #else |
217 char* optstring = "i:o:v"; | 238 char* optstring = "i:o:m:vh"; |
218 #endif | 239 #endif |
219 int opt = getopt_long (argc, argv, optstring, longopts, 0); | 240 int opt = getopt_long (argc, argv, optstring, longopts, 0); |
220 | 241 |
221 if (opt == EOF) | 242 if (opt == EOF) |
222 break; | 243 break; |
253 | 274 |
254 case 'r': /* regular expression */ | 275 case 'r': /* regular expression */ |
255 regexp_pattern = compile_regex (optarg); | 276 regexp_pattern = compile_regex (optarg); |
256 break; | 277 break; |
257 #endif | 278 #endif |
258 case 'v': verbose = 1; break; | 279 |
280 case 'm': | |
281 lock_method = parse_lock_method(optarg); | |
282 break; | |
283 case 'h': | |
284 usage(lock_method); | |
285 exit(0); | |
286 case 'v': | |
287 verbose = 1; | |
288 break; | |
259 } | 289 } |
260 } | 290 } |
261 | 291 |
262 while (optind < argc) | 292 while (optind < argc) |
263 { | 293 { |
270 optind++; | 300 optind++; |
271 } | 301 } |
272 | 302 |
273 if (!inname || !outname) | 303 if (!inname || !outname) |
274 { | 304 { |
275 fprintf (stderr, "Usage: movemail [-rvxk] [-l lines ] [-i] inbox [-o] destfile [[-p] POP-password]\n"); | 305 usage(lock_method); |
276 exit(1); | 306 exit(1); |
277 } | 307 } |
278 | 308 |
279 #ifdef MAIL_USE_MMDF | 309 #ifdef HAVE_MMDF |
280 mmdf_init (argv[0]); | 310 if (lock_method == MMDF) |
311 mmdf_init (argv[0]); | |
281 #endif | 312 #endif |
282 | 313 |
283 if (*outname == 0) | 314 if (*outname == 0) |
284 fatal ("Destination file name is empty", 0); | 315 fatal ("Destination file name is empty", 0); |
285 | 316 |
317 VERBOSE(("checking access to output file\n")); | |
286 /* Check access to output file. */ | 318 /* Check access to output file. */ |
287 if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0) | 319 if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0) |
288 pfatal_with_name (outname); | 320 pfatal_with_name (outname); |
289 | 321 |
290 /* Also check that outname's directory is writable to the real uid. */ | 322 /* Also check that outname's directory is writable to the real uid. */ |
318 | 350 |
319 /* Check access to input file. */ | 351 /* Check access to input file. */ |
320 if (access (inname, R_OK | W_OK) != 0) | 352 if (access (inname, R_OK | W_OK) != 0) |
321 pfatal_with_name (inname); | 353 pfatal_with_name (inname); |
322 | 354 |
323 #ifndef MAIL_USE_MMDF | 355 |
324 #ifndef MAIL_USE_SYSTEM_LOCK | 356 if (fork () == 0) |
325 /* Use a lock file named after our first argument with .lock appended: | 357 { |
326 If it exists, the mail file is locked. */ | 358 setuid (getuid ()); |
327 /* Note: this locking mechanism is *required* by the mailer | 359 |
328 (on systems which use it) to prevent loss of mail. | 360 VERBOSE(("opening input file\n")); |
329 | 361 |
330 On systems that use a lock file, extracting the mail without locking | 362 switch (lock_method) |
331 WILL occasionally cause loss of mail due to timing errors! | |
332 | |
333 So, if creation of the lock file fails | |
334 due to access permission on the mail spool directory, | |
335 you simply MUST change the permission | |
336 and/or make movemail a setgid program | |
337 so it can create lock files properly. | |
338 | |
339 You might also wish to verify that your system is one | |
340 which uses lock files for this purpose. Some systems use other methods. | |
341 | |
342 If your system uses the `flock' system call for mail locking, | |
343 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file | |
344 and recompile movemail. If the s- file for your system | |
345 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report | |
346 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */ | |
347 | |
348 lockname = concat (inname, ".lock", ""); | |
349 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1); | |
350 strcpy (tempname, inname); | |
351 p = tempname + strlen (tempname); | |
352 while (p != tempname && !IS_DIRECTORY_SEP (p[-1])) | |
353 p--; | |
354 *p = 0; | |
355 strcpy (p, "EXXXXXX"); | |
356 mktemp (tempname); | |
357 unlink (tempname); | |
358 | |
359 while (1) | |
360 { | |
361 /* Create the lock file, but not under the lock file name. */ | |
362 /* Give up if cannot do that. */ | |
363 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666); | |
364 if (desc < 0) | |
365 { | 363 { |
366 char *message = (char *) xmalloc (strlen (tempname) + 50); | 364 case DOTLOCKING: |
367 sprintf (message, "%s--see source file lib-src/movemail.c", | 365 indesc = open (inname, O_RDONLY); |
368 tempname); | 366 break; |
369 pfatal_with_name (message); | 367 #ifdef HAVE_LOCKF |
368 case LOCKFING: | |
369 indesc = open (inname, O_RDWR); | |
370 break; | |
371 #endif | |
372 #ifdef HAVE_FLOCK | |
373 case FLOCKING: | |
374 indesc = open (inname, O_RDWR); | |
375 break; | |
376 #endif | |
377 #ifdef HAVE_LOCKING | |
378 case LOCKING: | |
379 indesc = open (inname, O_RDWR); | |
380 break; | |
381 #endif | |
382 #ifdef HAVE_MMDF | |
383 case MMDF: | |
384 indesc = lk_open (inname, O_RDONLY, 0, 0, 10); | |
385 break; | |
386 #endif | |
387 default: abort(); | |
370 } | 388 } |
371 close (desc); | |
372 | |
373 tem = link (tempname, lockname); | |
374 unlink (tempname); | |
375 if (tem >= 0) | |
376 break; | |
377 sleep (1); | |
378 | |
379 /* If lock file is five minutes old, unlock it. | |
380 Five minutes should be good enough to cope with crashes | |
381 and wedgitude, and long enough to avoid being fooled | |
382 by time differences between machines. */ | |
383 if (stat (lockname, &st) >= 0) | |
384 { | |
385 now = time (0); | |
386 if (st.st_ctime < now - 300) | |
387 unlink (lockname); | |
388 } | |
389 } | |
390 | |
391 delete_lockname = lockname; | |
392 #endif /* not MAIL_USE_SYSTEM_LOCK */ | |
393 #endif /* not MAIL_USE_MMDF */ | |
394 | |
395 if (fork () == 0) | |
396 { | |
397 setuid (getuid ()); | |
398 | |
399 #ifndef MAIL_USE_MMDF | |
400 #ifdef MAIL_USE_SYSTEM_LOCK | |
401 indesc = open (inname, O_RDWR); | |
402 #else /* if not MAIL_USE_SYSTEM_LOCK */ | |
403 indesc = open (inname, O_RDONLY); | |
404 #endif /* not MAIL_USE_SYSTEM_LOCK */ | |
405 #else /* MAIL_USE_MMDF */ | |
406 indesc = lk_open (inname, O_RDONLY, 0, 0, 10); | |
407 #endif /* MAIL_USE_MMDF */ | |
408 | 389 |
409 if (indesc < 0) | 390 if (indesc < 0) |
410 pfatal_with_name (inname); | 391 pfatal_with_name (inname); |
411 | 392 |
412 #if defined (BSD) || defined (XENIX) | 393 #ifdef HAVE_UMASK |
413 /* In case movemail is setuid to root, make sure the user can | 394 /* In case movemail is setuid to root, make sure the user can |
414 read the output file. */ | 395 read the output file. */ |
415 /* This is desirable for all systems | |
416 but I don't want to assume all have the umask system call */ | |
417 umask (umask (0) & 0333); | 396 umask (umask (0) & 0333); |
418 #endif /* BSD or Xenix */ | 397 #endif |
398 | |
419 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666); | 399 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666); |
420 if (outdesc < 0) | 400 if (outdesc < 0) |
421 pfatal_with_name (outname); | 401 pfatal_with_name (outname); |
422 #ifdef MAIL_USE_SYSTEM_LOCK | 402 |
423 #ifdef MAIL_USE_LOCKF | 403 VERBOSE(("locking input file\n")); |
424 if (lockf (indesc, F_LOCK, 0) < 0) pfatal_with_name (inname); | 404 |
425 #else /* not MAIL_USE_LOCKF */ | 405 switch (lock_method) |
426 #ifdef XENIX | 406 { |
427 if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname); | 407 #ifdef HAVE_LOCKF |
428 #else | 408 case LOCKFING: |
429 #ifdef WINDOWSNT | 409 if (lockf (indesc, F_LOCK, 0) < 0) |
430 if (locking (indesc, LK_RLCK, -1L) < 0) pfatal_with_name (inname); | 410 pfatal_with_name (inname); |
431 #else | 411 break; |
432 if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname); | 412 #endif |
433 #endif | 413 #ifdef HAVE_FLOCK |
434 #endif | 414 case FLOCKING: |
435 #endif /* not MAIL_USE_LOCKF */ | 415 if (flock (indesc, LOCK_EX) < 0) |
436 #endif /* MAIL_USE_SYSTEM_LOCK */ | 416 pfatal_with_name (inname); |
437 | 417 break; |
418 #endif | |
419 #ifdef HAVE_LOCKING | |
420 case LOCKING: | |
421 if (locking (indesc, LK_RLCK, -1L) < 0) | |
422 pfatal_with_name (inname); | |
423 break; | |
424 #endif | |
425 case DOTLOCKING: | |
426 lock_dot(inname); | |
427 break; | |
428 } | |
429 | |
430 VERBOSE(("copying input file to output file\n")); | |
431 | |
438 { | 432 { |
439 char buf[1024]; | 433 char buf[1024]; |
440 | 434 |
441 while (1) | 435 while (1) |
442 { | 436 { |
451 if (nread < sizeof buf) | 445 if (nread < sizeof buf) |
452 break; | 446 break; |
453 } | 447 } |
454 } | 448 } |
455 | 449 |
456 #ifdef BSD | 450 #ifdef HAVE_FSYNC |
457 if (fsync (outdesc) < 0) | 451 if (fsync (outdesc) < 0) |
458 pfatal_and_delete (outname); | 452 pfatal_and_delete (outname); |
459 #endif | 453 #endif |
460 | 454 |
461 /* Check to make sure no errors before we zap the inbox. */ | 455 /* Check to make sure no errors before we zap the inbox. */ |
462 if (close (outdesc) != 0) | 456 if (close (outdesc) != 0) |
463 pfatal_and_delete (outname); | 457 pfatal_and_delete (outname); |
464 | 458 |
465 #ifdef MAIL_USE_SYSTEM_LOCK | 459 VERBOSE(("deleting or truncating input file\n")); |
466 #if defined (STRIDE) || defined (XENIX) || defined (WINDOWSNT) | 460 |
467 /* Stride, xenix have file locking, but no ftruncate. This mess will do. */ | 461 switch (lock_method) |
468 close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666)); | 462 { |
463 case LOCKFING: | |
464 case FLOCKING: | |
465 case LOCKING: | |
466 #ifdef HAVE_FTRUNCATE | |
467 ftruncate (indesc, 0L); | |
469 #else | 468 #else |
470 ftruncate (indesc, 0L); | 469 close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666)); |
471 #endif /* STRIDE or XENIX */ | 470 #endif |
472 #endif /* MAIL_USE_SYSTEM_LOCK */ | 471 close (indesc); |
473 | 472 break; |
474 #ifdef MAIL_USE_MMDF | 473 #ifdef HAVE_MMDF |
475 lk_close (indesc, 0, 0, 0); | 474 case MMDF: |
476 #else | 475 lk_close (indesc, 0, 0, 0); |
477 close (indesc); | 476 break; |
478 #endif | 477 #endif |
479 | 478 case DOTLOCKING: |
480 #ifndef MAIL_USE_SYSTEM_LOCK | 479 creat (inname, 0600); |
481 /* Delete the input file; if we can't, at least get rid of its | 480 break; |
482 contents. */ | 481 } |
483 #ifdef MAIL_UNLINK_SPOOL | |
484 /* This is generally bad to do, because it destroys the permissions | |
485 that were set on the file. Better to just empty the file. */ | |
486 if (unlink (inname) < 0 && errno != ENOENT) | |
487 #endif /* MAIL_UNLINK_SPOOL */ | |
488 creat (inname, 0600); | |
489 #endif /* not MAIL_USE_SYSTEM_LOCK */ | |
490 | 482 |
491 exit (0); | 483 exit (0); |
492 } | 484 } |
493 | 485 |
494 wait (&status); | 486 wait (&status); |
495 if (!WIFEXITED (status)) | 487 if (!WIFEXITED (status)) |
496 exit (1); | 488 exit (1); |
497 else if (WEXITSTATUS (status) != 0) | 489 else if (WEXITSTATUS (status) != 0) |
498 exit (WEXITSTATUS (status)); | 490 exit (WEXITSTATUS (status)); |
499 | 491 |
500 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK) | 492 if (lock_method == DOTLOCKING) |
501 unlink (lockname); | 493 unlock_dot(inname); |
502 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */ | 494 |
503 | 495 #endif /* not DISABLE_DIRECT_ACCESS */ |
504 #endif /* ! DISABLE_DIRECT_ACCESS */ | |
505 | 496 |
506 return 0; | 497 return 0; |
507 } | 498 } |
508 | 499 |
500 static void | |
501 usage(int lock_method) | |
502 { | |
503 printf ("Usage: movemail [-rvxkh] [-l lines ] [-m method ] [-i] inbox [-o] destfile [[-p] POP-password]\n"); | |
504 printf("where method is one of: dot"); | |
505 #ifdef HAVE_LOCKF | |
506 printf(", lockf"); | |
507 #endif | |
508 #ifdef HAVE_FLOCK | |
509 printf(", flock"); | |
510 #endif | |
511 #ifdef HAVE_MMDF | |
512 printf(", mmdf"); | |
513 #endif | |
514 #ifdef HAVE_LOCKING | |
515 printf(", locking"); | |
516 #endif | |
517 printf("\nDefault is: %s\n", unparse_lock_method(lock_method)); | |
518 | |
519 } | |
520 | |
521 static char * | |
522 unparse_lock_method(int lock_method) | |
523 { | |
524 switch (lock_method) | |
525 { | |
526 case DOTLOCKING: return "dot"; | |
527 case FLOCKING: return "flock"; | |
528 case LOCKFING: return "lockf"; | |
529 case LOCKING: return "locking"; | |
530 case MMDF: return "mmdf"; | |
531 default: abort();return 0; | |
532 } | |
533 } | |
534 | |
535 static int | |
536 parse_lock_method(char *method_name) | |
537 { | |
538 if (!strcmp("dot", method_name) || !strcmp("file", method_name)) | |
539 return DOTLOCKING; | |
540 #ifdef HAVE_LOCKF | |
541 else if (!strcmp("lockf", method_name)) | |
542 return LOCKFING; | |
543 #endif | |
544 #ifdef HAVE_FLOCK | |
545 else if (!strcmp("flock", method_name)) | |
546 return FLOCKING; | |
547 #endif | |
548 #ifdef HAVE_MMDF | |
549 else if (!strcmp("mmdf", method_name)) | |
550 return MMDF; | |
551 #endif | |
552 #ifdef HAVE_LOCKING | |
553 else if (!strcmp("locking", method_name)) | |
554 return LOCKING; | |
555 #endif | |
556 else | |
557 fatal("invalid lock method: %s", method_name); | |
558 return 0; /* unreached */ | |
559 } | |
560 | |
561 static char * | |
562 dot_filename(char *filename) | |
563 { | |
564 return concat (filename, ".lock", ""); | |
565 } | |
566 | |
567 static char *dotlock_filename = NULL; | |
568 | |
569 static void | |
570 lock_dot(char *filename) | |
571 { | |
572 struct stat st; | |
573 long now; | |
574 int tem; | |
575 char *lockname, *p; | |
576 char *tempname; | |
577 int desc; | |
578 | |
579 dotlock_filename = (char *) xmalloc(strlen(filename) + 1); | |
580 | |
581 /* Use a lock file named after our first argument with .lock appended: | |
582 If it exists, the mail file is locked. */ | |
583 | |
584 lockname = dot_filename(filename); | |
585 tempname = (char *) xmalloc (strlen (filename) + strlen ("EXXXXXX") + 1); | |
586 strcpy (tempname, filename); | |
587 p = tempname + strlen (tempname); | |
588 while (p != tempname && !IS_DIRECTORY_SEP (p[-1])) | |
589 p--; | |
590 *p = 0; | |
591 strcpy (p, "EXXXXXX"); | |
592 mktemp (tempname); | |
593 unlink (tempname); | |
594 | |
595 for (;;) | |
596 { | |
597 /* Create the lock file, but not under the lock file name. */ | |
598 /* Give up if cannot do that. */ | |
599 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666); | |
600 if (desc < 0) | |
601 { | |
602 char *message = (char *) xmalloc (strlen (tempname) + 50); | |
603 sprintf (message, "%s--see source file lib-src/movemail.c", | |
604 tempname); | |
605 pfatal_with_name (message); | |
606 } | |
607 close (desc); | |
608 | |
609 tem = link (tempname, lockname); | |
610 unlink (tempname); | |
611 if (tem >= 0) | |
612 break; | |
613 sleep (1); | |
614 | |
615 /* If lock file is five minutes old, unlock it. | |
616 Five minutes should be good enough to cope with crashes | |
617 and wedgitude, and long enough to avoid being fooled | |
618 by time differences between machines. */ | |
619 if (stat (lockname, &st) >= 0) | |
620 { | |
621 now = time (0); | |
622 if (st.st_ctime < now - 300) | |
623 unlink (lockname); | |
624 } | |
625 } | |
626 strcpy(dotlock_filename, filename); | |
627 } | |
628 | |
629 static void | |
630 unlock_dot(char *filename) | |
631 { | |
632 unlink(dot_filename(filename)); | |
633 } | |
634 | |
635 static void | |
636 maybe_unlock_dot(void) | |
637 { | |
638 if (dotlock_filename) | |
639 unlock_dot(dotlock_filename); | |
640 } | |
641 | |
509 /* Print error message and exit. */ | 642 /* Print error message and exit. */ |
510 | 643 |
511 static void | 644 static void |
512 fatal (char *s1, char *s2) | 645 fatal (char *s1, char *s2) |
513 { | 646 { |
514 if (delete_lockname) | 647 maybe_unlock_dot(); |
515 unlink (delete_lockname); | |
516 error (s1, s2, NULL); | 648 error (s1, s2, NULL); |
517 exit (1); | 649 exit (1); |
518 } | 650 } |
519 | 651 |
520 /* Print error message. `s1' is printf control string, `s2' is arg for it. */ | 652 /* Print error message. `s1' is printf control string, `s2' is arg for it. */ |
566 long *result = (long *) malloc (size); | 698 long *result = (long *) malloc (size); |
567 if (!result) | 699 if (!result) |
568 fatal ("virtual memory exhausted", 0); | 700 fatal ("virtual memory exhausted", 0); |
569 return result; | 701 return result; |
570 } | 702 } |
571 | 703 |
572 /* This is the guts of the interface to the Post Office Protocol. */ | 704 /* This is the guts of the interface to the Post Office Protocol. */ |
573 | 705 |
574 #ifdef MAIL_USE_POP | 706 #ifdef MAIL_USE_POP |
575 | 707 |
576 #ifndef WINDOWSNT | 708 #ifndef WINDOWSNT |
603 int mbfi; | 735 int mbfi; |
604 short* retrieved_list; | 736 short* retrieved_list; |
605 FILE *mbf; | 737 FILE *mbf; |
606 popserver server; | 738 popserver server; |
607 | 739 |
608 VERBOSE(("opening server\r")); | 740 VERBOSE(("opening server\n")); |
609 server = pop_open (0, user, password, POP_NO_GETPASS); | 741 server = pop_open (0, user, password, POP_NO_GETPASS); |
610 if (! server) | 742 if (! server) |
611 { | 743 { |
612 error (pop_error, NULL, NULL); | 744 error (pop_error, NULL, NULL); |
613 return (1); | 745 return (1); |
614 } | 746 } |
615 | 747 |
616 VERBOSE(("stat'ing messages\r")); | 748 VERBOSE(("stat'ing messages\n")); |
617 if (pop_stat (server, &nmsgs, &nbytes)) | 749 if (pop_stat (server, &nmsgs, &nbytes)) |
618 { | 750 { |
619 error (pop_error, NULL, NULL); | 751 error (pop_error, NULL, NULL); |
620 return (1); | 752 return (1); |
621 } | 753 } |
637 pop_close (server); | 769 pop_close (server); |
638 error ("Error in open: %s, %s", strerror (errno), outfile); | 770 error ("Error in open: %s, %s", strerror (errno), outfile); |
639 return (1); | 771 return (1); |
640 } | 772 } |
641 #if !defined(__CYGWIN32__) && !defined(WINDOWSNT) | 773 #if !defined(__CYGWIN32__) && !defined(WINDOWSNT) |
642 fchown (mbfi, getuid (), -1); | 774 fchown (mbfi, getuid (), (gid_t) -1); |
643 #endif | 775 #endif |
644 | 776 |
645 if ((mbf = fdopen (mbfi, "wb")) == NULL) | 777 if ((mbf = fdopen (mbfi, "wb")) == NULL) |
646 { | 778 { |
647 pop_close (server); | 779 pop_close (server); |
652 } | 784 } |
653 | 785 |
654 for (idx = 0; idx < nmsgs; idx++) | 786 for (idx = 0; idx < nmsgs; idx++) |
655 { | 787 { |
656 i = reverse ? nmsgs - idx : idx + 1; | 788 i = reverse ? nmsgs - idx : idx + 1; |
657 VERBOSE(("checking message %d \r", i)); | 789 VERBOSE(("checking message %d \n", i)); |
658 | 790 |
659 if (!regexp_pattern | 791 if (!regexp_pattern |
660 || | 792 || |
661 pop_search_top (server, i, match_lines, regexp_pattern) == POP_RETRIEVED) | 793 pop_search_top (server, i, match_lines, regexp_pattern) == POP_RETRIEVED) |
662 { | 794 { |
663 VERBOSE(("retrieving message %d \r", i)); | 795 VERBOSE(("retrieving message %d \n", i)); |
664 mbx_delimit_begin (mbf); | 796 mbx_delimit_begin (mbf); |
665 if (pop_retr (server, i, mbx_write, mbf) != POP_RETRIEVED) | 797 if (pop_retr (server, i, mbx_write, mbf) != POP_RETRIEVED) |
666 { | 798 { |
667 error (Errmsg, NULL, NULL); | 799 error (Errmsg, NULL, NULL); |
668 close (mbfi); | 800 close (mbfi); |
687 * workstation's AFS cache. The changes are not written to the server | 819 * workstation's AFS cache. The changes are not written to the server |
688 * until a call to fsync or close is made. Users with AFS home | 820 * until a call to fsync or close is made. Users with AFS home |
689 * directories have lost mail when over quota because these checks were | 821 * directories have lost mail when over quota because these checks were |
690 * not made in previous versions of movemail. */ | 822 * not made in previous versions of movemail. */ |
691 | 823 |
692 #ifdef BSD | 824 #ifdef HAVE_FSYNC |
693 if (fsync (mbfi) < 0) | 825 if (fsync (mbfi) < 0) |
694 { | 826 { |
695 error ("Error in fsync: %s", strerror (errno), NULL); | 827 error ("Error in fsync: %s", strerror (errno), NULL); |
696 return (1); | 828 return (1); |
697 } | 829 } |
707 { | 839 { |
708 for (i = 1; i <= nmsgs; i++) | 840 for (i = 1; i <= nmsgs; i++) |
709 { | 841 { |
710 if (retrieved_list[i] == 1) | 842 if (retrieved_list[i] == 1) |
711 { | 843 { |
712 VERBOSE(("deleting message %d \r", i)); | 844 VERBOSE(("deleting message %d \n", i)); |
713 if (pop_delete (server, i)) | 845 if (pop_delete (server, i)) |
714 { | 846 { |
715 error (pop_error, NULL, NULL); | 847 error (pop_error, NULL, NULL); |
716 pop_close (server); | 848 pop_close (server); |
717 return (1); | 849 return (1); |
729 | 861 |
730 return (0); | 862 return (0); |
731 } | 863 } |
732 | 864 |
733 static int | 865 static int |
734 pop_retr (popserver server, int msgno, int (*action)(), void *arg) | 866 pop_retr (popserver server, int msgno, int (*action)(char *, FILE *), FILE *arg) |
735 { | 867 { |
736 char *line; | 868 char *line; |
737 int ret; | 869 int ret; |
738 | 870 |
739 if (pop_retrieve_first (server, msgno, &line)) | 871 if (pop_retrieve_first (server, msgno, &line)) |
875 } | 1007 } |
876 | 1008 |
877 | 1009 |
878 | 1010 |
879 #endif /* MAIL_USE_POP */ | 1011 #endif /* MAIL_USE_POP */ |
880 | 1012 |
881 #ifndef HAVE_STRERROR | 1013 #ifndef HAVE_STRERROR |
882 char * | 1014 char * |
883 strerror (int errnum) | 1015 strerror (int errnum) |
884 { | 1016 { |
885 extern char *sys_errlist[]; | 1017 extern char *sys_errlist[]; |