butc: -Wformat-truncation fallout
[openafs.git] / src / butc / tcmain.c
index c616375..3d1a1f5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID("$Header$");
+#include <afs/procmgmt.h>
+
+#include <roken.h>
+#include <afs/opr.h>
+
+#ifdef IGNORE_SOME_GCC_WARNINGS
+# pragma GCC diagnostic warning "-Wimplicit-function-declaration"
+#endif
 
-#include <sys/types.h>
-#include <sys/stat.h>
 #ifdef AFS_NT40_ENV
-#include <winsock2.h>
 #include <WINNT/afsevent.h>
-#else
-#include <netinet/in.h>
-#include <sys/time.h>
 #endif
-#include <afs/procmgmt.h>
+
+#include <ctype.h>
+
+#include <rx/rx.h>
+#include <rx/rx_globals.h>
+#include <rx/rxkad.h>
 #include <rx/xdr.h>
+
 #include <afs/afsint.h>
-#include <stdio.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else
-#include <afs/assert.h>
-#endif
 #include <afs/prs_fs.h>
 #include <afs/nfs.h>
-#include <string.h>
 #include <afs/vlserver.h>
 #include <lwp.h>
 #include <lock.h>
 #include <afs/afsutil.h>
-#include <rx/rx.h>
-#include <rx/rx_globals.h>
-#include <afs/auth.h>
-#include <rx/rxkad.h>
 #include <afs/cellconfig.h>
 #include <afs/keys.h>
 #include <afs/volser.h>
 #include <ubik.h>
+#include <afs/audit.h>
 #include <afs/com_err.h>
-#include <errno.h>
 #include <afs/cmd.h>
 #include <afs/tcdata.h>
 #include <afs/bubasics.h>
-#include <ctype.h>
-#include "error_macros.h"
 #include <afs/budb_errs.h>
-#include "afs/butx.h"
+#include <afs/budb_client.h>
+#include <afs/bucoord_prototypes.h>
+#include <afs/butx.h>
+#include <afs/kautils.h>
+#include <afs/bc.h>
+
+#include "error_macros.h"
+#define XBSA_TCMAIN
 #include "butc_xbsa.h"
+#include "butc_prototypes.h"
+#include "butc_internal.h"
 
 #define N_SECURITY_OBJECTS 3
-#define ERRCODE_RANGE 8                        /* from error_table.h */
+#define ERRCODE_RANGE 8                /* from error_table.h */
 
 #define TE_PREFIX  "TE"
 #define TL_PREFIX  "TL"
 #define CFG_PREFIX "CFG"
 
 struct ubik_client *cstruct;
-extern void TC_ExecuteRequest();
-extern int  dbWatcher();
 FILE *logIO, *ErrorlogIO, *centralLogIO, *lastLogIO;
 char lFile[AFSDIR_PATH_MAX];
-char logFile[256];
-char ErrorlogFile[256];
-char lastLogFile[256];
+char logFile[AFSDIR_PATH_MAX + 256];
+char ErrorlogFile[AFSDIR_PATH_MAX + 256];
+char lastLogFile[AFSDIR_PATH_MAX + 256];
 char eFile[AFSDIR_PATH_MAX];
-char tapeConfigFile[AFSDIR_PATH_MAX]; 
+char tapeConfigFile[AFSDIR_PATH_MAX];
 char pFile[AFSDIR_PATH_MAX];
 int debugLevel = 0;
 struct tapeConfig globalTapeConfig;
@@ -89,21 +90,7 @@ int tapemounted;
 char *opencallout;
 char *closecallout;
 char *restoretofile;
-int  forcemultiple;
-
-/* XBSA Global Parameters */
-afs_int32 xbsaType;
-#ifdef xbsa
-struct butx_transactionInfo butxInfo;
-
-#define rpc_c_protect_level_default 0
-afs_uint32 dumpRestAuthnLevel = rpc_c_protect_level_default;
-char *xbsaObjectOwner;
-char *appObjectOwner;
-char *adsmServerName;
-char *xbsaSecToken;
-char *xbsalGName;
-#endif
+int forcemultiple;
 
 int maxpass;
 #define PASSESMIN  1
@@ -115,22 +102,26 @@ afs_int32 groupId;
 afs_int32 statusSize;
 #define MINSTATUS  1
 #define MAXSTATUS  0x7fffffff
-afs_int32 BufferSize;     /* Size in B stored for data */
+afs_int32 BufferSize;          /* Size in B stored for data */
 char *centralLogFile;
-afs_int32 lastLog;           /* Log last pass info */
+afs_int32 lastLog;             /* Log last pass info */
+int rxBind = 0;
+struct afsconf_dir *butc_confdir;
+int allow_unauth = 0;
 
-/* dummy routine for the audit work.  It should do nothing since audits */
-/* occur at the server level and bos is not a server. */
-osi_audit() {return 0;}
+#define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
+afs_uint32 SHostAddrs[ADDRSPERSITE];
 
-static afs_int32 SafeATOL(anum)
-register char *anum; {
-    register afs_int32 total;
-    register int tc;
+static afs_int32
+SafeATOL(char *anum)
+{
+    afs_int32 total;
+    int tc;
 
     total = 0;
-    while(tc = *anum) {
-       if (tc < '0' || tc > '9') return -1;
+    while ((tc = *anum)) {
+       if (tc < '0' || tc > '9')
+           return -1;
        total *= 10;
        total += (tc - '0');
        anum++;
@@ -157,123 +148,122 @@ register char *anum; {
  *     should deal with signed numbers. Should signal error if no digits
  *     seen.
  */
-atocl(numstring, crunit, number)
-     char *numstring;
-     char  crunit;         /* Units to report number in */
-     afs_int32 *number;
+int
+atocl(char *numstring, char crunit, afs_int32 *number)
 {
     float total;
     afs_int32 runits;
-    char  cunit;
+    char cunit;
     afs_int32 units;
     afs_int32 count;
     char rest[256];
 
     /* Determine which units to report in */
-    switch ( crunit ) {
-      case 't':
-      case 'T':
+    switch (crunit) {
+    case 't':
+    case 'T':
        runits = 12;
        break;
 
-      case 'g':
-      case 'G':
+    case 'g':
+    case 'G':
        runits = 9;
        break;
 
-      case 'm':
-      case 'M':
+    case 'm':
+    case 'M':
        runits = 6;
        break;
 
-      case 'k':
-      case 'K':
+    case 'k':
+    case 'K':
        runits = 3;
        break;
 
-      case 'b':
-      case 'B':
-      case ' ':
-      case 0:
+    case 'b':
+    case 'B':
+    case ' ':
+    case 0:
        runits = 0;
        break;
 
-      default:
-       return(-1);
+    default:
+       return (-1);
     }
 
-    count = sscanf(numstring, "%f%c%s", (unsigned char *)&total, &cunit, rest);
+    count =
+       sscanf(numstring, "%f%c%s", &total, &cunit, rest);
     if ((count > 2) || (count <= 0))
-       return -1;
+       return -1;
     if (count == 1)
-       cunit = 'B';        /* bytes */
+       cunit = 'B';            /* bytes */
 
-    switch ( cunit ) {
-      case 't':
-      case 'T':
+    switch (cunit) {
+    case 't':
+    case 'T':
        units = 12;
        break;
 
-      case 'g':
-      case 'G':
+    case 'g':
+    case 'G':
        units = 9;
        break;
 
-      case 'm':
-      case 'M':
+    case 'm':
+    case 'M':
        units = 6;
        break;
 
-      case 'k':
-      case 'K':
+    case 'k':
+    case 'K':
        units = 3;
        break;
 
-      case 'b':
-      case 'B':
-      case ' ':
-      case 0:
+    case 'b':
+    case 'B':
+    case ' ':
+    case 0:
        units = 0;
        break;
 
-      default:
-       return(-1);
+    default:
+       return (-1);
     }
 
     /* Go to correct unit */
     for (; units < runits; units += 3)
-       total /= 1024.0;
+       total /= 1024.0;
     for (; units > runits; units -= 3)
-       total *= 1024.0;
+       total *= 1024.0;
 
-    total += 0.5;              /* Round up */   
-    if ((total > 0x7fffffff) || (total < 0))    /* Don't go over 2G */
-       total = 0x7fffffff;
+    total += 0.5;              /* Round up */
+    if ((total > 0x7fffffff) || (total < 0))   /* Don't go over 2G */
+       total = 0x7fffffff;
 
     *number = total;
-    return(0);
+    return (0);
 }
 
 /* replace last two ocurrences of / by _ */
-static stringReplace(name)
-char *name;
+#if 0
+static int
+stringReplace(char *name)
 {
     char *pos;
-    int i;
     char buffer[256];
 
-    pos = strrchr(name,'/');
+    pos = strrchr(name, '/');
     *pos = '_';
-    strcpy(buffer,pos);
-    pos = strrchr(name,'/');
+    strcpy(buffer, pos);
+    pos = strrchr(name, '/');
     *pos = '\0';
-    strcat(name,buffer);
+    strcat(name, buffer);
     return 0;
 }
+#endif
 
-static stringNowReplace (logFile, deviceName)
-char *logFile, *deviceName;
-
+static int
+stringNowReplace(char *logFile, char *deviceName)
 {
     char *pos = 0;
     char storeDevice[256];
@@ -290,15 +280,14 @@ char *logFile, *deviceName;
        deviceName += devPrefLen;
        mvFlag++;
     }
-    while (pos = strchr(deviceName, devPrefix[0])) /* look for / or \ */
+    while ((pos = strchr(deviceName, devPrefix[0])))   /* look for / or \ */
        *pos = '_';
-    strcat (logFile, deviceName);
+    strcat(logFile, deviceName);
     /* now put back deviceName to the way it was */
-    if (mvFlag) {
-       mvFlag = 0;
+    if (mvFlag)
        deviceName -= devPrefLen;
-    }
-    strcpy (deviceName, storeDevice);
+
+    strcpy(deviceName, storeDevice);
 
     return (0);
 }
@@ -322,59 +311,64 @@ char *logFile, *deviceName;
  */
 
 #define        LINESIZE        256
-static afs_int32 GetDeviceConfig(filename, config, portOffset)
-     char *filename;
-     struct tapeConfig *config;
-     afs_int32 portOffset;
+static afs_int32
+GetDeviceConfig(char *filename, struct tapeConfig *config, afs_int32 portOffset)
 {
-    FILE *devFile=0;
+    FILE *devFile = 0;
     char line[LINESIZE];
-    char devName[LINESIZE], tcapacity[LINESIZE],
-         tfmsize[LINESIZE], trest[LINESIZE];
+    char devName[LINESIZE], tcapacity[LINESIZE], tfmsize[LINESIZE],
+       trest[LINESIZE];
     afs_int32 aport;
-    afs_uint32 capacity;
-    afs_uint32 fmSize;
-    afs_int32 code=0, count;
+    afs_int32 capacity;
+    afs_int32 fmSize;
+    afs_int32 code = 0, count;
 
     /* Initialize the config struct */
-    config->capacity     = 0;
+    config->capacity = 0;
     config->fileMarkSize = 0;
-    config->portOffset   = portOffset;
+    config->portOffset = portOffset;
     strcpy(config->device, "");
 
-    devFile = fopen(filename,"r");
+    devFile = fopen(filename, "r");
     if (!devFile) {
-        if (errno == ENOENT) ERROR_EXIT(1);
-        fprintf(stderr, "Error %d: Can't open %s\n", errno, filename);
+       if (errno == ENOENT)
+           ERROR_EXIT(1);
+       fprintf(stderr, "Error %d: Can't open %s\n", errno, filename);
        ERROR_EXIT(-1);
     }
 
-    while ( fgets(line,LINESIZE-1,devFile) ) {
-        count = sscanf(line, "%s %s %s %u%s\n",
-                     tcapacity, tfmsize, devName, &aport, trest);
+    while (fgets(line, LINESIZE - 1, devFile)) {
+       count =
+           sscanf(line, "%s %s %s %u%s\n", tcapacity, tfmsize, devName,
+                  &aport, trest);
 
        if (count == 4 || count == 5) {
-           if ( atocl(tcapacity, 'K', &capacity) ) {
-              fprintf(stderr, "tapeconfig: Tape capacity parse error in: %s\n", line);
-              ERROR_EXIT(-1);
+           if (atocl(tcapacity, 'K', &capacity)) {
+               fprintf(stderr,
+                       "tapeconfig: Tape capacity parse error in: %s\n",
+                       line);
+               ERROR_EXIT(-1);
            }
-           if ( atocl(tfmsize, 'B', &fmSize) ) {
-               fprintf(stderr, "tapeconfig: File-mark size parse error in: %s\n", line);
+           if (atocl(tfmsize, 'B', &fmSize)) {
+               fprintf(stderr,
+                       "tapeconfig: File-mark size parse error in: %s\n",
+                       line);
                ERROR_EXIT(-1);
            }
        } else {
            count = sscanf(line, "%s %u%s\n", devName, &aport, trest);
            if (count == 2 || count == 3) {
-               capacity = 0x7fffffff;
+               capacity = 0x7fffffff;
                fmSize = 0;
            } else {
-               fprintf(stderr, "tapeconfig: Parse error in: %s\n", line);
+               fprintf(stderr, "tapeconfig: Parse error in: %s\n", line);
                ERROR_EXIT(-1);
            }
        }
 
        if ((aport < 0) || (aport > BC_MAXPORTOFFSET)) {
-           fprintf(stderr, "tapeconfig: Port offset parse error in: %s\n", line);
+           fprintf(stderr, "tapeconfig: Port offset parse error in: %s\n",
+                   line);
            ERROR_EXIT(-1);
        }
 
@@ -382,13 +376,14 @@ static afs_int32 GetDeviceConfig(filename, config, portOffset)
            continue;
 
        if (fmSize < 0) {
-          fprintf(stderr, "Invalid file mark size, %d, in: %s\n", fmSize, line);
-          ERROR_EXIT(-1);
+           fprintf(stderr, "Invalid file mark size, %d, in: %s\n", fmSize,
+                   line);
+           ERROR_EXIT(-1);
        }
 
-       config->capacity     = capacity;
+       config->capacity = capacity;
        config->fileMarkSize = fmSize;
-       config->portOffset   = aport;
+       config->portOffset = aport;
        strncpy(config->device, devName, 100);
 
        ERROR_EXIT(0);
@@ -398,433 +393,465 @@ static afs_int32 GetDeviceConfig(filename, config, portOffset)
     ERROR_EXIT(1);
 
   error_exit:
-    if (devFile) fclose(devFile);
-    return(code);
+    if (devFile)
+       fclose(devFile);
+    return (code);
 }
 
 /* GetConfigParams
  */
-static afs_int32 GetConfigParams(filename, port)
-    char *filename;
-    afs_int32 port;
+static afs_int32
+GetConfigParams(char *filename, afs_int32 port)
 {
-    char paramFile[256];
-    FILE *devFile=0;
+    char paramFile[AFSDIR_PATH_MAX + 257];
+    FILE *devFile = 0;
     char line[LINESIZE], cmd[LINESIZE], value[LINESIZE];
-    afs_int32 code=0;
+    afs_int32 code = 0;
     int cnt;
 
     /* DEFAULT SETTINGS FOR GLOBAL PARAMETERS */
-    dump_namecheck = 1;                   /* check tape name on dumps */
-    queryoperator  = 1;                   /* can question operator */
-    autoQuery      = 1;                   /* prompt for first tape */
-    isafile        = 0;                   /* Do not dump to a file */
-    opencallout    = NULL;           /* open  callout routine */
-    closecallout   = NULL;           /* close callout routine */
-    tapemounted    = 0;                   /* tape is not mounted */
+    dump_namecheck = 1;                /* check tape name on dumps */
+    queryoperator = 1;         /* can question operator */
+    autoQuery = 1;             /* prompt for first tape */
+    isafile = 0;               /* Do not dump to a file */
+    opencallout = NULL;                /* open  callout routine */
+    closecallout = NULL;       /* close callout routine */
+    tapemounted = 0;           /* tape is not mounted */
 #ifdef xbsa
-    BufferSize     = (CONF_XBSA ? XBSADFLTBUFFER : BUTM_BLOCKSIZE);
-    dumpRestAuthnLevel = rpc_c_protect_level_default;   
-    xbsaObjectOwner  = NULL;         /* bsaObjectOwner */
-    appObjectOwner   = NULL;         /* appObjectOwner */
-    adsmServerName   = NULL;         /* TSM server name - same as ADSM */
-    xbsaSecToken     = NULL;         /* XBSA sercurity token */
-    xbsalGName       = NULL;         /* XBSA IGName */
+    BufferSize = (CONF_XBSA ? XBSADFLTBUFFER : BUTM_BLOCKSIZE);
+    dumpRestAuthnLevel = rpc_c_protect_level_default;
+    xbsaObjectOwner = NULL;    /* bsaObjectOwner */
+    appObjectOwner = NULL;     /* appObjectOwner */
+    adsmServerName = NULL;     /* TSM server name - same as ADSM */
+    xbsaSecToken = NULL;       /* XBSA sercurity token */
+    xbsalGName = NULL;         /* XBSA IGName */
 #else
-    BufferSize     = BUTM_BLOCKSIZE;
-#endif /*xbsa*/
-    centralLogFile   = NULL;         /* Log for all butcs */
-    centralLogIO = 0;                     /* Log for all butcs */
-    statusSize   = 0;                     /* size before status message */
-    maxpass      = PASSESDFLT;            /* dump passes */
-    lastLog      = 0;                     /* separate log for last pass */
-    lastLogIO    = 0;                     /* separate log for last pass */
-    groupId      = 0;                     /* Group id for multiple dumps */
+    BufferSize = BUTM_BLOCKSIZE;
+#endif /*xbsa */
+    centralLogFile = NULL;     /* Log for all butcs */
+    centralLogIO = 0;          /* Log for all butcs */
+    statusSize = 0;            /* size before status message */
+    maxpass = PASSESDFLT;      /* dump passes */
+    lastLog = 0;               /* separate log for last pass */
+    lastLogIO = 0;             /* separate log for last pass */
+    groupId = 0;               /* Group id for multiple dumps */
 
     /* Try opening the CFG_<port> file */
-    sprintf(paramFile,    "%s_%d", filename, port);
+    snprintf(paramFile, sizeof(paramFile), "%s_%d", filename, port);
     devFile = fopen(paramFile, "r");
     if (devFile) {
-       /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
-       sprintf(logFile,      "%s_%d",    lFile, port);
-       sprintf(lastLogFile,  "%s_%d.lp", lFile, port);
-       sprintf(ErrorlogFile, "%s_%d",    eFile, port);
+       /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
+       snprintf(logFile, sizeof(logFile), "%s_%d", lFile, port);
+       snprintf(lastLogFile, sizeof(lastLogFile), "%s_%d.lp", lFile, port);
+       snprintf(ErrorlogFile, sizeof(ErrorlogFile), "%s_%d", eFile, port);
     } else if (CONF_XBSA) {
-       /* If configured as XBSA, a configuration file CFG_<port> must exist */
-       printf("Cannot open configuration file %s", paramFile);
-       ERROR_EXIT(1);
+       /* If configured as XBSA, a configuration file CFG_<port> must exist */
+       printf("Cannot open configuration file %s", paramFile);
+       ERROR_EXIT(1);
     } else {
-       /* Try the CFG_<device> name as the device file */
-       strcpy(paramFile, filename);
-       stringNowReplace(paramFile, globalTapeConfig.device);
-       /* Set log names to TL_<device>, TL_<device> and TE_<device> */
-       strcpy(logFile,lFile);
-       stringNowReplace(logFile,globalTapeConfig.device);
-       strcpy(lastLogFile,lFile);
-       stringNowReplace(lastLogFile,globalTapeConfig.device);
-       strcat(lastLogFile, ".lp");
-       strcpy(ErrorlogFile,eFile);
-       stringNowReplace(ErrorlogFile, globalTapeConfig.device);
-
-       /* Now open the device file */
-       devFile = fopen(paramFile, "r");
-       if (!devFile)
-         ERROR_EXIT(0);/* CFG file doesn't exist for non-XBSA and that's ok */
+       /* Try the CFG_<device> name as the device file */
+       strcpy(paramFile, filename);
+       stringNowReplace(paramFile, globalTapeConfig.device);
+       /* Set log names to TL_<device>, TL_<device> and TE_<device> */
+       strcpy(logFile, lFile);
+       stringNowReplace(logFile, globalTapeConfig.device);
+       strcpy(lastLogFile, lFile);
+       stringNowReplace(lastLogFile, globalTapeConfig.device);
+       strcat(lastLogFile, ".lp");
+       strcpy(ErrorlogFile, eFile);
+       stringNowReplace(ErrorlogFile, globalTapeConfig.device);
+
+       /* Now open the device file */
+       devFile = fopen(paramFile, "r");
+       if (!devFile)
+           ERROR_EXIT(0);      /* CFG file doesn't exist for non-XBSA and that's ok */
     }
 
     /* Read each line of the Configuration file */
-    while (fgets(line,LINESIZE-1,devFile)) {
+    while (fgets(line, LINESIZE - 1, devFile)) {
        cnt = sscanf(line, "%s %s", cmd, value);
-       if (cnt != 2)
-       {
+       if (cnt != 2) {
            if (cnt > 0)
-               printf("Bad line in %s: %s\n", paramFile, line);
+               printf("Bad line in %s: %s\n", paramFile, line);
            continue;
        }
-         
-       for (cnt=0; cnt<strlen(cmd); cnt++)
-         if (islower(cmd[cnt])) cmd[cnt] = toupper(cmd[cnt]);
 
-       if (!strcmp(cmd,"NAME_CHECK"))
-       {
+       for (cnt = 0; cnt < strlen(cmd); cnt++)
+           if (islower(cmd[cnt]))
+               cmd[cnt] = toupper(cmd[cnt]);
+
+       if (!strcmp(cmd, "NAME_CHECK")) {
            if (CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a Backup Service\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a Backup Service\n",
+                    cmd);
                continue;
            }
 
-           for (cnt=0; cnt<strlen(value); cnt++)
-               if (islower(value[cnt])) value[cnt] = toupper(value[cnt]);
+           for (cnt = 0; cnt < strlen(value); cnt++)
+               if (islower(value[cnt]))
+                   value[cnt] = toupper(value[cnt]);
 
-           if (!strcmp(value,"NO"))
-           {
-               printf("Dump tape name check is disabled\n");
-               dump_namecheck = 0;
-           }
-           else
-           {
-               printf("Dump tape name check is enabled\n");
-               dump_namecheck = 1;
+           if (!strcmp(value, "NO")) {
+               printf("Dump tape name check is disabled\n");
+               dump_namecheck = 0;
+           } else {
+               printf("Dump tape name check is enabled\n");
+               dump_namecheck = 1;
            }
        }
 
-       else if (!strcmp(cmd,"MOUNT"))
-       {
+       else if (!strcmp(cmd, "MOUNT")) {
            if (CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a Backup Service\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a Backup Service\n",
+                    cmd);
                continue;
            }
 
-           opencallout = (char*)malloc(strlen(value)+1);
-           strcpy(opencallout, value);
+           opencallout = strdup(value);
            printf("Tape mount callout routine is %s\n", opencallout);
        }
-         
-       else if (!strcmp(cmd,"UNMOUNT"))
-       {
+
+       else if (!strcmp(cmd, "UNMOUNT")) {
            if (CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a Backup Service\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a Backup Service\n",
+                    cmd);
                continue;
            }
 
-           closecallout = (char*)malloc(strlen(value)+1);
-           strcpy(closecallout, value);
+           closecallout = strdup(value);
            printf("Tape unmount callout routine is %s\n", closecallout);
        }
 
-       else if (!strcmp(cmd,"ASK"))
-       {
-           for (cnt=0; cnt<strlen(value); cnt++)
-               if (islower(value[cnt])) value[cnt] = toupper(value[cnt]);
+       else if (!strcmp(cmd, "ASK")) {
+           for (cnt = 0; cnt < strlen(value); cnt++)
+               if (islower(value[cnt]))
+                   value[cnt] = toupper(value[cnt]);
 
-           if (!strcmp(value,"NO"))
-           {
-               printf("Operator queries are disabled\n");
+           if (!strcmp(value, "NO")) {
+               printf("Operator queries are disabled\n");
                queryoperator = 0;
-           }
-           else
-           {
-               printf("Operator queries are enabled\n");
+           } else {
+               printf("Operator queries are enabled\n");
                queryoperator = 1;
            }
        }
 
-       else if (!strcmp(cmd,"FILE"))
-       {
+       else if (!strcmp(cmd, "FILE")) {
            if (CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a Backup Service\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a Backup Service\n",
+                    cmd);
                continue;
            }
 
-           for (cnt=0; cnt<strlen(value); cnt++)
-               if (islower(value[cnt])) value[cnt] = toupper(value[cnt]);
+           for (cnt = 0; cnt < strlen(value); cnt++)
+               if (islower(value[cnt]))
+                   value[cnt] = toupper(value[cnt]);
 
-           if (!strcmp(value,"YES"))
-           {
-               printf("Will dump to a file\n");
+           if (!strcmp(value, "YES")) {
+               printf("Will dump to a file\n");
                isafile = 1;
-           }
-           else
-           {
-               printf("Will not dump to a file\n");
+           } else {
+               printf("Will not dump to a file\n");
                isafile = 0;
            }
        }
 
-       else if (!strcmp(cmd,"AUTOQUERY"))
-       {
+       else if (!strcmp(cmd, "AUTOQUERY")) {
            if (CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a Backup Service\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a Backup Service\n",
+                    cmd);
                continue;
            }
 
-           for (cnt=0; cnt<strlen(value); cnt++)
-               if (islower(value[cnt])) value[cnt] = toupper(value[cnt]);
+           for (cnt = 0; cnt < strlen(value); cnt++)
+               if (islower(value[cnt]))
+                   value[cnt] = toupper(value[cnt]);
 
-           if (!strcmp(value,"NO"))
-           {
-               printf("Auto query is disabled\n");
+           if (!strcmp(value, "NO")) {
+               printf("Auto query is disabled\n");
                autoQuery = 0;
-           }
-           else
-           {
-               printf("Auto query is enabled\n");
+           } else {
+               printf("Auto query is enabled\n");
                autoQuery = 1;
            }
        }
 
-       else if (!strcmp(cmd,"BUFFERSIZE"))
-       {
+       else if (!strcmp(cmd, "BUFFERSIZE")) {
            afs_int32 size;
            afs_int32 tapeblocks;
 
            if (!CONF_XBSA) {
-              if ( atocl(value, 'K', &size) ) {
-                 fprintf(stderr, "BUFFERSIZE parse error\n");
-                 size = 0;
-              }
-
-              /* A tapeblock is 16KB. Determine # of tapeblocks. Then
-               * determine BufferSize needed for that many tapeblocks.
-               */
-              tapeblocks = size / 16;
-              if (tapeblocks <= 0) tapeblocks = 1;
-              printf("BUFFERSIZE is %u KBytes\n", (tapeblocks*16));
-              BufferSize = tapeblocks * BUTM_BLOCKSIZE;
+               if (atocl(value, 'K', &size)) {
+                   fprintf(stderr, "BUFFERSIZE parse error\n");
+                   size = 0;
+               }
+
+               /* A tapeblock is 16KB. Determine # of tapeblocks. Then
+                * determine BufferSize needed for that many tapeblocks.
+                */
+               tapeblocks = size / 16;
+               if (tapeblocks <= 0)
+                   tapeblocks = 1;
+               printf("BUFFERSIZE is %u KBytes\n", (tapeblocks * 16));
+               BufferSize = tapeblocks * BUTM_BLOCKSIZE;
            } else {
 #ifdef xbsa
-              if ( atocl(value, 'B', &size) ) {
-                 fprintf(stderr, "BUFFERSIZE parse error\n");
-                 size = 0;
-              }
-              if (size < XBSAMINBUFFER) size = XBSAMINBUFFER;
-              if (size > XBSAMAXBUFFER) size = XBSAMAXBUFFER;
-              printf("XBSA buffer size is %u Bytes\n", size);
-              BufferSize = size;
+               if (atocl(value, 'B', &size)) {
+                   fprintf(stderr, "BUFFERSIZE parse error\n");
+                   size = 0;
+               }
+               if (size < XBSAMINBUFFER)
+                   size = XBSAMINBUFFER;
+               if (size > XBSAMAXBUFFER)
+                   size = XBSAMAXBUFFER;
+               printf("XBSA buffer size is %u Bytes\n", size);
+               BufferSize = size;
 #endif
            }
        }
-
-
-
-
 #ifndef xbsa
        /* All the xbsa spacific parameters */
-       else if (!strcmp(cmd,"TYPE")     || !strcmp(cmd,"NODE")     ||
-                !strcmp(cmd,"SERVER")   || !strcmp(cmd,"PASSWORD") ||
-                !strcmp(cmd,"PASSFILE") || !strcmp(cmd,"MGMTCLASS"))
-       {
+       else if (!strcmp(cmd, "TYPE") || !strcmp(cmd, "NODE")
+                || !strcmp(cmd, "SERVER") || !strcmp(cmd, "PASSWORD")
+                || !strcmp(cmd, "PASSFILE") || !strcmp(cmd, "MGMTCLASS")) {
            printf("This binary does not have XBSA support\n");
            return 1;
        }
 #else
-       else if (!strcmp(cmd,"TYPE"))   /* required for XBSA */
-       {
+       else if (!strcmp(cmd, "TYPE")) {        /* required for XBSA */
            if (!CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a tape drive\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a tape drive\n",
+                    cmd);
                continue;
            }
 
-           for (cnt=0; (size_t)cnt<strlen(value); cnt++)
-               if (islower(value[cnt])) value[cnt] = toupper(value[cnt]);
+           for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
+               if (islower(value[cnt]))
+                   value[cnt] = toupper(value[cnt]);
 
-           if (strcmp(value,"TSM") == 0) {
-               xbsaType = XBSA_SERVER_TYPE_ADSM;     /* Known XBSA server type */
+           if (strcmp(value, "TSM") == 0) {
+               xbsaType = XBSA_SERVER_TYPE_ADSM;       /* Known XBSA server type */
            } else {
-               printf("Configuration file error, %s %s is not recognized\n", cmd, value);
+               printf("Configuration file error, %s %s is not recognized\n",
+                      cmd, value);
                xbsaType = XBSA_SERVER_TYPE_UNKNOWN;
            }
-           printf("XBSA type is %s\n", 
-                  ((xbsaType == XBSA_SERVER_TYPE_UNKNOWN)?"Unknown":value));
+           printf("XBSA type is %s\n",
+                  ((xbsaType ==
+                    XBSA_SERVER_TYPE_UNKNOWN) ? "Unknown" : value));
        }
 
-       else if (!strcmp(cmd,"NODE"))
-       {
+       else if (!strcmp(cmd, "NODE")) {
            if (!CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a tape drive\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a tape drive\n",
+                    cmd);
                continue;
            }
-           xbsaObjectOwner = malloc(strlen(value)+1);
-           strcpy(xbsaObjectOwner, value);
+           xbsaObjectOwner = strdup(value);
            printf("XBSA node is %s\n", xbsaObjectOwner);
        }
 
-       else if (!strcmp(cmd,"SERVER")) /* required for XBSA */
-       {
+       else if (!strcmp(cmd, "SERVER")) {      /* required for XBSA */
            if (!CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a tape drive\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a tape drive\n",
+                    cmd);
                continue;
            }
-           adsmServerName = malloc(strlen(value)+1);
-           strcpy(adsmServerName, value);
+           adsmServerName = strdup(value);
            printf("XBSA server is %s\n", adsmServerName);
        }
 
-       else if (!strcmp(cmd,"PASSWORD"))  /* This or PASSFILE required for XBSA */
-       {
+       else if (!strcmp(cmd, "PASSWORD")) {    /* This or PASSFILE required for XBSA */
            if (!CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a tape drive\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a tape drive\n",
+                    cmd);
                continue;
            }
            if (xbsaSecToken) {
-               printf("Warning: The %s parameter is ignored. Already read password\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored. Already read password\n",
+                    cmd);
                continue;
            }
 
-           xbsaSecToken = malloc(strlen(value)+1);
-           strcpy(xbsaSecToken, value);
+           xbsaSecToken = strdup(value);
            printf("XBSA Password has been read\n");
        }
 
-       else if (!strcmp(cmd,"PASSFILE"))  /* This or PASSWORD required for XBSA */
-       {
+       else if (!strcmp(cmd, "PASSFILE")) {    /* This or PASSWORD required for XBSA */
            FILE *pwdFile;
            if (!CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a tape drive\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a tape drive\n",
+                    cmd);
                continue;
            }
            if (xbsaSecToken) {
-               printf("Warning: The %s parameter is ignored. Already read password\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored. Already read password\n",
+                    cmd);
                continue;
            }
-           
-           pwdFile = fopen(value,"r");
+
+           pwdFile = fopen(value, "r");
            if (!pwdFile) {
-              printf("Configuration file error, cannot open password file %s\n", value);
-              ERROR_EXIT(1);
+               printf
+                   ("Configuration file error, cannot open password file %s\n",
+                    value);
+               ERROR_EXIT(1);
            }
            xbsaSecToken = malloc(LINESIZE);
            if (!fscanf(pwdFile, "%s", xbsaSecToken)) {
-              printf("Configuration file error, cannot read password file %s\n", value);
-              ERROR_EXIT(1);
+               printf
+                   ("Configuration file error, cannot read password file %s\n",
+                    value);
+               ERROR_EXIT(1);
            }
            printf("XBSA password retrieved from password file\n");
        }
 
-       else if (!strcmp(cmd,"MGMTCLASS")) /* XBSA */
-       {
+       else if (!strcmp(cmd, "MGMTCLASS")) {   /* XBSA */
            if (!CONF_XBSA) {
-               printf("Warning: The %s parameter is ignored with a tape drive\n", cmd);
+               printf
+                   ("Warning: The %s parameter is ignored with a tape drive\n",
+                    cmd);
                continue;
            }
-           xbsalGName = malloc(strlen(value)+1);
-           strcpy(xbsalGName, value);
+           xbsalGName = strdup(value);
            printf("XBSA management class is %s\n", xbsalGName);
        }
 #endif
 
-       else if (!strcmp(cmd,"MAXPASS"))
-       {
+       else if (!strcmp(cmd, "MAXPASS")) {
            maxpass = SafeATOL(value);
-           if (maxpass < PASSESMIN) maxpass = PASSESMIN;
-           if (maxpass > PASSESMAX) maxpass = PASSESMAX;
+           if (maxpass < PASSESMIN)
+               maxpass = PASSESMIN;
+           if (maxpass > PASSESMAX)
+               maxpass = PASSESMAX;
            printf("MAXPASS is %d\n", maxpass);
        }
 
-       else if (!strcmp(cmd,"GROUPID"))
-       {
+       else if (!strcmp(cmd, "GROUPID")) {
            groupId = SafeATOL(value);
            if ((groupId < MINGROUPID) || (groupId > MAXGROUPID)) {
-               printf("Configuration file error, %s %s is invalid\n", cmd, value);
+               printf("Configuration file error, %s %s is invalid\n", cmd,
+                      value);
                ERROR_EXIT(1);
            }
            printf("Group Id is %d\n", groupId);
        }
 
-       else if (!strcmp(cmd,"LASTLOG"))
-       {
-           for (cnt=0; (size_t)cnt<strlen(value); cnt++)
-               if (islower(value[cnt])) value[cnt] = toupper(value[cnt]);
+       else if (!strcmp(cmd, "LASTLOG")) {
+           for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
+               if (islower(value[cnt]))
+                   value[cnt] = toupper(value[cnt]);
 
-           lastLog = (strcmp(value,"YES") == 0);
-           printf("Will %sgenerate a last log\n", (lastLog?"":"not "));
+           lastLog = (strcmp(value, "YES") == 0);
+           printf("Will %sgenerate a last log\n", (lastLog ? "" : "not "));
        }
 
-       else if (!strcmp(cmd,"CENTRALLOG"))
-       {
-           centralLogFile = malloc(strlen(value)+1);
-           strcpy(centralLogFile, value);
+       else if (!strcmp(cmd, "CENTRALLOG")) {
+           centralLogFile = strdup(value);
            printf("Central log file is %s\n", centralLogFile);
        }
 
-       else if (!strcmp(cmd,"STATUS"))
-       {
+       else if (!strcmp(cmd, "STATUS")) {
            if (atocl(value, 'B', &statusSize)) {
-              fprintf(stderr, "STATUS parse error\n");
-              statusSize = 0;
+               fprintf(stderr, "STATUS parse error\n");
+               statusSize = 0;
            }
-           if (statusSize < MINSTATUS) statusSize = MINSTATUS;
-           if (statusSize > MAXSTATUS) statusSize = MAXSTATUS;
+           if (statusSize < MINSTATUS)
+               statusSize = MINSTATUS;
+           if (statusSize > MAXSTATUS)
+               statusSize = MAXSTATUS;
        }
 
        else {
-          printf("Warning: Unrecognized configuration parameter: %s", line);
+           printf("Warning: Unrecognized configuration parameter: %s", line);
        }
-    } /*fgets*/
+    }                          /*fgets */
 
     if (statusSize) {
-       /* Statussize is in bytes and requires that BufferSize be set first */
-       statusSize *= BufferSize;
-       if (statusSize < 0) statusSize = 0x7fffffff; /*max size*/
-       printf("Status every %ld Bytes\n", statusSize);
+       /* Statussize is in bytes and requires that BufferSize be set first */
+       statusSize *= BufferSize;
+       if (statusSize < 0)
+           statusSize = 0x7fffffff;    /*max size */
+       printf("Status every %ld Bytes\n", afs_printable_int32_ld(statusSize));
     }
 
   error_exit:
-    if (devFile) fclose(devFile);
+    if (devFile)
+       fclose(devFile);
 
     /* If the butc is configured as XBSA, check for required parameters */
 #ifdef xbsa
     if (!code && CONF_XBSA) {
-       if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
-         printf("Configuration file error, the TYPE parameter must be specified, or\n");
-         printf("an entry must exist in %s for port %d\n", tapeConfigFile, port);
-         code = 1;
-       }
-       if (!adsmServerName) {
-         printf("Configuration file error, the SERVER parameter must be specified\n");
-         code = 1;
-       }
-       if (!xbsaSecToken) {
-         printf("Configuration file error, the PASSWORD or PASSFILE parameter must be specified\n");
-         code = 1;
-       }
+       if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
+           printf
+               ("Configuration file error, the TYPE parameter must be specified, or\n");
+           printf("an entry must exist in %s for port %d\n", tapeConfigFile,
+                  port);
+           code = 1;
+       }
+       if (!adsmServerName) {
+           printf
+               ("Configuration file error, the SERVER parameter must be specified\n");
+           code = 1;
+       }
+       if (!xbsaSecToken) {
+           printf
+               ("Configuration file error, the PASSWORD or PASSFILE parameter must be specified\n");
+           code = 1;
+       }
+    }
+#endif /*xbsa */
+    return (code);
+}
+
+#ifdef xbsa
+static void
+xbsa_shutdown(int x)
+{
+    xbsa_Finalize(&butxInfo);
+    exit(0);
+}
+#endif
+
+static int
+tc_IsLocalRealmMatch(void *rock, char *name, char *inst, char *cell)
+{
+    struct afsconf_dir *dir = (struct afsconf_dir *)rock;
+    afs_int32 islocal = 0;     /* default to no */
+    int code;
+
+    code = afsconf_IsLocalRealmMatch(dir, &islocal, name, inst, cell);
+    if (code) {
+       TLog(0, "Failed local realm check; code=%d, name=%s, inst=%s, cell=%s\n",
+                code, name, inst, cell);
     }
-#endif /*xbsa*/
-    return(code);
+    return islocal;
 }
 
-static WorkerBee(as, arock)
-struct cmd_syndesc *as;
-char *arock; {
-    char *pid;
-    register afs_int32 code;
-    struct rx_securityClass *(securityObjects[3]);
+static int
+WorkerBee(struct cmd_syndesc *as, void *arock)
+{
+    afs_int32 code, numClasses;
+    struct rx_securityClass *(nullObjects[1]), **secObjs, **allObjs;
     struct rx_service *service;
-    struct ktc_token ttoken;
+    time_t tokenExpires;
     char cellName[64];
     int localauth;
     /*process arguments */
     afs_int32 portOffset = 0;
-    afs_int32 logIOName;
 #ifdef AFS_PTHREAD_ENV
     pthread_t dbWatcherPid;
     pthread_attr_t tattr;
@@ -832,6 +859,10 @@ char *arock; {
 #else
     PROCESS dbWatcherPid;
 #endif
+    char hoststr[16];
+    afs_uint32 host = htonl(INADDR_ANY);
+    char *auditFileName = NULL;
+    char *auditInterface = NULL;
 
     debugLevel = 0;
 
@@ -846,176 +877,240 @@ char *arock; {
     initialize_BUTC_error_table();
 #ifdef xbsa
     initialize_BUTX_error_table();
-#endif /*xbs*/
+#endif /*xbs */
     initialize_VOLS_error_table();
     initialize_BUDB_error_table();
     initialize_BUCD_error_table();
 
-    if (as->parms[0].items)
-    {
+    if (as->parms[0].items) {
        portOffset = SafeATOL(as->parms[0].items->data);
-       if (portOffset == -1)
-       {
-           fprintf(stderr, "Illegal port offset '%s'\n", as->parms[0].items->data);
+       if (portOffset == -1) {
+           fprintf(stderr, "Illegal port offset '%s'\n",
+                   as->parms[0].items->data);
            exit(1);
-       }
-       else if (portOffset > BC_MAXPORTOFFSET)
-       {
-           fprintf(stderr, "%u exceeds max port offset %u\n", portOffset, BC_MAXPORTOFFSET);
+       } else if (portOffset > BC_MAXPORTOFFSET) {
+           fprintf(stderr, "%u exceeds max port offset %u\n", portOffset,
+                   BC_MAXPORTOFFSET);
            exit(1);
        }
     }
-    
-    xbsaType = XBSA_SERVER_TYPE_NONE; /* default */
-    if (as->parms[3].items) {                           /* -device */
-       globalTapeConfig.capacity     = 0x7fffffff;      /* 2T for max tape capacity */
-       globalTapeConfig.fileMarkSize = 0;
-       globalTapeConfig.portOffset   = portOffset;
-       strncpy(globalTapeConfig.device, as->parms[3].items->data, 100);
-       xbsaType = XBSA_SERVER_TYPE_NONE;                /* Not XBSA */
+
+    xbsaType = XBSA_SERVER_TYPE_NONE;  /* default */
+    if (as->parms[3].items) {  /* -device */
+       globalTapeConfig.capacity = 0x7fffffff; /* 2T for max tape capacity */
+       globalTapeConfig.fileMarkSize = 0;
+       globalTapeConfig.portOffset = portOffset;
+       strncpy(globalTapeConfig.device, as->parms[3].items->data, 100);
+       xbsaType = XBSA_SERVER_TYPE_NONE;       /* Not XBSA */
     } else {
-       /* Search for an entry in tapeconfig file */
-       code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset);
-       if (code == -1) {
-         fprintf(stderr, "Problem in reading config file %s\n", tapeConfigFile);
-         exit(1);
-       }
-       /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so
-       * it's an XBSA server. Don't know if its ADSM or not so its unknown.
-       */
-       xbsaType = ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE);
+       /* Search for an entry in tapeconfig file */
+       code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset);
+       if (code == -1) {
+           fprintf(stderr, "Problem in reading config file %s\n",
+                   tapeConfigFile);
+           exit(1);
+       }
+       /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so
+        * it's an XBSA server. Don't know if its ADSM or not so its unknown.
+        */
+       xbsaType =
+           ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE);
     }
 
-    if (as->parms[6].items) {                           /* -restoretofile */
-       int s = strlen(as->parms[6].items->data);
-       restoretofile = malloc(s+1);
-       strncpy(restoretofile, as->parms[6].items->data, s+1);
-       printf("Restore to file '%s'\n", restoretofile);
+    if (as->parms[6].items) {  /* -restoretofile */
+       restoretofile = strdup(as->parms[6].items->data);
+       printf("Restore to file '%s'\n", restoretofile);
     }
 
     /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set
      * the exact xbsaType within the call (won't be unknown) - double check.
      */
     code = GetConfigParams(pFile, portOffset);
-    if (code) exit(code);
+    if (code)
+       exit(code);
 #ifdef xbsa
     if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
-       printf("\nConfiguration file error, the TYPE parameter must be specified, or\n");
-       printf("an entry must exist in %s for port %d\n", tapeConfigFile, portOffset);
-       exit(1);
+       printf
+           ("\nConfiguration file error, the TYPE parameter must be specified, or\n");
+       printf("an entry must exist in %s for port %d\n", tapeConfigFile,
+              portOffset);
+       exit(1);
     }
 #else
     /* Not compiled for XBSA code so we can't support it */
     if (CONF_XBSA) {
-       printf("\nNo entry found in %s for port %d\n", tapeConfigFile, portOffset);
-       printf("This binary does not have XBSA support\n");
-       exit(1);
+       printf("\nNo entry found in %s for port %d\n", tapeConfigFile,
+              portOffset);
+       printf("This binary does not have XBSA support\n");
+       exit(1);
     }
 #endif
 
     /* Open the log files. The pathnames were set in GetConfigParams() */
-    logIO = fopen(logFile,"a");
-    if(!logIO){
-       fprintf(stderr,"Failed to open %s\n",logFile);
+    logIO = fopen(logFile, "a");
+    if (!logIO) {
+       fprintf(stderr, "Failed to open %s\n", logFile);
        exit(1);
     }
-    ErrorlogIO = fopen(ErrorlogFile,"a");
-    if(!ErrorlogIO){
-       fprintf(stderr,"Failed to open %s\n",ErrorlogFile);
+    ErrorlogIO = fopen(ErrorlogFile, "a");
+    if (!ErrorlogIO) {
+       fprintf(stderr, "Failed to open %s\n", ErrorlogFile);
        exit(1);
     }
     if (lastLog) {
-       lastLogIO = fopen(lastLogFile,"a");
-       if (!lastLogIO) {
-         fprintf(stderr,"Failed to open %s\n", lastLogFile);
-         exit(1);
-       }
+       lastLogIO = fopen(lastLogFile, "a");
+       if (!lastLogIO) {
+           fprintf(stderr, "Failed to open %s\n", lastLogFile);
+           exit(1);
+       }
     }
     if (centralLogFile) {
-       struct stat sbuf;
-       afs_int32 statcode;
-       char path[AFSDIR_PATH_MAX];
-
-       statcode = stat(centralLogFile, &sbuf);
-       centralLogIO = fopen(centralLogFile,"a");
-       if(!centralLogIO){
-         fprintf(stderr,"Failed to open %s; error %d\n",centralLogFile, errno);
-         exit(1);
-       }
+       struct stat sbuf;
+       afs_int32 statcode;
+#ifndef AFS_NT40_ENV
+       char *path;
+#endif
 
+       statcode = stat(centralLogFile, &sbuf);
+       centralLogIO = fopen(centralLogFile, "a");
+       if (!centralLogIO) {
+           fprintf(stderr, "Failed to open %s; error %d\n", centralLogFile,
+                   errno);
+           exit(1);
+       }
 #ifndef AFS_NT40_ENV
-       /* Make sure it is not in AFS, has to have been created first */
-       if (!realpath(centralLogFile, path)) {
-         fprintf(stderr,"Warning: can't determine real path of '%s' (%d)\n", centralLogFile, errno);
-       } else {
-         if (strncmp(path,"/afs/",5) == 0) {
-            fprintf(stderr,"The central log '%s' should not be in AFS\n", centralLogFile);
-            exit(1);
-         }
-       }
+       /* Make sure it is not in AFS, has to have been created first */
+       path = malloc(AFSDIR_PATH_MAX);
+       if (path == NULL || !realpath(centralLogFile, path)) {
+           fprintf(stderr,
+                   "Warning: can't determine real path of '%s' (%d)\n",
+                   centralLogFile, errno);
+       } else {
+           if (strncmp(path, "/afs/", 5) == 0) {
+               fprintf(stderr, "The central log '%s' should not be in AFS\n",
+                       centralLogFile);
+               exit(1);
+           }
+       }
+       free(path);
 #endif
 
-       /* Write header if created it */
-       if (statcode) {
-         char *h1="TASK   START DATE/TIME      END DATE/TIME        ELAPSED   VOLUMESET\n";
-         char *h2="-----  -------------------  -------------------  --------  ---------\n";
-         /* File didn't exist before so write the header lines */
-         fwrite(h1, strlen(h1), 1, centralLogIO);
-         fwrite(h2, strlen(h2), 1, centralLogIO);
-         fflush(centralLogIO);
-       }
+       /* Write header if created it */
+       if (statcode) {
+           char *h1 =
+               "TASK   START DATE/TIME      END DATE/TIME        ELAPSED   VOLUMESET\n";
+           char *h2 =
+               "-----  -------------------  -------------------  --------  ---------\n";
+           /* File didn't exist before so write the header lines */
+           fwrite(h1, strlen(h1), 1, centralLogIO);
+           fwrite(h2, strlen(h2), 1, centralLogIO);
+           fflush(centralLogIO);
+       }
     }
 
-    if (as->parms[1].items) 
-    {
+    /* Open the configuration directory */
+    butc_confdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
+    if (butc_confdir == NULL) {
+       TLog(0, "Failed to open server configuration directory");
+       exit(1);
+    }
+
+    /* Start auditing */
+    osi_audit_init();
+    if (as->parms[9].items) {
+       auditFileName = as->parms[9].items->data;
+    }
+    if (auditFileName != NULL)
+       osi_audit_file(auditFileName);
+    if (as->parms[10].items) {
+       auditInterface = as->parms[10].items->data;
+       if (osi_audit_interface(auditInterface)) {
+           TLog(0, "Invalid audit interface '%s'\n", auditInterface);
+           exit(1);
+       }
+    }
+    osi_audit(TC_StartEvent, 0, AUD_END);
+    osi_audit_set_user_check(butc_confdir, tc_IsLocalRealmMatch);
+
+    if (as->parms[1].items) {
        debugLevel = SafeATOL(as->parms[1].items->data);
-       if(debugLevel == -1)
-       {
+       if (debugLevel == -1) {
            TLog(0, "Illegal debug level '%s'\n", as->parms[1].items->data);
            exit(1);
        }
     }
-
 #ifdef xbsa
     /* Setup XBSA library interface */
     if (CONF_XBSA) {
-       afs_int32 rc;
-       rc = xbsa_MountLibrary(&butxInfo, xbsaType);
-       if (rc != XBSA_SUCCESS) {
-         TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n");
-         return(1);
-       }
-
-       forcemultiple = (as->parms[7].items ? 1 : 0); /*-xbsaforcemultiple */
-       if (forcemultiple)
-         printf("Force XBSA multiple server support\n");
-
-       rc = InitToServer(0/*taskid*/, &butxInfo, adsmServerName);
-       if (rc != XBSA_SUCCESS) return(1);
-   }
-#endif /*xbsa*/
+       afs_int32 rc;
+       rc = xbsa_MountLibrary(&butxInfo, xbsaType);
+       if (rc != XBSA_SUCCESS) {
+           TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n");
+           return (1);
+       }
+
+       forcemultiple = (as->parms[7].items ? 1 : 0);/*-xbsaforcemultiple */
+       if (forcemultiple)
+           printf("Force XBSA multiple server support\n");
+
+       rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName);
+       if (rc != XBSA_SUCCESS)
+           return (1);
+       (void)signal(SIGINT, xbsa_shutdown);
+       (void)signal(SIGHUP, xbsa_shutdown);
+    }
+#endif /*xbsa */
 
     /* cell switch */
-    if (as->parms[2].items) strncpy(cellName, as->parms[2].items->data, sizeof(cellName));
-    else                    cellName[0] = '\0';
+    if (as->parms[2].items)
+       strncpy(cellName, as->parms[2].items->data, sizeof(cellName));
+    else
+       cellName[0] = '\0';
 
-    if (as->parms[4].items) autoQuery = 0;
+    if (as->parms[4].items)
+       autoQuery = 0;
 
     localauth = (as->parms[5].items ? 1 : 0);
+    rxBind = (as->parms[8].items ? 1 : 0);
+    allow_unauth = (as->parms[11].items ? 1 : 0);
+
+    if (!allow_unauth && !localauth) {
+       const char *errstr = "Neither -localauth nor -allow_unauthenticated was provided; refusing to start in unintended insecure configuration\n";
+       TLog(0, "%s", (char *)errstr);
+       exit(1);
+    }
 
-    code = rx_Init(htons(BC_TAPEPORT + portOffset));
-    if (code) 
-    {
-       TapeLog(0, 0, code, 0, "rx init failed on port %u\n", BC_TAPEPORT + portOffset);
+    if (rxBind) {
+        afs_int32 ccode;
+        if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
+            AFSDIR_SERVER_NETINFO_FILEPATH) {
+            char reason[1024];
+            ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL,
+                                          ADDRSPERSITE, reason,
+                                          AFSDIR_SERVER_NETINFO_FILEPATH,
+                                          AFSDIR_SERVER_NETRESTRICT_FILEPATH);
+        } else
+       {
+            ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
+        }
+        if (ccode == 1)
+            host = SHostAddrs[0];
+    }
+
+    TLog(0, "butc binding rx to %s:%d\n",
+         afs_inet_ntoa_r(host, hoststr), BC_TAPEPORT + portOffset);
+    code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset));
+    if (code) {
+       TapeLog(0, 0, code, 0, "rx init failed on port %u\n",
+               BC_TAPEPORT + portOffset);
        exit(1);
     }
     rx_SetRxDeadTime(150);
 
     /* Establish connection with the vldb server */
-    code = vldbClientInit(0, localauth, cellName, &cstruct, &ttoken);
-    if (code) 
-    {
-        TapeLog(0, 0, code, 0, "Can't access vldb\n");
+    code = vldbClientInit(0, localauth, cellName, &cstruct, &tokenExpires);
+    if (code) {
+       TapeLog(0, 0, code, 0, "Can't access vldb\n");
        return code;
     }
 
@@ -1024,28 +1119,55 @@ char *arock; {
     /*initialize the dumpNode list */
     InitNodeList(portOffset);
 
-    deviceLatch = (struct deviceSyncNode *)(malloc (sizeof(struct deviceSyncNode)));
+    deviceLatch = malloc(sizeof(struct deviceSyncNode));
     Lock_Init(&(deviceLatch->lock));
     deviceLatch->flags = 0;
 
     /* initialize database support, volume support, and logs */
 
-    /* Create a single security object, in this case the null security
-     * object, for unauthenticated connections, which will be used to control
-     * security on connections made to this server 
+    /*
+     * Create security objects for the Rx server functionality.  Historically
+     * this was a single rxnull security object, since the tape controller was
+     * run by an operator that had local access to the tape device and some
+     * administrative privilege in the cell (to be able to perform volume-level
+     * accesses), but on a machine that was not necessarily trusted to hold the
+     * cell-wide key.
+     *
+     * Such a configuration is, of course, insecure because anyone can make
+     * inbound RPCs and manipulate the database, including creating bogus
+     * dumps and restoring them!  Additionally, in modern usage, butc is
+     * frequently run with -localauth to authenticate its outbound connections
+     * to the volservers and budb with the cell-wide key, in which case the
+     * cell-wide key is present and could be used to authenticate incoming
+     * connections as well.
+     *
+     * If -localauth is in use, create the full barrage of server security
+     * objects, including rxkad, so that inbound connections can be verified
+     * to only be made by authenticated clients.  Otherwise, only the rxnull
+     * class is in use with a single server security object.  Note that butc
+     * will refuse to start in this configuration unless the
+     * "-allow_unauthenticated" flag is provided, indicating that the operator
+     * has ensured that incoming connections are appropriately restricted by
+     * firewall configuration or network topology.
      */
 
-    securityObjects[0] = rxnull_NewServerSecurityObject();
-    securityObjects[1] = (struct rx_securityClass *) 0;        /* don't bother with rxvab */
-    if ( !securityObjects[0] ) 
-    {
-        TLog(0, "rxnull_NewServerSecurityObject");
-       exit(1);
+    if (allow_unauth) {
+       nullObjects[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
+       if (!nullObjects[RX_SECIDX_NULL]) {
+           TLog(0, "rxnull_NewServerSecurityObject");
+           exit(1);
+       }
+       numClasses = 1;
+       secObjs = nullObjects;
+    } else {
+       /* Must be -localauth, so the cell keys are available. */
+       afsconf_BuildServerSecurityObjects(butc_confdir, &allObjs, &numClasses);
+       secObjs = allObjs;
     }
 
-    service = rx_NewService(0, 1, "BUTC", securityObjects, 3, TC_ExecuteRequest);
-    if ( !service ) 
-    {
+    service =
+       rx_NewServiceHost(host, 0, 1, "BUTC", secObjs, numClasses, TC_ExecuteRequest);
+    if (!service) {
        TLog(0, "rx_NewService");
        exit(1);
     }
@@ -1053,52 +1175,52 @@ char *arock; {
 
     /* Establish connection to the backup database */
     code = udbClientInit(0, localauth, cellName);
-    if (code) 
-    {
-        TapeLog(0, 0, code, 0, "Can't access backup database\n");
+    if (code) {
+       TapeLog(0, 0, code, 0, "Can't access backup database\n");
        exit(1);
     }
     /* This call is here to verify that we are authentiated.
-     * The call does nothing and will return BUDB_NOTPERMITTED 
+     * The call does nothing and will return BUDB_NOTPERMITTED
      * if we don't belong.
      */
-    code = bcdb_deleteDump(0,0,0,0);
+    code = bcdb_deleteDump(0, 0, 0, 0);
     if (code == BUDB_NOTPERMITTED) {
-        TapeLog(0, 0, code, 0, "Can't access backup database\n");
+       TapeLog(0, 0, code, 0, "Can't access backup database\n");
        exit(1);
     }
-    
+
     initStatus();
 #ifdef AFS_PTHREAD_ENV
     code = pthread_attr_init(&tattr);
-    if (code)
-    {
-        TapeLog(0, 0, code, 0, "Can't pthread_attr_init database monitor task");
+    if (code) {
+       TapeLog(0, 0, code, 0,
+               "Can't pthread_attr_init database monitor task");
        exit(1);
     }
     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-    if (code)
-    {
-        TapeLog(0, 0, code, 0, "Can't pthread_attr_setdetachstate database monitor task");
+    if (code) {
+       TapeLog(0, 0, code, 0,
+               "Can't pthread_attr_setdetachstate database monitor task");
        exit(1);
     }
     AFS_SIGSET_CLEAR();
     code = pthread_create(&dbWatcherPid, &tattr, dbWatcher, (void *)2);
     AFS_SIGSET_RESTORE();
 #else
-    code = LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, 2, "dbWatcher", &dbWatcherPid);
+    code =
+       LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2,
+                         "dbWatcher", &dbWatcherPid);
 #endif
-    if (code)
-    {
-        TapeLog(0, 0, code, 0, "Can't create database monitor task");
+    if (code) {
+       TapeLog(0, 0, code, 0, "Can't create database monitor task");
        exit(1);
     }
 
     TLog(0, "Starting Tape Coordinator: Port offset %u   Debug level %u\n",
-            portOffset, debugLevel);
-    TLog(0, "Token expires: %s\n", cTIME(&ttoken.endTime));
+        portOffset, debugLevel);
+    TLog(0, "Token expires: %s\n", cTIME(&tokenExpires));
 
-    rx_StartServer(1); /* Donate this process to the server process pool */
+    rx_StartServer(1);         /* Donate this process to the server process pool */
     TLog(0, "Error: StartServer returned");
     exit(1);
 }
@@ -1107,22 +1229,21 @@ char *arock; {
 #include "AFS_component_version_number.c"
 #endif
 
-main(argc, argv)
-int argc;
-char **argv; 
+int
+main(int argc, char **argv)
 {
-    register struct cmd_syndesc *ts;
-    register struct cmd_item *ti;
+    struct cmd_syndesc *ts;
+    struct cmd_item *ti;
 
 #ifdef AFS_AIX32_ENV
     /*
-     * The following signal action for AIX is necessary so that in case of a 
-     * crash (i.e. core is generated) we can include the user's data section 
+     * The following signal action for AIX is necessary so that in case of a
+     * crash (i.e. core is generated) we can include the user's data section
      * in the core dump. Unfortunately, by default, only a partial core is
      * generated which, in many cases, isn't too useful.
      */
     struct sigaction nsa;
-    
+
     sigemptyset(&nsa.sa_mask);
     nsa.sa_handler = SIG_DFL;
     nsa.sa_flags = SA_FULLDUMP;
@@ -1132,53 +1253,65 @@ char **argv;
 
     setlinebuf(stdout);
 
-    ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, "tape coordinator");
+    ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, 0, "tape coordinator");
     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "port offset");
     cmd_AddParm(ts, "-debuglevel", CMD_SINGLE, CMD_OPTIONAL, "0 | 1 | 2");
     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
-    cmd_AddParm(ts, "-device", CMD_SINGLE, (CMD_OPTIONAL|CMD_HIDE), "tape device path");
-    cmd_AddParm(ts, "-noautoquery", CMD_FLAG, CMD_OPTIONAL, 
-                   "do not query operator for first tape");
-    cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL, "create tickets from KeyFile");
-    cmd_AddParm(ts, "-restoretofile", CMD_SINGLE, (CMD_OPTIONAL|CMD_HIDE), "file to restore to");
-    cmd_AddParm(ts, "-xbsaforcemultiple", CMD_FLAG, (CMD_OPTIONAL|CMD_HIDE), "Force multiple XBSA server support");
+    cmd_AddParm(ts, "-device", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
+               "tape device path");
+    cmd_AddParm(ts, "-noautoquery", CMD_FLAG, CMD_OPTIONAL,
+               "do not query operator for first tape");
+    cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
+               "create tickets from KeyFile");
+    cmd_AddParm(ts, "-restoretofile", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
+               "file to restore to");
+    cmd_AddParm(ts, "-xbsaforcemultiple", CMD_FLAG, (CMD_OPTIONAL | CMD_HIDE),
+               "Force multiple XBSA server support");
+    cmd_AddParm(ts, "-rxbind", CMD_FLAG, CMD_OPTIONAL,
+               "bind Rx socket");
+    cmd_AddParm(ts, "-auditlog", CMD_SINGLE, CMD_OPTIONAL, "location of audit log");
+    cmd_AddParm(ts, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL,
+               "interface to use for audit logging");
+    cmd_AddParm(ts, "-allow_unauthenticated", CMD_FLAG, CMD_OPTIONAL,
+               "allow unauthenticated inbound RPCs (requires firewalling)");
 
     /* Initialize dirpaths */
     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
 #ifdef AFS_NT40_ENV
        ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
 #endif
-       fprintf(stderr,"Unable to obtain AFS server directory.\n");
+       fprintf(stderr, "Unable to obtain AFS server directory.\n");
        exit(2);
     }
 
     /* setup the file paths */
-    strcompose(eFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/", TE_PREFIX, NULL);
-    strcompose(lFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/", TL_PREFIX, NULL);
-    strcompose(pFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/", CFG_PREFIX, NULL);
+    strcompose(eFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
+              TE_PREFIX, (char *)NULL);
+    strcompose(lFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
+              TL_PREFIX, (char *)NULL);
+    strcompose(pFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
+              CFG_PREFIX, (char *)NULL);
     strcpy(tapeConfigFile, AFSDIR_SERVER_TAPECONFIG_FILEPATH);
 
     /* special case "no args" case since cmd_dispatch gives help message
      * instead
      */
     if (argc == 1) {
-       ts = (struct cmd_syndesc *) malloc(sizeof(struct cmd_syndesc));
-       memset(ts, 0, sizeof(*ts));
-       
-       ti = (struct cmd_item *) malloc(sizeof(struct cmd_item));
+       ts = calloc(1, sizeof(struct cmd_syndesc));
+
+       ti = malloc(sizeof(struct cmd_item));
        ti->next = 0;
        ti->data = "0";
        ts->parms[0].items = ti;
-       ti = (struct cmd_item *) malloc(sizeof(struct cmd_item));
+       ti = malloc(sizeof(struct cmd_item));
        ti->next = 0;
        ti->data = "0";
        ts->parms[1].items = ti;
-       ts->parms[2].items = (struct cmd_item *) NULL;
-       ts->parms[3].items = (struct cmd_item *) NULL;
-       ts->parms[4].items = (struct cmd_item *) NULL;
-       ts->parms[5].items = (struct cmd_item *) NULL;
+       ts->parms[2].items = NULL;
+       ts->parms[3].items = NULL;
+       ts->parms[4].items = NULL;
+       ts->parms[5].items = NULL;
        return WorkerBee(ts, NULL);
-    }
-    else
+    } else
        return cmd_Dispatch(argc, argv);
 }