|
|
1.1 root 1: /* movemail foo bar -- move file foo to file bar,
2: locking file foo the way /bin/mail respects.
3: Copyright (C) 1985 Richard M. Stallman.
4:
5: This file is part of GNU Emacs.
6:
7: GNU Emacs is distributed in the hope that it will be useful,
8: but without any warranty. No author or distributor
9: accepts responsibility to anyone for the consequences of using it
10: or for whether it serves any particular purpose or works at all,
11: unless he says so in writing.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU Emacs, but only under the conditions described in the
15: document "GNU Emacs copying permission notice". An exact copy
16: of the document is supposed to have been given to you along with
17: GNU Emacs so that you can know how you may redistribute it all.
18: It should be in a file named COPYING. Among other things, the
19: copyright notice and this notice must be preserved on all copies. */
20:
21: #include <sys/types.h>
22: #include <sys/stat.h>
23: #include <sys/file.h>
24: #define NO_SHORTNAMES /* Tell config not to load remap.h */
25: #include "../src/config.h"
26:
27: #ifdef USG
28: #include <fcntl.h>
29: #endif /* USG */
30:
31: /* Cancel substitutions made by config.h for Emacs. */
32: #undef open
33: #undef read
34: #undef write
35:
36: char *concat ();
37:
38: main (argc, argv)
39: int argc;
40: char **argv;
41: {
42: char *inname, *outname;
43: int indesc, outdesc;
44: char buf[1024];
45: int nread;
46:
47: #ifndef MAIL_USE_FLOCK
48: struct stat st;
49: long now;
50: int tem;
51: char *lockname, *p;
52: char tempname[40];
53: int desc;
54: #endif /* not MAIL_USE_FLOCK */
55:
56: if (argc < 3)
57: fatal ("two arguments required");
58:
59: inname = argv[1];
60: outname = argv[2];
61:
62: #ifndef MAIL_USE_FLOCK
63: /* Use a lock file named /usr/spool/mail/$USER.lock:
64: If it exists, the mail file is locked. */
65: lockname = concat (inname, ".lock", "");
66: strcpy (tempname, inname);
67: p = tempname + strlen (tempname);
68: while (p != tempname && p[-1] != '/')
69: p--;
70: *p = 0;
71: strcpy (p, "EXXXXXX");
72: mktemp (tempname);
73: unlink (tempname);
74:
75: while (1)
76: {
77: /* Create the lock file, but not under the lock file name. */
78: /* Give up if cannot do that. */
79: desc = open (tempname, O_WRONLY | O_CREAT, 0666);
80: if (desc < 0)
81: exit (1);
82: close (desc);
83:
84: tem = link (tempname, lockname);
85: unlink (tempname);
86: if (tem >= 0)
87: break;
88: sleep (1);
89:
90: /* If lock file is a minute old, unlock it. */
91: if (stat (lockname, &st) >= 0)
92: {
93: now = time (0);
94: if (st.st_ctime < now - 60)
95: unlink (lockname);
96: }
97: }
98: #endif /* not MAIL_USE_FLOCK */
99:
100: #ifdef MAIL_USE_FLOCK
101: indesc = open (inname, O_RDWR);
102: #else /* if not MAIL_USE_FLOCK */
103: indesc = open (inname, O_RDONLY);
104: #endif /* not MAIL_USE_FLOCK */
105: if (indesc < 0)
106: pfatal_with_name (inname);
107: #ifdef BSD
108: /* In case movemail is setuid to root, make sure the user can
109: read the output file. */
110: /* This is desirable for all systems
111: but I don't want to assume all have the umask system call */
112: umask (umask (0) & 0333);
113: #endif /* BSD */
114: outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
115: if (outdesc < 0)
116: pfatal_with_name (outname);
117: #ifdef MAIL_USE_FLOCK
118: (void) flock (indesc, LOCK_EX);
119: #endif /* MAIL_USE_FLOCK */
120:
121: while (1)
122: {
123: nread = read (indesc, buf, sizeof buf);
124: if (nread != write (outdesc, buf, nread))
125: fatal ("error writing to %s", outname);
126: if (nread < sizeof buf)
127: break;
128: }
129:
130: #ifdef MAIL_USE_FLOCK
131: (void) ftruncate (indesc, 0L);
132: #endif /* MAIL_USE_FLOCK */
133: close (indesc);
134: close (outdesc);
135: #ifndef MAIL_USE_FLOCK
136: unlink (inname);
137: unlink (lockname);
138: #endif /* not MAIL_USE_FLOCK */
139: exit (0);
140: }
141:
142: /* Print error message and exit. */
143:
144: fatal (s1, s2)
145: char *s1, *s2;
146: {
147: error (s1, s2);
148: exit (1);
149: }
150:
151: /* Print error message. `s1' is printf control string, `s2' is arg for it. */
152:
153: error (s1, s2)
154: char *s1, *s2;
155: {
156: printf ("movemail: ");
157: printf (s1, s2);
158: printf ("\n");
159: }
160:
161: pfatal_with_name (name)
162: char *name;
163: {
164: extern int errno, sys_nerr;
165: extern char *sys_errlist[];
166: char *s;
167:
168: if (errno < sys_nerr)
169: s = concat ("", sys_errlist[errno], " for %s");
170: else
171: s = "cannot open %s";
172: fatal (s, name);
173: }
174:
175: /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
176:
177: char *
178: concat (s1, s2, s3)
179: char *s1, *s2, *s3;
180: {
181: int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
182: char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
183:
184: strcpy (result, s1);
185: strcpy (result + len1, s2);
186: strcpy (result + len1 + len2, s3);
187: *(result + len1 + len2 + len3) = 0;
188:
189: return result;
190: }
191:
192: /* Like malloc but get fatal error if memory is exhausted. */
193:
194: int
195: xmalloc (size)
196: int size;
197: {
198: int result = malloc (size);
199: if (!result)
200: fatal ("virtual memory exhausted", 0);
201: return result;
202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.