fsi_util.c revision 119679
1/* 2 * Copyright (c) 1997-2003 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.5 2003/07/18 04:50:19 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 173fsi_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 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 fsi_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