time_t-pointer-conversions-20040908
[openafs.git] / src / butc / tcmain.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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #ifdef AFS_NT40_ENV
19 #include <winsock2.h>
20 #include <WINNT/afsevent.h>
21 #else
22 #include <netinet/in.h>
23 #include <sys/time.h>
24 #endif
25 #include <afs/procmgmt.h>
26 #include <rx/xdr.h>
27 #include <afs/afsint.h>
28 #include <stdio.h>
29 #ifdef AFS_PTHREAD_ENV
30 #include <assert.h>
31 #else
32 #include <afs/assert.h>
33 #endif
34 #include <afs/prs_fs.h>
35 #include <afs/nfs.h>
36 #include <string.h>
37 #include <afs/vlserver.h>
38 #include <lwp.h>
39 #include <lock.h>
40 #include <afs/afsutil.h>
41 #include <rx/rx.h>
42 #include <rx/rx_globals.h>
43 #include <afs/auth.h>
44 #include <rx/rxkad.h>
45 #include <afs/cellconfig.h>
46 #include <afs/keys.h>
47 #include <afs/volser.h>
48 #include <ubik.h>
49 #include <afs/com_err.h>
50 #include <errno.h>
51 #include <afs/cmd.h>
52 #include <afs/tcdata.h>
53 #include <afs/bubasics.h>
54 #include <ctype.h>
55 #include "error_macros.h"
56 #include <afs/budb_errs.h>
57 #include "afs/butx.h"
58 #define XBSA_TCMAIN
59 #include "butc_xbsa.h"
60
61 #define N_SECURITY_OBJECTS 3
62 #define ERRCODE_RANGE 8         /* from error_table.h */
63
64 #define TE_PREFIX  "TE"
65 #define TL_PREFIX  "TL"
66 #define CFG_PREFIX "CFG"
67
68 struct ubik_client *cstruct;
69 extern void TC_ExecuteRequest();
70 extern int dbWatcher();
71 FILE *logIO, *ErrorlogIO, *centralLogIO, *lastLogIO;
72 char lFile[AFSDIR_PATH_MAX];
73 char logFile[256];
74 char ErrorlogFile[256];
75 char lastLogFile[256];
76 char eFile[AFSDIR_PATH_MAX];
77 char tapeConfigFile[AFSDIR_PATH_MAX];
78 char pFile[AFSDIR_PATH_MAX];
79 int debugLevel = 0;
80 struct tapeConfig globalTapeConfig;
81 struct deviceSyncNode *deviceLatch;
82 char globalCellName[64];
83 char *whoami = "butc";
84
85 /* GLOBAL CONFIGURATION PARAMETERS */
86 int dump_namecheck;
87 int queryoperator;
88 int autoQuery;
89 int isafile;
90 int tapemounted;
91 char *opencallout;
92 char *closecallout;
93 char *restoretofile;
94 int forcemultiple;
95
96 int maxpass;
97 #define PASSESMIN  1
98 #define PASSESMAX  10
99 #define PASSESDFLT 2
100 afs_int32 groupId;
101 #define MINGROUPID 0x1
102 #define MAXGROUPID 0x7FFFFFFF
103 afs_int32 statusSize;
104 #define MINSTATUS  1
105 #define MAXSTATUS  0x7fffffff
106 afs_int32 BufferSize;           /* Size in B stored for data */
107 char *centralLogFile;
108 afs_int32 lastLog;              /* Log last pass info */
109
110 /* dummy routine for the audit work.  It should do nothing since audits */
111 /* occur at the server level and bos is not a server. */
112 osi_audit()
113 {
114     return 0;
115 }
116
117 static afs_int32
118 SafeATOL(anum)
119      register char *anum;
120 {
121     register afs_int32 total;
122     register int tc;
123
124     total = 0;
125     while (tc = *anum) {
126         if (tc < '0' || tc > '9')
127             return -1;
128         total *= 10;
129         total += (tc - '0');
130         anum++;
131     }
132     return total;
133 }
134
135 /* atocl
136  *      Convert a string into an afs_int32.
137  *      Returned afs_int32 is in Bytes, Kb, Mb, Gb, or Tb. Based on crunit char.
138  *      This routine only converts unsigned float values.
139  *      The returned value is a whole number.
140  * entry:
141  *      numstring - text string to be converted.
142  *      crunit - value returned in 'B', 'K', 'M', 'G', 'T'.
143  *               ' ' or NULL ==> 'B' (bytes).
144  * exit:
145  *      number - returned value in requested crunit - rounded
146  *               to nearest whole number.
147  * fn return value:
148  *       0 - conversion ok
149  *      -1 - error in conversion
150  * notes:
151  *      should deal with signed numbers. Should signal error if no digits
152  *      seen.
153  */
154 atocl(numstring, crunit, number)
155      char *numstring;
156      char crunit;               /* Units to report number in */
157      afs_int32 *number;
158 {
159     float total;
160     afs_int32 runits;
161     char cunit;
162     afs_int32 units;
163     afs_int32 count;
164     char rest[256];
165
166     /* Determine which units to report in */
167     switch (crunit) {
168     case 't':
169     case 'T':
170         runits = 12;
171         break;
172
173     case 'g':
174     case 'G':
175         runits = 9;
176         break;
177
178     case 'm':
179     case 'M':
180         runits = 6;
181         break;
182
183     case 'k':
184     case 'K':
185         runits = 3;
186         break;
187
188     case 'b':
189     case 'B':
190     case ' ':
191     case 0:
192         runits = 0;
193         break;
194
195     default:
196         return (-1);
197     }
198
199     count =
200         sscanf(numstring, "%f%c%s", &total, &cunit, rest);
201     if ((count > 2) || (count <= 0))
202         return -1;
203     if (count == 1)
204         cunit = 'B';            /* bytes */
205
206     switch (cunit) {
207     case 't':
208     case 'T':
209         units = 12;
210         break;
211
212     case 'g':
213     case 'G':
214         units = 9;
215         break;
216
217     case 'm':
218     case 'M':
219         units = 6;
220         break;
221
222     case 'k':
223     case 'K':
224         units = 3;
225         break;
226
227     case 'b':
228     case 'B':
229     case ' ':
230     case 0:
231         units = 0;
232         break;
233
234     default:
235         return (-1);
236     }
237
238     /* Go to correct unit */
239     for (; units < runits; units += 3)
240         total /= 1024.0;
241     for (; units > runits; units -= 3)
242         total *= 1024.0;
243
244     total += 0.5;               /* Round up */
245     if ((total > 0x7fffffff) || (total < 0))    /* Don't go over 2G */
246         total = 0x7fffffff;
247
248     *number = total;
249     return (0);
250 }
251
252 /* replace last two ocurrences of / by _ */
253 static
254 stringReplace(name)
255      char *name;
256 {
257     char *pos;
258     char buffer[256];
259
260     pos = strrchr(name, '/');
261     *pos = '_';
262     strcpy(buffer, pos);
263     pos = strrchr(name, '/');
264     *pos = '\0';
265     strcat(name, buffer);
266     return 0;
267 }
268
269 static
270 stringNowReplace(logFile, deviceName)
271      char *logFile, *deviceName;
272
273 {
274     char *pos = 0;
275     char storeDevice[256];
276     int mvFlag = 0, devPrefLen;
277 #ifdef AFS_NT40_ENV
278     char devPrefix[] = "\\\\.";
279 #else
280     char devPrefix[] = "/dev";
281 #endif
282
283     devPrefLen = strlen(devPrefix);
284     strcpy(storeDevice, deviceName);
285     if (strncmp(deviceName, devPrefix, devPrefLen) == 0) {
286         deviceName += devPrefLen;
287         mvFlag++;
288     }
289     while (pos = strchr(deviceName, devPrefix[0]))      /* look for / or \ */
290         *pos = '_';
291     strcat(logFile, deviceName);
292     /* now put back deviceName to the way it was */
293     if (mvFlag) {
294         mvFlag = 0;
295         deviceName -= devPrefLen;
296     }
297     strcpy(deviceName, storeDevice);
298
299     return (0);
300 }
301
302
303 /* GetDeviceConfig
304  *      get the configuration information for a particular tape device
305  *      as specified by the portoffset
306  * entry:
307  *      filename - full pathname of file containing the tape device
308  *              configuration information
309  *      config - for return results
310  *      portOffset - for which configuration is required
311  * notes:
312  *      logging not available when this routine is called
313  *      caller return value checks
314  * exit:
315  *      0 => Found entry with same port, return info in config.
316  *     -1 => Error encountered trying to read the file.
317  *      1 => Desired entry does not exist or file does not exist.
318  */
319
320 #define LINESIZE        256
321 static afs_int32
322 GetDeviceConfig(filename, config, portOffset)
323      char *filename;
324      struct tapeConfig *config;
325      afs_int32 portOffset;
326 {
327     FILE *devFile = 0;
328     char line[LINESIZE];
329     char devName[LINESIZE], tcapacity[LINESIZE], tfmsize[LINESIZE],
330         trest[LINESIZE];
331     afs_int32 aport;
332     afs_uint32 capacity;
333     afs_uint32 fmSize;
334     afs_int32 code = 0, count;
335
336     /* Initialize the config struct */
337     config->capacity = 0;
338     config->fileMarkSize = 0;
339     config->portOffset = portOffset;
340     strcpy(config->device, "");
341
342     devFile = fopen(filename, "r");
343     if (!devFile) {
344         if (errno == ENOENT)
345             ERROR_EXIT(1);
346         fprintf(stderr, "Error %d: Can't open %s\n", errno, filename);
347         ERROR_EXIT(-1);
348     }
349
350     while (fgets(line, LINESIZE - 1, devFile)) {
351         count =
352             sscanf(line, "%s %s %s %u%s\n", tcapacity, tfmsize, devName,
353                    &aport, trest);
354
355         if (count == 4 || count == 5) {
356             if (atocl(tcapacity, 'K', &capacity)) {
357                 fprintf(stderr,
358                         "tapeconfig: Tape capacity parse error in: %s\n",
359                         line);
360                 ERROR_EXIT(-1);
361             }
362             if (atocl(tfmsize, 'B', &fmSize)) {
363                 fprintf(stderr,
364                         "tapeconfig: File-mark size parse error in: %s\n",
365                         line);
366                 ERROR_EXIT(-1);
367             }
368         } else {
369             count = sscanf(line, "%s %u%s\n", devName, &aport, trest);
370             if (count == 2 || count == 3) {
371                 capacity = 0x7fffffff;
372                 fmSize = 0;
373             } else {
374                 fprintf(stderr, "tapeconfig: Parse error in: %s\n", line);
375                 ERROR_EXIT(-1);
376             }
377         }
378
379         if ((aport < 0) || (aport > BC_MAXPORTOFFSET)) {
380             fprintf(stderr, "tapeconfig: Port offset parse error in: %s\n",
381                     line);
382             ERROR_EXIT(-1);
383         }
384
385         if (aport != portOffset)
386             continue;
387
388         if (fmSize < 0) {
389             fprintf(stderr, "Invalid file mark size, %d, in: %s\n", fmSize,
390                     line);
391             ERROR_EXIT(-1);
392         }
393
394         config->capacity = capacity;
395         config->fileMarkSize = fmSize;
396         config->portOffset = aport;
397         strncpy(config->device, devName, 100);
398
399         ERROR_EXIT(0);
400     }
401
402     /* fprintf(stderr, "Can't find tapeconfig entry for port offset %d\n", portOffset); */
403     ERROR_EXIT(1);
404
405   error_exit:
406     if (devFile)
407         fclose(devFile);
408     return (code);
409 }
410
411 /* GetConfigParams
412  */
413 static afs_int32
414 GetConfigParams(filename, port)
415      char *filename;
416      afs_int32 port;
417 {
418     char paramFile[256];
419     FILE *devFile = 0;
420     char line[LINESIZE], cmd[LINESIZE], value[LINESIZE];
421     afs_int32 code = 0;
422     int cnt;
423
424     /* DEFAULT SETTINGS FOR GLOBAL PARAMETERS */
425     dump_namecheck = 1;         /* check tape name on dumps */
426     queryoperator = 1;          /* can question operator */
427     autoQuery = 1;              /* prompt for first tape */
428     isafile = 0;                /* Do not dump to a file */
429     opencallout = NULL;         /* open  callout routine */
430     closecallout = NULL;        /* close callout routine */
431     tapemounted = 0;            /* tape is not mounted */
432 #ifdef xbsa
433     BufferSize = (CONF_XBSA ? XBSADFLTBUFFER : BUTM_BLOCKSIZE);
434     dumpRestAuthnLevel = rpc_c_protect_level_default;
435     xbsaObjectOwner = NULL;     /* bsaObjectOwner */
436     appObjectOwner = NULL;      /* appObjectOwner */
437     adsmServerName = NULL;      /* TSM server name - same as ADSM */
438     xbsaSecToken = NULL;        /* XBSA sercurity token */
439     xbsalGName = NULL;          /* XBSA IGName */
440 #else
441     BufferSize = BUTM_BLOCKSIZE;
442 #endif /*xbsa */
443     centralLogFile = NULL;      /* Log for all butcs */
444     centralLogIO = 0;           /* Log for all butcs */
445     statusSize = 0;             /* size before status message */
446     maxpass = PASSESDFLT;       /* dump passes */
447     lastLog = 0;                /* separate log for last pass */
448     lastLogIO = 0;              /* separate log for last pass */
449     groupId = 0;                /* Group id for multiple dumps */
450
451     /* Try opening the CFG_<port> file */
452     sprintf(paramFile, "%s_%d", filename, port);
453     devFile = fopen(paramFile, "r");
454     if (devFile) {
455         /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
456         sprintf(logFile, "%s_%d", lFile, port);
457         sprintf(lastLogFile, "%s_%d.lp", lFile, port);
458         sprintf(ErrorlogFile, "%s_%d", eFile, port);
459     } else if (CONF_XBSA) {
460         /* If configured as XBSA, a configuration file CFG_<port> must exist */
461         printf("Cannot open configuration file %s", paramFile);
462         ERROR_EXIT(1);
463     } else {
464         /* Try the CFG_<device> name as the device file */
465         strcpy(paramFile, filename);
466         stringNowReplace(paramFile, globalTapeConfig.device);
467         /* Set log names to TL_<device>, TL_<device> and TE_<device> */
468         strcpy(logFile, lFile);
469         stringNowReplace(logFile, globalTapeConfig.device);
470         strcpy(lastLogFile, lFile);
471         stringNowReplace(lastLogFile, globalTapeConfig.device);
472         strcat(lastLogFile, ".lp");
473         strcpy(ErrorlogFile, eFile);
474         stringNowReplace(ErrorlogFile, globalTapeConfig.device);
475
476         /* Now open the device file */
477         devFile = fopen(paramFile, "r");
478         if (!devFile)
479             ERROR_EXIT(0);      /* CFG file doesn't exist for non-XBSA and that's ok */
480     }
481
482     /* Read each line of the Configuration file */
483     while (fgets(line, LINESIZE - 1, devFile)) {
484         cnt = sscanf(line, "%s %s", cmd, value);
485         if (cnt != 2) {
486             if (cnt > 0)
487                 printf("Bad line in %s: %s\n", paramFile, line);
488             continue;
489         }
490
491         for (cnt = 0; cnt < strlen(cmd); cnt++)
492             if (islower(cmd[cnt]))
493                 cmd[cnt] = toupper(cmd[cnt]);
494
495         if (!strcmp(cmd, "NAME_CHECK")) {
496             if (CONF_XBSA) {
497                 printf
498                     ("Warning: The %s parameter is ignored with a Backup Service\n",
499                      cmd);
500                 continue;
501             }
502
503             for (cnt = 0; cnt < strlen(value); cnt++)
504                 if (islower(value[cnt]))
505                     value[cnt] = toupper(value[cnt]);
506
507             if (!strcmp(value, "NO")) {
508                 printf("Dump tape name check is disabled\n");
509                 dump_namecheck = 0;
510             } else {
511                 printf("Dump tape name check is enabled\n");
512                 dump_namecheck = 1;
513             }
514         }
515
516         else if (!strcmp(cmd, "MOUNT")) {
517             if (CONF_XBSA) {
518                 printf
519                     ("Warning: The %s parameter is ignored with a Backup Service\n",
520                      cmd);
521                 continue;
522             }
523
524             opencallout = (char *)malloc(strlen(value) + 1);
525             strcpy(opencallout, value);
526             printf("Tape mount callout routine is %s\n", opencallout);
527         }
528
529         else if (!strcmp(cmd, "UNMOUNT")) {
530             if (CONF_XBSA) {
531                 printf
532                     ("Warning: The %s parameter is ignored with a Backup Service\n",
533                      cmd);
534                 continue;
535             }
536
537             closecallout = (char *)malloc(strlen(value) + 1);
538             strcpy(closecallout, value);
539             printf("Tape unmount callout routine is %s\n", closecallout);
540         }
541
542         else if (!strcmp(cmd, "ASK")) {
543             for (cnt = 0; cnt < strlen(value); cnt++)
544                 if (islower(value[cnt]))
545                     value[cnt] = toupper(value[cnt]);
546
547             if (!strcmp(value, "NO")) {
548                 printf("Operator queries are disabled\n");
549                 queryoperator = 0;
550             } else {
551                 printf("Operator queries are enabled\n");
552                 queryoperator = 1;
553             }
554         }
555
556         else if (!strcmp(cmd, "FILE")) {
557             if (CONF_XBSA) {
558                 printf
559                     ("Warning: The %s parameter is ignored with a Backup Service\n",
560                      cmd);
561                 continue;
562             }
563
564             for (cnt = 0; cnt < strlen(value); cnt++)
565                 if (islower(value[cnt]))
566                     value[cnt] = toupper(value[cnt]);
567
568             if (!strcmp(value, "YES")) {
569                 printf("Will dump to a file\n");
570                 isafile = 1;
571             } else {
572                 printf("Will not dump to a file\n");
573                 isafile = 0;
574             }
575         }
576
577         else if (!strcmp(cmd, "AUTOQUERY")) {
578             if (CONF_XBSA) {
579                 printf
580                     ("Warning: The %s parameter is ignored with a Backup Service\n",
581                      cmd);
582                 continue;
583             }
584
585             for (cnt = 0; cnt < strlen(value); cnt++)
586                 if (islower(value[cnt]))
587                     value[cnt] = toupper(value[cnt]);
588
589             if (!strcmp(value, "NO")) {
590                 printf("Auto query is disabled\n");
591                 autoQuery = 0;
592             } else {
593                 printf("Auto query is enabled\n");
594                 autoQuery = 1;
595             }
596         }
597
598         else if (!strcmp(cmd, "BUFFERSIZE")) {
599             afs_int32 size;
600             afs_int32 tapeblocks;
601
602             if (!CONF_XBSA) {
603                 if (atocl(value, 'K', &size)) {
604                     fprintf(stderr, "BUFFERSIZE parse error\n");
605                     size = 0;
606                 }
607
608                 /* A tapeblock is 16KB. Determine # of tapeblocks. Then
609                  * determine BufferSize needed for that many tapeblocks.
610                  */
611                 tapeblocks = size / 16;
612                 if (tapeblocks <= 0)
613                     tapeblocks = 1;
614                 printf("BUFFERSIZE is %u KBytes\n", (tapeblocks * 16));
615                 BufferSize = tapeblocks * BUTM_BLOCKSIZE;
616             } else {
617 #ifdef xbsa
618                 if (atocl(value, 'B', &size)) {
619                     fprintf(stderr, "BUFFERSIZE parse error\n");
620                     size = 0;
621                 }
622                 if (size < XBSAMINBUFFER)
623                     size = XBSAMINBUFFER;
624                 if (size > XBSAMAXBUFFER)
625                     size = XBSAMAXBUFFER;
626                 printf("XBSA buffer size is %u Bytes\n", size);
627                 BufferSize = size;
628 #endif
629             }
630         }
631 #ifndef xbsa
632         /* All the xbsa spacific parameters */
633         else if (!strcmp(cmd, "TYPE") || !strcmp(cmd, "NODE")
634                  || !strcmp(cmd, "SERVER") || !strcmp(cmd, "PASSWORD")
635                  || !strcmp(cmd, "PASSFILE") || !strcmp(cmd, "MGMTCLASS")) {
636             printf("This binary does not have XBSA support\n");
637             return 1;
638         }
639 #else
640         else if (!strcmp(cmd, "TYPE")) {        /* required for XBSA */
641             if (!CONF_XBSA) {
642                 printf
643                     ("Warning: The %s parameter is ignored with a tape drive\n",
644                      cmd);
645                 continue;
646             }
647
648             for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
649                 if (islower(value[cnt]))
650                     value[cnt] = toupper(value[cnt]);
651
652             if (strcmp(value, "TSM") == 0) {
653                 xbsaType = XBSA_SERVER_TYPE_ADSM;       /* Known XBSA server type */
654             } else {
655                 printf("Configuration file error, %s %s is not recognized\n",
656                        cmd, value);
657                 xbsaType = XBSA_SERVER_TYPE_UNKNOWN;
658             }
659             printf("XBSA type is %s\n",
660                    ((xbsaType ==
661                      XBSA_SERVER_TYPE_UNKNOWN) ? "Unknown" : value));
662         }
663
664         else if (!strcmp(cmd, "NODE")) {
665             if (!CONF_XBSA) {
666                 printf
667                     ("Warning: The %s parameter is ignored with a tape drive\n",
668                      cmd);
669                 continue;
670             }
671             xbsaObjectOwner = malloc(strlen(value) + 1);
672             strcpy(xbsaObjectOwner, value);
673             printf("XBSA node is %s\n", xbsaObjectOwner);
674         }
675
676         else if (!strcmp(cmd, "SERVER")) {      /* required for XBSA */
677             if (!CONF_XBSA) {
678                 printf
679                     ("Warning: The %s parameter is ignored with a tape drive\n",
680                      cmd);
681                 continue;
682             }
683             adsmServerName = malloc(strlen(value) + 1);
684             strcpy(adsmServerName, value);
685             printf("XBSA server is %s\n", adsmServerName);
686         }
687
688         else if (!strcmp(cmd, "PASSWORD")) {    /* This or PASSFILE required for XBSA */
689             if (!CONF_XBSA) {
690                 printf
691                     ("Warning: The %s parameter is ignored with a tape drive\n",
692                      cmd);
693                 continue;
694             }
695             if (xbsaSecToken) {
696                 printf
697                     ("Warning: The %s parameter is ignored. Already read password\n",
698                      cmd);
699                 continue;
700             }
701
702             xbsaSecToken = malloc(strlen(value) + 1);
703             strcpy(xbsaSecToken, value);
704             printf("XBSA Password has been read\n");
705         }
706
707         else if (!strcmp(cmd, "PASSFILE")) {    /* This or PASSWORD required for XBSA */
708             FILE *pwdFile;
709             if (!CONF_XBSA) {
710                 printf
711                     ("Warning: The %s parameter is ignored with a tape drive\n",
712                      cmd);
713                 continue;
714             }
715             if (xbsaSecToken) {
716                 printf
717                     ("Warning: The %s parameter is ignored. Already read password\n",
718                      cmd);
719                 continue;
720             }
721
722             pwdFile = fopen(value, "r");
723             if (!pwdFile) {
724                 printf
725                     ("Configuration file error, cannot open password file %s\n",
726                      value);
727                 ERROR_EXIT(1);
728             }
729             xbsaSecToken = malloc(LINESIZE);
730             if (!fscanf(pwdFile, "%s", xbsaSecToken)) {
731                 printf
732                     ("Configuration file error, cannot read password file %s\n",
733                      value);
734                 ERROR_EXIT(1);
735             }
736             printf("XBSA password retrieved from password file\n");
737         }
738
739         else if (!strcmp(cmd, "MGMTCLASS")) {   /* XBSA */
740             if (!CONF_XBSA) {
741                 printf
742                     ("Warning: The %s parameter is ignored with a tape drive\n",
743                      cmd);
744                 continue;
745             }
746             xbsalGName = malloc(strlen(value) + 1);
747             strcpy(xbsalGName, value);
748             printf("XBSA management class is %s\n", xbsalGName);
749         }
750 #endif
751
752         else if (!strcmp(cmd, "MAXPASS")) {
753             maxpass = SafeATOL(value);
754             if (maxpass < PASSESMIN)
755                 maxpass = PASSESMIN;
756             if (maxpass > PASSESMAX)
757                 maxpass = PASSESMAX;
758             printf("MAXPASS is %d\n", maxpass);
759         }
760
761         else if (!strcmp(cmd, "GROUPID")) {
762             groupId = SafeATOL(value);
763             if ((groupId < MINGROUPID) || (groupId > MAXGROUPID)) {
764                 printf("Configuration file error, %s %s is invalid\n", cmd,
765                        value);
766                 ERROR_EXIT(1);
767             }
768             printf("Group Id is %d\n", groupId);
769         }
770
771         else if (!strcmp(cmd, "LASTLOG")) {
772             for (cnt = 0; (size_t) cnt < strlen(value); cnt++)
773                 if (islower(value[cnt]))
774                     value[cnt] = toupper(value[cnt]);
775
776             lastLog = (strcmp(value, "YES") == 0);
777             printf("Will %sgenerate a last log\n", (lastLog ? "" : "not "));
778         }
779
780         else if (!strcmp(cmd, "CENTRALLOG")) {
781             centralLogFile = malloc(strlen(value) + 1);
782             strcpy(centralLogFile, value);
783             printf("Central log file is %s\n", centralLogFile);
784         }
785
786         else if (!strcmp(cmd, "STATUS")) {
787             if (atocl(value, 'B', &statusSize)) {
788                 fprintf(stderr, "STATUS parse error\n");
789                 statusSize = 0;
790             }
791             if (statusSize < MINSTATUS)
792                 statusSize = MINSTATUS;
793             if (statusSize > MAXSTATUS)
794                 statusSize = MAXSTATUS;
795         }
796
797         else {
798             printf("Warning: Unrecognized configuration parameter: %s", line);
799         }
800     }                           /*fgets */
801
802     if (statusSize) {
803         /* Statussize is in bytes and requires that BufferSize be set first */
804         statusSize *= BufferSize;
805         if (statusSize < 0)
806             statusSize = 0x7fffffff;    /*max size */
807         printf("Status every %ld Bytes\n", statusSize);
808     }
809
810   error_exit:
811     if (devFile)
812         fclose(devFile);
813
814     /* If the butc is configured as XBSA, check for required parameters */
815 #ifdef xbsa
816     if (!code && CONF_XBSA) {
817         if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
818             printf
819                 ("Configuration file error, the TYPE parameter must be specified, or\n");
820             printf("an entry must exist in %s for port %d\n", tapeConfigFile,
821                    port);
822             code = 1;
823         }
824         if (!adsmServerName) {
825             printf
826                 ("Configuration file error, the SERVER parameter must be specified\n");
827             code = 1;
828         }
829         if (!xbsaSecToken) {
830             printf
831                 ("Configuration file error, the PASSWORD or PASSFILE parameter must be specified\n");
832             code = 1;
833         }
834     }
835 #endif /*xbsa */
836     return (code);
837 }
838
839 static
840 WorkerBee(as, arock)
841      struct cmd_syndesc *as;
842      char *arock;
843 {
844     register afs_int32 code;
845     struct rx_securityClass *(securityObjects[3]);
846     struct rx_service *service;
847     struct ktc_token ttoken;
848     char cellName[64];
849     int localauth;
850     /*process arguments */
851     afs_int32 portOffset = 0;
852 #ifdef AFS_PTHREAD_ENV
853     pthread_t dbWatcherPid;
854     pthread_attr_t tattr;
855     AFS_SIGSET_DECL;
856 #else
857     PROCESS dbWatcherPid;
858 #endif
859     time_t t;
860
861     debugLevel = 0;
862
863     /*initialize the error tables */
864     initialize_KA_error_table();
865     initialize_RXK_error_table();
866     initialize_KTC_error_table();
867     initialize_ACFG_error_table();
868     initialize_CMD_error_table();
869     initialize_VL_error_table();
870     initialize_BUTM_error_table();
871     initialize_BUTC_error_table();
872 #ifdef xbsa
873     initialize_BUTX_error_table();
874 #endif /*xbs */
875     initialize_VOLS_error_table();
876     initialize_BUDB_error_table();
877     initialize_BUCD_error_table();
878
879     if (as->parms[0].items) {
880         portOffset = SafeATOL(as->parms[0].items->data);
881         if (portOffset == -1) {
882             fprintf(stderr, "Illegal port offset '%s'\n",
883                     as->parms[0].items->data);
884             exit(1);
885         } else if (portOffset > BC_MAXPORTOFFSET) {
886             fprintf(stderr, "%u exceeds max port offset %u\n", portOffset,
887                     BC_MAXPORTOFFSET);
888             exit(1);
889         }
890     }
891
892     xbsaType = XBSA_SERVER_TYPE_NONE;   /* default */
893     if (as->parms[3].items) {   /* -device */
894         globalTapeConfig.capacity = 0x7fffffff; /* 2T for max tape capacity */
895         globalTapeConfig.fileMarkSize = 0;
896         globalTapeConfig.portOffset = portOffset;
897         strncpy(globalTapeConfig.device, as->parms[3].items->data, 100);
898         xbsaType = XBSA_SERVER_TYPE_NONE;       /* Not XBSA */
899     } else {
900         /* Search for an entry in tapeconfig file */
901         code = GetDeviceConfig(tapeConfigFile, &globalTapeConfig, portOffset);
902         if (code == -1) {
903             fprintf(stderr, "Problem in reading config file %s\n",
904                     tapeConfigFile);
905             exit(1);
906         }
907         /* Set xbsaType. If code == 1, no entry was found in the tapeconfig file so
908          * it's an XBSA server. Don't know if its ADSM or not so its unknown.
909          */
910         xbsaType =
911             ((code == 1) ? XBSA_SERVER_TYPE_UNKNOWN : XBSA_SERVER_TYPE_NONE);
912     }
913
914     if (as->parms[6].items) {   /* -restoretofile */
915         int s = strlen(as->parms[6].items->data);
916         restoretofile = malloc(s + 1);
917         strncpy(restoretofile, as->parms[6].items->data, s + 1);
918         printf("Restore to file '%s'\n", restoretofile);
919     }
920
921     /* Go and read the config file: CFG_<device> or CFG_<port>. We will also set
922      * the exact xbsaType within the call (won't be unknown) - double check.
923      */
924     code = GetConfigParams(pFile, portOffset);
925     if (code)
926         exit(code);
927 #ifdef xbsa
928     if (xbsaType == XBSA_SERVER_TYPE_UNKNOWN) {
929         printf
930             ("\nConfiguration file error, the TYPE parameter must be specified, or\n");
931         printf("an entry must exist in %s for port %d\n", tapeConfigFile,
932                portOffset);
933         exit(1);
934     }
935 #else
936     /* Not compiled for XBSA code so we can't support it */
937     if (CONF_XBSA) {
938         printf("\nNo entry found in %s for port %d\n", tapeConfigFile,
939                portOffset);
940         printf("This binary does not have XBSA support\n");
941         exit(1);
942     }
943 #endif
944
945     /* Open the log files. The pathnames were set in GetConfigParams() */
946     logIO = fopen(logFile, "a");
947     if (!logIO) {
948         fprintf(stderr, "Failed to open %s\n", logFile);
949         exit(1);
950     }
951     ErrorlogIO = fopen(ErrorlogFile, "a");
952     if (!ErrorlogIO) {
953         fprintf(stderr, "Failed to open %s\n", ErrorlogFile);
954         exit(1);
955     }
956     if (lastLog) {
957         lastLogIO = fopen(lastLogFile, "a");
958         if (!lastLogIO) {
959             fprintf(stderr, "Failed to open %s\n", lastLogFile);
960             exit(1);
961         }
962     }
963     if (centralLogFile) {
964         struct stat sbuf;
965         afs_int32 statcode;
966 #ifndef AFS_NT40_ENV
967         char path[AFSDIR_PATH_MAX];
968 #endif
969
970         statcode = stat(centralLogFile, &sbuf);
971         centralLogIO = fopen(centralLogFile, "a");
972         if (!centralLogIO) {
973             fprintf(stderr, "Failed to open %s; error %d\n", centralLogFile,
974                     errno);
975             exit(1);
976         }
977 #ifndef AFS_NT40_ENV
978         /* Make sure it is not in AFS, has to have been created first */
979         if (!realpath(centralLogFile, path)) {
980             fprintf(stderr,
981                     "Warning: can't determine real path of '%s' (%d)\n",
982                     centralLogFile, errno);
983         } else {
984             if (strncmp(path, "/afs/", 5) == 0) {
985                 fprintf(stderr, "The central log '%s' should not be in AFS\n",
986                         centralLogFile);
987                 exit(1);
988             }
989         }
990 #endif
991
992         /* Write header if created it */
993         if (statcode) {
994             char *h1 =
995                 "TASK   START DATE/TIME      END DATE/TIME        ELAPSED   VOLUMESET\n";
996             char *h2 =
997                 "-----  -------------------  -------------------  --------  ---------\n";
998             /* File didn't exist before so write the header lines */
999             fwrite(h1, strlen(h1), 1, centralLogIO);
1000             fwrite(h2, strlen(h2), 1, centralLogIO);
1001             fflush(centralLogIO);
1002         }
1003     }
1004
1005     if (as->parms[1].items) {
1006         debugLevel = SafeATOL(as->parms[1].items->data);
1007         if (debugLevel == -1) {
1008             TLog(0, "Illegal debug level '%s'\n", as->parms[1].items->data);
1009             exit(1);
1010         }
1011     }
1012 #ifdef xbsa
1013     /* Setup XBSA library interface */
1014     if (CONF_XBSA) {
1015         afs_int32 rc;
1016         rc = xbsa_MountLibrary(&butxInfo, xbsaType);
1017         if (rc != XBSA_SUCCESS) {
1018             TapeLog(0, 0, rc, 0, "Unable to mount the XBSA library\n");
1019             return (1);
1020         }
1021
1022         forcemultiple = (as->parms[7].items ? 1 : 0);/*-xbsaforcemultiple */
1023         if (forcemultiple)
1024             printf("Force XBSA multiple server support\n");
1025
1026         rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName);
1027         if (rc != XBSA_SUCCESS)
1028             return (1);
1029     }
1030 #endif /*xbsa */
1031
1032     /* cell switch */
1033     if (as->parms[2].items)
1034         strncpy(cellName, as->parms[2].items->data, sizeof(cellName));
1035     else
1036         cellName[0] = '\0';
1037
1038     if (as->parms[4].items)
1039         autoQuery = 0;
1040
1041     localauth = (as->parms[5].items ? 1 : 0);
1042
1043     code = rx_Init(htons(BC_TAPEPORT + portOffset));
1044     if (code) {
1045         TapeLog(0, 0, code, 0, "rx init failed on port %u\n",
1046                 BC_TAPEPORT + portOffset);
1047         exit(1);
1048     }
1049     rx_SetRxDeadTime(150);
1050
1051     /* Establish connection with the vldb server */
1052     code = vldbClientInit(0, localauth, cellName, &cstruct, &ttoken);
1053     if (code) {
1054         TapeLog(0, 0, code, 0, "Can't access vldb\n");
1055         return code;
1056     }
1057
1058     strcpy(globalCellName, cellName);
1059
1060     /*initialize the dumpNode list */
1061     InitNodeList(portOffset);
1062
1063     deviceLatch =
1064         (struct deviceSyncNode *)(malloc(sizeof(struct deviceSyncNode)));
1065     Lock_Init(&(deviceLatch->lock));
1066     deviceLatch->flags = 0;
1067
1068     /* initialize database support, volume support, and logs */
1069
1070     /* Create a single security object, in this case the null security
1071      * object, for unauthenticated connections, which will be used to control
1072      * security on connections made to this server 
1073      */
1074
1075     securityObjects[0] = rxnull_NewServerSecurityObject();
1076     securityObjects[1] = (struct rx_securityClass *)0;  /* don't bother with rxvab */
1077     if (!securityObjects[0]) {
1078         TLog(0, "rxnull_NewServerSecurityObject");
1079         exit(1);
1080     }
1081
1082     service =
1083         rx_NewService(0, 1, "BUTC", securityObjects, 3, TC_ExecuteRequest);
1084     if (!service) {
1085         TLog(0, "rx_NewService");
1086         exit(1);
1087     }
1088     rx_SetMaxProcs(service, 4);
1089
1090     /* Establish connection to the backup database */
1091     code = udbClientInit(0, localauth, cellName);
1092     if (code) {
1093         TapeLog(0, 0, code, 0, "Can't access backup database\n");
1094         exit(1);
1095     }
1096     /* This call is here to verify that we are authentiated.
1097      * The call does nothing and will return BUDB_NOTPERMITTED 
1098      * if we don't belong.
1099      */
1100     code = bcdb_deleteDump(0, 0, 0, 0);
1101     if (code == BUDB_NOTPERMITTED) {
1102         TapeLog(0, 0, code, 0, "Can't access backup database\n");
1103         exit(1);
1104     }
1105
1106     initStatus();
1107 #ifdef AFS_PTHREAD_ENV
1108     code = pthread_attr_init(&tattr);
1109     if (code) {
1110         TapeLog(0, 0, code, 0,
1111                 "Can't pthread_attr_init database monitor task");
1112         exit(1);
1113     }
1114     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1115     if (code) {
1116         TapeLog(0, 0, code, 0,
1117                 "Can't pthread_attr_setdetachstate database monitor task");
1118         exit(1);
1119     }
1120     AFS_SIGSET_CLEAR();
1121     code = pthread_create(&dbWatcherPid, &tattr, dbWatcher, (void *)2);
1122     AFS_SIGSET_RESTORE();
1123 #else
1124     code =
1125         LWP_CreateProcess(dbWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2,
1126                           "dbWatcher", &dbWatcherPid);
1127 #endif
1128     if (code) {
1129         TapeLog(0, 0, code, 0, "Can't create database monitor task");
1130         exit(1);
1131     }
1132
1133     TLog(0, "Starting Tape Coordinator: Port offset %u   Debug level %u\n",
1134          portOffset, debugLevel);
1135     t = ttoken.endTime;
1136     TLog(0, "Token expires: %s\n", cTIME(&t));
1137
1138     rx_StartServer(1);          /* Donate this process to the server process pool */
1139     TLog(0, "Error: StartServer returned");
1140     exit(1);
1141 }
1142
1143 #ifndef AFS_NT40_ENV
1144 #include "AFS_component_version_number.c"
1145 #endif
1146
1147 main(argc, argv)
1148      int argc;
1149      char **argv;
1150 {
1151     register struct cmd_syndesc *ts;
1152     register struct cmd_item *ti;
1153
1154 #ifdef  AFS_AIX32_ENV
1155     /*
1156      * The following signal action for AIX is necessary so that in case of a 
1157      * crash (i.e. core is generated) we can include the user's data section 
1158      * in the core dump. Unfortunately, by default, only a partial core is
1159      * generated which, in many cases, isn't too useful.
1160      */
1161     struct sigaction nsa;
1162
1163     sigemptyset(&nsa.sa_mask);
1164     nsa.sa_handler = SIG_DFL;
1165     nsa.sa_flags = SA_FULLDUMP;
1166     sigaction(SIGSEGV, &nsa, NULL);
1167     sigaction(SIGABRT, &nsa, NULL);
1168 #endif
1169
1170     setlinebuf(stdout);
1171
1172     ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, "tape coordinator");
1173     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "port offset");
1174     cmd_AddParm(ts, "-debuglevel", CMD_SINGLE, CMD_OPTIONAL, "0 | 1 | 2");
1175     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1176     cmd_AddParm(ts, "-device", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1177                 "tape device path");
1178     cmd_AddParm(ts, "-noautoquery", CMD_FLAG, CMD_OPTIONAL,
1179                 "do not query operator for first tape");
1180     cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
1181                 "create tickets from KeyFile");
1182     cmd_AddParm(ts, "-restoretofile", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1183                 "file to restore to");
1184     cmd_AddParm(ts, "-xbsaforcemultiple", CMD_FLAG, (CMD_OPTIONAL | CMD_HIDE),
1185                 "Force multiple XBSA server support");
1186
1187     /* Initialize dirpaths */
1188     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
1189 #ifdef AFS_NT40_ENV
1190         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
1191 #endif
1192         fprintf(stderr, "Unable to obtain AFS server directory.\n");
1193         exit(2);
1194     }
1195
1196     /* setup the file paths */
1197     strcompose(eFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1198                TE_PREFIX, NULL);
1199     strcompose(lFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1200                TL_PREFIX, NULL);
1201     strcompose(pFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
1202                CFG_PREFIX, NULL);
1203     strcpy(tapeConfigFile, AFSDIR_SERVER_TAPECONFIG_FILEPATH);
1204
1205     /* special case "no args" case since cmd_dispatch gives help message
1206      * instead
1207      */
1208     if (argc == 1) {
1209         ts = (struct cmd_syndesc *)malloc(sizeof(struct cmd_syndesc));
1210         memset(ts, 0, sizeof(*ts));
1211
1212         ti = (struct cmd_item *)malloc(sizeof(struct cmd_item));
1213         ti->next = 0;
1214         ti->data = "0";
1215         ts->parms[0].items = ti;
1216         ti = (struct cmd_item *)malloc(sizeof(struct cmd_item));
1217         ti->next = 0;
1218         ti->data = "0";
1219         ts->parms[1].items = ti;
1220         ts->parms[2].items = (struct cmd_item *)NULL;
1221         ts->parms[3].items = (struct cmd_item *)NULL;
1222         ts->parms[4].items = (struct cmd_item *)NULL;
1223         ts->parms[5].items = (struct cmd_item *)NULL;
1224         return WorkerBee(ts, NULL);
1225     } else
1226         return cmd_Dispatch(argc, argv);
1227 }