xref: /netbsd-src/external/bsd/am-utils/dist/fsinfo/fsi_util.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /*	$NetBSD: fsi_util.c,v 1.1.1.2 2009/03/20 20:26:55 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1997-2009 Erez Zadok
5  * Copyright (c) 1989 Jan-Simon Pendry
6  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
7  * Copyright (c) 1989 The Regents of the University of California.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgment:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *
39  * File: am-utils/fsinfo/fsi_util.c
40  *
41  */
42 
43 #ifdef HAVE_CONFIG_H
44 # include <config.h>
45 #endif /* HAVE_CONFIG_H */
46 #include <am_defs.h>
47 #include <fsi_data.h>
48 #include <fsinfo.h>
49 
50 /* static variables */
51 static int show_range = 10;
52 static int col = 0;
53 static int total_shown = 0;
54 static int total_mmm = 8;
55 
56 
57 static int
58 col_output(int len)
59 {
60   int wrapped = 0;
61 
62   col += len;
63   if (col > 77) {
64     fputc('\n', stdout);
65     col = len;
66     wrapped = 1;
67   }
68   return wrapped;
69 }
70 
71 
72 static void
73 show_total(void)
74 {
75   if (total_mmm != -show_range + 1) {
76     char n[8];
77     int len;
78 
79     if (total_mmm < 0)
80       fputc('*', stdout);
81     xsnprintf(n, sizeof(n), "%d", total_shown);
82     len = strlen(n);
83     if (col_output(len))
84       fputc(' ', stdout);
85     fputs(n, stdout);
86     fflush(stdout);
87     total_mmm = -show_range;
88   }
89 }
90 
91 
92 void
93 col_cleanup(int eoj)
94 {
95   if (verbose < 0)
96     return;
97   if (eoj) {
98     show_total();
99     fputs(")]", stdout);
100   }
101   if (col) {
102     fputc('\n', stdout);
103     col = 0;
104   }
105 }
106 
107 
108 /*
109  * Lots of ways of reporting errors...
110  */
111 void
112 error(char *fmt, ...)
113 {
114   va_list ap;
115 
116   va_start(ap, fmt);
117   col_cleanup(0);
118   fprintf(stderr, "%s: Error, ", progname);
119   vfprintf(stderr, fmt, ap);
120   fputc('\n', stderr);
121   errors++;
122   va_end(ap);
123 }
124 
125 
126 void
127 lerror(ioloc *l, char *fmt, ...)
128 {
129   va_list ap;
130 
131   va_start(ap, fmt);
132   col_cleanup(0);
133   fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
134   vfprintf(stderr, fmt, ap);
135   fputc('\n', stderr);
136   errors++;
137   va_end(ap);
138 }
139 
140 
141 void
142 lwarning(ioloc *l, char *fmt, ...)
143 {
144   va_list ap;
145 
146   va_start(ap, fmt);
147   col_cleanup(0);
148   fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
149   vfprintf(stderr, fmt, ap);
150   fputc('\n', stderr);
151   va_end(ap);
152 }
153 
154 
155 void
156 fatal(char *fmt, ...)
157 {
158   va_list ap;
159 
160   va_start(ap, fmt);
161   col_cleanup(1);
162   fprintf(stderr, "%s: Fatal, ", progname);
163   vfprintf(stderr, fmt, ap);
164   fputc('\n', stderr);
165   va_end(ap);
166   exit(1);
167 }
168 
169 
170 /*
171  * Debug log
172  */
173 void
174 fsi_log(char *fmt, ...)
175 {
176   va_list ap;
177 
178   if (verbose > 0) {
179     va_start(ap, fmt);
180     fputc('#', stdout);
181     fprintf(stdout, "%s: ", progname);
182     vfprintf(stdout, fmt, ap);
183     putc('\n', stdout);
184     va_end(ap);
185   }
186 }
187 
188 
189 void
190 info_hdr(FILE *ef, char *info)
191 {
192   fprintf(ef, "# *** NOTE: This file contains %s info\n", info);
193 }
194 
195 
196 void
197 gen_hdr(FILE *ef, char *hn)
198 {
199   fprintf(ef, "# *** NOTE: Only for use on %s\n", hn);
200 }
201 
202 
203 static void
204 make_banner(FILE *fp)
205 {
206   time_t t = time((time_t *) NULL);
207   char *cp = ctime(&t);
208 
209   fprintf(fp,
210 	  "\
211 # *** This file was automatically generated -- DO NOT EDIT HERE ***\n\
212 # \"%s\" run by %s@%s on %s\
213 #\n\
214 ",
215 	  progname, username, hostname, cp);
216 }
217 
218 
219 void
220 show_new(char *msg)
221 {
222   if (verbose < 0)
223     return;
224 
225   total_shown++;
226   if (total_mmm > show_range) {
227     show_total();
228   } else if (total_mmm == 0) {
229     fputc('*', stdout);
230     fflush(stdout);
231     col += 1;
232   }
233   total_mmm++;
234 }
235 
236 
237 void
238 show_area_being_processed(char *area, int n)
239 {
240   static char *last_area = NULL;
241 
242   if (verbose < 0)
243     return;
244   if (last_area) {
245     if (total_shown)
246       show_total();
247     fputs(")", stdout);
248     col += 1;
249   }
250 
251   if (!last_area || !STREQ(area, last_area)) {
252     if (last_area) {
253       col_cleanup(0);
254       total_shown = 0;
255       total_mmm = show_range + 1;
256     }
257     (void) col_output(strlen(area) + 2);
258     fprintf(stdout, "[%s", area);
259     last_area = area;
260   }
261 
262   fputs(" (", stdout);
263   col += 2;
264   show_range = n;
265   total_mmm = n + 1;
266 
267   fflush(stdout);
268 }
269 
270 
271 /*
272  * Open a file with the given prefix and name
273  */
274 FILE *
275 pref_open(char *pref, char *hn, void (*hdr) (FILE *, char *), char *arg)
276 {
277   char p[MAXPATHLEN];
278   FILE *ef;
279 
280   xsnprintf(p, sizeof(p), "%s%s", pref, hn);
281   fsi_log("Writing %s info for %s to %s", pref, hn, p);
282   ef = fopen(p, "w");
283   if (ef) {
284     (*hdr) (ef, arg);
285     make_banner(ef);
286   } else {
287     error("can't open %s for writing", p);
288   }
289 
290   return ef;
291 }
292 
293 
294 int
295 pref_close(FILE *fp)
296 {
297   return fclose(fp) == 0;
298 }
299 
300 
301 /*
302  * Determine where Amd would automount the host/volname pair
303  */
304 void
305 compute_automount_point(char *buf, size_t l, host *hp, char *vn)
306 {
307   xsnprintf(buf, l, "%s/%s%s", autodir, hp->h_lochost, vn);
308 }
309 
310 
311 /*
312  * Data constructors..
313  */
314 automount *
315 new_automount(char *name)
316 {
317   automount *ap = CALLOC(struct automount);
318 
319   ap->a_ioloc = current_location();
320   ap->a_name = name;
321   ap->a_volname = NULL;
322   ap->a_mount = NULL;
323   ap->a_opts = NULL;
324   show_new("automount");
325   return ap;
326 }
327 
328 
329 auto_tree *
330 new_auto_tree(char *def, qelem *ap)
331 {
332   auto_tree *tp = CALLOC(struct auto_tree);
333 
334   tp->t_ioloc = current_location();
335   tp->t_defaults = def;
336   tp->t_mount = ap;
337   show_new("auto_tree");
338   return tp;
339 }
340 
341 
342 host *
343 new_host(void)
344 {
345   host *hp = CALLOC(struct host);
346 
347   hp->h_ioloc = current_location();
348   hp->h_mask = 0;
349   show_new("host");
350   return hp;
351 }
352 
353 
354 void
355 set_host(host *hp, int k, char *v)
356 {
357   int m = 1 << k;
358 
359   if (hp->h_mask & m) {
360     fsi_yyerror("host field \"%s\" already set", host_strings[k]);
361     return;
362   }
363   hp->h_mask |= m;
364 
365   switch (k) {
366 
367   case HF_HOST:{
368       char *p = strdup(v);
369       dict_ent *de = dict_locate(dict_of_hosts, v);
370 
371       if (de)
372 	fsi_yyerror("duplicate host %s!", v);
373       else
374 	dict_add(dict_of_hosts, v, (char *) hp);
375       hp->h_hostname = v;
376       domain_strip(p, hostname);
377       if (strchr(p, '.') != 0)
378 	XFREE(p);
379       else
380 	hp->h_lochost = p;
381     }
382     break;
383 
384   case HF_CONFIG:{
385       qelem *q;
386       qelem *vq = (qelem *) v;
387 
388       hp->h_mask &= ~m;
389       if (hp->h_config)
390 	q = hp->h_config;
391       else
392 	q = hp->h_config = new_que();
393       ins_que(vq, q->q_back);
394     }
395     break;
396 
397   case HF_ETHER:{
398       qelem *q;
399       qelem *vq = (qelem *) v;
400 
401       hp->h_mask &= ~m;
402       if (hp->h_ether)
403 	q = hp->h_ether;
404       else
405 	q = hp->h_ether = new_que();
406       ins_que(vq, q->q_back);
407     }
408     break;
409 
410   case HF_ARCH:
411     hp->h_arch = v;
412     break;
413 
414   case HF_OS:
415     hp->h_os = v;
416     break;
417 
418   case HF_CLUSTER:
419     hp->h_cluster = v;
420     break;
421 
422   default:
423     abort();
424     break;
425   }
426 }
427 
428 
429 ether_if *
430 new_ether_if(void)
431 {
432   ether_if *ep = CALLOC(struct ether_if);
433 
434   ep->e_mask = 0;
435   ep->e_ioloc = current_location();
436   show_new("ether_if");
437   return ep;
438 }
439 
440 
441 void
442 set_ether_if(ether_if *ep, int k, char *v)
443 {
444   int m = 1 << k;
445 
446   if (ep->e_mask & m) {
447     fsi_yyerror("netif field \"%s\" already set", ether_if_strings[k]);
448     return;
449   }
450   ep->e_mask |= m;
451 
452   switch (k) {
453 
454   case EF_INADDR:{
455       ep->e_inaddr.s_addr = inet_addr(v);
456       if ((int) ep->e_inaddr.s_addr == (int) INADDR_NONE)
457 	fsi_yyerror("malformed IP dotted quad: %s", v);
458       XFREE(v);
459     }
460     break;
461 
462   case EF_NETMASK:{
463       u_long nm = 0;
464 
465       if ((sscanf(v, "0x%lx", &nm) == 1 || sscanf(v, "%lx", &nm) == 1) && nm != 0)
466 	ep->e_netmask = htonl(nm);
467       else
468 	fsi_yyerror("malformed netmask: %s", v);
469       XFREE(v);
470     }
471     break;
472 
473   case EF_HWADDR:
474     ep->e_hwaddr = v;
475     break;
476 
477   default:
478     abort();
479     break;
480   }
481 }
482 
483 
484 void
485 set_disk_fs(disk_fs *dp, int k, char *v)
486 {
487   int m = 1 << k;
488 
489   if (dp->d_mask & m) {
490     fsi_yyerror("fs field \"%s\" already set", disk_fs_strings[k]);
491     return;
492   }
493   dp->d_mask |= m;
494 
495   switch (k) {
496 
497   case DF_FSTYPE:
498     dp->d_fstype = v;
499     break;
500 
501   case DF_OPTS:
502     dp->d_opts = v;
503     break;
504 
505   case DF_DUMPSET:
506     dp->d_dumpset = v;
507     break;
508 
509   case DF_LOG:
510     dp->d_log = v;
511     break;
512 
513   case DF_PASSNO:
514     dp->d_passno = atoi(v);
515     XFREE(v);
516     break;
517 
518   case DF_FREQ:
519     dp->d_freq = atoi(v);
520     XFREE(v);
521     break;
522 
523   case DF_MOUNT:
524     dp->d_mount = &((fsi_mount *) v)->m_q;
525     break;
526 
527   default:
528     abort();
529     break;
530   }
531 }
532 
533 
534 disk_fs *
535 new_disk_fs(void)
536 {
537   disk_fs *dp = CALLOC(struct disk_fs);
538 
539   dp->d_ioloc = current_location();
540   show_new("disk_fs");
541   return dp;
542 }
543 
544 
545 void
546 set_mount(fsi_mount *mp, int k, char *v)
547 {
548   int m = 1 << k;
549 
550   if (mp->m_mask & m) {
551     fsi_yyerror("mount tree field \"%s\" already set", mount_strings[k]);
552     return;
553   }
554   mp->m_mask |= m;
555 
556   switch (k) {
557 
558   case DM_VOLNAME:
559     dict_add(dict_of_volnames, v, (char *) mp);
560     mp->m_volname = v;
561     break;
562 
563   case DM_EXPORTFS:
564     mp->m_exportfs = v;
565     break;
566 
567   case DM_SEL:
568     mp->m_sel = v;
569     break;
570 
571   default:
572     abort();
573     break;
574   }
575 }
576 
577 
578 fsi_mount *
579 new_mount(void)
580 {
581   fsi_mount *fp = CALLOC(struct fsi_mount);
582 
583   fp->m_ioloc = current_location();
584   show_new("mount");
585   return fp;
586 }
587 
588 
589 void
590 set_fsmount(fsmount *fp, int k, char *v)
591 {
592   int m = 1 << k;
593 
594   if (fp->f_mask & m) {
595     fsi_yyerror("mount field \"%s\" already set", fsmount_strings[k]);
596     return;
597   }
598   fp->f_mask |= m;
599 
600   switch (k) {
601 
602   case FM_LOCALNAME:
603     fp->f_localname = v;
604     break;
605 
606   case FM_VOLNAME:
607     fp->f_volname = v;
608     break;
609 
610   case FM_FSTYPE:
611     fp->f_fstype = v;
612     break;
613 
614   case FM_OPTS:
615     fp->f_opts = v;
616     break;
617 
618   case FM_FROM:
619     fp->f_from = v;
620     break;
621 
622   case FM_DIRECT:
623     break;
624 
625   default:
626     abort();
627     break;
628   }
629 }
630 
631 
632 fsmount *
633 new_fsmount(void)
634 {
635   fsmount *fp = CALLOC(struct fsmount);
636 
637   fp->f_ioloc = current_location();
638   show_new("fsmount");
639   return fp;
640 }
641 
642 
643 void
644 init_que(qelem *q)
645 {
646   q->q_forw = q->q_back = q;
647 }
648 
649 
650 qelem *
651 new_que(void)
652 {
653   qelem *q = CALLOC(qelem);
654 
655   init_que(q);
656   return q;
657 }
658 
659 
660 void
661 ins_que(qelem *elem, qelem *pred)
662 {
663   qelem *p;
664 
665   p = pred->q_forw;
666   elem->q_back = pred;
667   elem->q_forw = p;
668   pred->q_forw = elem;
669   p->q_back = elem;
670 }
671 
672 
673 void
674 rem_que(qelem *elem)
675 {
676   qelem *p, *p2;
677 
678   p = elem->q_forw;
679   p2 = elem->q_back;
680 
681   p2->q_forw = p;
682   p->q_back = p2;
683 }
684