]> diplodocus.org Git - nmh/blob - docs/historical/2.9BSD/cmds/refile.c
Added start_test/finish_test to a bunch of tests.
[nmh] / docs / historical / 2.9BSD / cmds / refile.c
1 #ifndef lint
2 static char sccsid[] = "@(#)refile.c 1.1 5/26/83";
3 #endif
4
5 #include "mh.h"
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <errno.h>
10 #include <strings.h>
11
12 #define NFOLD 20 /* Allow 20 folder specs */
13
14 /* file [-src folder] [msgs] +folder [+folder ...]
15 *
16 * moves messages from src folder (or current) to other one(s).
17 *
18 * all = 1-999 for a message sequence
19 * -preserve says preserve msg numbers
20 * -link says don't delete old msg
21 */
22
23 char *anoyes[]; /* Std no/yes gans array */
24
25 int vecp, foldp, prsrvf;
26 char **vec, maildir[128], *folder, *file;
27 struct msgs *mp;
28
29 struct st_fold {
30 char *f_name;
31 struct msgs *f_mp;
32 } folders[NFOLD];
33
34 char *files[NFOLD + 1]; /* Vec of files to process--starts at 1! */
35 int filec = 1;
36 char *bellfile = "/usr/bin/file";
37 extern int errno;
38 char *rindex();
39
40 struct swit switches[] = {
41 "all", -3, /* 0 */
42 "link", 0, /* 1 */
43 "nolink", 0, /* 2 */
44 "preserve", 0, /* 3 */
45 "nopreserve", 0, /* 4 */
46 "src +folder", 0, /* 5 */
47 "file", 0, /* 6 */
48 "help", 4, /* 7 */
49 0, 0
50 };
51 main(argc, argv)
52 char *argv[];
53 {
54 register int i, msgnum;
55 register char *cp;
56 char *msgs[128];
57 int msgp, linkf;
58 int ismhfile = 0;
59 char **ap;
60 char *arguments[50], **argp;
61 char *pwd(), *pwds;
62
63 /*
64 * Rand has committed the sin of picking a name that already is
65 * used (file). We fix this here since we can tell the difference
66 * between the two (mh file has -'s and +'s always, bell file never
67 * has them.)
68 */
69 for (i=1; i<argc; i++)
70 if (argv[i][0] == '-' || argv[i][0]=='+')
71 ismhfile++;
72 if (!ismhfile) {
73 execv(bellfile, argv);
74 fprintf(stderr, "Cannot find %s\n", bellfile);
75 exit(1);
76 }
77
78 #ifdef NEWS
79 m_news();
80 #endif
81 folder = 0; msgp = 0; linkf = 0;
82 cp = r1bindex(argv[0], '/');
83 if((cp = m_find(cp)) != NULL) {
84 ap = brkstring(cp = getcpy(cp), " ", "\n");
85 ap = copyip(ap, arguments);
86 } else
87 ap = arguments;
88 copyip(argv+1, ap);
89 argp = arguments;
90 while(cp = *argp++) {
91 if(*cp == '-') {
92 switch(smatch(++cp, switches)) {
93 case -2:ambigsw(cp, switches); /* ambiguous */
94 goto leave;
95 /* unknown */
96 case -1:fprintf(stderr, "file: -%s unknown\n", cp);
97 goto leave;
98 /* -all */
99 case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
100 goto leave;
101 case 1: linkf = 1; continue; /* -link */
102 case 2: linkf = 0; continue; /* -nolink */
103 case 3: prsrvf = 1; continue; /* -preserve */
104 case 4: prsrvf = 0; continue; /* -nopreserve */
105 case 5: if(folder) { /* -src */
106 fprintf(stderr, "Only one src folder.\n");
107 goto leave;
108 }
109 if(!(folder = *argp++) || *folder == '-') {
110 missing: fprintf(stderr, "file: Missing argument for %s switch\n", argp[-2]);
111 goto leave;
112 }
113 if(*folder == '+')
114 folder++;
115 continue;
116 /* -help */
117 case 6:
118 if(filec >= NFOLD) {
119 fprintf(stderr, "Too many src files.\n");
120 goto leave;
121 }
122 if(!(files[filec++] = *argp) || **argp++ == '-')
123 goto missing;
124 continue;
125
126 case 7: help("file [msgs] [switches] +folder ...",
127 switches);
128 goto leave;
129 }
130 }
131 if(*cp == '+') {
132 if(foldp < NFOLD)
133 folders[foldp++].f_name = cp + 1;
134 else {
135 fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
136 goto leave;
137 }
138 } else
139 msgs[msgp++] = cp;
140 }
141 if(!foldp) {
142 fprintf(stderr, "No folder specified.\n");
143 fprintf(stderr, "Usage: file [-src folder] [msg ...] [switches] +folder [+folder]\n");
144 goto leave;
145 }
146 if(filec > 1) {
147 if(msgp) {
148 fprintf(stderr, "File: Can't mix files and messages.\n");
149 goto leave;
150 }
151 for(i = 1; i < filec; i++)
152 if(*files[i] != '/') {
153 if(!pwds)
154 pwds = pwd();
155 files[i] = concat(pwds, "/", files[i], 0);
156 }
157 if(opnfolds())
158 goto leave;
159 for(i = 1; i < filec; i++) {
160 if(process(files[i]))
161 goto leave;
162 }
163 if(!linkf) {
164 if((cp = m_find("delete-prog")) != NULL) {
165 files[0] = cp;
166 execvp(cp, files);
167 fprintf(stderr, "Can't exec deletion-prog--");
168 perror(cp);
169 } else for(i = 1; i < filec; i++) {
170 if(unlink(files[i]) == -1) {
171 fprintf(stderr, "Can't unlink ");
172 perror(files[i]);
173 }
174 }
175 }
176 goto leave;
177 }
178 if(!msgp)
179 msgs[msgp++] = "cur";
180 if(!folder)
181 folder = m_getfolder();
182 copy(m_maildir(folder), maildir);
183 if(chdir(maildir) < 0) {
184 fprintf(stderr, "Can't chdir to: ");
185 perror(maildir);
186 goto leave;
187 }
188 if(!(mp = m_gmsg(folder))) {
189 fprintf(stderr, "Can't read folder %s!?\n",folder);
190 goto leave;
191 }
192 if(mp->hghmsg == 0) {
193 fprintf(stderr, "No messages in \"%s\".\n", folder);
194 goto leave;
195 }
196 for(msgnum = 0; msgnum < msgp; msgnum++)
197 if(!m_convert((cp = msgs[msgnum])))
198 goto leave;
199 if(mp->numsel == 0) {
200 fprintf(stderr, "file: ham 'n cheese\n"); /* never get here */
201 goto leave;
202 }
203 m_replace(pfolder, folder);
204 if(mp->hghsel != mp->curmsg && ((mp->numsel != mp->nummsg) || linkf))
205 m_setcur(mp->hghsel);
206 if(opnfolds())
207 goto leave;
208 for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
209 if(mp->msgstats[msgnum] & SELECTED)
210 if(process(cp = getcpy(m_name(msgnum))))
211 goto leave;
212 else
213 cndfree(cp);
214 if(!linkf) {
215 if((cp = m_find("delete-prog")) != NULL) {
216 if(mp->numsel > MAXARGS-2) {
217 fprintf(stderr, "file: more than %d messages for deletion-prog\n",MAXARGS-2);
218 printf("[messages not unlinked]\n");
219 goto leave;
220 }
221 vecp = 1;
222 vec = (char **) calloc(MAXARGS + 2, sizeof *vec);
223 for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
224 if(mp->msgstats[msgnum]&SELECTED)
225 vec[vecp++] = getcpy(m_name(msgnum));
226 vec[vecp] = 0;
227 m_update();
228 fflush(stdout);
229 vec[0] = cp;
230 execv(vec[0], vec);
231 fprintf(stderr, "Can't exec deletion-prog--");
232 perror(cp);
233 } else {
234 for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
235 if(mp->msgstats[msgnum] & SELECTED)
236 if(unlink(cp = m_name(msgnum))== -1) {
237 fprintf(stderr, "Can't unlink %s:",folder);
238 perror(cp);
239 }
240 }
241 }
242 leave:
243 m_update();
244 done(0);
245 }
246
247
248 opnfolds()
249 {
250 register int i;
251 register char *cp;
252 char nmaildir[128];
253
254 for(i = 0; i < foldp; i++) {
255 copy(m_maildir(folders[i].f_name), nmaildir);
256 if(access(nmaildir, 5) < 0) {
257 cp = concat("Create folder \"", nmaildir, "\"? ", 0);
258 if(!gans(cp, anoyes))
259 goto bad;
260 free(cp);
261 if(!makedir(nmaildir)) {
262 fprintf(stderr, "Can't create folder.\n");
263 goto bad;
264 }
265 }
266 if(chdir(nmaildir) < 0) {
267 fprintf(stderr, "Can't chdir to: ");
268 perror(nmaildir);
269 goto bad;
270 }
271 if(!(folders[i].f_mp = m_gmsg())) {
272 fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
273 goto bad;
274 }
275 }
276 chdir(maildir); /* return to src folder */
277 return(0);
278 bad:
279 return(1);
280 }
281
282
283 process(msg)
284 char *msg;
285 {
286 char newmsg[256], buf[BUFSIZ];
287 register int i;
288 register char *nmsg;
289 register struct st_fold *fp;
290 struct stat stbuf, stbf1;
291 int n, o, linkerr;
292
293 for(fp = folders; fp < &folders[foldp]; fp++) {
294 if(prsrvf)
295 nmsg = msg;
296 else
297 nmsg = m_name(fp->f_mp->hghmsg++ + 1);
298 copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
299 if(link(msg, newmsg) < 0) {
300 linkerr = errno;
301 if(linkerr == EEXIST ||
302 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
303 if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
304 stat(newmsg, &stbuf) < 0 ||
305 stbf1.st_ino != stbuf.st_ino) {
306 fprintf(stderr, "Message %s:%s already exists.\n",
307 fp->f_name, msg);
308 return(1);
309 }
310 continue;
311 }
312 if(linkerr == EXDEV) {
313 if((o = open(msg, 0)) == -1) {
314 fprintf(stderr, "Can't open %s:%s.\n",
315 folder, msg);
316 return(1);
317 }
318 fstat(o, &stbuf);
319 if((n = creat(newmsg, stbuf.st_mode&0777)) == -1) {
320 fprintf(stderr, "Can't create %s:%s.\n",
321 fp->f_name, nmsg);
322 close(o);
323 return(1);
324 }
325 do
326 if((i=read(o, buf, sizeof buf)) < 0 ||
327 write(n, buf, i) == -1) {
328 fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
329 folder, msg, fp->f_name, nmsg);
330 close(o); close(n);
331 return(1);
332 }
333 while(i == sizeof buf);
334 close(n); close(o);
335 } else {
336 fprintf(stderr, "Error on link %s:%s to %s:",
337 folder, msg, fp->f_name);
338 perror(nmsg);
339 return(1);
340 }
341 }
342 cont: ;
343 }
344 return(0);
345 }
346
347
348 char *
349 pwd()
350 {
351 register FILE *pp;
352 static char curpath[128];
353 register int i;
354 FILE *popen();
355
356 if((pp = popen("pwd", "r")) == NULL ||
357 fgets(curpath, sizeof curpath, pp) == NULL ||
358 pclose(pp) != 0) {
359 fprintf(stderr, "Can't find current directory!\n");
360 done(1);
361 }
362 *rindex(curpath, '\n') = 0; /* Zap the lf */
363 return curpath;
364 }