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 }