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