5eefe0aaafa899d6ee17d45a1fc2e7a9379d8456
[openafs.git] / src / libadmin / test / client.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * This file implements the client related funtions for afscp
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 #include <roken.h>
18
19 #include "client.h"
20 #include <afs/cellconfig.h>
21 #include <afs/bosint.h>
22 #include <rx/rxstat.h>
23 #include <afs/afsint.h>
24 #define FSINT_COMMON_XG
25 #include <afs/afscbint.h>
26 #include <afs/kauth.h>
27 #include <afs/kautils.h>
28 #include <afs/ptint.h>
29 #include <afs/ptserver.h>
30 #include <afs/vldbint.h>
31 #include <afs/volint.h>
32 #include <afs/volser.h>
33 #include <ubik.h>
34 #include <ubik_int.h>
35 #ifdef AFS_NT40_ENV
36 #include <pthread.h>
37 #endif
38
39 /*
40  * This structure stores the client and server function lists.
41  * This is kept separate from the actual interface definitions
42  * since an rpc interface can be offered by several servers
43  * (e.g. ubik and rxstat)
44  *
45  * The purpose of these functions is to allow a mapping from interfaceId
46  * to text representations of server process names and function names.
47  */
48
49 typedef struct {
50     const char **functionList;
51     size_t functionListLen;
52 } interface_function_list_t, *interface_function_list_p;
53
54 #ifdef AFS_NT40_ENV
55
56 /*
57  * On NT, you cannot define an array of character pointers in a dll
58  * and then access this array outside the dll via a global initialization
59  * because the msvc compiler will complain that the initializer is not
60  * a constant (i.e. C2099: initializer is not a constant).  This is because
61  * the dllimport and dllexport c language extensions cause references
62  * to the character array to go through another level of indirection -
63  * and this indirection is unknown at compilation time.
64  *
65  * To get around this problem I hand initialize this array on NT only
66  */
67
68 static interface_function_list_t afs_server;
69 static interface_function_list_t afscb_server;
70 static interface_function_list_t bos_server;
71 static interface_function_list_t kauth_kaa_server;
72 static interface_function_list_t kauth_kam_server;
73 static interface_function_list_t kauth_kat_server;
74 static interface_function_list_t pts_server;
75 static interface_function_list_t rxstat_server;
76 static interface_function_list_t ubik_disk_server;
77 static interface_function_list_t ubik_vote_server;
78 static interface_function_list_t vl_server;
79 static interface_function_list_t vol_server;
80 static pthread_once_t pthread_func_list_once = PTHREAD_ONCE_INIT;
81 static int pthread_func_list_done;
82
83 static void
84 cr_list(void)
85 {
86     afs_server.functionList = RXAFS_function_names;
87     afs_server.functionListLen = RXAFS_NO_OF_STAT_FUNCS;
88     afscb_server.functionList = RXAFSCB_function_names;
89     afscb_server.functionListLen = RXAFSCB_NO_OF_STAT_FUNCS;
90     bos_server.functionList = BOZO_function_names;
91     bos_server.functionListLen = BOZO_NO_OF_STAT_FUNCS;
92     kauth_kaa_server.functionList = KAA_function_names;
93     kauth_kaa_server.functionListLen = KAA_NO_OF_STAT_FUNCS;
94     kauth_kam_server.functionList = KAM_function_names;
95     kauth_kam_server.functionListLen = KAM_NO_OF_STAT_FUNCS;
96     kauth_kat_server.functionList = KAT_function_names;
97     kauth_kat_server.functionListLen = KAT_NO_OF_STAT_FUNCS;
98     pts_server.functionList = PR_function_names;
99     pts_server.functionListLen = PR_NO_OF_STAT_FUNCS;
100     rxstat_server.functionList = RXSTATS_function_names;
101     rxstat_server.functionListLen = RXSTATS_NO_OF_STAT_FUNCS;
102     ubik_disk_server.functionList = DISK_function_names;
103     ubik_disk_server.functionListLen = DISK_NO_OF_STAT_FUNCS;
104     ubik_vote_server.functionList = VOTE_function_names;
105     ubik_vote_server.functionListLen = VOTE_NO_OF_STAT_FUNCS;
106     vl_server.functionList = VL_function_names;
107     vl_server.functionListLen = VL_NO_OF_STAT_FUNCS;
108     vol_server.functionList = AFSVolfunction_names;
109     vol_server.functionListLen = AFSVolNO_OF_STAT_FUNCS;
110     pthread_func_list_done = 1;
111 }
112
113 #else
114
115 static interface_function_list_t afs_server = {
116     RXAFS_function_names,
117     RXAFS_NO_OF_STAT_FUNCS
118 };
119
120 static interface_function_list_t afscb_server = {
121     RXAFSCB_function_names,
122     RXAFSCB_NO_OF_STAT_FUNCS
123 };
124
125 static interface_function_list_t bos_server = {
126     BOZO_function_names,
127     BOZO_NO_OF_STAT_FUNCS
128 };
129
130 static interface_function_list_t kauth_kaa_server = {
131     KAA_function_names,
132     KAA_NO_OF_STAT_FUNCS
133 };
134
135 static interface_function_list_t kauth_kam_server = {
136     KAM_function_names,
137     KAM_NO_OF_STAT_FUNCS
138 };
139
140 static interface_function_list_t kauth_kat_server = {
141     KAT_function_names,
142     KAT_NO_OF_STAT_FUNCS
143 };
144
145 static interface_function_list_t pts_server = {
146     PR_function_names,
147     PR_NO_OF_STAT_FUNCS
148 };
149
150 static interface_function_list_t rxstat_server = {
151     RXSTATS_function_names,
152     RXSTATS_NO_OF_STAT_FUNCS
153 };
154
155 static interface_function_list_t ubik_disk_server = {
156     DISK_function_names,
157     DISK_NO_OF_STAT_FUNCS,
158 };
159
160 static interface_function_list_t ubik_vote_server = {
161     VOTE_function_names,
162     VOTE_NO_OF_STAT_FUNCS,
163 };
164
165 static interface_function_list_t vl_server = {
166     VL_function_names,
167     VL_NO_OF_STAT_FUNCS
168 };
169
170 static interface_function_list_t vol_server = {
171     AFSVolfunction_names,
172     AFSVolNO_OF_STAT_FUNCS
173 };
174
175 #endif /* AFS_NT40_ENV */
176
177 static interface_function_list_t unknown_server = {
178     0,
179     0
180 };
181
182 typedef struct {
183     afs_uint32 interfaceId;
184     const char *interfaceName;
185     interface_function_list_p functionList;
186 } interface_t, *interface_p;
187
188 interface_t int_list[] = {
189     {RXAFS_STATINDEX,
190      "file server",
191      &afs_server},
192
193     {RXSTATS_STATINDEX,
194      "rx stats",
195      &rxstat_server},
196
197     {RXAFSCB_STATINDEX,
198      "cache manager",
199      &afscb_server},
200
201     {PR_STATINDEX,
202      "pts server",
203      &pts_server},
204
205     {DISK_STATINDEX,
206      "ubik disk server",
207      &ubik_disk_server},
208
209     {VOTE_STATINDEX,
210      "ubik vote server",
211      &ubik_vote_server},
212
213     {VL_STATINDEX,
214      "vldb server",
215      &vl_server},
216
217     {AFSVolSTATINDEX,
218      "vol server",
219      &vol_server},
220
221     {BOZO_STATINDEX,
222      "bos server",
223      &bos_server},
224
225     {KAA_STATINDEX,
226      "kas kaa server",
227      &kauth_kaa_server},
228
229     {KAM_STATINDEX,
230      "kas kam server",
231      &kauth_kam_server},
232
233     {KAT_STATINDEX,
234      "kas kat server",
235      &kauth_kat_server},
236
237     /*
238      * Note the code below assumes that the following entry is the last entry
239      * in this array
240      */
241
242     {0, "unknown", &unknown_server}
243 };
244
245 /*
246  * Utility functions
247  */
248
249 int
250 DoClientLocalCellGet(struct cmd_syndesc *as, void *arock)
251 {
252     afs_status_t st = 0;
253     char cellName[MAXCELLCHARS];
254
255     if (!afsclient_LocalCellGet(cellName, &st)) {
256         ERR_ST_EXT("afsclient_LocalCellGet", st);
257     }
258
259     printf("This machine belongs to cell: %s\n", cellName);
260
261     return 0;
262 }
263
264 int
265 DoClientMountPointCreate(struct cmd_syndesc *as, void *arock)
266 {
267     enum { DIRECTORY, VOLUME, READWRITE,
268         CHECK
269     };
270     afs_status_t st = 0;
271     const char *directory = NULL;
272     const char *volume = NULL;
273     vol_type_t vol_type = READ_ONLY;
274     vol_check_t vol_check = DONT_CHECK_VOLUME;
275
276     if (as->parms[DIRECTORY].items) {
277         directory = as->parms[DIRECTORY].items->data;
278     }
279
280     if (as->parms[VOLUME].items) {
281         volume = as->parms[VOLUME].items->data;
282     }
283
284     if (as->parms[READWRITE].items) {
285         vol_type = READ_WRITE;
286     }
287
288     if (as->parms[CHECK].items) {
289         vol_check = CHECK_VOLUME;
290     }
291
292     if (!afsclient_MountPointCreate
293         (cellHandle, directory, volume, vol_type, vol_check, &st)) {
294         ERR_ST_EXT("afsclient_MountPointCreate", st);
295     }
296
297     return 0;
298 }
299
300 static void
301 Print_afs_serverEntry_p(afs_serverEntry_p serv, const char *prefix)
302 {
303     int i = 0;
304
305     printf("%sInformation for server %s\n", prefix, serv->serverName);
306     if (serv->serverType & DATABASE_SERVER) {
307         printf("%s\tIt is a database server\n", prefix);
308     }
309     if (serv->serverType & FILE_SERVER) {
310         printf("%s\tIt is a file server\n", prefix);
311     }
312     printf("%s\tServer addresses:%s\n", prefix, serv->serverName);
313     while (serv->serverAddress[i] != 0) {
314         printf("\t\t%s%x\n", prefix, serv->serverAddress[i++]);
315     }
316 }
317
318 int
319 DoClientAFSServerGet(struct cmd_syndesc *as, void *arock)
320 {
321     enum { SERVER };
322     afs_status_t st = 0;
323     const char *server = NULL;
324     afs_serverEntry_t entry;
325
326     if (as->parms[SERVER].items) {
327         server = as->parms[SERVER].items->data;
328     }
329
330     if (!afsclient_AFSServerGet(cellHandle, server, &entry, &st)) {
331         ERR_ST_EXT("afsclient_AFSServerGet", st);
332     }
333
334     Print_afs_serverEntry_p(&entry, "");
335
336     return 0;
337 }
338
339 int
340 DoClientAFSServerList(struct cmd_syndesc *as, void *arock)
341 {
342     afs_status_t st = 0;
343     afs_serverEntry_t entry;
344     void *iter = NULL;
345
346     if (!afsclient_AFSServerGetBegin(cellHandle, &iter, &st)) {
347         ERR_ST_EXT("afsclient_AFSServerGetBegin", st);
348     }
349
350     while (afsclient_AFSServerGetNext(iter, &entry, &st)) {
351         Print_afs_serverEntry_p(&entry, "");
352     }
353
354     if (st != ADMITERATORDONE) {
355         ERR_ST_EXT("afsclient_AFSServerGetNext", st);
356     }
357
358     if (!afsclient_AFSServerGetDone(iter, &st)) {
359         ERR_ST_EXT("afsclient_AFSServerGetDone", st);
360     }
361
362
363     return 0;
364 }
365
366 static void
367 Print_afs_RPCStatsState_p(afs_RPCStatsState_p state, const char *prefix)
368 {
369     printf("%sThe rpc stats state is: ", prefix);
370     switch (*state) {
371     case AFS_RPC_STATS_DISABLED:
372         printf("disabled\n");
373         break;
374     case AFS_RPC_STATS_ENABLED:
375         printf("enabled\n");
376         break;
377     }
378 }
379
380 typedef struct {
381     const char *tag;
382     afs_stat_source_t value;
383 } afs_type_map_t, *afs_type_map_p;
384
385 static afs_type_map_t map[] = {
386     {"bosserver", AFS_BOSSERVER},
387     {"fileserver", AFS_FILESERVER},
388     {"kaserver", AFS_KASERVER},
389     {"ptserver", AFS_PTSERVER},
390     {"volserver", AFS_VOLSERVER},
391     {"vlserver", AFS_VLSERVER},
392     {"client", AFS_CLIENT},
393     {0, 0}
394 };
395
396 static int
397 GetStatPortFromString(const char *type, int *port)
398 {
399     char *end;
400     long tport;
401
402     errno = 0;
403     tport = strtol(type, &end, 0);
404     if (tport == 0 || end == type || *end != '\0') {
405         return 0;
406     }
407
408     *port = (int)tport;
409     return 1;
410 }
411
412 static int
413 GetStatSourceFromString(const char *type, afs_stat_source_t * src, int *port)
414 {
415     int i;
416     size_t type_len = strlen(type);
417
418     for (i = 0; (map[i].tag) && strncasecmp(type, map[i].tag, type_len); i++);
419
420     if (map[i].tag == 0) {
421         /*
422          * Try to convert string to port number
423          */
424         if (GetStatPortFromString(type, port)) {
425             return 0;
426         }
427
428         fprintf(stderr,
429                 "couldn't convert server to type, try one of the "
430                 "following:\n");
431         for (i = 0; map[i].tag; i++) {
432             fprintf(stderr, "%s ", map[i].tag);
433         }
434
435         ERR_EXT("");
436     } else {
437         *src = map[i].value;
438         return 1;
439     }
440 }
441
442 typedef enum {
443     AFS_PEER_STATS,
444     afs_proc_tESS_STATS
445 } afs_stat_type_t, *afs_stat_type_p;
446
447 static afs_stat_type_t
448 GetStatTypeFromString(const char *type)
449 {
450     afs_stat_type_t rc;
451
452     if (!strcmp(type, "peer")) {
453         rc = AFS_PEER_STATS;
454     } else if (!strcmp(type, "process")) {
455         rc = afs_proc_tESS_STATS;
456     } else {
457         ERR_EXT("stat_type must be process or peer");
458     }
459
460     return rc;
461 }
462
463 int
464 DoClientRPCStatsStateGet(struct cmd_syndesc *as, void *arock)
465 {
466     enum { SERVER, PROCESS,
467         STAT_TYPE
468     };
469     afs_status_t st = 0;
470     struct rx_connection *conn;
471     afs_stat_source_t type;
472     int srvrPort;
473     int typeIsValid = 0;
474     afs_stat_type_t which = 0;
475     afs_RPCStatsState_t state;
476
477     typeIsValid = GetStatSourceFromString(as->parms[PROCESS].items->data,
478                                           &type, &srvrPort);
479
480     which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
481
482     if (typeIsValid) {
483         if (!afsclient_RPCStatOpen(cellHandle,
484                                    as->parms[SERVER].items->data,
485                                    type, &conn, &st)) {
486             ERR_ST_EXT("afsclient_RPCStatOpen", st);
487         }
488     } else {
489         if (!afsclient_RPCStatOpenPort(cellHandle,
490                                        as->parms[SERVER].items->data,
491                                        srvrPort, &conn, &st)) {
492             ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
493         }
494     }
495
496     if (which == AFS_PEER_STATS) {
497         if (!util_RPCStatsStateGet
498             (conn, RXSTATS_QueryPeerRPCStats, &state, &st)) {
499             ERR_ST_EXT("util_RPCStatsStateGet", st);
500         }
501     } else {
502         if (!util_RPCStatsStateGet
503             (conn, RXSTATS_QueryProcessRPCStats, &state, &st)) {
504             ERR_ST_EXT("util_RPCStatsStateGet", st);
505         }
506     }
507
508     Print_afs_RPCStatsState_p(&state, "");
509
510     afsclient_RPCStatClose(conn, 0);
511
512     return 0;
513 }
514
515 int
516 DoClientRPCStatsStateEnable(struct cmd_syndesc *as, void *arock)
517 {
518     enum { SERVER, PROCESS, STAT_TYPE };
519     afs_status_t st = 0;
520     struct rx_connection *conn;
521     afs_stat_source_t type;
522     int srvrPort;
523     int typeIsValid;
524     afs_stat_type_t which;
525
526     typeIsValid = GetStatSourceFromString(as->parms[PROCESS].items->data,
527                                           &type, &srvrPort);
528
529     which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
530
531     if (typeIsValid) {
532         if (!afsclient_RPCStatOpen(cellHandle,
533                                    as->parms[SERVER].items->data,
534                                    type, &conn, &st)) {
535             ERR_ST_EXT("afsclient_RPCStatOpen", st);
536         }
537     } else {
538         if (!afsclient_RPCStatOpenPort(cellHandle,
539                                        as->parms[SERVER].items->data,
540                                        srvrPort, &conn, &st)) {
541             ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
542         }
543     }
544
545     if (which == AFS_PEER_STATS) {
546         if (!util_RPCStatsStateEnable(conn, RXSTATS_EnablePeerRPCStats, &st)) {
547             ERR_ST_EXT("util_RPCStatsStateEnable", st);
548         }
549     } else {
550         if (!util_RPCStatsStateEnable
551             (conn, RXSTATS_EnableProcessRPCStats, &st)) {
552             ERR_ST_EXT("util_RPCStatsStateEnable", st);
553         }
554     }
555
556     afsclient_RPCStatClose(conn, 0);
557
558     return 0;
559 }
560
561 int
562 DoClientRPCStatsStateDisable(struct cmd_syndesc *as, void *arock)
563 {
564     enum { SERVER, PROCESS,
565         STAT_TYPE
566     };
567     afs_status_t st = 0;
568     struct rx_connection *conn;
569     afs_stat_source_t type;
570     int srvrPort;
571     int typeIsValid;
572     afs_stat_type_t which;
573
574     typeIsValid = GetStatSourceFromString(as->parms[PROCESS].items->data,
575                                           &type, &srvrPort);
576
577     which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
578
579     if (typeIsValid) {
580         if (!afsclient_RPCStatOpen(cellHandle,
581                                    as->parms[SERVER].items->data,
582                                    type, &conn, &st)) {
583             ERR_ST_EXT("afsclient_RPCStatOpen", st);
584         }
585     } else {
586         if (!afsclient_RPCStatOpenPort(cellHandle,
587                                        as->parms[SERVER].items->data,
588                                        srvrPort, &conn, &st)) {
589             ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
590         }
591     }
592
593     if (which == AFS_PEER_STATS) {
594         if (!util_RPCStatsStateDisable
595             (conn, RXSTATS_DisablePeerRPCStats, &st)) {
596             ERR_ST_EXT("util_RPCStatsStateDisable", st);
597         }
598     } else {
599         if (!util_RPCStatsStateDisable
600             (conn, RXSTATS_DisableProcessRPCStats, &st)) {
601             ERR_ST_EXT("util_RPCStatsStateDisable", st);
602         }
603     }
604
605     afsclient_RPCStatClose(conn, 0);
606
607     return 0;
608 }
609
610 static void
611 Print_afs_RPCStats_p(afs_RPCStats_p stat, interface_function_list_p f_list,
612                      const char *prefix)
613 {
614     afs_int32 index = stat->s.stats_v1.func_index;
615
616     if (index > ((afs_int32) f_list->functionListLen - 1)) {
617         printf("%sUnknown function ", prefix);
618     } else {
619         printf("%s%s ", prefix,
620                f_list->functionList[stat->s.stats_v1.func_index]);
621     }
622
623     if (stat->s.stats_v1.invocations != 0) {
624         printf("%sinvoc %"AFS_UINT64_FMT
625                " bytes_sent %"AFS_UINT64_FMT
626                " bytes_rcvd %"AFS_UINT64_FMT"\n",
627                prefix,
628                stat->s.stats_v1.invocations,
629                stat->s.stats_v1.bytes_sent,
630                stat->s.stats_v1.bytes_rcvd
631               );
632         printf("\tqsum %d.%06d\tqsqr %d.%06d"
633                "\tqmin %d.%06d\tqmax %d.%06d\n",
634                stat->s.stats_v1.queue_time_sum.sec,
635                stat->s.stats_v1.queue_time_sum.usec,
636                stat->s.stats_v1.queue_time_sum_sqr.sec,
637                stat->s.stats_v1.queue_time_sum_sqr.usec,
638                stat->s.stats_v1.queue_time_min.sec,
639                stat->s.stats_v1.queue_time_min.usec,
640                stat->s.stats_v1.queue_time_max.sec,
641                stat->s.stats_v1.queue_time_max.usec);
642         printf("\txsum %d.%06d\txsqr %d.%06d"
643                "\txmin %d.%06d\txmax %d.%06d\n",
644                stat->s.stats_v1.execution_time_sum.sec,
645                stat->s.stats_v1.execution_time_sum.usec,
646                stat->s.stats_v1.execution_time_sum_sqr.sec,
647                stat->s.stats_v1.execution_time_sum_sqr.usec,
648                stat->s.stats_v1.execution_time_min.sec,
649                stat->s.stats_v1.execution_time_min.usec,
650                stat->s.stats_v1.execution_time_max.sec,
651                stat->s.stats_v1.execution_time_max.usec);
652     } else {
653         printf("never invoked\n");
654     }
655 }
656
657 int
658 DoClientRPCStatsList(struct cmd_syndesc *as, void *arock)
659 {
660     enum { SERVER, PROCESS, STAT_TYPE };
661     afs_status_t st = 0;
662     struct rx_connection *conn;
663     afs_stat_source_t type;
664     int srvrPort;
665     int typeIsValid;
666     afs_stat_type_t which;
667     afs_RPCStats_t stats;
668     void *iter;
669     int i = 0;
670
671 #ifdef AFS_NT40_ENV
672     (pthread_func_list_done
673      || pthread_once(&pthread_func_list_once, cr_list));
674 #endif
675
676     typeIsValid = GetStatSourceFromString(as->parms[PROCESS].items->data,
677                                           &type, &srvrPort);
678
679     which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
680
681     if (typeIsValid) {
682         if (!afsclient_RPCStatOpen(cellHandle,
683                                    as->parms[SERVER].items->data,
684                                    type, &conn, &st)) {
685             ERR_ST_EXT("afsclient_RPCStatOpen", st);
686         }
687     } else {
688         if (!afsclient_RPCStatOpenPort(cellHandle,
689                                        as->parms[SERVER].items->data,
690                                        srvrPort, &conn, &st)) {
691             ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
692         }
693     }
694
695     if (which == AFS_PEER_STATS) {
696         if (!util_RPCStatsGetBegin
697             (conn, RXSTATS_RetrievePeerRPCStats, &iter, &st)) {
698             ERR_ST_EXT("util_RPCStatsGetBegin", st);
699         }
700     } else {
701         if (!util_RPCStatsGetBegin
702             (conn, RXSTATS_RetrieveProcessRPCStats, &iter, &st)) {
703             ERR_ST_EXT("util_RPCStatsGetBegin", st);
704         }
705     }
706
707     printf("Listing rpc stats at server %s process %s:\n",
708            as->parms[SERVER].items->data, as->parms[PROCESS].items->data);
709
710     while (util_RPCStatsGetNext(iter, &stats, &st)) {
711
712         /*
713          * Print a new heading for each stat collection
714          */
715
716         if (stats.s.stats_v1.func_index == 0) {
717
718             printf("\n\n");
719
720             /*
721              * Look up the interface in our list
722              */
723
724             for (i = 0; i < ((sizeof(int_list) - 1) / sizeof(interface_t));
725                  i++) {
726                 if (stats.s.stats_v1.interfaceId == int_list[i].interfaceId) {
727                     break;
728                 }
729             }
730
731             /*
732              * Print out a meaningful header for each stat collection
733              */
734
735             if (which == AFS_PEER_STATS) {
736                 struct in_addr ina;
737                 ina.s_addr = htonl(stats.s.stats_v1.remote_peer);
738
739                 printf("%s stats for remote peer located at %s port %u "
740                        "%s %s as a %s via the %s interface\n",
741                        as->parms[PROCESS].items->data, inet_ntoa(ina),
742                        stats.s.stats_v1.remote_port,
743                        ((stats.s.stats_v1.
744                          remote_is_server) ? "accessed by" : "accessing"),
745                        as->parms[PROCESS].items->data,
746                        ((stats.s.stats_v1.
747                          remote_is_server) ? "client" : "server"),
748                        int_list[i].interfaceName);
749             } else {
750                 printf("%s stats for the %s interface " "accessed as a %s\n",
751                        as->parms[PROCESS].items->data,
752                        int_list[i].interfaceName,
753                        ((stats.s.stats_v1.
754                          remote_is_server) ? "client" : "server")
755                     );
756             }
757         }
758         Print_afs_RPCStats_p(&stats, int_list[i].functionList, "    ");
759     }
760
761     if (st != ADMITERATORDONE) {
762         ERR_ST_EXT("util_RPCStatsGetNext", st);
763     }
764
765     if (!util_RPCStatsGetDone(iter, &st)) {
766         ERR_ST_EXT("util_RPCStatsGetDone", st);
767     }
768
769     afsclient_RPCStatClose(conn, 0);
770
771     return 0;
772 }
773
774 int
775 DoClientRPCStatsClear(struct cmd_syndesc *as, void *arock)
776 {
777     enum { SERVER, PROCESS, STAT_TYPE, CLEAR_ALL, CLEAR_INVOCATIONS,
778         CLEAR_BYTES_SENT, CLEAR_BYTES_RCVD,
779         CLEAR_QUEUE_TIME_SUM, CLEAR_QUEUE_TIME_SQUARE,
780         CLEAR_QUEUE_TIME_MIN, CLEAR_QUEUE_TIME_MAX,
781         CLEAR_EXEC_TIME_SUM, CLEAR_EXEC_TIME_SQUARE,
782         CLEAR_EXEC_TIME_MIN, CLEAR_EXEC_TIME_MAX
783     };
784     afs_status_t st = 0;
785     struct rx_connection *conn;
786     afs_stat_source_t type;
787     int srvrPort;
788     int typeIsValid;
789     afs_stat_type_t which;
790     afs_RPCStatsClearFlag_t flag = 0;
791     int seen_all = 0;
792     int seen_any = 0;
793
794     typeIsValid = GetStatSourceFromString(as->parms[PROCESS].items->data,
795                                           &type, &srvrPort);
796
797     which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
798
799     if (typeIsValid) {
800         if (!afsclient_RPCStatOpen(cellHandle,
801                                    as->parms[SERVER].items->data,
802                                    type, &conn, &st)) {
803             ERR_ST_EXT("afsclient_RPCStatOpen", st);
804         }
805     } else {
806         if (!afsclient_RPCStatOpenPort(cellHandle,
807                                        as->parms[SERVER].items->data,
808                                        srvrPort, &conn, &st)) {
809             ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
810         }
811     }
812
813     if (as->parms[CLEAR_ALL].items) {
814         seen_all = 1;
815         seen_any = 1;
816         flag = AFS_RX_STATS_CLEAR_ALL;
817     }
818
819     if (as->parms[CLEAR_INVOCATIONS].items) {
820         if (seen_all) {
821             ERR_EXT("cannot specify additional flags when "
822                     "specifying clear_all");
823         }
824         seen_any = 1;
825         flag |= AFS_RX_STATS_CLEAR_INVOCATIONS;
826     }
827
828     if (as->parms[CLEAR_BYTES_SENT].items) {
829         if (seen_all) {
830             ERR_EXT("cannot specify additional flags when "
831                     "specifying clear_all");
832         }
833         seen_any = 1;
834         flag |= AFS_RX_STATS_CLEAR_BYTES_SENT;
835     }
836
837     if (as->parms[CLEAR_BYTES_RCVD].items) {
838         if (seen_all) {
839             ERR_EXT("cannot specify additional flags when "
840                     "specifying clear_all");
841         }
842         seen_any = 1;
843         flag |= AFS_RX_STATS_CLEAR_BYTES_RCVD;
844     }
845
846     if (as->parms[CLEAR_QUEUE_TIME_SUM].items) {
847         if (seen_all) {
848             ERR_EXT("cannot specify additional flags when "
849                     "specifying clear_all");
850         }
851         seen_any = 1;
852         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_SUM;
853     }
854
855     if (as->parms[CLEAR_QUEUE_TIME_SQUARE].items) {
856         if (seen_all) {
857             ERR_EXT("cannot specify additional flags when "
858                     "specifying clear_all");
859         }
860         seen_any = 1;
861         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_SQUARE;
862     }
863
864     if (as->parms[CLEAR_QUEUE_TIME_MIN].items) {
865         if (seen_all) {
866             ERR_EXT("cannot specify additional flags when "
867                     "specifying clear_all");
868         }
869         seen_any = 1;
870         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_MIN;
871     }
872
873     if (as->parms[CLEAR_QUEUE_TIME_MAX].items) {
874         if (seen_all) {
875             ERR_EXT("cannot specify additional flags when "
876                     "specifying clear_all");
877         }
878         seen_any = 1;
879         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_MAX;
880     }
881
882     if (as->parms[CLEAR_EXEC_TIME_SUM].items) {
883         if (seen_all) {
884             ERR_EXT("cannot specify additional flags when "
885                     "specifying clear_all");
886         }
887         seen_any = 1;
888         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_SUM;
889     }
890
891     if (as->parms[CLEAR_EXEC_TIME_SQUARE].items) {
892         if (seen_all) {
893             ERR_EXT("cannot specify additional flags when "
894                     "specifying clear_all");
895         }
896         seen_any = 1;
897         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_SQUARE;
898     }
899
900     if (as->parms[CLEAR_EXEC_TIME_MIN].items) {
901         if (seen_all) {
902             ERR_EXT("cannot specify additional flags when "
903                     "specifying clear_all");
904         }
905         seen_any = 1;
906         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_MIN;
907     }
908
909     if (as->parms[CLEAR_EXEC_TIME_MAX].items) {
910         if (seen_all) {
911             ERR_EXT("cannot specify additional flags when "
912                     "specifying clear_all");
913         }
914         seen_any = 1;
915         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_MAX;
916     }
917
918     if (!seen_any) {
919         ERR_EXT("you must specify something to clear");
920     }
921
922     if (which == AFS_PEER_STATS) {
923         if (!util_RPCStatsClear(conn, RXSTATS_ClearPeerRPCStats, flag, &st)) {
924             ERR_ST_EXT("util_RPCStatsClear", st);
925         }
926     } else {
927         if (!util_RPCStatsClear
928             (conn, RXSTATS_ClearProcessRPCStats, flag, &st)) {
929             ERR_ST_EXT("util_RPCStatsClear", st);
930         }
931     }
932
933     afsclient_RPCStatClose(conn, 0);
934
935     return 0;
936 }
937
938 int
939 DoClientRPCStatsVersionGet(struct cmd_syndesc *as, void *arock)
940 {
941     enum { SERVER, PROCESS };
942     afs_status_t st = 0;
943     struct rx_connection *conn;
944     afs_stat_source_t type;
945     int srvrPort;
946     int typeIsValid;
947     afs_RPCStatsVersion_t version;
948
949     typeIsValid = GetStatSourceFromString(as->parms[PROCESS].items->data,
950                                           &type, &srvrPort);
951
952     if (typeIsValid) {
953         if (!afsclient_RPCStatOpen(cellHandle,
954                                    as->parms[SERVER].items->data,
955                                    type, &conn, &st)) {
956             ERR_ST_EXT("afsclient_RPCStatOpen", st);
957         }
958     } else {
959         if (!afsclient_RPCStatOpenPort(cellHandle,
960                                        as->parms[SERVER].items->data,
961                                        srvrPort, &conn, &st)) {
962             ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
963         }
964     }
965
966     if (!util_RPCStatsVersionGet(conn, &version, &st)) {
967         ERR_ST_EXT("util_RPCStatsVersionGet", st);
968     }
969
970     printf("the rpc stat version number is %u\n", version);
971
972     afsclient_RPCStatClose(conn, 0);
973
974     return 0;
975 }
976
977 static void
978 Print_afs_CMServerPref_p(afs_CMServerPref_p pref)
979 {
980     afs_uint32 taddr;
981
982     taddr = pref->ipAddr;
983     printf("%d.%d.%d.%d\t\t\t%d\n", (taddr >> 24) & 0xff,
984            (taddr >> 16) & 0xff, (taddr >> 8) & 0xff, taddr & 0xff,
985            pref->ipRank);
986 }
987
988 int
989 DoClientCMGetServerPrefs(struct cmd_syndesc *as, void *arock)
990 {
991     afs_status_t st = 0;
992     enum { SERVER, PORT };
993     struct rx_connection *conn;
994     int srvrPort = AFSCONF_CALLBACKPORT;
995     afs_CMServerPref_t prefs;
996     void *iter;
997
998 #ifdef AFS_NT40_ENV
999     (pthread_func_list_done
1000      || pthread_once(&pthread_func_list_once, cr_list));
1001 #endif
1002
1003     if (as->parms[PORT].items) {
1004         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1005             ERR_EXT("Couldn't undertand port number");
1006         }
1007     }
1008
1009     if (!afsclient_CMStatOpenPort(cellHandle,
1010                                   as->parms[SERVER].items->data,
1011                                   srvrPort, &conn, &st)) {
1012         ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1013     }
1014
1015     if (!util_CMGetServerPrefsBegin(conn, &iter, &st)) {
1016         ERR_ST_EXT("util_CMGetServerPrefsBegin", st);
1017     }
1018
1019     printf("Listing CellServDB for %s at port %s:\n",
1020            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1021
1022     while (util_CMGetServerPrefsNext(iter, &prefs, &st)) {
1023
1024         Print_afs_CMServerPref_p(&prefs);
1025     }
1026
1027     if (st != ADMITERATORDONE) {
1028         ERR_ST_EXT("util_CMGetServerPrefsNext", st);
1029     }
1030
1031     if (!util_CMGetServerPrefsDone(iter, &st)) {
1032         ERR_ST_EXT("util_CMGetServerPrefsDone", st);
1033     }
1034
1035     afsclient_CMStatClose(conn, 0);
1036
1037     return 0;
1038 }
1039
1040 static void
1041 Print_afs_CMListCell_p(afs_CMListCell_p cellInfo)
1042 {
1043     int i;
1044     afs_uint32 taddr;
1045
1046     printf("Cell %s on hosts", cellInfo->cellname);
1047     for (i = 0; i < UTIL_MAX_CELL_HOSTS && cellInfo->serverAddr[i]; i++) {
1048         taddr = cellInfo->serverAddr[i];
1049         printf(" %d.%d.%d.%d", (taddr >> 24) & 0xff, (taddr >> 16) & 0xff,
1050                (taddr >> 8) & 0xff, taddr & 0xff);
1051     }
1052     printf("\n");
1053 }
1054
1055 int
1056 DoClientCMListCells(struct cmd_syndesc *as, void *arock)
1057 {
1058     afs_status_t st = 0;
1059     enum { SERVER, PORT };
1060     struct rx_connection *conn;
1061     int srvrPort = AFSCONF_CALLBACKPORT;
1062     afs_CMListCell_t cellInfo;
1063     void *iter;
1064
1065 #ifdef AFS_NT40_ENV
1066     (pthread_func_list_done
1067      || pthread_once(&pthread_func_list_once, cr_list));
1068 #endif
1069
1070     if (as->parms[PORT].items) {
1071         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1072             ERR_EXT("Couldn't undertand port number");
1073         }
1074     }
1075
1076     if (!afsclient_CMStatOpenPort(cellHandle,
1077                                   as->parms[SERVER].items->data,
1078                                   srvrPort, &conn, &st)) {
1079         ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1080     }
1081
1082     if (!util_CMListCellsBegin(conn, &iter, &st)) {
1083         ERR_ST_EXT("util_CMListCellsBegin", st);
1084     }
1085
1086     printf("Listing CellServDB for %s at port %s:\n",
1087            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1088
1089     while (util_CMListCellsNext(iter, &cellInfo, &st)) {
1090
1091         Print_afs_CMListCell_p(&cellInfo);
1092     }
1093
1094     if (st != ADMITERATORDONE) {
1095         ERR_ST_EXT("util_CMListCellsNext", st);
1096     }
1097
1098     if (!util_CMListCellsDone(iter, &st)) {
1099         ERR_ST_EXT("util_CMListCellsDone", st);
1100     }
1101
1102     afsclient_CMStatClose(conn, 0);
1103
1104     return 0;
1105 }
1106
1107 int
1108 DoClientCMLocalCell(struct cmd_syndesc *as, void *arock)
1109 {
1110     afs_status_t st = 0;
1111     enum { SERVER, PORT };
1112     struct rx_connection *conn;
1113     int srvrPort = AFSCONF_CALLBACKPORT;
1114     afs_CMCellName_t cellname;
1115
1116 #ifdef AFS_NT40_ENV
1117     (pthread_func_list_done
1118      || pthread_once(&pthread_func_list_once, cr_list));
1119 #endif
1120
1121     if (as->parms[PORT].items) {
1122         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1123             ERR_EXT("Couldn't undertand port number");
1124         }
1125     }
1126
1127     if (!afsclient_CMStatOpenPort(cellHandle,
1128                                   as->parms[SERVER].items->data,
1129                                   srvrPort, &conn, &st)) {
1130         ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1131     }
1132
1133     if (!util_CMLocalCell(conn, cellname, &st)) {
1134         ERR_ST_EXT("util_CMLocalCell", st);
1135     }
1136
1137     printf("Client %s (port %s) is in cell %s\n",
1138            as->parms[SERVER].items->data, as->parms[PORT].items->data,
1139            cellname);
1140
1141     afsclient_CMStatClose(conn, 0);
1142
1143     return 0;
1144 }
1145
1146 static void
1147 Print_afs_ClientConfig_p(afs_ClientConfig_p config)
1148 {
1149     printf("    clientVersion:  %d\n", config->clientVersion);
1150     printf("    serverVersion:  %d\n", config->serverVersion);
1151     printf("    nChunkFiles:    %d\n", config->c.config_v1.nChunkFiles);
1152     printf("    nStatCaches:    %d\n", config->c.config_v1.nStatCaches);
1153     printf("    nDataCaches:    %d\n", config->c.config_v1.nDataCaches);
1154     printf("    nVolumeCaches:  %d\n", config->c.config_v1.nVolumeCaches);
1155     printf("    firstChunkSize: %d\n", config->c.config_v1.firstChunkSize);
1156     printf("    otherChunkSize: %d\n", config->c.config_v1.otherChunkSize);
1157     printf("    cacheSize:      %d\n", config->c.config_v1.cacheSize);
1158     printf("    setTime:        %d\n", config->c.config_v1.setTime);
1159     printf("    memCache:       %d\n", config->c.config_v1.memCache);
1160
1161 }
1162
1163 int
1164 DoClientCMClientConfig(struct cmd_syndesc *as, void *arock)
1165 {
1166     afs_status_t st = 0;
1167     enum { SERVER, PORT };
1168     struct rx_connection *conn;
1169     int srvrPort = AFSCONF_CALLBACKPORT;
1170     afs_ClientConfig_t config;
1171
1172 #ifdef AFS_NT40_ENV
1173     (pthread_func_list_done
1174      || pthread_once(&pthread_func_list_once, cr_list));
1175 #endif
1176
1177     if (as->parms[PORT].items) {
1178         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1179             ERR_EXT("Couldn't undertand port number");
1180         }
1181     }
1182
1183     if (!afsclient_CMStatOpenPort(cellHandle,
1184                                   as->parms[SERVER].items->data,
1185                                   srvrPort, &conn, &st)) {
1186         ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1187     }
1188
1189     if (!util_CMClientConfig(conn, &config, &st)) {
1190         ERR_ST_EXT("util_CMClientConfig", st);
1191     }
1192
1193     printf("Cache configuration for client %s (port %s):\n\n",
1194            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1195
1196     Print_afs_ClientConfig_p(&config);
1197
1198     printf("\n");
1199
1200     afsclient_CMStatClose(conn, 0);
1201
1202     return 0;
1203 }
1204
1205 void
1206 SetupClientAdminCmd(void)
1207 {
1208     struct cmd_syndesc *ts;
1209
1210     ts = cmd_CreateSyntax("ClientLocalCellGet", DoClientLocalCellGet, NULL,
1211                           "get the name of this machine's cell");
1212     SetupCommonCmdArgs(ts);
1213
1214     ts = cmd_CreateSyntax("ClientMountPointCreate", DoClientMountPointCreate,
1215                           NULL, "create a mount point");
1216     cmd_AddParm(ts, "-directory", CMD_SINGLE, CMD_REQUIRED,
1217                 "directory where mount point will be created");
1218     cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_REQUIRED,
1219                 "the name of the volume to mount");
1220     cmd_AddParm(ts, "-readwrite", CMD_FLAG, CMD_OPTIONAL,
1221                 "mount a read write volume");
1222     cmd_AddParm(ts, "-check", CMD_FLAG, CMD_OPTIONAL,
1223                 "check that the volume exists before mounting");
1224     SetupCommonCmdArgs(ts);
1225
1226     ts = cmd_CreateSyntax("ClientAFSServerGet", DoClientAFSServerGet, NULL,
1227                           "retrieve information about an afs server");
1228     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "server to query");
1229     SetupCommonCmdArgs(ts);
1230
1231     ts = cmd_CreateSyntax("ClientAFSServerList", DoClientAFSServerList, NULL,
1232                           "retrieve information about all afs "
1233                           "servers in a cell");
1234     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1235                 "server where command will execute");
1236     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1237                 "process to query <bosserver fileserver ptserver "
1238                 "kaserver client vlserver volserver>");
1239     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1240                 "stats to retrieve <peer or process>");
1241     SetupCommonCmdArgs(ts);
1242
1243     ts = cmd_CreateSyntax("ClientRPCStatsStateGet", DoClientRPCStatsStateGet,
1244                           NULL, "retrieve the rpc stat collection state");
1245     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1246                 "server where command will execute");
1247     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1248                 "process to query <bosserver fileserver ptserver "
1249                 "kaserver client vlserver volserver>");
1250     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1251                 "stats to retrieve <peer or process>");
1252     SetupCommonCmdArgs(ts);
1253
1254     ts = cmd_CreateSyntax("ClientRPCStatsStateEnable",
1255                           DoClientRPCStatsStateEnable, NULL,
1256                           "set the rpc stat collection state to on");
1257     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1258                 "server where command will execute");
1259     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1260                 "process to query <bosserver fileserver ptserver "
1261                 "kaserver client vlserver volserver>");
1262     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1263                 "stats to retrieve <peer or process>");
1264     SetupCommonCmdArgs(ts);
1265
1266     ts = cmd_CreateSyntax("ClientRPCStatsStateDisable",
1267                           DoClientRPCStatsStateDisable, NULL,
1268                           "set the rpc stat collection state to off");
1269     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1270                 "server where command will execute");
1271     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1272                 "process to query <bosserver fileserver ptserver "
1273                 "kaserver client vlserver volserver>");
1274     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1275                 "stats to retrieve <peer or process>");
1276     SetupCommonCmdArgs(ts);
1277
1278     ts = cmd_CreateSyntax("ClientRPCStatsList", DoClientRPCStatsList, NULL,
1279                           "list the rpc stats");
1280     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1281                 "server where command will execute");
1282     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1283                 "process to query <bosserver fileserver ptserver "
1284                 "kaserver client vlserver volserver>");
1285     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1286                 "stats to retrieve <peer or process>");
1287     SetupCommonCmdArgs(ts);
1288
1289     ts = cmd_CreateSyntax("ClientRPCStatsClear", DoClientRPCStatsClear, NULL,
1290                           "reset rpc stat counters");
1291     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1292                 "server where command will execute");
1293     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1294                 "process to query <bosserver fileserver ptserver "
1295                 "kaserver client vlserver volserver>");
1296     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1297                 "stats to retrieve <peer or process>");
1298     cmd_AddParm(ts, "-clear_all", CMD_FLAG, CMD_OPTIONAL,
1299                 "clear all existing counters");
1300     cmd_AddParm(ts, "-clear_invocations", CMD_FLAG, CMD_OPTIONAL,
1301                 "clear invocation count");
1302     cmd_AddParm(ts, "-clear_bytes_sent", CMD_FLAG, CMD_OPTIONAL,
1303                 "clear bytes_sent count");
1304     cmd_AddParm(ts, "-clear_bytes_rcvd", CMD_FLAG, CMD_OPTIONAL,
1305                 "clear bytes_rcvd count");
1306     cmd_AddParm(ts, "-clear_queue_time_sum", CMD_FLAG, CMD_OPTIONAL,
1307                 "clear queue time sum");
1308     cmd_AddParm(ts, "-clear_queue_time_square", CMD_FLAG, CMD_OPTIONAL,
1309                 "clear queue time square");
1310     cmd_AddParm(ts, "-clear_queue_time_min", CMD_FLAG, CMD_OPTIONAL,
1311                 "clear queue time min");
1312     cmd_AddParm(ts, "-clear_queue_time_max", CMD_FLAG, CMD_OPTIONAL,
1313                 "clear queue time max");
1314     cmd_AddParm(ts, "-clear_exec_time_sum", CMD_FLAG, CMD_OPTIONAL,
1315                 "clear exec time sum");
1316     cmd_AddParm(ts, "-clear_exec_time_square", CMD_FLAG, CMD_OPTIONAL,
1317                 "clear exec time square");
1318     cmd_AddParm(ts, "-clear_exec_time_min", CMD_FLAG, CMD_OPTIONAL,
1319                 "clear exec time min");
1320     cmd_AddParm(ts, "-clear_exec_time_max", CMD_FLAG, CMD_OPTIONAL,
1321                 "clear exec time max");
1322     SetupCommonCmdArgs(ts);
1323
1324     ts = cmd_CreateSyntax("ClientRPCStatsVersionGet",
1325                           DoClientRPCStatsVersionGet, NULL,
1326                           "list the server's rpc stats version");
1327     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1328                 "server where command will execute");
1329     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1330                 "process to query <bosserver fileserver ptserver "
1331                 "kaserver client vlserver volserver>");
1332     SetupCommonCmdArgs(ts);
1333
1334     ts = cmd_CreateSyntax("ClientCMGetServerPrefs", DoClientCMGetServerPrefs,
1335                           NULL, "list a client's server preferences ");
1336     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1337                 "server where command will execute");
1338     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1339     SetupCommonCmdArgs(ts);
1340
1341     ts = cmd_CreateSyntax("ClientCMListCells", DoClientCMListCells, NULL,
1342                           "list a client's CellServDB ");
1343     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1344                 "server where command will execute");
1345     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1346     SetupCommonCmdArgs(ts);
1347
1348     ts = cmd_CreateSyntax("ClientCMLocalCell", DoClientCMLocalCell, NULL,
1349                           "get the name of the client's local cell");
1350     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1351                 "server where command will execute");
1352     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1353     SetupCommonCmdArgs(ts);
1354
1355     ts = cmd_CreateSyntax("ClientCMClientConfig", DoClientCMClientConfig, NULL,
1356                           "get the client's cache configuration");
1357     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1358                 "server where command will execute");
1359     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1360     SetupCommonCmdArgs(ts);
1361 }