0
|
1 /* bbl.c - ease the tasks of a BBleader */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: bbl.c,v 1.1.1.1 2005/04/18 14:46:07 kono Exp $";
|
0
|
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 }
|