1 /* 2 * $Id: amq.c,v 5.2 90/06/23 22:20:07 jsp Rel $ 3 * 4 * Copyright (c) 1990 Jan-Simon Pendry 5 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 6 * Copyright (c) 1990 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Jan-Simon Pendry at Imperial College, London. 11 * 12 * %sccs.include.redist.c% 13 */ 14 15 /* 16 * Automounter query tool 17 */ 18 19 #ifndef lint 20 char copyright[] = "\ 21 @(#)Copyright (c) 1990 Jan-Simon Pendry\n\ 22 @(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\ 23 @(#)Copyright (c) 1990 The Regents of the University of California.\n\ 24 @(#)All rights reserved.\n"; 25 #endif /* not lint */ 26 27 #ifndef lint 28 static char rcsid[] = "$Id: amq.c,v 5.2 90/06/23 22:20:07 jsp Rel $"; 29 static char sccsid[] = "@(#)amq.c 5.1 (Berkeley) 06/29/90"; 30 #endif /* not lint */ 31 32 #include "am.h" 33 #include "amq.h" 34 #include <stdio.h> 35 #include <fcntl.h> 36 #include <netdb.h> 37 38 char *progname; 39 static int flush_flag; 40 static int minfo_flag; 41 static int unmount_flag; 42 static int stats_flag; 43 static char *debug_opts; 44 static char *logfile; 45 static char *xlog_opt; 46 static char localhost[] = "localhost"; 47 static char *def_server = localhost; 48 49 extern int optind; 50 extern char *optarg; 51 52 static struct timeval tmo = { 10, 0 }; 53 #define TIMEOUT tmo 54 55 enum show_opt { Full, Stats, Calc, Short, ShowDone }; 56 57 /* 58 * If (e) is Calc then just calculate the sizes 59 * Otherwise display the mount node on stdout 60 */ 61 static void show_mti(mt, e, mwid, dwid, twid) 62 amq_mount_tree *mt; 63 enum show_opt e; 64 int *mwid; 65 int *dwid; 66 int *twid; 67 { 68 switch (e) { 69 case Calc: { 70 int mw = strlen(mt->mt_mountinfo); 71 int dw = strlen(mt->mt_directory); 72 int tw = strlen(mt->mt_type); 73 if (mw > *mwid) *mwid = mw; 74 if (dw > *dwid) *dwid = dw; 75 if (tw > *twid) *twid = tw; 76 } break; 77 78 case Full: { 79 struct tm *tp = localtime(&mt->mt_mounttime); 80 printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n", 81 *dwid, *dwid, 82 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 83 *twid, *twid, 84 mt->mt_type, 85 *mwid, *mwid, 86 mt->mt_mountinfo, 87 mt->mt_mountpoint, 88 89 mt->mt_mountuid, 90 mt->mt_getattr, 91 mt->mt_lookup, 92 mt->mt_readdir, 93 mt->mt_readlink, 94 mt->mt_statfs, 95 96 tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year, 97 tp->tm_mon+1, tp->tm_mday, 98 tp->tm_hour, tp->tm_min, tp->tm_sec); 99 } break; 100 101 case Stats: { 102 struct tm *tp = localtime(&mt->mt_mounttime); 103 printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n", 104 *dwid, *dwid, 105 *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 106 107 mt->mt_mountuid, 108 mt->mt_getattr, 109 mt->mt_lookup, 110 mt->mt_readdir, 111 mt->mt_readlink, 112 mt->mt_statfs, 113 114 tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year, 115 tp->tm_mon+1, tp->tm_mday, 116 tp->tm_hour, tp->tm_min, tp->tm_sec); 117 } break; 118 119 case Short: { 120 printf("%-*.*s %-*.*s %-*.*s %s\n", 121 *dwid, *dwid, 122 *mt->mt_directory ? mt->mt_directory : "/", 123 *twid, *twid, 124 mt->mt_type, 125 *mwid, *mwid, 126 mt->mt_mountinfo, 127 mt->mt_mountpoint); 128 } break; 129 } 130 } 131 132 /* 133 * Display a mount tree. 134 */ 135 static void show_mt(mt, e, mwid, dwid, pwid) 136 amq_mount_tree *mt; 137 enum show_opt e; 138 int *mwid; 139 int *dwid; 140 int *pwid; 141 { 142 while (mt) { 143 show_mti(mt, e, mwid, dwid, pwid); 144 show_mt(mt->mt_next, e, mwid, dwid, pwid); 145 mt = mt->mt_child; 146 } 147 } 148 149 static void show_mi(ml, e, mwid, dwid, twid) 150 amq_mount_info_list *ml; 151 enum show_opt e; 152 int *mwid; 153 int *dwid; 154 int *twid; 155 { 156 int i; 157 switch (e) { 158 case Calc: { 159 for (i = 0; i < ml->amq_mount_info_list_len; i++) { 160 amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 161 int mw = strlen(mi->mi_mountinfo); 162 int dw = strlen(mi->mi_mountpt); 163 int tw = strlen(mi->mi_type); 164 if (mw > *mwid) *mwid = mw; 165 if (dw > *dwid) *dwid = dw; 166 if (tw > *twid) *twid = tw; 167 } 168 } break; 169 170 case Full: { 171 for (i = 0; i < ml->amq_mount_info_list_len; i++) { 172 amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 173 printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s", 174 *mwid, *mwid, mi->mi_mountinfo, 175 *dwid, *dwid, mi->mi_mountpt, 176 *twid, *twid, mi->mi_type, 177 mi->mi_refc, mi->mi_fserver, 178 mi->mi_up > 0 ? "up" : 179 mi->mi_up < 0 ? "starting" : "down"); 180 if (mi->mi_error > 0) { 181 extern char *sys_errlist[]; 182 extern int sys_nerr; 183 if (mi->mi_error < sys_nerr) 184 printf(" (%s)", sys_errlist[mi->mi_error]); 185 else 186 printf(" (Error %d)", mi->mi_error); 187 } else if (mi->mi_error < 0) { 188 fputs(" (in progress)", stdout); 189 } 190 fputc('\n', stdout); 191 } 192 } break; 193 } 194 } 195 196 /* 197 * Display general mount statistics 198 */ 199 static void show_ms(ms) 200 amq_mount_stats *ms; 201 { 202 printf("\ 203 requests stale mount mount unmount\n\ 204 deferred fhandles ok failed failed\n\ 205 %-9d %-9d %-9d %-9d %-9d\n", 206 ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr); 207 } 208 209 static bool_t 210 xdr_pri_free(xdr_args, args_ptr) 211 xdrproc_t xdr_args; 212 caddr_t args_ptr; 213 { 214 XDR xdr; 215 xdr.x_op = XDR_FREE; 216 return ((*xdr_args)(&xdr, args_ptr)); 217 } 218 219 #ifdef hpux 220 #include <cluster.h> 221 static char *cluster_server() 222 { 223 struct cct_entry *cp; 224 225 if (cnodeid() == 0) { 226 /* 227 * Not clustered 228 */ 229 return def_server; 230 } 231 232 while (cp = getccent()) 233 if (cp->cnode_type == 'r') 234 return cp->cnode_name; 235 236 237 return def_server; 238 } 239 #endif /* hpux */ 240 241 /* 242 * MAIN 243 */ 244 main(argc, argv) 245 int argc; 246 char *argv[]; 247 { 248 int opt_ch; 249 int errs = 0; 250 char *server; 251 struct sockaddr_in server_addr; 252 int s = RPC_ANYSOCK; 253 CLIENT *clnt; 254 struct hostent *hp; 255 int nodefault = 0; 256 257 /* 258 * Compute program name 259 */ 260 if (argv[0]) { 261 progname = strrchr(argv[0], '/'); 262 if (progname && progname[1]) 263 progname++; 264 else 265 progname = argv[0]; 266 } 267 if (!progname) 268 progname = "amq"; 269 270 /* 271 * Parse arguments 272 */ 273 while ((opt_ch = getopt(argc, argv, "fh:l:msux:D:")) != EOF) 274 switch (opt_ch) { 275 case 'f': 276 flush_flag = 1; 277 break; 278 279 case 'h': 280 def_server = optarg; 281 break; 282 283 case 'l': 284 logfile = optarg; 285 nodefault = 1; 286 break; 287 288 case 'm': 289 minfo_flag = 1; 290 nodefault = 1; 291 break; 292 293 case 's': 294 stats_flag = 1; 295 break; 296 297 case 'u': 298 unmount_flag = 1; 299 break; 300 301 case 'x': 302 xlog_opt = optarg; 303 nodefault = 1; 304 break; 305 306 case 'D': 307 debug_opts = optarg; 308 nodefault = 1; 309 break; 310 311 default: 312 errs = 1; 313 break; 314 } 315 316 if (errs) { 317 show_usage: 318 fprintf(stderr, "\ 319 Usage: %s [-h host] [[-f] [-m] | | [-s] | [[-u] directory ...]] |\n\ 320 \t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts]\n", progname); 321 exit(1); 322 } 323 324 #ifdef hpux 325 /* 326 * Figure out root server of cluster 327 */ 328 if (def_server == localhost) 329 server = cluster_server(); 330 else 331 #endif /* hpux */ 332 server = def_server; 333 334 /* 335 * Get address of server 336 */ 337 if ((hp = gethostbyname(server)) == 0) { 338 fprintf(stderr, "%s: Can't get address of %s\n", progname, server); 339 exit(1); 340 } 341 bzero(&server_addr, sizeof server_addr); 342 server_addr.sin_family = AF_INET; 343 server_addr.sin_addr = *(struct in_addr *) hp->h_addr; 344 345 /* 346 * Create RPC endpoint 347 */ 348 clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, TIMEOUT, &s); 349 if (clnt == 0) { 350 fprintf(stderr, "%s: ", progname); 351 clnt_pcreateerror(server); 352 exit(1); 353 } 354 355 /* 356 * Control debugging 357 */ 358 if (debug_opts) { 359 int *rc; 360 amq_setopt opt; 361 opt.as_opt = AMOPT_DEBUG; 362 opt.as_str = debug_opts; 363 rc = amqproc_setopt_1(&opt, clnt); 364 if (rc && *rc < 0) { 365 fprintf(stderr, "%s: daemon not compiled for debug", progname); 366 errs = 1; 367 } else if (!rc || *rc > 0) { 368 fprintf(stderr, "%s: debug setting for \"%s\" failed\n", progname, debug_opts); 369 errs = 1; 370 } 371 } 372 373 /* 374 * Control logging 375 */ 376 if (xlog_opt) { 377 int *rc; 378 amq_setopt opt; 379 opt.as_opt = AMOPT_XLOG; 380 opt.as_str = xlog_opt; 381 rc = amqproc_setopt_1(&opt, clnt); 382 if (!rc || *rc) { 383 fprintf(stderr, "%s: setting log level to \"%s\" failed\n", progname, xlog_opt); 384 errs = 1; 385 } 386 } 387 388 /* 389 * Control log file 390 */ 391 if (logfile) { 392 int *rc; 393 amq_setopt opt; 394 opt.as_opt = AMOPT_LOGFILE; 395 opt.as_str = logfile; 396 rc = amqproc_setopt_1(&opt, clnt); 397 if (!rc || *rc) { 398 fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", progname, logfile); 399 errs = 1; 400 } 401 } 402 403 /* 404 * Flush map cache 405 */ 406 if (logfile) { 407 int *rc; 408 amq_setopt opt; 409 opt.as_opt = AMOPT_FLUSHMAPC; 410 opt.as_str = ""; 411 rc = amqproc_setopt_1(&opt, clnt); 412 if (!rc || *rc) { 413 fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", progname, server); 414 errs = 1; 415 } 416 } 417 418 /* 419 * Mount info 420 */ 421 if (minfo_flag) { 422 int dummy; 423 amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt); 424 if (ml) { 425 int mwid = 0, dwid = 0, twid = 0; 426 show_mi(ml, Calc, &mwid, &dwid, &twid); 427 mwid++; dwid++; twid++; 428 show_mi(ml, Full, &mwid, &dwid, &twid); 429 430 } else { 431 fprintf(stderr, "%s: amd on %s cannot provide mount info\n", progname, server); 432 } 433 } 434 435 /* 436 * Apply required operation to all remaining arguments 437 */ 438 if (optind < argc) { 439 do { 440 char *fs = argv[optind++]; 441 if (unmount_flag) { 442 /* 443 * Unmount request 444 */ 445 amqproc_umnt_1(&fs, clnt); 446 } else { 447 /* 448 * Stats request 449 */ 450 amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt); 451 if (mtp) { 452 amq_mount_tree *mt = *mtp; 453 if (mt) { 454 int mwid = 0, dwid = 0, twid = 0; 455 show_mt(mt, Calc, &mwid, &dwid, &twid); 456 mwid++; dwid++, twid++; 457 #ifdef notdef 458 printf("\t%s\n%-*.*s %-*.*s %-*.*s %s\n", 459 "Uid Getattr Lookup RdDir RdLnk Statfs Mounted@", 460 dwid, dwid, "What", twid, twid, "Type", mwid, mwid, "Info", "Where"); 461 show_mt(mt, Full, &mwid, &dwid, &twid); 462 #endif /* notdef */ 463 printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n", 464 dwid, dwid, "What"); 465 show_mt(mt, Stats, &mwid, &dwid, &twid); 466 } else { 467 fprintf(stderr, "%s: %s not automounted\n", progname, fs); 468 } 469 xdr_pri_free(xdr_amq_mount_tree_p, (caddr_t) mtp); 470 } else { 471 fprintf(stderr, "%s: ", progname); 472 clnt_perror(clnt, server); 473 errs = 1; 474 } 475 } 476 } while (optind < argc); 477 } else if (unmount_flag) { 478 goto show_usage; 479 } else if (stats_flag) { 480 amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt); 481 if (ms) { 482 show_ms(ms); 483 } else { 484 fprintf(stderr, "%s: ", progname); 485 clnt_perror(clnt, server); 486 errs = 1; 487 } 488 } else if (!nodefault) { 489 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt); 490 if (mlp) { 491 enum show_opt e = Calc; 492 int mwid = 0, dwid = 0, pwid = 0; 493 while (e != ShowDone) { 494 int i; 495 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) { 496 show_mt(mlp->amq_mount_tree_list_val[i], 497 e, &mwid, &dwid, &pwid); 498 } 499 mwid++; dwid++, pwid++; 500 if (e == Calc) e = Short; 501 else if (e == Short) e = ShowDone; 502 } 503 } else { 504 fprintf(stderr, "%s: ", progname); 505 clnt_perror(clnt, server); 506 errs = 1; 507 } 508 } 509 510 exit(errs); 511 } 512 513 #ifdef DEBUG 514 xfree(f, l, p) 515 char *f, *l; 516 voidp p; 517 { 518 free(p); 519 } 520 #endif /* DEBUG */ 521