Commit | Line | Data |
---|---|---|
e1a31032 KM |
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) %G%"; | |
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 */ |