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