xref: /original-bsd/usr.sbin/amd/amq/amq.c (revision 92ab646d)
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