date and time created 91/03/17 13:41:25 by pendry
[unix-history] / usr / src / usr.sbin / amd / amq / amq.c
CommitLineData
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
20char 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
28static char rcsid[] = "$Id: amq.c,v 5.2 90/06/23 22:20:07 jsp Rel $";
29static 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
38char *progname;
39static int flush_flag;
40static int minfo_flag;
41static int unmount_flag;
42static int stats_flag;
43static char *debug_opts;
44static char *logfile;
45static char *xlog_opt;
46static char localhost[] = "localhost";
47static char *def_server = localhost;
48
49extern int optind;
50extern char *optarg;
51
52static struct timeval tmo = { 10, 0 };
53#define TIMEOUT tmo
54
55enum 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 */
61static void show_mti(mt, e, mwid, dwid, twid)
62amq_mount_tree *mt;
63enum show_opt e;
64int *mwid;
65int *dwid;
66int *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);
80printf("%-*.*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);
103printf("%-*.*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 */
135static void show_mt(mt, e, mwid, dwid, pwid)
136amq_mount_tree *mt;
137enum show_opt e;
138int *mwid;
139int *dwid;
140int *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
149static void show_mi(ml, e, mwid, dwid, twid)
150amq_mount_info_list *ml;
151enum show_opt e;
152int *mwid;
153int *dwid;
154int *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 */
199static void show_ms(ms)
200amq_mount_stats *ms;
201{
202 printf("\
203requests stale mount mount unmount\n\
204deferred 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
209static bool_t
210xdr_pri_free(xdr_args, args_ptr)
211xdrproc_t xdr_args;
212caddr_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>
221static 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 */
244main(argc, argv)
245int argc;
246char *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) {
317show_usage:
318 fprintf(stderr, "\
319Usage: %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
514xfree(f, l, p)
515char *f, *l;
516voidp p;
517{
518 free(p);
519}
520#endif /* DEBUG */