pull-prototypes-to-head-20020821
[openafs.git] / src / uss / uss.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  *      Main module for the AFS user account management tool.
12  */
13
14 /*
15  * --------------------- Required definitions ---------------------
16  */
17 #include <stdlib.h>
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 RCSID("$Header$");
22
23 #ifdef  AFS_AIX32_ENV
24 #include <signal.h>
25 #endif
26
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #else
30 #ifdef HAVE_STRINGS_H
31 #include <strings.h>
32 #endif
33 #endif
34
35 #include "uss_common.h" /*Common uss definitions, globals*/
36 #include "uss_procs.h"  /*Main uss operations*/
37 #include "uss_kauth.h"  /*AuthServer routines*/
38 #include "uss_fs.h"     /*CacheManager ops*/
39 #include <afs/cmd.h>    /*Command line parsing*/
40 #include <afs/cellconfig.h> /*Cell config defs*/
41 #include <afs/kautils.h>        /*MAXKTCREALMLEN & MAXKTCNAMELEN*/
42 #include <ubik.h>
43
44 /*
45  * Label certain things which will be activated at a later time,
46  * as well as certain semi-implemented features/switches which need
47  * to be hidden for the general AFS 3.2 release.
48  */
49 #define USS_FUTURE_FEATURES             1
50 #define USS_DONT_HIDE_SOME_FEATURES     0
51
52 /*
53  * ---------------------- Exported variables ----------------------
54  */
55 char *uss_fs_InBuff  = NULL; /*Cache Manager input  buff*/
56 char *uss_fs_OutBuff = NULL; /*Cache Manager output buff*/
57
58 /*
59  * Set up convenient tags for the command line parameter indicies.
60  */
61
62 /*Add*/
63 #define AUP_USER         0
64 #define AUP_REALNAME     1
65 #define AUP_PASSWD       2
66 #define AUP_PWEXPIRES    3
67 #define AUP_SERVER       4  /* was 3 */
68 #define AUP_PART         5  /* was 4 */
69 #define AUP_MNTPT        6  /* was 5 */
70 #define AUP_UID          7  /* was 6 */
71
72 /*Bulk*/
73 #define ABULK_FILE       0
74
75 extern int uss_perr;
76 /*Delete*/
77 #define DUP_USER         0
78 #define DUP_MNTPT        1
79 #define DUP_RESTOREDIR   2
80 #define DUP_SAVEVOLUME   3
81 #define DUP_PWDPATH      4
82 #define DUP_PWDFORMAT    5
83
84 /*PurgeVolumes*/
85 #define PVP_VOLNAME      0
86 #define PVP_VOLFILE      1
87
88 /*Common ones*/
89 #define AUSS_TEMPLATE   10  /* was 7 */
90 #define AUSS_VERBOSE    11  /* was 8 */
91 #define AUSS_VAR        12  /* was 9 */
92 #define AUSS_CELL       13  /* was 10 */
93 #define AUSS_ADMIN      14  /* was 11 */
94 #define AUSS_DRYRUN     15  /* was 12 */
95 #define AUSS_SKIPAUTH   16  /* was 13 */
96 #define AUSS_OVERWRITE  17  /* was 14 */
97 #define AUSS_PWEXPIRES  18  /* was 15 */
98 #define AUSS_PIPE       19  /*  was 16 */
99
100 #undef USS_DB
101
102 static char Template[300]=
103     "uss.template";                     /*Default name*/
104
105 extern FILE *yyin, *yyout;              /*YACC input & output files*/
106 extern int doUnlog;
107 int uss_BulkExpires = 0;
108 int local_Cell=1;
109
110 static int DoAdd();
111
112 /*-----------------------------------------------------------------------
113  * static GetCommon
114  *
115  * Description:
116  *      Read in the command line arguments common to all uss operations.
117  *
118  * Arguments:
119  *      a_as : Ptr to the command line syntax descriptor.
120  *
121  * Returns:
122  *      0 (always)
123  *
124  * Environment:
125  *      May exit the program if trouble is encountered determining the
126  *      cell name.  Set up as the command line parser's BeforeProc().
127  *
128  * Side Effects:
129  *      As advertised.
130  *------------------------------------------------------------------------*/
131
132 static afs_int32 GetCommon(a_as)
133     register struct cmd_syndesc *a_as;
134
135 { /*GetCommon*/
136
137     int code;                           /*Result of ka_LocalCell*/
138
139     if (strcmp(a_as->name, "help") == 0)
140         return;
141     if (a_as->parms[AUSS_TEMPLATE].items)
142         strcpy(Template, a_as->parms[AUSS_TEMPLATE].items->data);
143     if (a_as->parms[AUSS_VERBOSE].items)
144         uss_verbose = 1;
145     else 
146         uss_verbose = 0;
147
148     code = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH);
149     if (code)
150         fprintf(stderr, "%s: ** Call to ka_CellConfig() failed (code=%d)\n",
151                 uss_whoami, code);
152                 
153     if (a_as->parms[AUSS_CELL].items) {
154         char local_cell[MAXKTCREALMLEN];
155         if (ka_ExpandCell(a_as->parms[AUSS_CELL].items->data,
156                           uss_Cell,
157                           0/*local*/)) {
158             fprintf(stderr,
159                     "%s: ** Unknown or ambiguous cell name: %s\n",
160                     uss_whoami, a_as->parms[AUSS_CELL].items->data);
161             exit(-1);
162         }
163         /*
164          * Get the local cell name
165          */
166         if (ka_ExpandCell((char*)0, local_cell, 0/*local*/)) {
167             fprintf(stderr, "Can't get local cellname\n");
168             exit(-1);
169         }
170         if (strcmp(uss_Cell, local_cell)) {
171             /*
172              * Not the same; not a local cell
173              */
174             local_Cell = 0;
175         }
176     }
177     else {
178         /*
179          * Get the local cell name
180          */
181         if (ka_ExpandCell((char*)0, uss_Cell, 0/*local*/)) {
182             fprintf(stderr, "Can't get local cellname\n");
183             exit(-1);
184         }
185         if (uss_verbose)
186             fprintf(stderr, "No cell specified; assuming '%s'.\n",
187                     uss_Cell);
188     }
189
190     return(0);
191
192 } /*GetCommon*/
193
194
195 /*-----------------------------------------------------------------------
196  * static SaveRestoreInfo
197  *
198  * Description:
199  *      Save all the information required to restore the currently
200  *      parsed user account.
201  *
202  * Arguments:
203  *      None.
204  *
205  * Returns:
206  *      0 if everything went well,
207  *      1 if something went wrong in the function, or
208  *      Lower-level error code if something went wrong below us.
209  *
210  * Environment:
211  *      We need to determine and store the following new pieces of
212  *      information:
213  *              User's AFS ID
214  *              Name of user's volume
215  *              FileServer & partition hosting the volume
216  *
217  * Side Effects:
218  *      As advertised.
219  *------------------------------------------------------------------------*/
220
221 static int SaveRestoreInfo()
222
223 { /*SaveRestoreInfo*/
224
225     static char rn[] =
226        "uss:SaveRestoreInfo";   /*Routine name*/
227     register afs_int32 code;            /*Return code*/
228     afs_int32 deletedUid;               /*Uid to be nuked*/
229
230     /*
231      * Translate the user name to the user ID.
232      */
233     code = uss_ptserver_XlateUser(uss_User, &deletedUid);
234     if (code)
235         return(code);
236 #ifdef USS_DB
237     printf("%s: User '%s' translated to uid %d\n",
238            rn, uss_User, deletedUid);
239 #endif /* USS_DB */
240     sprintf(uss_Uid, "%d", deletedUid);
241
242     /*
243      * Pull out the name of the volume at the given mountpoint, along
244      * with the name of the FileServer and partition hosting it.  This
245      * also sets up all the numerical info for the above.
246      */
247     code = uss_vol_GetVolInfoFromMountPoint(uss_MountPoint);
248     if (code)
249         return(code);
250
251     /*
252      * Report back that we did fine.
253      */
254     return(0);
255
256 } /*SaveRestoreInfo*/
257
258
259 /*-----------------------------------------------------------------------
260  * static DoDelete
261  *
262  * Description:
263  *      With everything properly inserted into the common variables,
264  *      delete the specified user account.
265  *
266  * Arguments:
267  *      None.
268  *
269  * Returns:
270  *      0 if everything went well,
271  *      1 if something went wrong in the function, or
272  *      Lower-level error code if something went wrong below us.
273  *
274  * Environment:
275  *      Nothing interesting.
276  *
277  * Side Effects:
278  *      As advertised.
279  *------------------------------------------------------------------------*/
280
281 static int DoDelete()
282
283 { /*DoDelete*/
284
285     int code;                   /*Return code*/
286
287     /*
288      * Make sure the user name is a lega one.
289      */
290     code = uss_kauth_CheckUserName();
291     if (code)
292         return(code);
293
294     /*
295      * Store all the info about the account before actually doing
296      * anything.
297      */
298     code = SaveRestoreInfo();
299     if (code)
300         return(code);
301
302     if ((uss_VolumeID != 0) && (uss_MountPoint[0] != '\0')) {
303         /*
304          * Unmount the user's volume from the file system.
305          */
306         if (uss_verbose) {
307            fprintf(stderr, "Unmounting volume '%s' (ID %u) mounted at '%s'\n", 
308                    uss_Volume, uss_VolumeID, uss_MountPoint);
309         }
310
311         code = uss_fs_RmMountPoint(uss_MountPoint);
312         if (code) {
313             if (uss_verbose)
314                 fprintf(stderr, "%s: Can't remove mountpoint '%s'\n",
315                         uss_whoami, uss_MountPoint);
316             return(code); /* Must return - we may have incorrect volume */
317         }
318     }
319
320     /*
321      * If our caller has elected to delete the user's volume now,
322      * then do so.
323      */
324     if (!uss_SaveVolume && (uss_VolumeID != 0)) {
325         if (uss_verbose) {
326            fprintf(stderr, "Deleting volume '%s' (ID %u)\n",
327                    uss_Volume, uss_VolumeID);
328         }
329
330         code = uss_vol_DeleteVol(uss_Volume,
331                                  uss_VolumeID,
332                                  uss_Server,
333                                  uss_ServerID,
334                                  uss_Partition,
335                                  uss_PartitionID);
336         if (code) {
337             if (uss_verbose)
338                 fprintf(stderr, "%s: Can't delete volume '%s' (ID %u)\n",
339                         uss_whoami, uss_Volume, uss_VolumeID);
340             return(code);
341         }
342     }
343     else
344         if (uss_verbose && (uss_MountPoint[0] != '\0')) 
345             printf("%s: Warning: Not attempting to delete volume at '%s'\n",
346                    uss_whoami, uss_MountPoint);
347
348     /*
349      * Get rid of the user's authentication entry.
350      */
351     code = uss_kauth_DelUser(uss_User);
352     if (code)
353         return(code);
354
355     /*
356      * Finally, remove the user's AFS ID from the Protection DB and
357      * return that result.
358      */
359     code = uss_ptserver_DelUser(uss_User);
360     return(code);
361     
362 } /*DoDelete*/
363
364
365 /*-----------------------------------------------------------------------
366  * static DelUser
367  *
368  * Description:
369  *      Process the given (non-bulk) delete command.
370  *
371  * Arguments:
372  *      a_as   : Ptr to the command line syntax descriptor.
373  *      a_rock : Ptr to the rock passed in.
374  *
375  * Returns:
376  *      0 if everything went well,
377  *      1 if something went wrong in the function, or
378  *      Lower-level error code if something went wrong below us.
379  *
380  * Environment:
381  *      Nothing interesting.
382  *
383  * Side Effects:
384  *      As advertised.
385  *------------------------------------------------------------------------*/
386
387 static int DelUser(a_as, a_rock)
388      struct cmd_syndesc *a_as;
389      char *a_rock;
390
391 { /*DelUser*/
392
393     int code;
394
395     /*
396      * Before we do anything else, make sure we initialize the
397      * global field settings.
398      */
399     uss_common_Reset();
400     
401     /*
402      * Pull out the fields as passed in by the caller on the command
403      * line.
404      */
405     strcpy(uss_User, a_as->parms[DUP_USER].items->data);
406     if (a_as->parms[DUP_MNTPT].items)   
407         strcpy(uss_MountPoint, a_as->parms[DUP_MNTPT].items->data);
408 #if USS_FUTURE_FEATURES
409 #if USS_DONT_HIDE_SOME_FEATURES
410     strcpy(uss_RestoreDir, a_as->parms[DUP_RESTOREDIR].items->data);
411 #endif /* USS_DONT_HIDE_SOME_FEATURES */
412 #endif /* USS_FUTURE_FEATURES */
413
414 /*
415     if (a_as->parms[DUP_SAVEVOLUME].items)
416         uss_SaveVolume = 1;
417 */
418
419     if (a_as->parms[2].items)
420         {
421                 uss_SaveVolume = 1;
422         }
423
424 #if USS_FUTURE_FEATURES
425 #if USS_DONT_HIDE_SOME_FEATURES
426     if (a_as->parms[DUP_PWDPATH].items)
427         strcpy(uss_PwdPath, a_as->parms[DUP_PWDPATH].items->data);
428     if (a_as->parms[DUP_PWDFORMAT].items)
429         strcpy(uss_PwdFormat, a_as->parms[DUP_PWDFORMAT].items->data);
430 #endif /* USS_DONT_HIDE_SOME_FEATURES */
431 #endif /* USS_FUTURE_FEATURES */
432
433     if (a_as->parms[AUSS_DRYRUN].items)
434         uss_DryRun = 1;
435     if (a_as->parms[AUSS_SKIPAUTH].items)
436         uss_SkipKaserver = 1;
437     if (a_as->parms[AUSS_ADMIN].items) {
438         strcpy(uss_Administrator, a_as->parms[AUSS_ADMIN].items->data);
439         /*      fprintf(stderr, "debugging: uss_Administrator set to '%s'\n",
440                 uss_Administrator);*/
441     }
442     else {
443         /*      fprintf(stderr, "debugging: No administrator value given\n");*/
444         uss_Administrator[0] = '\0';
445     }
446     
447     /*
448      * Initialize uss_AccountCreator().
449      */
450     code = uss_kauth_InitAccountCreator();
451     if (code)
452         return(code);
453
454     /*
455      * Now that the command line arguments are parsed and properly stored,
456      * go for it!
457      */
458
459     return(DoDelete());
460
461 } /*DelUser*/
462
463
464 /*-----------------------------------------------------------------------
465  * static PurgeVolumes
466  *
467  * Description:
468  *      Purge the given volume(s).
469  *
470  * Arguments:
471  *      a_as   : Ptr to the command line syntax descriptor.
472  *      a_rock : Ptr to the rock passed in.
473  *
474  * Returns:
475  *      0 if everything went well,
476  *      1 if something went wrong in the function, or
477  *      Lower-level error code if something went wrong below us.
478  *
479  * Environment:
480  *      Nothing interesting.
481  *
482  * Side Effects:
483  *      As advertised.
484  *------------------------------------------------------------------------*/
485
486 static int PurgeVolumes(a_as, a_rock)
487      struct cmd_syndesc *a_as;
488      char *a_rock;
489
490 { /*PurgeVolumes*/
491
492     fprintf(stderr, "Sorry, purgevolumes has not yet been implemented.\n");
493     return(0);
494
495 } /*PurgeVolumes*/
496
497
498 /*-----------------------------------------------------------------------
499  * static RestoreUser
500  *
501  * Description:
502  *      Process the given delete command.
503  *
504  * Arguments:
505  *      a_as   : Ptr to the command line syntax descriptor.
506  *      a_rock : Ptr to the rock passed in.
507  *
508  * Returns:
509  *      0 if everything went well,
510  *      1 if something went wrong in the function, or
511  *      Lower-level error code if something went wrong below us.
512  *
513  * Environment:
514  *      Nothing interesting.
515  *
516  * Side Effects:
517  *      As advertised.
518  *------------------------------------------------------------------------*/
519
520 static int RestoreUser(a_as, a_rock)
521      struct cmd_syndesc *a_as;
522      char *a_rock;
523
524 { /*RestoreUser*/
525
526     fprintf(stderr, "Sorry, restoreuser has not yet been implemented.\n");
527     return(0);
528
529 } /*RestoreUser*/
530
531
532 /*-----------------------------------------------------------------------
533  * static DoBulkAddLine
534  *
535  * Description:
536  *      Process the given bulk add command.
537  *
538  * Arguments:
539  *      a_buf : Ptr to the buffer holding the bulk add command.
540  *      a_tp  : Ptr to the first char past the opcode.
541  *
542  * Returns:
543  *      0  if everything went well,
544  *      -1 if something went wrong in the function, or
545  *      Lower-level error code if something went wrong below us.
546  *
547  * Environment:
548  *      The required fields are:
549  *              -user
550  *
551  * Side Effects:
552  *      As advertised.
553  *------------------------------------------------------------------------*/
554
555 static int DoBulkAddLine(a_buf, a_tp)
556     char *a_buf;
557     char *a_tp;
558
559 { /*DoBulkAddLine*/
560
561     register int i;                     /*Loop variable*/
562     static char rn[] = "DoBulkAddLine"; /*Routine name*/
563     int overflow;                       /*Overflow in field copy?*/
564
565 #ifdef USS_DB
566     printf("%s: Command buffer left to parse: '%s'\n",
567            rn, a_tp);
568 #endif /* USS_DB */
569     uss_Expires = uss_BulkExpires;
570
571     /*
572      * Pull out all the fields.
573      */
574     a_tp = uss_common_FieldCp(uss_User, a_tp, ':', uss_UserLen, &overflow);
575     if (overflow) {
576         fprintf(stderr,
577                 "%s: * User field in add cmd too long (max is %d chars; truncated value is '%s')\n",
578                 uss_whoami, uss_UserLen, uss_User);
579         return(-1);
580     }
581     if ((*a_tp == '\0') || (*a_tp == '\n')) {
582         fprintf(stderr,
583                 "%s: * The user field must appear in a bulk add command.\n",
584                 uss_whoami);
585         return(-1);
586     }
587
588     a_tp = uss_common_FieldCp(uss_RealName, a_tp, ':', uss_RealNameLen, &overflow);
589     if (overflow) {
590         fprintf(stderr,
591                 "%s: * Real name field in add cmd too long (max is %d chars; truncated value is '%s')\n",
592                 uss_whoami, uss_RealNameLen, uss_RealName);
593         return(-1);
594     }
595     if (uss_RealName[0] == '\0') {
596         /*
597          * The user's real name has not been supplied.  As a
598          * default, we use the account name.
599          */
600         sprintf(uss_RealName, "%s", uss_User);
601         if (uss_verbose)
602             fprintf(stderr,
603                     "%s: Using default real name, '%s'\n",
604                     uss_whoami, uss_User);
605     } /*Use default full name*/
606     
607     a_tp = uss_common_FieldCp(uss_Pwd, a_tp, ':', uss_PwdLen, &overflow);
608     if (overflow) {
609         fprintf(stderr,
610                 "%s: * Password field in add cmd too long (max is %d chars; truncated value is '%s')\n",
611                 uss_whoami, uss_PwdLen, uss_Pwd);
612         return(-1);
613     }
614     if (uss_Pwd[0] == '\0') {
615         /*
616          * The user's password has not been provided.  Use
617          * the default.
618          */
619         sprintf(uss_Pwd, "%s", uss_DEFAULT_PASSWORD);
620         if (uss_verbose)
621             fprintf(stderr,
622                     "%s: Using default password, '%s'\n",
623                     uss_whoami, uss_Pwd);
624     } /*Use default password*/
625     if ((*a_tp == '\0') || (*a_tp == '\n'))
626         goto DoBulkAddLine_ParsingDone;
627     
628
629     {
630       char temp[10];
631       a_tp = uss_common_FieldCp(temp, a_tp, ':', 9, &overflow);
632       if (overflow) {
633         fprintf(stderr,
634         "%s: * Password expiration time is longer than %d characters, ignoring...\n",
635         uss_whoami, 9);
636       }
637       if (temp[0] == '\0') {
638         /* Expiration time not specified.  Use default */
639         if (uss_verbose)
640             fprintf(stderr, "%s: Using default expiration time, '%d'\n",
641                     uss_whoami, uss_Expires);
642       } 
643       else {
644         int te;
645         te = atoi(temp);
646         if (te < 0 || te > 254) {
647           fprintf(stderr,
648             "%s: * Password Expiration must be in [0..254] days, using default %d\n",
649             uss_whoami, uss_Expires);
650         }
651         else uss_Expires = te;
652       }
653
654       if ((*a_tp == '\0') || (*a_tp == '\n'))
655         goto DoBulkAddLine_ParsingDone;
656     }
657
658
659     a_tp = uss_common_FieldCp(uss_Server, a_tp, ':', uss_ServerLen, &overflow);
660     if (overflow) {
661         fprintf(stderr,
662                 "%s: * Server field in add cmd too long (max is %d chars; truncated value is '%s')\n",
663                 uss_whoami, uss_ServerLen, uss_Server);
664         return(-1);
665     }
666     if ((*a_tp == '\0') || (*a_tp == '\n'))
667         goto DoBulkAddLine_ParsingDone;
668
669     a_tp = uss_common_FieldCp(uss_Partition, a_tp, ':', uss_PartitionLen, &overflow);
670     if (overflow) {
671         fprintf(stderr,
672                 "%s: * Partition field in add cmd too long (max is %d chars; truncated value is '%s')\n",
673                 uss_whoami, uss_PartitionLen, uss_Partition);
674         return(-1);
675     }
676     if ((*a_tp == '\0') || (*a_tp == '\n'))
677         goto DoBulkAddLine_ParsingDone;
678
679     a_tp = uss_common_FieldCp(uss_MountPoint, a_tp, ':', uss_MountPointLen,
680                               &overflow);
681     if (overflow) {
682         fprintf(stderr,
683                 "%s: * Mountpoint field in add cmd too long (max is %d chars; truncated value is '%s')\n",
684                 uss_whoami, uss_MountPointLen, uss_MountPoint);
685         return(-1);
686     }
687     if ((*a_tp == '\0') || (*a_tp == '\n'))
688         goto DoBulkAddLine_ParsingDone;
689
690     a_tp = uss_common_FieldCp(uss_Uid, a_tp, ':', uss_UidLen, &overflow);
691     if (overflow) {
692         fprintf(stderr,
693                 "%s: * UID field in add cmd too long (max is %d chars; truncated value is '%s')\n",
694                 uss_whoami, uss_UidLen, uss_Uid);
695         return(-1);
696     }
697     uss_DesiredUID = atoi(uss_Uid);
698     if ((*a_tp == '\0') || (*a_tp == '\n'))
699         goto DoBulkAddLine_ParsingDone;
700
701     for (uss_VarMax = 1; uss_VarMax < 10; uss_VarMax++) {
702         a_tp = uss_common_FieldCp(uss_Var[uss_VarMax],
703                                   a_tp,
704                                   ':',
705                                   uss_MAX_ARG_SIZE,
706                                   &overflow);
707         if (overflow) {
708             fprintf(stderr,
709                     "%s: * Variable %d field in add cmd too long (max is %d chars; truncated value is '%s')\n",
710                     uss_whoami, uss_VarMax, uss_MAX_ARG_SIZE, uss_Var[uss_VarMax]);
711             return(-1);
712         }
713         if ((*a_tp == '\0') || (*a_tp == '\n'))
714             goto DoBulkAddLine_ParsingDone;
715     }
716
717 DoBulkAddLine_ParsingDone:
718     /*
719      * If there's anything left on the line, we ignore it.  Announce
720      * the bulk add parameters we've parsed or filled in if we're
721      * being verbose, then go for it.
722      */
723     if (uss_verbose) {
724         fprintf(stderr, "\nAdding user '%s' ('%s'), password='%s' on server '%s', partition '%s', home directory='%s'",
725                 uss_User, uss_RealName, uss_Pwd,
726                 (uss_Server[0] != '\0' ? uss_Server : "<default>"),
727                 (uss_Partition[0] != '\0' ? uss_Partition : "<default>"),
728                 (uss_MountPoint[0] != '\0' ? uss_MountPoint : "<default>"));
729         if (uss_DesiredUID)
730             fprintf(stderr, ", uid preset to %d\n", uss_DesiredUID);
731         else
732             fprintf(stderr, ", no preset uid\n");
733         for (i = 1; i <= uss_VarMax; i++) {
734             if (uss_Var[i][0] != '\0')
735                 fprintf(stderr, "$%1d='%s' ", i, uss_Var[i]);
736         }
737         if (uss_VarMax > 0)
738             fprintf(stderr, "\n");
739     } /*Verbose status of add command*/
740     
741     /*
742      * Now do the real work.
743      */
744     return(DoAdd());
745
746 } /*DoBulkAddLine*/
747
748
749 /*-----------------------------------------------------------------------
750  * static DoBulkDeleteLine
751  *
752  * Description:
753  *      Process the given bulk delete command.
754  *
755  * Arguments:
756  *      a_buf : Ptr to the buffer holding the bulk delete command.
757  *      a_tp  : Ptr to the first char past the opcode.
758  *
759  * Returns:
760  *      0  if everything went well,
761  *      -1 if something went wrong in the function, or
762  *      Lower-level error code if something went wrong below us.
763  *
764  * Environment:
765  *      The required fields are:
766  *              -user, -mountpoint, -restoredir
767  *
768  * Side Effects:
769  *      As advertised.
770  *------------------------------------------------------------------------*/
771
772 static int DoBulkDeleteLine(a_buf, a_tp)
773     char *a_buf;
774     char *a_tp;
775
776 { /*DoBulkDeleteLine*/
777
778     char volField[32];    /*Value of optional vol disposition field*/
779     int overflow;         /*Was there an overflow in field copying?*/
780
781     /*
782      * Pull out all the fields.
783      */
784     a_tp = uss_common_FieldCp(uss_User, a_tp, ':', uss_UserLen, &overflow);
785     if (overflow) {
786         fprintf(stderr,
787                 "%s: * User field in delete cmd too long (max is %d chars; truncated value is '%s')\n",
788                 uss_whoami, uss_UserLen, uss_User);
789         return(-1);
790     }
791     if ((uss_User[0] == '\0') || (*a_tp == '\0') || (*a_tp == '\n'))
792         goto Delete_MissingRequiredParam;
793
794     a_tp = uss_common_FieldCp(uss_MountPoint, a_tp, ':', uss_MountPointLen,
795                               &overflow);
796     if (overflow) {
797         fprintf(stderr,
798                 "%s: * Mountpoint field in delete cmd too long (max is %d chars; truncated value is '%s')\n",
799                 uss_whoami, uss_MountPointLen, uss_MountPoint);
800         return(-1);
801     }
802 #if USS_FUTURE_FEATURES
803 #if USS_DONT_HIDE_SOME_FEATURES
804     if ((uss_MountPoint[0] == '\0') || (*a_tp == '\0') || (*a_tp == '\n'))
805         goto Delete_MissingRequiredParam;
806 #endif /* USS_DONT_HIDE_SOME_FEATURES */
807 #else
808     if ((*a_tp == '\0') || (*a_tp == '\n'))
809         goto Delete_ParsingDone;
810 #endif /* USS_FUTURE_FEATURES */
811
812 #if USS_FUTURE_FEATURES
813 #if USS_DONT_HIDE_SOME_FEATURES
814     a_tp = uss_common_FieldCp(uss_RestoreDir, a_tp, ':', uss_RestoreDirLen,
815                               &overflow);
816     if (overflow) {
817         fprintf(stderr,
818                 "%s: * RestoreDir field in delete cmd too long (max is %d chars; truncated value is '%s')\n",
819                 uss_whoami, uss_RestoreDirLen, uss_RestoreDir);
820         return(-1);
821     }
822     if (uss_RestoreDir[0] == '\0')
823         goto Delete_MissingRequiredParam;
824     if ((*a_tp == '\0') || (*a_tp == '\n'))
825         goto Delete_ParsingDone;
826
827     a_tp = uss_common_FieldCp(uss_PwdPath, a_tp, ':', uss_PwdPathLen, &overflow);
828     if (overflow) {
829         fprintf(stderr,
830                 "%s: * Password path field in delete cmd too long (max is %d chars; truncated value is '%s')\n",
831                 uss_whoami, uss_PwdPathLen, uss_PwdPath);
832         return(-1);
833     }
834     if ((*a_tp == '\0') || (*a_tp == '\n'))
835         goto Delete_ParsingDone;
836
837     a_tp = uss_common_FieldCp(uss_PwdFormat, a_tp, ':', uss_PwdFormatLen, &overflow);
838     if (overflow) {
839         fprintf(stderr,
840                 "%s: * Password format field in delete cmd too long (max is %d chars; truncated value is '%s')\n",
841                 uss_whoami, uss_PwdFormatLen, uss_PwdFormat);
842         return(-1);
843     }
844     if ((*a_tp == '\0') || (*a_tp == '\n'))
845         goto Delete_ParsingDone;
846 #endif /* USS_DONT_HIDE_SOME_FEATURES */
847 #endif /* USS_FUTURE_FEATURES */
848
849     a_tp = uss_common_FieldCp(volField, a_tp, ':', 32, &overflow);
850     if (overflow) {
851         fprintf(stderr,
852                 "%s: * Volume save/del field in delete cmd too long (max is 32 chars; truncated value is '%s')\n",
853                 uss_whoami, volField);
854         return(-1);
855     }
856     if ((*a_tp == '\0') || (*a_tp == '\n'))
857         goto Delete_ParsingDone;
858
859     if (strcmp(volField, "delvolume") == 0)
860         uss_SaveVolume = 0;
861     else
862         uss_SaveVolume = 1;
863
864   Delete_ParsingDone:
865     /*
866      * If there's anything left on the line, we ignore it.  Announce
867      * the bulk delete parameters we've parsed if we're being verbose,
868      * then go for it.
869      */
870     if (uss_verbose) {
871 #if USS_FUTURE_FEATURES
872 #if USS_DONT_HIDE_SOME_FEATURES
873         fprintf(stderr,
874                 "\nDeleting user '%s' mounted at '%s', restoredir='%s', pwd path='%s', pwd format='%s'",
875                 uss_User, uss_MountPoint, uss_RestoreDir, uss_PwdPath,
876                 uss_PwdFormat);
877 #endif /* USS_DONT_HIDE_SOME_FEATURES */
878 #else
879         fprintf(stderr,
880                 "\nDeleting user '%s' mounted at '%s'",
881                 uss_User, uss_MountPoint);
882 #endif /* USS_FUTURE_FEATURES */
883         if (uss_SaveVolume)
884             fprintf(stderr, ", saving user's volume\n");
885         else
886             fprintf(stderr, ", deleting user's volume\n");
887     } /*Verbose status of delete command*/
888
889     /*
890      * Now do the real work.
891      */
892     return(DoDelete());
893
894   Delete_MissingRequiredParam:
895     fprintf(stderr,
896             "%s: * All of the user, mountpoint, and restoredir fields must appear in a bulk delete command line.\n",
897             uss_whoami);
898     return(-1);
899
900 } /*DoBulkDeleteLine*/
901
902 #if USS_FUTURE_FEATURES
903 #if USS_DONT_HIDE_SOME_FEATURES
904 /*-----------------------------------------------------------------------
905  * static DoBulkPurgeVolumeLine
906  *
907  * Description:
908  *      Process the given bulk add command.
909  *
910  * Arguments:
911  *      a_buf : Ptr to the buffer holding the bulk add command.
912  *      a_tp  : Ptr to the first char past the opcode.
913  *
914  * Returns:
915  *      0  if everything went well,
916  *      -1 if something went wrong in the function, or
917  *      Lower-level error code if something went wrong below us.
918  *
919  * Environment:
920  *      Nothing interesting.
921  *
922  * Side Effects:
923  *      As advertised.
924  *------------------------------------------------------------------------*/
925
926 static int DoBulkPurgeVolumeLine(a_buf, a_tp)
927     char *a_buf;
928     char *a_tp;
929
930 { /*DoBulkPurgeVolumeLine*/
931
932     register int i;             /*Loop variable*/
933     int overflow;               /*Did a field copy overflow happen?*/
934
935     /*
936      * Pull out all the fields.
937      */
938     a_tp = uss_common_FieldCp(uss_User, a_tp, ':', uss_UserLen, &overflow);
939     if (overflow) {
940         fprintf(stderr,
941                 "%s: * User field in purgevolume cmd too long (max is %d chars; truncated value is '%s')\n",
942                 uss_whoami, uss_UserLen, uss_User);
943         return(-1);
944     }
945     if ((*a_tp == '\0') || (*a_tp == '\n')) {
946         fprintf(stderr,
947                 "%s: * The user field must appear in a bulk add command.\n",
948                 uss_whoami);
949         return(-1);
950     }
951
952     a_tp = uss_common_FieldCp(uss_RealName, a_tp, ':', uss_RealNameLen, &overflow);
953     if (overflow) {
954         fprintf(stderr,
955                 "%s: * Real name field in purgevolume cmd too long (max is %d chars; truncated value is '%s')\n",
956                 uss_whoami, uss_RealNameLen, uss_RealName);
957         return(-1);
958     }
959     if (uss_RealName[0] == '\0') {
960         /*
961          * The user's real name has not been supplied.  As a
962          * default, we use the account name.
963          */
964         sprintf(uss_RealName, "%s", uss_User);
965         if (uss_verbose)
966             fprintf(stderr,
967                     "%s: Using default real name, '%s'\n",
968                     uss_whoami, uss_User);
969     } /*Use default full name*/
970     
971     a_tp = uss_common_FieldCp(uss_Pwd, a_tp, ':', uss_PwdLen, &overflow);
972     if (overflow) {
973         fprintf(stderr,
974                 "%s: * Password field in purgevolume cmd too long (max is %d chars; truncated value is '%s')\n",
975                 uss_whoami, uss_PwdLen, uss_Pwd);
976         return(-1);
977     }
978     if (uss_Pwd[0] == '\0') {
979         /*
980          * The user's password has not been provided.  Use
981          * the default.
982          */
983         sprintf(uss_Pwd, "%s", uss_DEFAULT_PASSWORD);
984         if (uss_verbose)
985             fprintf(stderr,
986                     "%s: Using default password, '%s'\n",
987                     uss_whoami, uss_Pwd);
988     } /*Use default password*/
989     if ((*a_tp == '\0') || (*a_tp == '\n'))
990         return(0);
991
992     a_tp = uss_common_FieldCp(uss_Server, a_tp, ':', uss_ServerLen, &overflow);
993     if (overflow) {
994         fprintf(stderr,
995                 "%s: * Server field too long (max is %d chars)\n",
996                 uss_whoami, uss_ServerLen);
997         return(-1);
998     }
999     if ((*a_tp == '\0') || (*a_tp == '\n'))
1000         return(0);
1001
1002     a_tp = uss_common_FieldCp(uss_Partition, a_tp, ':', uss_PartitionLen, &overflow);
1003     if (overflow) {
1004         fprintf(stderr,
1005                 "%s: * Partition field too long (max is %d chars)\n",
1006                 uss_whoami, uss_PartitionLen);
1007         return(-1);
1008     }
1009     if ((*a_tp == '\0') || (*a_tp == '\n'))
1010         return(0);
1011
1012     a_tp = uss_common_FieldCp(uss_MountPoint, a_tp, ':', uss_MountPointLen,
1013                               &overflow);
1014     if (overflow) {
1015         fprintf(stderr,
1016                 "%s: * Mountpoint field too long (max is %d chars)\n",
1017                 uss_whoami, uss_MountPointLen);
1018         return(-1);
1019     }
1020     if ((*a_tp == '\0') || (*a_tp == '\n'))
1021         return(0);
1022
1023     a_tp = uss_common_FieldCp(uss_Uid, a_tp, ':', uss_UidLen, &overflow);
1024     if (overflow) {
1025         fprintf(stderr,
1026                 "%s: * UID field too long (max is %d chars)\n",
1027                 uss_whoami, uss_UidLen);
1028         return(-1);
1029     }
1030     uss_DesiredUID = atoi(uss_Uid);
1031     if ((*a_tp == '\0') || (*a_tp == '\n'))
1032         return(0);
1033
1034     for (uss_VarMax = 1; uss_VarMax < 10; uss_VarMax++) {
1035         a_tp = uss_common_FieldCp(uss_Var[uss_VarMax],
1036                                   a_tp,
1037                                   ':',
1038                                   uss_MAX_ARG_SIZE,
1039                                   &overflow);
1040         if (overflow) {
1041             fprintf(stderr,
1042                     "%s: * Variable %d field too long (max is %d chars)\n",
1043                     uss_whoami, uss_VarMax, uss_MAX_ARG_SIZE);
1044             return(-1);
1045         }
1046         if ((*a_tp == '\0') || (*a_tp == '\n'))
1047             return(0);
1048     }
1049
1050     /*
1051      * If there's anything left on the line, we ignore it.  Announce
1052      * the bulk add parameters we've parsed or filled in if we're
1053      * being verbose, then go for it.
1054      */
1055     if (uss_verbose) {
1056         fprintf(stderr, "\nAdding user '%s' ('%s'), password='%s' on server '%s', partition '%s', home directory='%s'",
1057                 uss_User, uss_RealName, uss_Pwd,
1058                 (uss_Server[0] != '\0' ? uss_Server : "<default>"),
1059                 (uss_Partition[0] != '\0' ? uss_Partition : "<default>"),
1060                 (uss_MountPoint[0] != '\0' ? uss_MountPoint : "<default>"));
1061         if (uss_DesiredUID)
1062             fprintf(stderr, ", uid preset to %d\n", uss_DesiredUID);
1063         else
1064             fprintf(stderr, ", no preset uid\n");
1065         for (i = 1; i <= uss_VarMax; i++) {
1066             if (uss_Var[i][0] != '\0')
1067                 fprintf(stderr, "$%1d='%s' ", i, uss_Var[i]);
1068         }
1069         if (uss_VarMax > 0)
1070             fprintf(stderr, "\n");
1071     } /*Verbose status of add command*/
1072     
1073     /*
1074      * Now do the real work.
1075      */
1076     return(DoAdd());
1077
1078 } /*DoBulkPurgeVolumeLine*/
1079 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1080 #endif /* USS_FUTURE_FEATURES */
1081
1082 #if USS_FUTURE_FEATURES
1083 #if USS_DONT_HIDE_SOME_FEATURES
1084 /*-----------------------------------------------------------------------
1085  * static DoBulkRestoreLine
1086  *
1087  * Description:
1088  *      Process the given bulk add command.
1089  *
1090  * Arguments:
1091  *      a_buf : Ptr to the buffer holding the bulk add command.
1092  *      a_tp  : Ptr to the first char past the opcode.
1093  *
1094  * Returns:
1095  *      0  if everything went well,
1096  *      -1 if something went wrong in the function, or
1097  *      Lower-level error code if something went wrong below us.
1098  *
1099  * Environment:
1100  *      Nothing interesting.
1101  *
1102  * Side Effects:
1103  *      As advertised.
1104  *------------------------------------------------------------------------*/
1105
1106 static int DoBulkRestoreLine(a_buf, a_tp)
1107     char *a_buf;
1108     char *a_tp;
1109
1110 { /*DoBulkRestoreLine*/
1111
1112     register int i;             /*Loop variable*/
1113     int overflow;               /*Overflow occur on field copy?*/
1114
1115     /*
1116      * Pull out all the fields.
1117      */
1118     a_tp = uss_common_FieldCp(uss_User, a_tp, ':', uss_UserLen, &overflow);
1119     if (overflow) {
1120         fprintf(stderr,
1121                 "%s: * User field too long (max is %d chars)\n",
1122                 uss_whoami, uss_UserLen);
1123         return(-1);
1124     }
1125     if ((*a_tp == '\0') || (*a_tp == '\n')) {
1126         fprintf(stderr,
1127                 "%s: * The user field must appear in a bulk add command.\n",
1128                 uss_whoami);
1129         return(-1);
1130     }
1131
1132     a_tp = uss_common_FieldCp(uss_RealName, a_tp, ':', uss_RealNameLen, &overflow);
1133     if (overflow) {
1134         fprintf(stderr,
1135                 "%s: * Real name field too long (max is %d chars)\n",
1136                 uss_whoami, uss_RealNameLen);
1137         return(-1);
1138     }
1139     if (uss_RealName[0] == '\0') {
1140         /*
1141          * The user's real name has not been supplied.  As a
1142          * default, we use the account name.
1143          */
1144         sprintf(uss_RealName, "%s", uss_User);
1145         if (uss_verbose)
1146             fprintf(stderr,
1147                     "%s: Using default real name, '%s'\n",
1148                     uss_whoami, uss_User);
1149     } /*Use default full name*/
1150     
1151     a_tp = uss_common_FieldCp(uss_Pwd, a_tp, ':', uss_PwdLen, &overflow);
1152     if (overflow) {
1153         fprintf(stderr,
1154                 "%s: * Password field too long (max is %d chars)\n",
1155                 uss_whoami, uss_PwdLen);
1156         return(-1);
1157     }
1158     if (uss_Pwd[0] == '\0') {
1159         /*
1160          * The user's password has not been provided.  Use
1161          * the default.
1162          */
1163         sprintf(uss_Pwd, "%s", uss_DEFAULT_PASSWORD);
1164         if (uss_verbose)
1165             fprintf(stderr,
1166                     "%s: Using default password, '%s'\n",
1167                     uss_whoami, uss_Pwd);
1168     } /*Use default password*/
1169     if ((*a_tp == '\0') || (*a_tp == '\n'))
1170         return(0);
1171
1172     a_tp = uss_common_FieldCp(uss_Server, a_tp, ':', uss_ServerLen, &overflow);
1173     if (overflow) {
1174         fprintf(stderr,
1175                 "%s: * Server field too long (max is %d chars)\n",
1176                 uss_whoami, uss_ServerLen);
1177         return(-1);
1178     }
1179     if ((*a_tp == '\0') || (*a_tp == '\n'))
1180         return(0);
1181
1182     a_tp = uss_common_FieldCp(uss_Partition, a_tp, ':', uss_PartitionLen,
1183                               &overflow);
1184     if (overflow) {
1185         fprintf(stderr,
1186                 "%s: * Partition field too long (max is %d chars)\n",
1187                 uss_whoami, uss_PartitionLen);
1188         return(-1);
1189     }
1190     if ((*a_tp == '\0') || (*a_tp == '\n'))
1191         return(0);
1192
1193     a_tp = uss_common_FieldCp(uss_MountPoint, a_tp, ':', uss_MountPointLen,
1194                               &overflow);
1195     if (overflow) {
1196         fprintf(stderr,
1197                 "%s: * mountpoint field too long (max is %d chars)\n",
1198                 uss_whoami, uss_MountPointLen);
1199         return(-1);
1200     }
1201     if ((*a_tp == '\0') || (*a_tp == '\n'))
1202         return(0);
1203
1204     a_tp = uss_common_FieldCp(uss_Uid, a_tp, ':', uss_UidLen, &overflow);
1205     if (overflow) {
1206         fprintf(stderr,
1207                 "%s: * UID field too long (max is %d chars)\n",
1208                 uss_whoami, uss_UidLen);
1209         return(-1);
1210     }
1211     uss_DesiredUID = atoi(uss_Uid);
1212     if ((*a_tp == '\0') || (*a_tp == '\n'))
1213         return(0);
1214
1215     for (uss_VarMax = 1; uss_VarMax < 10; uss_VarMax++) {
1216         a_tp = uss_common_FieldCp(uss_Var[uss_VarMax],
1217                                   a_tp,
1218                                   ':',
1219                                   uss_MAX_ARG_SIZE,
1220                                   &overflow);
1221         if (overflow) {
1222             fprintf(stderr,
1223                     "%s: * Variable %d field too long (max is %d chars)\n",
1224                     uss_whoami, uss_VarMax, uss_MAX_ARG_SIZE);
1225             return(-1);
1226         }
1227         if ((*a_tp == '\0') || (*a_tp == '\n'))
1228             return(0);
1229     }
1230
1231     /*
1232      * If there's anything left on the line, we ignore it.  Announce
1233      * the bulk add parameters we've parsed or filled in if we're
1234      * being verbose, then go for it.
1235      */
1236     if (uss_verbose) {
1237         fprintf(stderr, "\nAdding user '%s' ('%s'), password='%s' on server '%s', partition '%s', home directory='%s'",
1238                 uss_User, uss_RealName, uss_Pwd,
1239                 (uss_Server[0] != '\0' ? uss_Server : "<default>"),
1240                 (uss_Partition[0] != '\0' ? uss_Partition : "<default>"),
1241                 (uss_MountPoint[0] != '\0' ? uss_MountPoint : "<default>"));
1242         if (uss_DesiredUID)
1243             fprintf(stderr, ", uid preset to %d\n", uss_DesiredUID);
1244         else
1245             fprintf(stderr, ", no preset uid\n");
1246         for (i = 1; i <= uss_VarMax; i++) {
1247             if (uss_Var[i][0] != '\0')
1248                 fprintf(stderr, "$%1d='%s' ", i, uss_Var[i]);
1249         }
1250         if (uss_VarMax > 0)
1251             fprintf(stderr, "\n");
1252     } /*Verbose status of add command*/
1253     
1254     /*
1255      * Now do the real work.
1256      */
1257     return(DoRestore());
1258
1259 } /*DoBulkRestoreLine*/
1260 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1261 #endif /* USS_FUTURE_FEATURES */
1262
1263
1264 /*-----------------------------------------------------------------------
1265  * static DoBulkExecLine
1266  *
1267  * Description:
1268  *      Process the given bulk exec command.
1269  *
1270  * Arguments:
1271  *      a_buf : Ptr to the buffer holding the bulk exec command.
1272  *      a_tp  : Ptr to the first char past the opcode.
1273  *
1274  * Returns:
1275  *      0  if everything went well,
1276  *      -1 if something went wrong in the function, or
1277  *      Lower-level error code if something went wrong below us.
1278  *
1279  * Environment:
1280  *      Nothing interesting.
1281  *
1282  * Side Effects:
1283  *      As advertised.
1284  *------------------------------------------------------------------------*/
1285
1286 static int DoBulkExecLine(a_buf, a_tp)
1287     char *a_buf;
1288     char *a_tp;
1289
1290 { /*DoBulkExecLine*/
1291
1292     register afs_int32 code;            /*Return code*/
1293
1294     /*
1295      * Really, uss_procs_Exec does all the work for us!
1296      */
1297     code = uss_procs_Exec(a_tp);
1298     return(code);
1299
1300 } /*DoBulkExecLine*/
1301
1302
1303 /*-----------------------------------------------------------------------
1304  * static HandleBulk
1305  *
1306  * Description:
1307  *      Process the given bulk command.
1308  *
1309  * Arguments:
1310  *      a_as   : Ptr to the command line syntax descriptor.
1311  *      a_rock : Ptr to the rock passed in.
1312  *
1313  * Returns:
1314  *      0 if everything went well,
1315  *      1 if something went wrong in the function, or
1316  *      Lower-level error code if something went wrong below us.
1317  *
1318  * Environment:
1319  *      Nothing interesting.
1320  *
1321  * Side Effects:
1322  *      As advertised.
1323  *------------------------------------------------------------------------*/
1324 extern int Pipe;
1325 static int HandleBulk(a_as, a_rock)
1326      register struct cmd_syndesc *a_as;
1327      char *a_rock;
1328
1329 { /*HandleBulk*/
1330
1331 #define USS_BULK_CMD_CHARS       128
1332 #define USS_BULK_BUF_CHARS      1024
1333
1334     char cmd[USS_BULK_CMD_CHARS], buf[USS_BULK_BUF_CHARS];
1335     FILE *infile;
1336     char *tp;
1337     int overflow;
1338     int code;
1339
1340         int line_no=0;
1341         int error;
1342         char tbuf[USS_BULK_BUF_CHARS];
1343
1344     /*
1345      * Open up the bulk file, croak if we can't.
1346      */
1347     if ((infile = fopen(a_as->parms[ABULK_FILE].items->data, "r")) == NULL) {
1348         fprintf(stderr,
1349                 "%s: * Failed to open input file %s\n",
1350                 uss_whoami, a_as->parms[ABULK_FILE].items->data);
1351         return(-1);
1352     }
1353     
1354     /*
1355      * Pull out the other fields as passed in by the caller on the
1356      * command line.
1357      */
1358     if (a_as->parms[AUSS_DRYRUN].items)
1359         uss_DryRun = 1;
1360     if (a_as->parms[AUSS_SKIPAUTH].items)
1361         uss_SkipKaserver = 1;
1362     if (a_as->parms[AUSS_OVERWRITE].items)
1363         uss_Overwrite = 1;
1364     if (a_as->parms[AUSS_PIPE].items)
1365         Pipe = 1;
1366     if (a_as->parms[AUSS_ADMIN].items)
1367         strcpy(uss_Administrator, a_as->parms[AUSS_ADMIN].items->data);
1368     else
1369         uss_Administrator[0] = '\0';
1370
1371     if (a_as->parms[AUSS_PWEXPIRES].items) {
1372         uss_BulkExpires = atoi(a_as->parms[AUSS_PWEXPIRES].items->data);
1373         if (uss_BulkExpires < 0 || uss_BulkExpires > 254) {
1374           fprintf(stderr,"%s: Password Expiration must be in [0..255] days\n",
1375                         uss_whoami);
1376           return(-1);
1377         }
1378       }
1379     else
1380       uss_BulkExpires = 0;
1381     
1382     /*
1383      * Initialize uss_AccountCreator().
1384      */
1385     code = uss_kauth_InitAccountCreator();
1386     if (code)
1387         return(code);
1388
1389     /*
1390      * Process all the lines in the bulk command file.
1391      */
1392     uss_VarMax = 0; /*No uss vars picked up yet*/
1393     while (fgets(buf, sizeof(buf), infile) != NULL) {
1394
1395         /* skip blank line */
1396
1397         if(buf[0]=='\n')
1398                 continue;
1399
1400         /* After executing the line, print the line and the result */
1401         if (line_no) {
1402            if (error == UNOQUORUM) {
1403               IOMGR_Sleep(1);
1404            }
1405
1406            if (!error) error = uss_perr;
1407            printf("LINE %d %s %s", line_no, (error?"FAIL":"SUCCESS"), tbuf);
1408            fflush(stdout);
1409         }
1410
1411         /*
1412          * Reset the common variables for each command line
1413          * processed.
1414          */
1415         uss_common_Reset();
1416
1417         sprintf(tbuf,"%s",buf);
1418
1419         /*
1420         First line of file = line 1.
1421         */
1422
1423         ++line_no;
1424
1425         /*
1426          * Get the opcode and act upon it.
1427          */
1428         tp = uss_common_FieldCp(cmd, buf, ' ', USS_BULK_CMD_CHARS, &overflow);
1429         if (overflow) {
1430             fprintf(stderr,
1431                     "%s: * Bulk opcode field too long (max is %d chars)\n",
1432                     uss_whoami, USS_BULK_CMD_CHARS);
1433
1434                 error = -1;
1435                 continue;
1436 /*
1437             return(-1);
1438 */
1439         }
1440         if (strcmp(cmd, "add") == 0) {
1441             error=DoBulkAddLine(buf, tp);
1442             continue;
1443         }
1444         if (strcmp(cmd, "delete") == 0) {
1445             error=DoBulkDeleteLine(buf, tp);
1446             continue;
1447         }
1448         if (strcmp(cmd, "delvolume") == 0) {
1449             uss_SaveVolume = 0;
1450                 error=0;
1451             continue;
1452         }
1453 #if USS_FUTURE_FEATURES
1454 #if USS_DONT_HIDE_SOME_FEATURES
1455         if (strcmp(cmd, "purgevolume") == 0) {
1456             error=DoBulkPurgeVolumeLine(buf, tp);
1457             continue;
1458         }
1459         if (strcmp(cmd, "pwdformat") == 0) {
1460             /*Set the password format here*/
1461             continue;
1462         }
1463         if (strcmp(cmd, "pwdpath") == 0) {
1464             /*Set the password path here*/
1465             continue;
1466         }
1467         if (strcmp(cmd, "restore") == 0) {
1468             error=DoBulkRestoreLine(buf, tp);
1469             continue;
1470         }
1471 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1472 #endif /* USS_FUTURE_FEATURES */
1473         if (strcmp(cmd, "savevolume") == 0) {
1474             /*Set the savevolume flag here*/
1475             continue;
1476         }
1477         if (strcmp(cmd, "exec") == 0) {
1478             error=DoBulkExecLine(buf, tp);
1479             continue;
1480         }
1481
1482         /*
1483          * If none of the valid opcodes match, see if the line is either
1484          * a comment of a blank.  If so, just ignore it.  Otherwise, we
1485          * have a problem.
1486          */
1487         if ((cmd[0] != '#') && (cmd[0] != '\0')) {
1488             fprintf(stderr,
1489                     "%s: ** Unrecognized command ('%s') in bulk file\n",
1490                     uss_whoami, cmd);
1491
1492                 error = -1;
1493                 continue;
1494
1495 /*
1496             return(-1);
1497 */
1498         } /*Bad bulk line*/
1499     } /*Process a line in the bulk file*/
1500
1501     /* Last line. */
1502     if (line_no) {
1503        if (!error) error = uss_perr;
1504        printf("LINE %d %s %s", line_no, (error?"FAIL":"SUCCESS"), tbuf);
1505        fflush(stdout);
1506     }
1507
1508     return(0);
1509 } /*HandleBulk*/
1510
1511
1512 /*-----------------------------------------------------------------------
1513  * static AddUser
1514  *
1515  * Description:
1516  *      Process the given (non-bulk) add command.
1517  *
1518  * Arguments:
1519  *      a_as   : Ptr to the command line syntax descriptor.
1520  *      a_rock : Ptr to the rock passed in.
1521  *
1522  * Returns:
1523  *      0 if everything went well,
1524  *      1 if something went wrong in the function, or
1525  *      Lower-level error code if something went wrong below us.
1526  *
1527  * Environment:
1528  *      Nothing interesting.
1529  *
1530  * Side Effects:
1531  *      As advertised.
1532  *------------------------------------------------------------------------*/
1533
1534 static int AddUser(a_as, a_rock)
1535      register struct cmd_syndesc *a_as;
1536      char *a_rock;
1537
1538 { /*AddUser*/
1539
1540     int i;
1541     register struct cmd_item *ti;
1542     int code;
1543
1544     /*
1545      * Before we do anything else, make sure we initialize the
1546      * global field settings.
1547      */
1548     uss_common_Reset();
1549     
1550     /*
1551      * Pull out the fields as passed in by the caller on the command
1552      * line.
1553      */
1554     strcpy(uss_User, a_as->parms[AUP_USER].items->data);
1555     if (a_as->parms[AUP_REALNAME].items)
1556         strcpy(uss_RealName, a_as->parms[AUP_REALNAME].items->data);
1557     else
1558         strcpy(uss_RealName, uss_User);
1559     if (a_as->parms[AUP_PASSWD].items)
1560         strcpy(uss_Pwd, a_as->parms[AUP_PASSWD].items->data);
1561     else
1562         strcpy(uss_Pwd, uss_DEFAULT_PASSWORD);
1563     if (a_as->parms[AUP_SERVER].items)
1564         strcpy(uss_Server, a_as->parms[AUP_SERVER].items->data);
1565     if (a_as->parms[AUP_PART].items)
1566         strcpy(uss_Partition, a_as->parms[AUP_PART].items->data);
1567     if (a_as->parms[AUP_MNTPT].items)
1568         strcpy(uss_MountPoint, a_as->parms[AUP_MNTPT].items->data);
1569     if (a_as->parms[AUP_UID].items)
1570         uss_DesiredUID = atoi(a_as->parms[AUP_UID].items->data);
1571     else
1572         uss_DesiredUID = 0;
1573     if (a_as->parms[AUP_PWEXPIRES].items) {
1574         uss_Expires = atoi(a_as->parms[AUP_PWEXPIRES].items->data);
1575         if (uss_Expires < 0 || uss_Expires > 254) {
1576           fprintf(stderr,"%s: Password Expiration must be in [0..255] days\n",
1577                         uss_whoami);
1578           return(-1);
1579         }
1580       }
1581     else
1582       uss_Expires = 0;
1583
1584     if (a_as->parms[AUSS_DRYRUN].items)
1585         uss_DryRun = 1;
1586     if (a_as->parms[AUSS_SKIPAUTH].items)
1587         uss_SkipKaserver = 1;
1588     if (a_as->parms[AUSS_OVERWRITE].items)
1589         uss_Overwrite = 1;
1590     if (a_as->parms[AUSS_ADMIN].items) {
1591         strcpy(uss_Administrator, a_as->parms[AUSS_ADMIN].items->data);
1592         /*      fprintf(stderr, "debugging: uss_Administrator set to '%s'\n",
1593                 uss_Administrator);*/
1594     }
1595     else {
1596         /*      fprintf(stderr, "debugging: No administrator value given\n");*/
1597         uss_Administrator[0] = '\0';
1598     }
1599     
1600     if (a_as->parms[AUSS_VAR].items) {
1601         for (ti = a_as->parms[AUSS_VAR].items; ti; ti = ti->next) {
1602             i = atoi(ti->data);
1603             if (i <0 || i>9 || (i==0 && *ti->data != '0')) {
1604                 fprintf(stderr,
1605                         "%s: Bad -var format: must be '0 val0 1 val1 ... 9 val9'\n",
1606                         uss_whoami);
1607                 return(-1);
1608             }
1609             ti = ti->next;
1610             if (!ti) {
1611                 fprintf(stderr,
1612                         "%s: -var values must appear in pairs: 'Num val'\n",
1613                         uss_whoami);
1614                 return(-1);
1615             }
1616             strcpy(uss_Var[i], ti->data);
1617             if (i > uss_VarMax) 
1618                 uss_VarMax = i;
1619         } /*Remember each VAR item*/
1620     } /*VAR items exist*/
1621
1622     /*
1623      * Initialize uss_AccountCreator().
1624      */
1625     code = uss_kauth_InitAccountCreator();
1626     if (code)
1627         return(code);
1628
1629     /*
1630      * Now that the command line arguments are parsed and properly stored,
1631      * go for it!
1632      */
1633     return(DoAdd());
1634
1635 } /*AddUser*/
1636
1637
1638 /*-----------------------------------------------------------------------
1639  * static DoAdd
1640  *
1641  * Description:
1642  *      Create the desired user account, having parsed the add command
1643  *      from either the command line or a bulk file.
1644  *
1645  * Arguments:
1646  *      None.
1647  *
1648  * Returns:
1649  *      0 if everything went well,
1650  *      1 if something went wrong in the function, or
1651  *      Lower-level error code if something went wrong below us.
1652  *
1653  * Environment:
1654  *      All values needed have been put in the common variables.
1655  *
1656  * Side Effects:
1657  *      As advertised.
1658  *------------------------------------------------------------------------*/
1659
1660 static int DoAdd()
1661
1662 { /*DoAdd*/
1663
1664     int code;           /*Return code*/
1665
1666     /*
1667      * Make sure the user name is legal.
1668      */
1669     code = uss_kauth_CheckUserName();
1670     if (code)
1671         return(code);
1672
1673     /*
1674      * This time around, we start off assuming the global value of the
1675      * -overwrite flag.
1676      */
1677     uss_OverwriteThisOne = uss_Overwrite;
1678
1679     /*
1680      * Open up the template file before doing any real processing,
1681      * so we can quit early should it not be found.
1682      */
1683     if (yyin == NULL) {
1684         if ((yyin = uss_procs_FindAndOpen(Template)) == NULL) {
1685             fprintf(stderr,
1686                     "%s: ** Can't open template file '%s'\n",
1687                     uss_whoami, Template);
1688             return(-1);
1689         }
1690         yyout = fopen("/dev/null", "w");
1691     }
1692     else
1693         rewind(yyin);
1694
1695     /*
1696      * Add the new user to the Protection DB.
1697      */
1698     code = uss_ptserver_AddUser(uss_User, uss_Uid);
1699     if (code) {
1700         fprintf(stderr,
1701                 "%s: Failed to add user '%s' to the Protection DB\n",
1702                 uss_whoami, uss_User);
1703         return(code);
1704     }
1705
1706     /*
1707      * Add the new user to the Authentication DB.
1708      */
1709     code = uss_kauth_AddUser(uss_User, uss_Pwd);
1710     if (code) {
1711         fprintf(stderr,
1712                 "%s: Can't add user '%s' to the Authentication DB\n",
1713                 uss_whoami, uss_User);
1714         return(code);
1715     }
1716     
1717     /*
1718      * Process the items covered by the template file.
1719      */
1720     if (yyparse() && (!uss_ignoreFlag))
1721         exit(-1);
1722
1723     /*
1724      * Finally, clean up after ourselves, removing the uss_AccountCreator
1725      * from various of the new user's ACLs.
1726      */
1727     return(uss_acl_CleanUp());
1728
1729 } /*DoAdd*/
1730
1731
1732 #if USS_FUTURE_FEATURES
1733 #if USS_DONT_HIDE_SOME_FEATURES
1734 /*-----------------------------------------------------------------------
1735  * static DoRestore
1736  *
1737  * Description:
1738  *      Perform the parsed restore command.
1739  *
1740  * Arguments:
1741  *      None.
1742  *
1743  * Returns:
1744  *      0 if everything went well,
1745  *      1 if something went wrong in the function, or
1746  *      Lower-level error code if something went wrong below us.
1747  *
1748  * Environment:
1749  *      All values needed have been put in the common variables.
1750  *
1751  * Side Effects:
1752  *      As advertised.
1753  *------------------------------------------------------------------------*/
1754
1755 static int DoRestore()
1756
1757 { /*DoRestore*/
1758
1759   return(0);
1760
1761 } /*DoRestore*/
1762 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1763 #endif /* USS_FUTURE_FEATURES */
1764
1765
1766 /*-----------------------------------------------------------------------
1767  * static InitETTables
1768  *
1769  * Description:
1770  *      Set up the error code tables for the various modules we use.
1771  *
1772  * Arguments:
1773  *      None.
1774  *
1775  * Returns:
1776  *      Nothing.
1777  *
1778  * Environment:
1779  *      Nothing interesting.
1780  *
1781  * Side Effects:
1782  *      As advertised.
1783  *------------------------------------------------------------------------*/
1784
1785 void InitETTables()
1786
1787 { /*InitETTables*/
1788
1789
1790     /*
1791      * In order to get error code -> error message translations to work,
1792      * we have to initialize all error tables.
1793      */
1794     initialize_CMD_error_table();
1795     initialize_RXK_error_table();
1796     initialize_KTC_error_table();
1797     initialize_KA_error_table();
1798     initialize_ACFG_error_table();
1799     initialize_VL_error_table();
1800     initialize_PT_error_table();
1801     initialize_U_error_table();
1802
1803 } /*InitETTables*/
1804
1805
1806 int osi_audit()
1807 {
1808 /* this sucks but it works for now.
1809 */
1810 return 0;
1811 }
1812
1813 #include "AFS_component_version_number.c"
1814
1815 main(argc,argv)
1816      int argc;
1817      char *argv[];
1818
1819 { /*Main routine*/
1820
1821     register struct cmd_syndesc *cs;    /*Command line syntax descriptor*/
1822     register afs_int32 code;                    /*Return code*/
1823
1824 #ifdef  AFS_AIX32_ENV
1825     /*
1826      * The following signal action for AIX is necessary so that in case of a 
1827      * crash (i.e. core is generated) we can include the user's data section 
1828      * in the core dump. Unfortunately, by default, only a partial core is
1829      * generated which, in many cases, isn't too useful.
1830      */
1831     struct sigaction nsa;
1832     
1833     sigemptyset(&nsa.sa_mask);
1834     nsa.sa_handler = SIG_DFL;
1835     nsa.sa_flags = SA_FULLDUMP;
1836     sigaction(SIGABRT, &nsa, NULL);
1837     sigaction(SIGSEGV, &nsa, NULL);
1838 #endif
1839     strcpy(uss_whoami, argv[0]);
1840     yyin = (FILE *)NULL;
1841
1842     uss_fs_InBuff  = (char*)malloc(USS_FS_MAX_SIZE); /*Cache Manager input buff*/
1843     uss_fs_OutBuff = (char*)malloc(USS_FS_MAX_SIZE); /*Cache Manager output buff*/
1844     if (!uss_fs_InBuff || !uss_fs_OutBuff) {
1845        fprintf(stderr, "%s: Can't malloc in/out buffers\n", uss_whoami);
1846        exit(-1);
1847     }
1848
1849     /* ----------------------------- add -----------------------------*/
1850
1851     cs = cmd_CreateSyntax("add", AddUser, 0, "create a new user account");
1852     cmd_AddParm(cs, "-user", CMD_SINGLE, 0,
1853                 "login name");
1854     cmd_AddParm(cs, "-realname", CMD_SINGLE, CMD_OPTIONAL,
1855                 "full name in quotes");
1856     cmd_AddParm(cs, "-pass", CMD_SINGLE, CMD_OPTIONAL,
1857                 "initial password");
1858     /* new parm */
1859     cmd_AddParm(cs, "-pwexpires", CMD_SINGLE, CMD_OPTIONAL,
1860                 "password expires in [0..254] days (0 => never)");
1861     cmd_AddParm(cs, "-server", CMD_SINGLE, CMD_OPTIONAL,
1862                 "FileServer for home volume");
1863     cmd_AddParm(cs, "-partition", CMD_SINGLE, CMD_OPTIONAL,
1864                 "FileServer's disk partition for home volume");
1865     cmd_AddParm(cs, "-mount", CMD_SINGLE, CMD_OPTIONAL,
1866                 "home directory mount point");
1867     cmd_AddParm(cs, "-uid", CMD_SINGLE, CMD_OPTIONAL,
1868                 "uid to assign the user");
1869     cmd_Seek(cs, AUSS_TEMPLATE);
1870     cmd_AddParm(cs, "-template", CMD_SINGLE, CMD_OPTIONAL,
1871                 "pathname of template file");
1872     cmd_AddParm(cs, "-verbose", CMD_FLAG, CMD_OPTIONAL,
1873                 "verbose operation");
1874     cmd_AddParm(cs, "-var", CMD_LIST, CMD_OPTIONAL|CMD_EXPANDS,
1875                 "auxiliary argument pairs (Num val)");
1876     cmd_AddParm(cs, "-cell", CMD_SINGLE, CMD_OPTIONAL,
1877                 "cell name");
1878     cmd_AddParm(cs, "-admin", CMD_SINGLE, CMD_OPTIONAL,
1879                 "administrator to authenticate");
1880     cmd_AddParm(cs, "-dryrun", CMD_FLAG, CMD_OPTIONAL,
1881                 "only list what would be done, don't do it");
1882     cmd_AddParm(cs, "-skipauth", CMD_FLAG, CMD_OPTIONAL,
1883                 "ignore all contact with the authentication server (kaserver)");
1884     cmd_AddParm(cs, "-overwrite", CMD_FLAG, CMD_OPTIONAL,
1885                 "Overwrite pre-existing files in user home directory tree");
1886
1887
1888     /* ---------------------------- bulk -----------------------------*/
1889
1890     cs = cmd_CreateSyntax("bulk", HandleBulk, 0, "bulk input mode");
1891     cmd_AddParm(cs, "-file", CMD_SINGLE, 0,
1892                 "bulk input file");
1893     cmd_Seek(cs, AUSS_TEMPLATE);
1894     cmd_AddParm(cs, "-template", CMD_SINGLE, CMD_OPTIONAL,
1895                 "pathname of template file");
1896     cmd_AddParm(cs, "-verbose", CMD_FLAG, CMD_OPTIONAL,
1897                 "verbose operation");
1898     cmd_Seek(cs, AUSS_CELL);
1899     cmd_AddParm(cs, "-cell", CMD_SINGLE, CMD_OPTIONAL,
1900                 "cell name");
1901     cmd_AddParm(cs, "-admin", CMD_SINGLE, CMD_OPTIONAL,
1902                 "administrator to authenticate");
1903     cmd_AddParm(cs, "-dryrun", CMD_FLAG, CMD_OPTIONAL,
1904                 "only list what would be done, don't do it");
1905     cmd_AddParm(cs, "-skipauth", CMD_FLAG, CMD_OPTIONAL,
1906                 "ignore all contact with the authentication server (kaserver)");
1907     cmd_AddParm(cs, "-overwrite", CMD_FLAG, CMD_OPTIONAL,
1908                 "Overwrite pre-existing files in user home directory tree");
1909     cmd_Seek(cs, AUSS_PWEXPIRES);
1910     cmd_AddParm(cs, "-pwexpires", CMD_SINGLE, CMD_OPTIONAL,
1911                 "password expires in [0..254] days (0 => never)");
1912     cmd_Seek(cs, AUSS_PIPE);
1913     cmd_AddParm(cs, "-pipe", CMD_FLAG, CMD_OPTIONAL,
1914                 "don't prompt for passwd; get it from standard input");
1915     
1916    /* ---------------------------- delete ---------------------------*/
1917
1918     cs = cmd_CreateSyntax("delete", DelUser, 0, "delete a user account");
1919     cmd_AddParm(cs, "-user", CMD_SINGLE, 0,
1920                 "login name");
1921     cmd_AddParm(cs, "-mountpoint", CMD_SINGLE, CMD_OPTIONAL,
1922                 "mountpoint for user's volume");
1923 #if USS_FUTURE_FEATURES
1924 #if USS_DONT_HIDE_SOME_FEATURES
1925     cmd_AddParm(cs, "-restoredir", CMD_SINGLE, 0,
1926                 "directory where restore info is to be placed");
1927 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1928 #endif /* USS_FUTURE_FEATURES */
1929     cmd_AddParm(cs, "-savevolume", CMD_FLAG, CMD_OPTIONAL,
1930                 "don't destroy the user's volume");
1931 #if USS_FUTURE_FEATURES
1932 #if USS_DONT_HIDE_SOME_FEATURES
1933     cmd_AddParm(cs, "-pwdpath", CMD_SINGLE, CMD_OPTIONAL,
1934                 "pathname to the password file");
1935     cmd_AddParm(cs, "-pwdformat", CMD_SINGLE, CMD_OPTIONAL,
1936                 "password entry format");
1937 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1938 #endif /* USS_FUTURE_FEATURES */
1939     cmd_Seek(cs, AUSS_VERBOSE);
1940     cmd_AddParm(cs, "-verbose", CMD_FLAG, CMD_OPTIONAL,
1941                 "verbose operation");
1942     cmd_Seek(cs, AUSS_CELL);
1943     cmd_AddParm(cs, "-cell", CMD_SINGLE, CMD_OPTIONAL,
1944                 "cell name");
1945     cmd_AddParm(cs, "-admin", CMD_SINGLE, CMD_OPTIONAL,
1946                 "administrator to authenticate");
1947     cmd_AddParm(cs, "-dryrun", CMD_FLAG, CMD_OPTIONAL,
1948                 "only list what would be done, don't do it");
1949     cmd_AddParm(cs, "-skipauth", CMD_FLAG, CMD_OPTIONAL,
1950                 "ignore all contact with the authentication server (kaserver)");
1951 #if USS_FUTURE_FEATURES
1952 #if USS_DONT_HIDE_SOME_FEATURES
1953     /* ------------------------- purgevolumes ------------------------*/
1954
1955     cs = cmd_CreateSyntax("purgevolumes", PurgeVolumes, 0,
1956                           "destroy a deleted user's volume");
1957     cmd_AddParm(cs, "-volname", CMD_LIST, CMD_OPTIONAL|CMD_EXPANDS,
1958                 "Name(s) of volume(s) to destroy");
1959     cmd_AddParm(cs, "-volfile", CMD_SINGLE, CMD_OPTIONAL,
1960                 "pathname to volume purge file");
1961     cmd_Seek(cs, AUSS_VERBOSE);
1962     cmd_AddParm(cs, "-verbose", CMD_FLAG, CMD_OPTIONAL,
1963                 "verbose operation");
1964     cmd_Seek(cs, AUSS_CELL);
1965     cmd_AddParm(cs, "-cell", CMD_SINGLE, CMD_OPTIONAL,
1966                 "cell name");
1967     cmd_AddParm(cs, "-admin", CMD_SINGLE, CMD_OPTIONAL,
1968                 "administrator to authenticate");
1969     cmd_AddParm(cs, "-dryrun", CMD_FLAG, CMD_OPTIONAL,
1970                 "only list what would be done, don't do it");
1971     cmd_AddParm(cs, "-skipauth", CMD_FLAG, CMD_OPTIONAL,
1972                 "ignore all contact with the authentication server (kaserver)");
1973 #endif /* USS_DONT_HIDE_SOME_FEATURES */
1974 #endif /* USS_FUTURE_FEATURES */
1975
1976 #if USS_FUTURE_FEATURES
1977 #if USS_DONT_HIDE_SOME_FEATURES
1978     /* ---------------------------- restore --------------------------*/
1979
1980     cs = cmd_CreateSyntax("restore", RestoreUser, 0,
1981                           "restore a deleted user account");
1982     cmd_AddParm(cs, "-user", CMD_SINGLE, 0,
1983                 "login name to restore");
1984     cmd_AddParm(cs, "-uid", CMD_SINGLE, 0,
1985                 "user id number");
1986     cmd_AddParm(cs, "-mount", CMD_SINGLE, 0,
1987                 "mountpoint for user's volume");
1988     cmd_AddParm(cs, "-volname", CMD_SINGLE, 0,
1989                 "name of user's volume");
1990     cmd_AddParm(cs, "-realname", CMD_SINGLE, CMD_OPTIONAL,
1991                 "user's full name");
1992     cmd_AddParm(cs, "-server", CMD_SINGLE, CMD_OPTIONAL,
1993                 "FileServer to host user's volume");
1994     cmd_AddParm(cs, "-partition", CMD_SINGLE, CMD_OPTIONAL,
1995                 "FileServer partition to host user's volume");
1996     cmd_AddParm(cs, "-pwdpath", CMD_SINGLE, CMD_OPTIONAL,
1997                 "pathname to the password file");
1998     cmd_AddParm(cs, "-pwdformat", CMD_SINGLE, CMD_OPTIONAL,
1999                 "password entry format");
2000     cmd_Seek(cs, AUSS_VERBOSE);
2001     cmd_AddParm(cs, "-verbose", CMD_FLAG, CMD_OPTIONAL,
2002                 "verbose operation");
2003     cmd_Seek(cs, AUSS_CELL);
2004     cmd_AddParm(cs, "-cell", CMD_SINGLE, CMD_OPTIONAL,
2005                 "cell name");
2006     cmd_AddParm(cs, "-admin", CMD_SINGLE, CMD_OPTIONAL,
2007                 "administrator to authenticate");
2008     cmd_AddParm(cs, "-dryrun", CMD_FLAG, CMD_OPTIONAL,
2009                 "only list what would be done, don't do it");
2010     cmd_AddParm(cs, "-skipauth", CMD_FLAG, CMD_OPTIONAL,
2011                 "ignore all contact with the authentication server (kaserver)");
2012 #endif /* USS_DONT_HIDE_SOME_FEATURES */
2013 #endif /* USS_FUTURE_FEATURES */
2014
2015     /*
2016      * Set up all the error code translation tables, initialize the
2017      * command variables, and set up to parse the common command line
2018      * parameters.
2019      */
2020     InitETTables();
2021     uss_common_Init();
2022     cmd_SetBeforeProc(GetCommon, NULL);
2023
2024     /*
2025      * Execute the parsed command.
2026      */
2027     code = cmd_Dispatch(argc, argv);
2028 #if 0
2029     if (code) {
2030       fprintf(stderr,
2031               "%s: Call to cmd_Dispatch() failed; code is %d\n",
2032               uss_whoami, code);
2033       exit(-1);
2034     }
2035 #endif /* 0 */
2036     if (doUnlog) {
2037         code = uss_fs_UnlogToken(uss_Cell);
2038     }
2039 } /*Main routine*/