fsi_util.c revision 82794
1/*
2 * Copyright (c) 1997-2001 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.3.2.2 2001/01/10 03:23:33 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 */
50static int show_range = 10;
51static int col = 0;
52static int total_shown = 0;
53static int total_mmm = 8;
54
55
56static int
57col_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
71static void
72show_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
91void
92col_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 */
110void
111error(char *fmt, ...)
112{
113  va_list ap;
114
115  va_start(ap, fmt);
116  col_cleanup(0);
117  fprintf(stderr, "%s: Error, ", progname);
118  vfprintf(stderr, fmt, ap);
119  fputc('\n', stderr);
120  errors++;
121  va_end(ap);
122}
123
124
125void
126lerror(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  vfprintf(stderr, fmt, ap);
134  fputc('\n', stderr);
135  errors++;
136  va_end(ap);
137}
138
139
140void
141lwarning(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  vfprintf(stderr, fmt, ap);
149  fputc('\n', stderr);
150  va_end(ap);
151}
152
153
154void
155fatal(char *fmt, ...)
156{
157  va_list ap;
158
159  va_start(ap, fmt);
160  col_cleanup(1);
161  fprintf(stderr, "%s: Fatal, ", progname);
162  vfprintf(stderr, fmt, ap);
163  fputc('\n', stderr);
164  va_end(ap);
165  exit(1);
166}
167
168
169/*
170 * Debug log
171 */
172void
173log(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    vfprintf(stdout, fmt, ap);
182    putc('\n', stdout);
183    va_end(ap);
184  }
185}
186
187
188void
189info_hdr(FILE *ef, char *info)
190{
191  fprintf(ef, "# *** NOTE: This file contains %s info\n", info);
192}
193
194
195void
196gen_hdr(FILE *ef, char *hn)
197{
198  fprintf(ef, "# *** NOTE: Only for use on %s\n", hn);
199}
200
201
202static void
203make_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
218void
219show_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
236void
237show_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 */
273FILE *
274pref_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
293int
294pref_close(FILE *fp)
295{
296  return fclose(fp) == 0;
297}
298
299
300/*
301 * Determine where Amd would automount the host/volname pair
302 */
303void
304compute_automount_point(char *buf, host *hp, char *vn)
305{
306  sprintf(buf, "%s/%s%s", autodir, hp->h_lochost, vn);
307}
308
309
310char *
311xcalloc(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 */
324automount *
325new_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
339auto_tree *
340new_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
352host *
353new_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
364void
365set_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
439ether_if *
440new_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
451void
452set_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
494void
495set_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
544disk_fs *
545new_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
555void
556set_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
588fsi_mount *
589new_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
599void
600set_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
642fsmount *
643new_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
653void
654init_que(qelem *q)
655{
656  q->q_forw = q->q_back = q;
657}
658
659
660qelem *
661new_que(void)
662{
663  qelem *q = CALLOC(qelem);
664
665  init_que(q);
666  return q;
667}
668
669
670void
671ins_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
683void
684rem_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}
694