Mercurial > hg > Applications > mh
comparison uip/bbl.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bce86c4163a3 |
---|---|
1 /* bbl.c - ease the tasks of a BBleader */ | |
2 #ifndef lint | |
3 static char ident[] = "@(#)$Id$"; | |
4 #endif lint | |
5 | |
6 #include "../h/mh.h" | |
7 #include "../h/local.h" | |
8 #include "../zotnet/bboards.h" | |
9 #include <ctype.h> | |
10 #include <pwd.h> | |
11 #include <stdio.h> | |
12 #ifdef LOCALE | |
13 #include <locale.h> | |
14 #endif | |
15 | |
16 /* */ | |
17 | |
18 static struct swit switches[] = { | |
19 #define SHELLSW 0 | |
20 "shell program", 0, | |
21 | |
22 #define VERBSW 1 | |
23 "verbose", 0, | |
24 #define NVERBSW 2 | |
25 "noverbose", 0, | |
26 | |
27 #define HELPSW 3 | |
28 "help", 4, | |
29 | |
30 NULL, 0 | |
31 }; | |
32 | |
33 /* */ | |
34 | |
35 static int verbosw = 0; | |
36 | |
37 static int sub_ok = 0; | |
38 | |
39 static char *bboards = BBOARDS; | |
40 | |
41 static char *cwd = NULL; | |
42 | |
43 static char *current_folder = NULL; | |
44 | |
45 static char *bbfolder = NULL; | |
46 static char subfolder[BUFSIZ]; | |
47 | |
48 static struct stat bbstat; | |
49 static struct stat substat; | |
50 | |
51 static char *shell = "/bin/sh"; | |
52 | |
53 static struct bboard *bb = NULL; | |
54 | |
55 | |
56 #ifndef __STDC__ | |
57 #ifdef SYS5 | |
58 struct passwd *getpwnam (), *getpwuid (); | |
59 #endif /* SYS5 */ | |
60 #endif | |
61 | |
62 /* */ | |
63 | |
64 /* ARGSUSED */ | |
65 | |
66 main (argc, argv) | |
67 int argc; | |
68 char **argv; | |
69 { | |
70 char *cp, | |
71 **ap, | |
72 **argp, | |
73 buffer[80], | |
74 *arguments[MAXARGS]; | |
75 struct passwd *pw; | |
76 | |
77 #ifdef LOCALE | |
78 setlocale(LC_ALL, ""); | |
79 #endif | |
80 #ifdef JAPAN | |
81 ml_init(); | |
82 #endif /* JAPAN */ | |
83 invo_name = r1bindex (argv[0], '/'); | |
84 if (strlen(invo_name) > NAMESZ) { | |
85 fprintf(stderr, "%s: argv[0] too long\n", invo_name); | |
86 exit(1); | |
87 } | |
88 if ((cp = m_find (invo_name)) != NULL) { | |
89 ap = brkstring (cp = getcpy (cp), " ", "\n"); | |
90 ap = copyip (ap, arguments); | |
91 } | |
92 else | |
93 ap = arguments; | |
94 if (argc > MAXARGS - (ap - arguments)) | |
95 adios (NULLCP, "too many arguments."); | |
96 (void) copyip (argv + 1, ap); | |
97 for (argp = arguments; *argp; argp++) | |
98 if (strlen(*argp) >= BUFSIZ / 4) | |
99 adios (NULLCP, "argument too long"); | |
100 argp = arguments; | |
101 | |
102 if ((shell = getenv ("SHELL")) == NULL) | |
103 if ((pw = getpwuid (getuid ())) != NULL | |
104 && pw -> pw_shell | |
105 && *pw -> pw_shell) | |
106 shell = getcpy (pw -> pw_shell); | |
107 if (strlen(shell) >= BUFSIZ / 4) | |
108 adios (NULLCP, "SHELL envariable too long"); | |
109 | |
110 if ((pw = getpwnam (bboards)) == NULL) | |
111 adios (NULLCP, "no entry for ~%s", bboards); | |
112 if (pw -> pw_uid != geteuid ()) | |
113 adios (NULLCP, "not running setuid to %s", bboards); | |
114 | |
115 current_folder = m_getfolder(); | |
116 | |
117 /* */ | |
118 | |
119 while (cp = *argp++) { | |
120 if (*cp == '-') | |
121 switch (smatch (++cp, switches)) { | |
122 case AMBIGSW: | |
123 ambigsw (cp, switches); | |
124 done (1); | |
125 case UNKWNSW: | |
126 adios (NULLCP, "-%s unknown", cp); | |
127 case HELPSW: | |
128 (void) sprintf (buffer, "%s [+folder] [switches] bboard", | |
129 invo_name); | |
130 help (buffer, switches); | |
131 done (1); | |
132 | |
133 case SHELLSW: | |
134 if (!(shell = *argp++) || *shell == '-') | |
135 adios (NULLCP, "missing argument to %s", argp[-2]); | |
136 continue; | |
137 | |
138 case VERBSW: | |
139 verbosw++; | |
140 continue; | |
141 case NVERBSW: | |
142 verbosw = 0; | |
143 continue; | |
144 } | |
145 if (*cp == '+') | |
146 if (bbfolder) | |
147 adios (NULLCP, "only one folder at a time!"); | |
148 else | |
149 bbfolder = cp; | |
150 else | |
151 if (bb != NULL) | |
152 adios (NULLCP, "only one BBoard a time!"); | |
153 else | |
154 if ((bb = getbbnam (cp)) == NULL | |
155 && (bb = getbbaka (cp)) == NULL) | |
156 adios (NULLCP, "no such BBoard as '%s'", cp); | |
157 } | |
158 | |
159 /* */ | |
160 | |
161 if (!bb) | |
162 adios (NULLCP, "no BBoard specified"); | |
163 if (!bbfolder) | |
164 bbfolder = "+bbl"; | |
165 (void) sprintf (subfolder, "%s/arc", bbfolder); | |
166 | |
167 if (!m_find ("path")) | |
168 free (path ("./", TFOLDER)); | |
169 cwd = getcpy (pwd ()); | |
170 | |
171 process (); | |
172 | |
173 m_replace (pfolder, current_folder); | |
174 m_update (); | |
175 | |
176 done (0); | |
177 } | |
178 | |
179 /* */ | |
180 | |
181 process () { | |
182 int child_id; | |
183 char buffer[BUFSIZ]; | |
184 | |
185 if (!ldrbb (bb) && !ldrchk (bb)) | |
186 return; | |
187 | |
188 if (stat (bb -> bb_file, &bbstat) == NOTOK) | |
189 adios (NULLCP, "no such file as %s", bb -> bb_file); | |
190 | |
191 if (stat (bb -> bb_archive, &substat) != NOTOK | |
192 && substat.st_size > 0) | |
193 sub_ok++; | |
194 /* else */ | |
195 substat.st_mode = bbstat.st_mode;/* archive should always match */ | |
196 substat.st_gid = bbstat.st_gid;/* actual bboard mode & gid */ | |
197 | |
198 /* do subfolder first, since you will lose otherwise... */ | |
199 (void) sprintf (buffer, "Remove messages currently in %s? ", subfolder); | |
200 if (check_folder (subfolder) && getanswer (buffer)) | |
201 rmf (subfolder); | |
202 | |
203 (void) sprintf (buffer, "Remove messages currently in %s? ", bbfolder); | |
204 if (check_folder (bbfolder) && getanswer (buffer)) | |
205 rmf (bbfolder); | |
206 | |
207 switch (child_id = fork ()) { | |
208 case NOTOK: | |
209 adios ("fork", "unable to"); | |
210 | |
211 case OK: | |
212 do_child (); /* NOTREACHED */ | |
213 | |
214 default: | |
215 do_parent (child_id); | |
216 break; | |
217 } | |
218 } | |
219 | |
220 /* */ | |
221 | |
222 int check_folder (folder) | |
223 char *folder; | |
224 { | |
225 char *maildir; | |
226 struct stat st; | |
227 struct msgs *mp; | |
228 | |
229 maildir = m_maildir (folder + 1); | |
230 | |
231 if (stat (maildir, &st) == NOTOK) | |
232 return 0; | |
233 | |
234 if ((st.st_mode & S_IFMT) != S_IFDIR) | |
235 adios (NULLCP, "not a directory '%s'", maildir); | |
236 check_mode (maildir, (st.st_mode | 0555) & 0777); | |
237 | |
238 if (chdir (maildir) == NOTOK) | |
239 adios (maildir, "unable to change to"); | |
240 if (!(mp = m_gmsg (folder + 1))) | |
241 adios (NULLCP, "unable to read %s", folder); | |
242 | |
243 if (chdir (cwd) == NOTOK) | |
244 admonish (cwd, "could not change back to"); | |
245 return (mp -> hghmsg != 0); | |
246 } | |
247 | |
248 /* */ | |
249 | |
250 do_parent (child_id) | |
251 int child_id; | |
252 { | |
253 int zap = 0; | |
254 char buffer[BUFSIZ]; | |
255 | |
256 if (pidwait (child_id, NOTOK) == NOTOK) | |
257 done (1); | |
258 | |
259 (void) putchar ('\n'); | |
260 | |
261 (void) check_folder (bbfolder); | |
262 if (getanswer ("Incorporate changes? ")) | |
263 update (&bbstat, bb -> bb_file, bbfolder, bb -> bb_info, bb -> bb_map); | |
264 (void) sprintf (buffer, "Remove %s? ", bbfolder); | |
265 if (getanswer (buffer)) | |
266 zap++; | |
267 | |
268 if (check_folder (subfolder)) { | |
269 if (getanswer ("Update archives? ")) | |
270 update (&substat, bb -> bb_archive, subfolder, NULLCP, NULLCP); | |
271 (void) sprintf (buffer, "Remove %s? ", subfolder); | |
272 if (getanswer (buffer)) | |
273 rmf (subfolder); | |
274 } | |
275 else | |
276 if (sub_ok | |
277 && getanswer ("Remove archives? ") | |
278 && getanswer ("Are you sure? ")) | |
279 if (unlink (bb -> bb_archive) == NOTOK) | |
280 admonish (bb -> bb_archive, "unable to remove %s"); | |
281 if (zap) | |
282 rmf (bbfolder); | |
283 } | |
284 | |
285 /* */ | |
286 | |
287 check_mode (dir, mode) | |
288 char *dir; | |
289 unsigned int mode; | |
290 { | |
291 int child_id; | |
292 struct stat st; | |
293 #ifdef SYS5DIR | |
294 struct dirent *dp; | |
295 #else SYS5DIR | |
296 struct direct *dp; | |
297 #endif SYS5DIR | |
298 DIR * dd; | |
299 | |
300 if (verbosw) | |
301 fprintf (stderr, "chmod %o %s\n", mode, dir); | |
302 | |
303 switch (child_id = fork ()) { | |
304 case NOTOK: | |
305 adios ("fork", "unable to"); | |
306 | |
307 case OK: | |
308 (void) setgid (getgid ()); | |
309 (void) setuid (getuid ()); | |
310 | |
311 if (chmod (dir, (int) mode) == NOTOK) | |
312 adios (dir, "unable to change mode of"); | |
313 if (chdir (dir) == NOTOK) | |
314 adios (dir, "unable to change to"); | |
315 if ((dd = opendir (dir)) == NULL) | |
316 adios (dir, "unable to read"); | |
317 while (dp = readdir (dd)) | |
318 if (dp -> d_name[0] != '.') { | |
319 if (stat (dp -> d_name, &st) == NOTOK) { | |
320 admonish (dp -> d_name, "unable to stat"); | |
321 continue; | |
322 } | |
323 if (chmod (dp -> d_name, (int) ((st.st_mode | 0444) & 0777)) | |
324 == NOTOK) | |
325 admonish (dp -> d_name, "unable to change mode of"); | |
326 } | |
327 closedir (dd); | |
328 done (0); | |
329 | |
330 default: | |
331 if (pidwait (child_id, OK)) | |
332 done (1); | |
333 break; | |
334 } | |
335 } | |
336 | |
337 /* */ | |
338 | |
339 /* ARGSUSED */ | |
340 | |
341 update (stp, file, folder, info, map) | |
342 struct stat *stp; | |
343 char *file, | |
344 *folder, | |
345 *info, | |
346 *map; | |
347 { | |
348 int fd; | |
349 struct stat st; | |
350 | |
351 if (stat (file, &st) != NOTOK | |
352 && st.st_mtime != stp -> st_mtime) { | |
353 printf ("File '%s' has changed...\n", file); | |
354 if (getanswer ("Append to it instead? ")) | |
355 goto work; | |
356 else | |
357 if (!getanswer ("Still update it? ")) | |
358 return; | |
359 } | |
360 if ((fd = creat (file, BBMODE)) == NOTOK) | |
361 adios (file, "unable to re-create"); | |
362 else { | |
363 (void) close (fd); | |
364 if (map) | |
365 (void) unlink (map); | |
366 } | |
367 #ifdef notdef | |
368 if (info) | |
369 check_info (folder, info); | |
370 #endif notdef | |
371 | |
372 work: ; | |
373 pack (folder, file); | |
374 if (chmod (file, (int) (stp -> st_mode & 0777)) == NOTOK) | |
375 admonish (file, "unable to change mode of"); | |
376 if (stat (file, &st) != NOTOK && st.st_gid != stp -> st_gid) | |
377 chgrp (file, stp -> st_gid); | |
378 } | |
379 | |
380 /* */ | |
381 | |
382 #ifdef notdef | |
383 check_info (folder, info) | |
384 char *folder, | |
385 *info; | |
386 { | |
387 int id, | |
388 state; | |
389 char *hdrptr, | |
390 *maildir, | |
391 *msgnam, | |
392 posted[BUFSIZ], | |
393 name[NAMESZ], | |
394 buf[BUFSIZ]; | |
395 struct msgs *mp; | |
396 FILE * fp; | |
397 | |
398 if (chdir (maildir = m_maildir (folder + 1)) == NOTOK) | |
399 adios (maildir, "unable to change to"); | |
400 | |
401 if (!(mp = m_gmsg (folder + 1))) | |
402 adios (NULL, "unable to read %s", folder); | |
403 if (mp -> hghmsg) { | |
404 if ((fp = fopen (msgnam = m_name (mp -> hghmsg), "r")) == NULL) | |
405 adios (NULL, "unable to read message %s in %s", | |
406 msgnam, folder); | |
407 id = 0; | |
408 posted[0] = NULL; | |
409 for (state = FLD;;) { | |
410 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) { | |
411 case FLD: | |
412 case FLDEOF: | |
413 case FLDPLUS: | |
414 hdrptr = add (buf, NULL); | |
415 while (state == FLDPLUS) { | |
416 state = m_getfld (state, name, buf, sizeof buf, fp); | |
417 hdrptr = add (buf, hdrptr); | |
418 } | |
419 if (uleq (name, "BBoard-ID")) { | |
420 id = atoi (buf); | |
421 if (id > 0 && posted[0]) | |
422 break; | |
423 } | |
424 if (uleq (name, "BB-Posted")) { | |
425 strncpy (posted, buf, sizeof posted - 2); | |
426 if (posted[strlen (posted) - 1] == '\n') | |
427 posted[strlen (posted) - 1] = NULL; | |
428 if (id > 0 && posted[0]) | |
429 break; | |
430 } | |
431 continue; | |
432 | |
433 default: | |
434 admonish (NULL, "unable to find BBoard-info in message %s", | |
435 msgnam); | |
436 (void) fclose (fp); | |
437 goto no_risk; | |
438 } | |
439 break; | |
440 } | |
441 (void) fclose (fp); | |
442 | |
443 if (verbosw) | |
444 fprintf (stderr, | |
445 "[ Highest message has %s%d and\n\t\t %s%s ]\n", | |
446 "BBoard-ID: ", id, "BB-Posted: ", posted); | |
447 | |
448 if ((fp = lkfopen (info, "w")) == NULL) | |
449 adios (info, "unable to lock and fopen"); | |
450 fprintf (fp, "%d\n%s\n", id, posted); | |
451 (void) lkfclose (fp, info); | |
452 } | |
453 | |
454 no_risk: ; | |
455 if (chdir (cwd) == NOTOK) | |
456 admonish (cwd, "could not change back to"); | |
457 } | |
458 #endif notdef | |
459 | |
460 /* */ | |
461 | |
462 pack (folder, file) | |
463 char *folder, | |
464 *file; | |
465 { | |
466 int child_id; | |
467 | |
468 switch (child_id = fork ()) { | |
469 case NOTOK: | |
470 admonish ("fork", "unable to"); | |
471 return; | |
472 | |
473 case OK: | |
474 if (verbosw) | |
475 fprintf (stderr, "pack %s -file %s\n", folder, file); | |
476 | |
477 execlp (packproc, r1bindex (packproc, '/'), | |
478 folder, "-file", file, NULLCP); | |
479 fprintf (stderr, "unable to exec "); | |
480 perror (packproc); | |
481 _exit (-1); | |
482 | |
483 default: | |
484 (void) pidXwait (child_id, packproc); | |
485 break; | |
486 } | |
487 } | |
488 | |
489 /* */ | |
490 | |
491 chgrp (file, gid) | |
492 char *file; | |
493 short gid; | |
494 { | |
495 int child_id; | |
496 char group[BUFSIZ]; | |
497 | |
498 switch (child_id = fork ()) { | |
499 case NOTOK: | |
500 admonish ("fork", "unable to"); | |
501 return; | |
502 | |
503 case OK: | |
504 (void) setuid (geteuid ());/* make sure chgrp works */ | |
505 (void) sprintf (group, "%d", gid); | |
506 if (verbosw) | |
507 fprintf (stderr, "chgrp %s %s\n", group, file); | |
508 | |
509 execlp ("/bin/chgrp", "chgrp", group, file, NULLCP); | |
510 execlp ("/usr/bin/chgrp", "chgrp", group, file, NULLCP); | |
511 fprintf (stderr, "unable to exec "); | |
512 perror ("chgrp"); | |
513 _exit (-1); | |
514 | |
515 default: | |
516 (void) pidXwait (child_id, "chgrp"); | |
517 break; | |
518 } | |
519 } | |
520 | |
521 /* */ | |
522 | |
523 rmf (folder) | |
524 char *folder; | |
525 { | |
526 int child_id; | |
527 | |
528 switch (child_id = fork ()) { | |
529 case NOTOK: | |
530 admonish ("fork", "unable to"); | |
531 return; | |
532 | |
533 case OK: | |
534 (void) setgid (getgid ()); | |
535 (void) setuid (getuid ()); | |
536 if (verbosw) | |
537 fprintf (stderr, "rmf %s\n", folder); | |
538 | |
539 execlp (rmfproc, r1bindex (rmfproc, '/'), folder, NULLCP); | |
540 fprintf (stderr, "unable to exec "); | |
541 perror (rmfproc); | |
542 _exit (-1); | |
543 | |
544 default: | |
545 (void) pidXwait (child_id, rmfproc); | |
546 break; | |
547 } | |
548 } | |
549 | |
550 /* */ | |
551 | |
552 do_child () { | |
553 char buffer[BUFSIZ]; | |
554 | |
555 (void) setgid (getgid ()); /* become the user, not bboards */ | |
556 (void) setuid (getuid ()); | |
557 | |
558 inc (bb -> bb_file, bbfolder); | |
559 if (sub_ok) | |
560 inc (bb -> bb_archive, subfolder); | |
561 /* else | |
562 create the folder */ | |
563 | |
564 if (verbosw) | |
565 (void) putchar ('\n'); | |
566 printf ("[ Working folder is %s, Archive folder is %s ]\n", | |
567 bbfolder, subfolder); | |
568 printf ("[ Type CTRL-D to finish ]\n"); | |
569 | |
570 m_replace (pfolder, bbfolder + 1); | |
571 m_update (); | |
572 | |
573 (void) sprintf (buffer, "=> %s: %s", invo_name, bb -> bb_name); | |
574 execlp (shell, buffer, NULLCP); | |
575 fprintf (stderr, "unable to exec "); | |
576 perror (shell); | |
577 _exit (-1); | |
578 } | |
579 | |
580 /* */ | |
581 | |
582 inc (file, folder) | |
583 char *file, | |
584 *folder; | |
585 { | |
586 int child_id; | |
587 | |
588 switch (child_id = fork ()) { | |
589 case NOTOK: | |
590 adios ("fork", "unable to"); | |
591 | |
592 case OK: | |
593 if (verbosw) | |
594 fprintf (stderr, "inc %s -file %s -silent\n", folder, file); | |
595 execlp (incproc, r1bindex (incproc, '/'), | |
596 folder, "-file", file, "-silent", NULLCP); | |
597 fprintf (stderr, "unable to exec "); | |
598 perror (incproc); | |
599 _exit (-1); | |
600 | |
601 default: | |
602 if (pidXwait (child_id, incproc)) | |
603 done (1); | |
604 break; | |
605 } | |
606 } |