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