b8bce583b29374b6d09d98419ccd3c6d5bd0aad7
[oweals/cde.git] / cde / lib / tt / bin / ttdbserverd / db_server_svc.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.
27 //%%  $TOG: db_server_svc.C /main/9 1999/10/12 10:01:35 mgreess $                                                       
28 /*
29  *  @(#)db_server_svc.C 1.54 95/06/07
30  *
31  *  Tool Talk Database Server
32  *
33  *  Copyright (c) 1992 Sun Microsystems, Inc.
34  *
35  *  This file contains the db server main rpc program _tt_dbserver_prog_1.
36  */
37 #define PORTMAP
38
39 #include "tt_options.h"
40 #include "tt_db_partition_redirection_map.h"
41 #include "util/tt_global_env.h"
42 #include "util/tt_new.h"
43 #include "util/copyright.h"
44 #include "dm_access_cache.h"
45 #include "dm/dm_enums.h"
46 #include "db/db_server.h"
47 #include "db/tt_db_rpc_routines.h"
48 #include "tt_db_msg_q_lock.h"
49 #include "util/tt_log.h"
50 #include "util/tt_port.h"
51 #include "util/tt_gettext.h"
52 #include "util/tt_file_system.h"
53 #include "db_server_globals.h"
54 #include <fcntl.h>
55 #include <limits.h>
56 #include <locale.h>
57 #include <stdlib.h>
58 #include <stdio.h>
59 #include <rpc/pmap_clnt.h>
60 #include <isam.h>     
61 #include <unistd.h>
62 #include <sys/socket.h>
63 #include <termios.h>
64 #include <time.h>
65
66 #if defined(sgi) || defined(CSRG_BASED)
67 #include <getopt.h>
68 #endif
69
70 #include <string.h>
71 #include <sys/param.h>
72 #include <sys/stat.h>
73
74 #include <signal.h>
75
76 #if defined(OPT_TLI)
77 #include <stropts.h>
78 #endif
79
80 #if (OPT_GARBAGE_IN_PARALLEL==1) && !defined(OPT_GARBAGE_THREADS)
81 #include <sys/wait.h>
82 #endif
83
84 #define _TT_TREC_INFO (sizeof(int) + sizeof(long) + sizeof(u_int))
85
86 extern "C" { int isclose(int); }
87 extern "C" { int iscntl(int, int, ...); }
88 extern "C" { int isopen(const char*, int); }
89 extern "C" { int isrewrec(int, long, char*); }
90 extern "C" { int iswrite(int, char*); }
91 extern char *optarg;
92 extern int opterr;
93 extern int _tt_run_garbage_collect(int in_parallel);
94 extern int _tt_run_garbage_collect(int);
95 static void _tt_dbserver_prog_1(struct svc_req*, SVCXPRT*);
96 void install_signal_handler();
97 void sig_handler(int sig);
98
99 #if defined(TTDB_DEBUG)
100 #define TTDB_DEBUG_SYSLOG(txt)  _tt_syslog(errstr, LOG_ERR, txt);
101 #else
102 #define TTDB_DEBUG_SYSLOG(txt)
103 #endif
104
105 TT_INSERT_COPYRIGHT
106
107 const char      *_TT_UNIX_OPT = "unix";
108 const char      *_TT_DES_OPT = "des";
109 const int       _TT_UMASK = 0022;       /* rwxr-xr-x max permissions. */
110
111 /*
112  * GLOBAL variables
113  */
114 uid_t   _tt_uid;
115 gid_t   _tt_gid;
116 gid_t   _tt_gidlist[NGROUPS];
117
118 #if defined(OPT_GARBAGE_THREADS)
119 mutex_t         rpc_client_busy; // Used to sync calls with the RPC clients.
120 mutex_t         garbage_run_in_process;
121 #endif
122
123 int     _tt_auth_level;
124 int     _tt_gidlen;
125
126 keydesc                         _tt_oid_keydesc;
127 _Tt_oid_access_queue_ptr        _tt_oa_cache;
128 _Tt_link_access_queue_ptr       _tt_la_cache;
129 char                            _tt_log_file[MAXPATHLEN];
130
131 /* table of NetISAM db opened */
132 _Tt_db_info                     _tt_db_table[_TT_MAX_ISFD];
133
134 // _tt_refclock is a "pseudo clock" that's just incremented every time
135 // a reference is made to an fd; the resulting value is placed 
136 // the _tt_db_table[fd].reftime field, so we can figure out which 
137 // fd is Least Recently Used when it comes time to re-use one.
138 int             _tt_refclock=0;
139 time_t          _tt_mtab_last_mtime;
140 static char     _tt_log_buf[ISMAXRECLEN];
141 static char     _tt_target_db[MAXPATHLEN];
142 int             _tt_debug_mode = 0;
143 int             access_checking = 1;
144
145 static bool_t   msg_q_unlock_flag = FALSE;
146 static bool_t   refresh_partition_redirection_map = TRUE;
147
148 // DB partition redirection map
149 _Tt_db_partition_redirection_map        * db_pr_map;
150
151 // Sink for error output.  If 0, output goes to syslog.
152 FILE            * errstr = stderr;
153
154 extern int      optind;
155
156 void sig_handler(int sig);
157
158 enum {STARTED_FROM_INETD, STARTED_FROM_SHELL} start_mode;
159
160 //
161 // This is used to hold the next time the automatic garbage
162 // collection should be run. It will be run when the current
163 // time is greator than or equal to next_garbage_run.
164 //
165 time_t  next_garbage_run = (time_t) 0;
166
167 int
168 isamfatalerror(char *msg)
169 {
170         _tt_syslog(errstr, LOG_ERR, "NetISAM: %s", msg);
171         return 1;
172 }
173
174 void
175 print_usage_and_exit()
176 {
177         static int usage_printed = 0;
178
179         if (!usage_printed) {
180
181                 _tt_syslog(errstr, LOG_ERR, "%s",
182                            catgets(_ttcatd, 5, 7,
183 "Usage:\n"
184 "rpc.ttdbserverd [-S] [-n] [-m DTMOUNTPOINT]\n"
185 "rpc.ttdbserverd [-S] [-v]\n"
186 "rpc.ttdbserverd -G\n"));
187
188                 usage_printed = 1;
189
190         }
191
192         // we only exit when started from the shell -- if started by
193         // inetd we're likely to just get started up again with bad options,
194         // probably better to try to keep going.
195
196         if (start_mode == STARTED_FROM_SHELL) {
197                 exit(1);
198         }
199         return;
200 }
201
202 int
203 #if defined(OPT_GARBAGE_THREADS)
204 main(int argc, char** argv)
205 #else
206 main(int argc, char** argv, char **envp)
207 #endif
208 {
209 #if !defined(OPT_GARBAGE_THREADS)
210         global_argv = argv;
211         global_envp = envp;
212 #endif
213         char *progname;
214         void install_signal_handler();
215         SVCXPRT *transp;
216         struct sockaddr_in saddr;
217 #if defined(DEC) || defined(HPUX)
218         int asize = sizeof(struct sockaddr);
219 #else
220 # if defined(linux) || defined(CSRG_BASED) || defined(sun)
221         socklen_t asize;
222 # else
223         size_t asize = sizeof(struct sockaddr);
224 # endif
225 #endif
226         int is_aix = 0;
227
228         int do_garbage_collect = 0;
229
230 #if defined(OPT_TLI)
231         char mname[FMNAMESZ + 1];
232         struct t_info info;
233 #endif
234
235         memset((char *)&saddr,0,sizeof(struct sockaddr));
236
237 #if defined(OPT_TLI)
238         memset((char *)&info,0,sizeof info);
239 #endif
240
241 #ifdef _AIX
242         is_aix = 1;
243 #endif
244
245         setlocale( LC_ALL, "" );
246         _tt_openlog( argv[0], LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_DAEMON );
247
248 // First, we have to determine if we are started from inetd or from the shell.
249 // Normal installations would start from inetd, but we do start from the shell
250 // when testing; also we\'d like to allow installations to start out of the
251 // init process (rc.local, rc?.d) if they\'d rather.
252
253 // The way to determine if we\'re started from inetd is to check if fd 0 is
254 // a connection endpoint (socket or TLI).  If so, that endpoint has been
255 // set up as an RPC connection by inetd and we should use it instead of
256 // creating our own.  If fd 0 is NOT a endpoint, we assume we\'re started
257 // from the shell, and create a new endpoint and redirect the portmapper to it.
258
259 // This is complicated by the fact that the inetd.conf file in Solaris 2.3
260 // and Solaris 2.3. specifies that rpc.ttdbserverd is rpc/tcp, not rpc/tli.
261 // We want this version of rpc.ttdbserverd to run on Solaris 2.3, so we have
262 // to cater to it by checking for a tcp socket being passed in; if there is
263 // such, we do some streams magic to convert it into a TLI endpoint.
264
265 // This is further complicated by having to run on systems that don\'t
266 // have TIRPC yet.
267
268         signal(SIGTTOU, SIG_IGN);
269         if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0) {
270         
271                 //  We were given a socket.  This means  we were started
272                 // from inetd.
273                 if (saddr.sin_family != AF_INET) {
274                         _tt_syslog(0, LOG_ERR, "saddr.sin_family != AF_INET");
275                         exit(1);
276                 }
277
278                 start_mode = STARTED_FROM_INETD;
279                 errstr = 0;
280
281 #if defined(OPT_TLI)
282
283                 // We were given a socket but need a TLI endpoint.  
284                 // Fortunately STREAMS caters to folks like us by making
285                 // it dead easy to change one into another.
286  
287                 if (!ioctl(0, I_LOOK, mname) && (!strcmp(mname, "sockmod"))) {
288                         if (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, "timod")) {
289                                 _tt_syslog(errstr, LOG_ERR, "ioctl(0, I_POP, 0)"
290                                            " || ioctl(0, I_PUSH, \"timod\")");
291                                 exit(1);
292                         }
293                 }
294         
295         } else if (0==t_getinfo(0, &info)) {
296                 
297                 // We were given a TLI endpoint. This means we were started
298                 // from inetd.  The TLI endpoint is suitable for later use.
299
300                 start_mode = STARTED_FROM_INETD;
301                 errstr = 0;
302
303 #endif /* defined(OPT_TLI) */
304
305         } else {
306
307                 // fd 0 is not a communications endpoint, so we must not
308                 // have been started from inetd.
309
310                 start_mode = STARTED_FROM_SHELL;
311         }
312                 
313
314         // At this point start_mode is set to tell us who started us.
315         // If start_mode is STARTED_FROM_INETD, then fd 0 is the 
316         // endpoint to use; if OPT_TLI is defined, fd 0 is a TLI endpoint;
317         // if OPT_TLI is not defined, fd 0 is a socket.
318
319         // it might be considered appropriate to fork into the background
320         // here if started from the shell here, but we never have before,
321         // we are usually started from inetd.  The usual reason we\'re 
322         // started from a a shell is for debugging, where forking into the
323         // background is a big pain, and we\'d have to have an option like
324         // the -S one on ttsession to skip the fork.
325
326         _tt_global = new _Tt_global;
327
328
329         // Create the DB parition redirection map
330         db_pr_map = new _Tt_db_partition_redirection_map;
331
332         /* set minimum authentication requirement */
333         _tt_auth_level = AUTH_UNIX;     /* default to UNIX authentication */
334
335         progname = *argv;
336
337         if (argc>1) {
338                 opterr = 0;
339                 int c;
340 // remove authentication option
341 //              int c = getopt(argc, argv, "vm:t:dna:");
342                 while ((c = getopt(argc, argv, "vm:t:dnSG")) != -1) {
343                         switch (c) {
344                               case 'v':
345                                 _TT_PRINT_VERSIONS(progname)
346                                 exit(0);
347                               case 'm':
348                                 _tt_putenv("DTMOUNTPOINT", optarg);
349                                 break;
350                               case 'n':
351                                 access_checking = 0;
352                                 break;
353                               case 'a':
354                                 // this is now disabled (see comment above)
355                                 if (strcmp(optarg, _TT_DES_OPT) == 0) {
356                                         _tt_auth_level = AUTH_DES;
357                                 } else if (strcmp(optarg, _TT_UNIX_OPT) != 0) {
358                                         print_usage_and_exit();
359                                 }
360                                 break;
361                               case 't':
362                                 break;
363                               case 'd':
364                                 break;
365                               case 'S':
366                                 _tt_debug_mode = 1;
367                                 break;
368                               case 'G':
369                                 do_garbage_collect = 1;
370                                 break;
371                               case '?':
372                               default:
373                                 print_usage_and_exit();
374                         }
375                 }
376
377                 // The, er, unusual inetd.conf syntax on the IBM platform
378                 // makes it necessary to *not* check for extraneous
379                 // command-line args on IBM when started out of inetd.
380                 // Since I need to check the value of a cpp macro
381                 // -- _AIX -- and a program variable -- start_mode --
382                 // use another "temp" program variable -- is_aix.
383         
384                 if (optind < argc &&
385                     !(is_aix && start_mode == STARTED_FROM_INETD))
386                 {
387                         print_usage_and_exit();
388                 }
389         }
390
391         //
392         // Start the garbage collection running.
393         //
394         if (do_garbage_collect) {
395
396                 //
397                 // As the garbage collection flag is set, we
398                 // start the garbage cleanup only (no server-d).
399                 //
400                 _tt_run_garbage_collect(FALSE);// Not in parallel.
401         }
402
403         //
404         // Lock down the RPC interface until we are ready.
405         //
406         LOCK_RPC();
407
408         /* setup oid key descriptor for access control */
409         
410         _tt_oid_keydesc.k_flags = ISNODUPS;
411         _tt_oid_keydesc.k_nparts = 1;
412         _tt_oid_keydesc.k_part[0].kp_start = 0;
413         _tt_oid_keydesc.k_part[0].kp_leng = OID_KEY_LENGTH;
414         _tt_oid_keydesc.k_part[0].kp_type = BINTYPE;
415         
416         install_signal_handler();
417         
418         /* set NetISAM fatal error handler */
419         if (iscntl(ALLISFD, ISCNTL_FATAL, isamfatalerror) == -1) {
420                 _tt_syslog(errstr, LOG_ERR,
421                            "iscntl(ALLISFD, ISCNTL_FATAL,) == -1");
422                 exit(1);
423         }
424         
425         /* setup database file creation mask */
426         mode_t pmask = umask(_TT_UMASK);
427         
428         /* initialize access control cache */
429         _tt_oa_cache = new _Tt_oid_access_queue();
430         _tt_la_cache = new _Tt_link_access_queue();
431         
432         /* initialize opened database table */
433         
434         for (int i = 0; i < _TT_MAX_ISFD; i++) {
435                 _tt_db_table[i].db_path = 0;
436                 _tt_db_table[i].opener_uid = (uid_t)-1;
437                 _tt_db_table[i].reftime = 0;
438                 _tt_db_table[i].server_has_open = 0;
439                 _tt_db_table[i].client_has_open = 0;
440         }
441         
442
443         // If we were started from inetd, inetd has already done all
444         // the negotiation with the portmapper.  We simply create a RPC
445         // connection over the endpoint that inetd handed us.  If
446         // we were started from the shell, we create a RPC connection
447         // with RPC_ANYSOCK (to create a new endpoint) and register
448         // that with the portmapper.
449                                                         
450         switch (start_mode) {
451             case STARTED_FROM_INETD:
452 #if defined(OPT_TLI)
453                 transp = svc_tli_create(0,
454                                         (struct netconfig *)0,
455                                         (struct t_bind *)0,
456                                         0, 0);
457                 if (transp == NULL) {
458                         _tt_syslog(errstr, LOG_ERR, "svc_tli_create() == 0");
459                         exit(1);
460                 }
461 #else
462                 transp = svctcp_create(0,0,0);
463                 if (transp == NULL) {
464                         _tt_syslog(errstr, LOG_ERR, "svctcp_create() == 0");
465                         exit(1);
466                 }
467 #endif                          /*OPT_TLI*/
468                 if (!svc_register(transp, TT_DBSERVER_PROG, TT_DBSERVER_VERS,
469 #ifdef _AIX
470                                   (void(*)())
471 #endif
472                                   _tt_dbserver_prog_1,
473                                   0)) // this zero means leave portmapper alone
474                 {
475                         _tt_syslog(errstr, LOG_ERR, "svc_register() == 0");
476                 }
477                 break;         
478                                                                 
479             case STARTED_FROM_SHELL:
480
481                 // Go into the background, unless the debug_mode -S
482                 // switch was set.
483
484                 if (!_tt_debug_mode) {
485                         if (0!=fork()) exit(0);
486
487 #if defined(__osf__) || defined(CSRG_BASED)
488                         setsid();
489 #else
490                         setpgrp();
491 #endif // __osf__
492
493                         close(0); close(1); close(2);
494
495                 }
496
497                 // Evict any previous user of our RPC number and tell
498                 // the portmapper we are here.
499
500                 (void)pmap_unset(TT_DBSERVER_PROG, TT_DBSERVER_VERS);
501                 // XXX: really ought to use svc_tli_create if OPT_TLI is set
502                 // but that requires searching for a suitable transport..
503                 transp = svctcp_create(RPC_ANYSOCK, 0, 0);
504                 if (transp == NULL) {
505                         _tt_syslog(errstr, LOG_ERR, "svctcp_create() == 0");
506                         exit(1);
507                 }
508                                                                 
509                 if (!svc_register(transp, TT_DBSERVER_PROG, TT_DBSERVER_VERS,
510 #ifdef _AIX
511                                   (void(*)())
512 #endif
513                                   _tt_dbserver_prog_1, IPPROTO_TCP)) {
514                         _tt_syslog(errstr, LOG_ERR, "svc_register() == 0");
515                         exit(1);
516                 }
517                 break;
518         }
519
520         // Maximize the number of possible file descriptors.
521         _tt_zoomdtablesize();
522
523         UNLOCK_RPC();
524
525         svc_run();
526         _tt_syslog(errstr, LOG_ERR, "svc_run()");
527         exit(1);
528         return 1;
529 }
530
531 int
532 _tt_write_trans_record(int isfd, _Tt_trans_record *trec)
533 {
534         LOCK_RPC();
535         /* if new record, writes it; otherwise updates it */
536         isreclen = trec->rec.rec_len;
537         if (trec->newp) {
538                 if (iswrite(isfd, trec->rec.rec_val) == -1) {
539                         UNLOCK_RPC();
540                         return 0;
541                 }
542         } else {
543                 if (isrewrec(isfd, trec->recnum, trec->rec.rec_val) == -1) {
544                         UNLOCK_RPC();
545                         return 0;
546                 }
547         }
548         UNLOCK_RPC();
549         return 1;
550 }
551
552 /*
553 *  _tt_dbserver_prog_cleanup - closes the log file and the target database file
554 *  when the database transacation processing fails.
555 */
556
557 void
558 _tt_dbserver_prog_cleanup(int log_fd, int isfd = -1)
559 {
560         LOCK_RPC();
561         /* close the log file */
562         if ((log_fd != -1) && (close(log_fd) == -1)) {
563                 _tt_syslog(errstr, LOG_ERR, "close(log_fd): %m");
564         }
565         /* close the target NetISAM database */
566         if ((isfd != -1) && (cached_isclose(isfd) == -1)) {
567                 _tt_syslog(errstr, LOG_ERR, "cached_isclose() == -1");
568         }
569         UNLOCK_RPC();
570 }
571
572 /*
573 *  _tt_process_transaction - process the log file by reading records stored
574 *  in the log file and writing them out to the target database.  If the
575 *  transaction flag is set, then the transaction was not successfully committed.
576 *  In this case, the log file is removed.  If the transaction flag is clear,
577 *  then process the log file and then removes it.
578 */
579
580 void
581 _tt_process_transaction()
582 {
583         int log_fd;
584
585         LOCK_RPC();
586
587         if (_tt_log_file[0] == '\0') {
588                 UNLOCK_RPC();
589                 return;
590         }
591         if ((log_fd = open(_tt_log_file, O_RDWR | O_CREAT, S_IREAD + S_IWRITE))
592             == -1)
593         {
594                 _tt_syslog(errstr, LOG_ERR, "open(\"%s\"): %m", _tt_log_file);
595                 UNLOCK_RPC();
596                 return;
597         }
598         /* Turn on close-on-exec */
599         fcntl(log_fd, F_SETFD, 1);
600
601         /* reset to beginning of log file */
602         off_t offset;
603         if ((offset = lseek(log_fd, 0, SEEK_SET)) == -1) {
604                 _tt_syslog(errstr, LOG_ERR, "lseek(): %m");
605                 UNLOCK_RPC();
606                 return;
607         }
608         /* Check the transaction flag */
609         int nbytes = read(log_fd, _tt_log_buf, sizeof(int));
610         if (nbytes < sizeof(int)) {
611                 _tt_syslog(errstr, LOG_ERR, "read(): %m");
612                 _tt_dbserver_prog_cleanup(log_fd);
613                 UNLOCK_RPC();
614                 return;
615         }
616         offset = sizeof(int);
617         int flag = *((int *)_tt_log_buf);
618         if (flag == 1) { /* transaction failed */
619                 _tt_dbserver_prog_cleanup(log_fd);
620                 if (unlink(_tt_log_file) == -1) { /* remove log file */
621                         _tt_syslog(errstr, LOG_ERR, "unlink(\"%s\"): %m",
622                                    _tt_log_file);
623                 }
624                 UNLOCK_RPC();
625                 return;
626         }
627         /* get the target database's path from the log file */
628         nbytes = read(log_fd, _tt_log_buf, MAXPATHLEN+1);
629         if (nbytes == -1) {
630                 _tt_syslog(errstr, LOG_ERR, "read(): %m");
631                 _tt_dbserver_prog_cleanup(log_fd);
632                 UNLOCK_RPC();
633                 return;
634         }
635         strcpy(_tt_target_db, _tt_log_buf);
636         /* open the NetISAM transaction target database */
637         int isfd = cached_isopen(_tt_target_db, ISINOUT+ISFIXLEN+ISMANULOCK);
638         if (isfd == -1) {
639                 _tt_syslog(errstr, LOG_ERR, "isopen(): %d", iserrno);
640                 _tt_dbserver_prog_cleanup(log_fd, isfd);
641                 UNLOCK_RPC();
642                 return;
643         }
644         /* set the log seek pointer to the first record */
645         offset += strlen(_tt_target_db) + 1;
646         if ((offset = lseek(log_fd, offset, SEEK_SET))
647             == -1) {
648                 _tt_syslog(errstr, LOG_ERR, "lseek(): %m");
649                 _tt_dbserver_prog_cleanup(log_fd, isfd);
650                 UNLOCK_RPC();
651                 return;
652         }
653         /* gets the records from the log file and writes them to the
654                 target database */
655         char *buf_rec;
656         _Tt_trans_record trec;
657         nbytes = read(log_fd, _tt_log_buf, _TT_TREC_INFO);
658         while (nbytes) {
659                 if (nbytes < _TT_TREC_INFO) {
660                         _tt_syslog(errstr, LOG_ERR, "read(): %m");
661                         _tt_dbserver_prog_cleanup(log_fd, isfd);
662                         UNLOCK_RPC();
663                         return;
664                 }
665                 /* process the batch of records just read */
666                 buf_rec = _tt_log_buf;
667                 trec.newp = *((int *) buf_rec);
668                 buf_rec += sizeof(int);
669                 trec.recnum = *((long *) buf_rec);
670                 buf_rec += sizeof(long);
671                 trec.rec.rec_len = *((u_int *) buf_rec);
672                 buf_rec += sizeof(u_int);
673                 /* read the record as a whole */
674                 nbytes = read(log_fd, _tt_log_buf, trec.rec.rec_len);
675                 if (nbytes < trec.rec.rec_len) {
676                         _tt_syslog(errstr, LOG_ERR, "read(): %m");
677                         _tt_dbserver_prog_cleanup(log_fd, isfd);
678                         UNLOCK_RPC();
679                         return;
680                 }
681                 trec.rec.rec_val = _tt_log_buf;
682                 if (_tt_write_trans_record(isfd, &trec) == 0) {
683                         _tt_dbserver_prog_cleanup(log_fd, isfd);
684                         UNLOCK_RPC();
685                         return;
686                 }
687                 nbytes = read(log_fd, _tt_log_buf, _TT_TREC_INFO);
688         }
689         _tt_dbserver_prog_cleanup(log_fd, isfd);
690         /* remove the log file (not until actually close it) */
691         if (unlink(_tt_log_file) == -1) {
692                 _tt_syslog(errstr, LOG_ERR, "unlink(\"%s\"): %m", _tt_log_file);
693         }
694         UNLOCK_RPC();
695         return;
696 }
697
698 /*
699 *  _tt_dbserver_prog_1 - the rpc db server program
700 */
701
702 static void
703 _tt_dbserver_prog_1(struct svc_req *rqstp, SVCXPRT *transp)
704 {
705         union arg_union {
706                 char *_tt_min_auth_level_1_arg;
707                 _Tt_isaddindex_args _tt_isaddindex_1_arg;
708                 _Tt_isbuild_args _tt_isbuild_1_arg;
709                 int _tt_isclose_1_arg;
710                 _Tt_iscntl_args _tt_iscntl_1_arg;
711                 _Tt_isdelrec_args _tt_isdelrec_1_arg;
712                 char *_tt_iserase_1_arg;
713                 _Tt_isopen_args _tt_isopen_1_arg;
714                 _Tt_isread_args _tt_isread_1_arg;
715                 _Tt_isrewrec_args _tt_isrewrec_1_arg;
716                 _Tt_isstart_args _tt_isstart_1_arg;
717                 _Tt_iswrite_args _tt_iswrite_1_arg;
718                 _Tt_test_and_set_args _tt_test_and_set_1_arg;
719                 _Tt_transaction_args _tt_transaction_1_arg;
720                 char *_tt_mfs_1_arg;
721                 _Tt_oidaccess_args _tt_getoidaccess_1_arg;
722                 _Tt_oidaccess_args _tt_setoiduser_1_arg;
723                 _Tt_oidaccess_args _tt_setoidgroup_1_arg;
724                 _Tt_oidaccess_args _tt_setoidmode_1_arg;
725                 _Tt_spec_props _tt_readspec_1_arg;
726                 _Tt_spec_props _tt_writespec_1_arg;
727                 _Tt_session_args _tt_addsession_1_arg;
728                 _Tt_session_args _tt_delsession_1_arg;
729                 _Tt_spec_props _tt_gettype_1_arg;
730                 char *_tt_get_file_partition_1_arg;
731                 _tt_create_file_args _tt_create_file_1_arg;
732                 _tt_create_obj_args _tt_create_obj_1_arg;
733                 _tt_remove_file_args _tt_remove_file_1_arg;
734                 _tt_remove_obj_args _tt_remove_obj_1_arg;
735                 _tt_move_file_args _tt_move_file_1_arg;
736                 _tt_set_file_props_args _tt_set_file_props_1_arg;
737                 _tt_set_file_prop_args _tt_set_file_prop_1_arg;
738                 _tt_add_file_prop_args _tt_add_file_prop_1_arg;
739                 _tt_del_file_prop_args _tt_delete_file_prop_1_arg;
740                 _tt_get_file_prop_args _tt_get_file_prop_1_arg;
741                 _tt_get_file_props_args _tt_get_file_props_1_arg;
742                 _tt_get_file_objs_args _tt_get_file_objs_1_arg;
743                 _tt_set_file_access_args _tt_set_file_access_1_arg;
744                 _tt_get_file_access_args _tt_get_file_access_1_arg;
745                 _tt_set_obj_props_args _tt_set_obj_props_1_arg;
746                 _tt_set_obj_prop_args _tt_set_obj_prop_1_arg;
747                 _tt_add_obj_prop_args _tt_add_obj_prop_1_arg;
748                 _tt_del_obj_prop_args _tt_delete_obj_prop_1_arg;
749                 _tt_get_obj_prop_args _tt_get_obj_prop_1_arg;
750                 _tt_get_obj_props_args _tt_get_obj_props_1_arg;
751                 _tt_set_obj_type_args _tt_set_obj_type_1_arg;
752                 _tt_get_obj_type_args _tt_get_obj_type_1_arg;
753                 _tt_set_obj_file_args _tt_set_obj_file_1_arg;
754                 _tt_get_obj_file_args _tt_get_obj_file_1_arg;
755                 _tt_set_obj_access_args _tt_set_obj_access_1_arg;
756                 _tt_get_obj_access_args _tt_get_obj_access_1_arg;
757                 _tt_is_file_in_db_args _tt_is_file_in_db_1_arg;
758                 _tt_is_obj_in_db_args _tt_is_obj_in_db_1_arg;
759                 _tt_queue_msg_args _tt_queue_message_1_arg;
760                 _tt_dequeue_msgs_args _tt_dequeue_messages_1_arg;
761                 _tt_file_netfile_args _tt_file_netfile_1_arg;
762                 _tt_file_netfile_args _tt_netfile_file_1_arg;
763         } argument;
764         char *result;
765         bool_t (*xdr_argument)(), (*xdr_result)();
766         char *(*local)();
767         
768         struct authunix_parms *unix_cred;
769 #if defined(OPT_SECURE_RPC)
770         struct authdes_cred *des_cred;
771 #endif
772
773         // Increment the counter for the number of RPC calls
774         // handled during the life of this process.
775         _tt_global->event_counter++;
776         
777         LOCK_RPC();
778         if (rqstp->rq_proc == NULLPROC) {
779                 (void)svc_sendreply(transp, (xdrproc_t)xdr_void, (caddr_t)NULL);
780                 UNLOCK_RPC();
781                 return;
782         } else if ((rqstp->rq_proc != _TT_MIN_AUTH_LEVEL) &&
783                    (rqstp->rq_proc != _TT_MFS) &&
784                    (rqstp->rq_proc != TT_GET_MIN_AUTH_LEVEL) &&
785                    (rqstp->rq_proc != TT_GET_FILE_PARTITION) &&
786                    (rqstp->rq_proc != TT_IS_FILE_IN_DB) &&
787                    (rqstp->rq_proc != TT_IS_OBJ_IN_DB)) {
788                 /* extract the uid and gids from the client's credential */
789                 switch (rqstp->rq_cred.oa_flavor) {
790                     case AUTH_UNIX:
791                         /* Check authentication level */
792                         if (_tt_auth_level == AUTH_DES) {
793                                 svcerr_weakauth(transp);
794                                 UNLOCK_RPC();
795                                 return;
796                         }
797                         unix_cred = (struct authunix_parms*) rqstp->rq_clntcred;
798                         _tt_uid = unix_cred->aup_uid;
799                         _tt_gid = unix_cred->aup_gid;
800                         _tt_gidlen = unix_cred->aup_len;
801                         int i;
802                         for (i = 0; i < _tt_gidlen; i++) {
803                                 _tt_gidlist[i] = unix_cred->aup_gids[i];
804                         }
805                         break;
806 #if defined(OPT_SECURE_RPC)
807                     case AUTH_DES:
808                         des_cred = (struct authdes_cred*) rqstp->rq_clntcred;
809 #if defined(OPT_BUG_SUNOS_4) && !defined(__GNUG__)
810 #       define CAST_IN_SUNOS_4 (int *)
811 #else
812 #       define CAST_IN_SUNOS_4
813 #endif
814                         if (!netname2user(des_cred->adc_fullname.name,
815                                           CAST_IN_SUNOS_4 &_tt_uid,
816                                           CAST_IN_SUNOS_4 &_tt_gid,
817                                           &_tt_gidlen,
818                                           CAST_IN_SUNOS_4 _tt_gidlist))
819                                 {
820                                         svcerr_systemerr(transp);
821                                         UNLOCK_RPC();
822                                         return;
823                                 }
824                         break;
825 #endif                  
826                         
827 #ifdef AUTH_NONE
828                     case AUTH_NONE:
829 #else
830                     case AUTH_NULL:
831 #endif
832                     default:
833                         svcerr_weakauth(transp);
834                         UNLOCK_RPC();
835                         return;
836                 }
837         }
838         
839         /* Bind the service procedure */
840         switch (rqstp->rq_proc) {
841             case _TT_MIN_AUTH_LEVEL:
842                 TTDB_DEBUG_SYSLOG("_TT_MIN_AUTH_LEVEL");
843                 xdr_argument = (bool_t (*)()) xdr_wrapstring;
844                 xdr_result = (bool_t (*)()) xdr_int;
845                 local = (char *(*)()) _tt_min_auth_level_1;
846                 break;
847                 
848             case _TT_ISADDINDEX:
849                 TTDB_DEBUG_SYSLOG("_TT_ISADDINDEX");
850                 xdr_argument = (bool_t (*)()) xdr_Tt_isaddindex_args;
851                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
852                 local = (char *(*)()) _tt_isaddindex_1;
853                 break;
854                 
855             case _TT_ISBUILD:
856                 TTDB_DEBUG_SYSLOG("_TT_ISBUILD");
857                 xdr_argument = (bool_t (*)()) xdr_Tt_isbuild_args;
858                 xdr_result =(bool_t (*)()) xdr_Tt_isam_results;
859                 local = (char *(*)()) _tt_isbuild_1;
860                 break;
861                 
862             case _TT_ISCLOSE:
863                 TTDB_DEBUG_SYSLOG("_TT_ISCLOSE");
864                 xdr_argument = (bool_t (*)()) xdr_int;
865                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
866                 local = (char *(*)()) _tt_isclose_1;
867                 break;
868                 
869             case _TT_ISCNTL:
870                 TTDB_DEBUG_SYSLOG("_TT_ISCNTL");
871                 xdr_argument = (bool_t (*)()) xdr_Tt_iscntl_args;
872                 xdr_result = (bool_t (*)()) xdr_Tt_iscntl_results;
873                 local = (char *(*)()) _tt_iscntl_1;
874                 break;
875                 
876             case _TT_ISDELREC:
877                 TTDB_DEBUG_SYSLOG("_TT_ISDELREC");
878                 xdr_argument = (bool_t (*)()) xdr_Tt_isdelrec_args;
879                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
880                 local = (char *(*)()) _tt_isdelrec_1;
881                 break;
882                 
883             case _TT_ISERASE:
884                 TTDB_DEBUG_SYSLOG("_TT_ISERASE");
885                 xdr_argument = (bool_t (*)()) xdr_wrapstring;
886                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
887                 local = (char *(*)()) _tt_iserase_1;
888                 break;
889                 
890             case _TT_ISOPEN:
891                 TTDB_DEBUG_SYSLOG("_TT_ISOPEN");
892                 xdr_argument = (bool_t (*)()) xdr_Tt_isopen_args;
893                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
894                 local = (char *(*)()) _tt_isopen_1;
895                 break;
896                 
897             case _TT_ISREAD:
898                 TTDB_DEBUG_SYSLOG("_TT_ISREAD");
899                 xdr_argument = (bool_t (*)()) xdr_Tt_isread_args;
900                 xdr_result = (bool_t (*)()) xdr_Tt_isread_results;
901                 local = (char *(*)()) _tt_isread_1;
902                 break;
903                 
904             case _TT_ISREWREC:
905                 TTDB_DEBUG_SYSLOG("_TT_ISREWREC");
906                 xdr_argument = (bool_t (*)()) xdr_Tt_isrewrec_args;
907                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
908                 local = (char *(*)()) _tt_isrewrec_1;
909                 break;
910                 
911             case _TT_ISSTART:
912                 TTDB_DEBUG_SYSLOG("_TT_ISSTART");
913                 xdr_argument = (bool_t (*)()) xdr_Tt_isstart_args;
914                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
915                 local = (char *(*)()) _tt_isstart_1;
916                 break;
917                 
918             case _TT_ISWRITE:
919                 TTDB_DEBUG_SYSLOG("_TT_ISWRITE");
920                 xdr_argument = (bool_t (*)()) xdr_Tt_iswrite_args;
921                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
922                 local = (char *(*)()) _tt_iswrite_1;
923                 break;
924                 
925             case _TT_TEST_AND_SET:
926                 TTDB_DEBUG_SYSLOG("_TT_TEST_AND_SET");
927                 xdr_argument = (bool_t (*)()) xdr_Tt_test_and_set_args;
928                 xdr_result = (bool_t (*)()) xdr_Tt_test_and_set_results;
929                 local = (char *(*)()) _tt_test_and_set_1;
930                 break;
931                 
932             case _TT_TRANSACTION:
933                 TTDB_DEBUG_SYSLOG("_TT_TRANSACTION");
934                 xdr_argument = (bool_t (*)()) xdr_Tt_transaction_args;
935                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
936                 local = (char *(*)()) _tt_transaction_1;
937                 break;
938                 
939             case _TT_MFS:
940                 TTDB_DEBUG_SYSLOG("_TT_MFS");
941                 xdr_argument = (bool_t (*)()) xdr_wrapstring;
942                 xdr_result = (bool_t (*)()) xdr_wrapstring;
943                 local = (char *(*)()) _tt_mfs_1;
944                 break;
945                 
946             case _TT_GETOIDACCESS:
947                 TTDB_DEBUG_SYSLOG("_TT_GETOIDACCESS");
948                 xdr_argument = (bool_t (*)()) xdr_Tt_oidaccess_args;
949                 xdr_result = (bool_t (*)()) xdr_Tt_oidaccess_results;
950                 local = (char *(*)()) _tt_getoidaccess_1;
951                 break;
952                 
953             case _TT_SETOIDUSER:
954                 TTDB_DEBUG_SYSLOG("_TT_SETOIDUSER");
955                 xdr_argument = (bool_t (*)()) xdr_Tt_oidaccess_args;
956                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
957                 local = (char *(*)()) _tt_setoiduser_1;
958                 break;
959                 
960             case _TT_SETOIDGROUP:
961                 TTDB_DEBUG_SYSLOG("_TT_SETOIDGROUP");
962                 xdr_argument = (bool_t (*)()) xdr_Tt_oidaccess_args;
963                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
964                 local = (char *(*)()) _tt_setoidgroup_1;
965                 break;
966                 
967             case _TT_SETOIDMODE:
968                 TTDB_DEBUG_SYSLOG("_TT_SETOIDMODE");
969                 xdr_argument = (bool_t (*)()) xdr_Tt_oidaccess_args;
970                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
971                 local = (char *(*)()) _tt_setoidmode_1;
972                 break;
973                 
974             case _TT_READSPEC:
975                 TTDB_DEBUG_SYSLOG("_TT_READSPEC");
976                 xdr_argument = (bool_t (*)()) xdr_Tt_spec_props;
977                 xdr_result = (bool_t (*)()) xdr_Tt_spec_props;
978                 local = (char *(*)()) _tt_readspec_1;
979                 break;
980                 
981             case _TT_WRITESPEC:
982                 TTDB_DEBUG_SYSLOG("_TT_WRITESPEC");
983                 xdr_argument = (bool_t (*)()) xdr_Tt_spec_props;
984                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
985                 local = (char *(*)()) _tt_writespec_1;
986                 break;
987                 
988             case _TT_ADDSESSION:
989                 TTDB_DEBUG_SYSLOG("_TT_ADDSESSION");
990                 xdr_argument = (bool_t (*)()) xdr_Tt_session_args;
991                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
992                 local = (char *(*)()) _tt_addsession_1;
993                 break;
994                 
995             case _TT_DELSESSION:
996                 TTDB_DEBUG_SYSLOG("_TT_DELSESSION");
997                 xdr_argument = (bool_t (*)()) xdr_Tt_session_args;
998                 xdr_result = (bool_t (*)()) xdr_Tt_isam_results;
999                 local = (char *(*)()) _tt_delsession_1;
1000                 break;
1001                 
1002             case _TT_GETTYPE:
1003                 TTDB_DEBUG_SYSLOG("_TT_GETTYPE");
1004                 xdr_argument = (bool_t (*)()) xdr_Tt_spec_props;
1005                 xdr_result = (bool_t (*)()) xdr_Tt_spec_props;
1006                 local = (char *(*)()) _tt_gettype_1;
1007                 break;
1008                 
1009             case TT_GET_MIN_AUTH_LEVEL:
1010                 TTDB_DEBUG_SYSLOG("TT_GET_MIN_AUTH_LEVEL");
1011                 xdr_argument = (bool_t (*)()) xdr_void;
1012                 xdr_result = (bool_t (*)()) xdr_tt_auth_level_results;
1013                 local = (char *(*)()) _tt_get_min_auth_level_1;
1014                 break;
1015                 
1016             case TT_GET_FILE_PARTITION:
1017                 TTDB_DEBUG_SYSLOG("TT_GET_FILE_PARTITION");
1018                 xdr_argument = (bool_t (*)()) xdr_wrapstring;
1019                 xdr_result = (bool_t (*)()) xdr_tt_file_partition_results;
1020                 local = (char *(*)()) _tt_get_file_partition_1;
1021                 break;
1022                 
1023             case TT_CREATE_FILE:
1024                 TTDB_DEBUG_SYSLOG("TT_CREATE_FILE");
1025                 xdr_argument = (bool_t (*)()) xdr_tt_create_file_args;
1026                 xdr_result = (bool_t (*)()) xdr_tt_db_cache_results;
1027                 local = (char *(*)()) _tt_create_file_1;
1028                 break;
1029                 
1030             case TT_CREATE_OBJ:
1031                 TTDB_DEBUG_SYSLOG("TT_CREATE_OBJ");
1032                 xdr_argument = (bool_t (*)()) xdr_tt_create_obj_args;
1033                 xdr_result = (bool_t (*)()) xdr_tt_db_cache_results;
1034                 local = (char *(*)()) _tt_create_obj_1;
1035                 break;
1036                 
1037             case TT_REMOVE_FILE:
1038                 TTDB_DEBUG_SYSLOG("TT_REMOVE_FILE");
1039                 xdr_argument = (bool_t (*)()) xdr_tt_remove_file_args;
1040                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1041                 local = (char *(*)()) _tt_remove_file_1;
1042                 break;
1043                 
1044             case TT_REMOVE_OBJ:
1045                 TTDB_DEBUG_SYSLOG("TT_REMOVE_OBJ");
1046                 xdr_argument = (bool_t (*)()) xdr_tt_remove_obj_args;
1047                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1048                 local = (char *(*)()) _tt_remove_obj_1;
1049                 break;
1050                 
1051             case TT_MOVE_FILE:
1052                 TTDB_DEBUG_SYSLOG("TT_MOVE_FILE");
1053                 xdr_argument = (bool_t (*)()) xdr_tt_move_file_args;
1054                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1055                 local = (char *(*)()) _tt_move_file_1;
1056                 break;
1057                 
1058             case TT_SET_FILE_PROPS:
1059                 TTDB_DEBUG_SYSLOG("TT_SET_FILE_PROPS");
1060                 xdr_argument = (bool_t (*)()) xdr_tt_set_file_props_args;
1061                 xdr_result = (bool_t (*)()) xdr_tt_db_cache_results;
1062                 local = (char *(*)()) _tt_set_file_props_1;
1063                 break;
1064                 
1065             case TT_SET_FILE_PROP:
1066                 TTDB_DEBUG_SYSLOG("TT_SET_FILE_PROP");
1067                 xdr_argument = (bool_t (*)()) xdr_tt_set_file_prop_args;
1068                 xdr_result = (bool_t (*)()) xdr_tt_db_cache_results;
1069                 local = (char *(*)()) _tt_set_file_prop_1;
1070                 break;
1071             case TT_ADD_FILE_PROP:
1072                 TTDB_DEBUG_SYSLOG("TT_ADD_FILE_PROP");
1073                 xdr_argument = (bool_t (*)()) xdr_tt_add_file_prop_args;
1074                 xdr_result = (bool_t (*)()) xdr_tt_db_cache_results;
1075                 local = (char *(*)()) _tt_add_file_prop_1;
1076                 break;
1077                 
1078             case TT_DELETE_FILE_PROP:
1079                 TTDB_DEBUG_SYSLOG("TT_DELETE_FILE_PROP");
1080                 xdr_argument = (bool_t (*)()) xdr_tt_del_file_prop_args;
1081                 xdr_result = (bool_t (*)()) xdr_tt_db_cache_results;
1082                 local = (char *(*)()) _tt_delete_file_prop_1;
1083                 break;
1084                 
1085             case TT_GET_FILE_PROP:
1086                 TTDB_DEBUG_SYSLOG("TT_GET_FILE_PROP");
1087                 xdr_argument = (bool_t (*)()) xdr_tt_get_file_prop_args;
1088                 xdr_result = (bool_t (*)()) xdr_tt_file_prop_results;
1089                 local = (char *(*)()) _tt_get_file_prop_1;
1090                 break;
1091                 
1092             case TT_GET_FILE_PROPS:
1093                 TTDB_DEBUG_SYSLOG("TT_GET_FILE_PROPS");
1094                 xdr_argument = (bool_t (*)()) xdr_tt_get_file_props_args;
1095                 xdr_result = (bool_t (*)()) xdr_tt_file_props_results;
1096                 local = (char *(*)()) _tt_get_file_props_1;
1097                 break;
1098                 
1099             case TT_GET_FILE_OBJS:
1100                 TTDB_DEBUG_SYSLOG("TT_GET_FILE_OBJS");
1101                 xdr_argument = (bool_t (*)()) xdr_tt_get_file_objs_args;
1102                 xdr_result = (bool_t (*)()) xdr_tt_file_objs_results;
1103                 local = (char *(*)()) _tt_get_file_objs_1;
1104                 break;
1105                 
1106             case TT_SET_FILE_ACCESS:
1107                 TTDB_DEBUG_SYSLOG("TT_SET_FILE_ACCESS");
1108                 xdr_argument = (bool_t (*)()) xdr_tt_set_file_access_args;
1109                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1110                 local = (char *(*)()) _tt_set_file_access_1;
1111                 break;
1112                 
1113             case TT_GET_FILE_ACCESS:
1114                 TTDB_DEBUG_SYSLOG("TT_GET_FILE_ACCESS");
1115                 xdr_argument = (bool_t (*)()) xdr_tt_get_file_access_args;
1116                 xdr_result = (bool_t (*)()) xdr_tt_file_access_results;
1117                 local = (char *(*)()) _tt_get_file_access_1;
1118                 break;
1119                 
1120             case TT_SET_OBJ_PROPS:
1121                 TTDB_DEBUG_SYSLOG("TT_SET_OBJ_PROPS");
1122                 xdr_argument = (bool_t (*)()) xdr_tt_set_obj_props_args;
1123                 xdr_result = (bool_t (*)()) xdr_tt_obj_props_results;
1124                 local = (char *(*)()) _tt_set_obj_props_1;
1125                 break;
1126                 
1127             case TT_SET_OBJ_PROP:
1128                 TTDB_DEBUG_SYSLOG("TT_SET_OBJ_PROP");
1129                 xdr_argument = (bool_t (*)()) xdr_tt_set_obj_prop_args;
1130                 xdr_result = (bool_t (*)()) xdr_tt_obj_props_results;
1131                 local = (char *(*)()) _tt_set_obj_prop_1;
1132                 break;
1133                 
1134             case TT_ADD_OBJ_PROP:
1135                 TTDB_DEBUG_SYSLOG("TT_ADD_OBJ_PROP");
1136                 xdr_argument = (bool_t (*)()) xdr_tt_add_obj_prop_args;
1137                 xdr_result = (bool_t (*)()) xdr_tt_obj_props_results;
1138                 local = (char *(*)()) _tt_add_obj_prop_1;
1139                 break;
1140                 
1141             case TT_DELETE_OBJ_PROP:
1142                 TTDB_DEBUG_SYSLOG("TT_DELETE_OBJ_PROP");
1143                 xdr_argument = (bool_t (*)()) xdr_tt_del_obj_prop_args;
1144                 xdr_result = (bool_t (*)()) xdr_tt_obj_props_results;
1145                 local = (char *(*)()) _tt_delete_obj_prop_1;
1146                 break;
1147                 
1148             case TT_GET_OBJ_PROP:
1149                 TTDB_DEBUG_SYSLOG("TT_GET_OBJ_PROP");
1150                 xdr_argument = (bool_t (*)()) xdr_tt_get_obj_prop_args;
1151                 xdr_result = (bool_t (*)()) xdr_tt_obj_prop_results;
1152                 local = (char *(*)()) _tt_get_obj_prop_1;
1153                 break;
1154                 
1155             case TT_GET_OBJ_PROPS:
1156                 TTDB_DEBUG_SYSLOG("TT_GET_OBJ_PROPS");
1157                 xdr_argument = (bool_t (*)()) xdr_tt_get_obj_props_args;
1158                 xdr_result = (bool_t (*)()) xdr_tt_obj_props_results;
1159                 local = (char *(*)()) _tt_get_obj_props_1;
1160                 break;
1161                 
1162             case TT_SET_OBJ_TYPE:
1163                 TTDB_DEBUG_SYSLOG("TT_SET_OBJ_TYPE");
1164                 xdr_argument = (bool_t (*)()) xdr_tt_set_obj_type_args;
1165                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1166                 local = (char *(*)()) _tt_set_obj_type_1;
1167                 break;
1168                 
1169             case TT_GET_OBJ_TYPE:
1170                 TTDB_DEBUG_SYSLOG("TT_GET_OBJ_TYPE");
1171                 xdr_argument = (bool_t (*)()) xdr_wrapstring;
1172                 xdr_result = (bool_t (*)()) xdr_tt_obj_type_results;
1173                 local = (char *(*)()) _tt_get_obj_type_1;
1174                 break;
1175                 
1176             case TT_SET_OBJ_FILE:
1177                 TTDB_DEBUG_SYSLOG("TT_SET_OBJ_FILE");
1178                 xdr_argument = (bool_t (*)()) xdr_tt_set_obj_file_args;
1179                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1180                 local = (char *(*)()) _tt_set_obj_file_1;
1181                 break;
1182                 
1183             case TT_GET_OBJ_FILE:
1184                 TTDB_DEBUG_SYSLOG("TT_GET_OBJ_FILE");
1185                 xdr_argument = (bool_t (*)()) xdr_tt_get_obj_file_args;
1186                 xdr_result = (bool_t (*)()) xdr_tt_obj_file_results;
1187                 local = (char *(*)()) _tt_get_obj_file_1;
1188                 break;
1189                 
1190             case TT_SET_OBJ_ACCESS:
1191                 TTDB_DEBUG_SYSLOG("TT_SET_OBJ_ACCESS");
1192                 xdr_argument = (bool_t (*)()) xdr_tt_set_obj_access_args;
1193                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1194                 local = (char *(*)()) _tt_set_obj_access_1;
1195                 break;
1196                 
1197             case TT_GET_OBJ_ACCESS:
1198                 TTDB_DEBUG_SYSLOG("TT_GET_OBJ_ACCESS");
1199                 xdr_argument = (bool_t (*)()) xdr_tt_get_obj_access_args;
1200                 xdr_result = (bool_t (*)()) xdr_tt_obj_access_results;
1201                 local = (char *(*)()) _tt_get_obj_access_1;
1202                 break;
1203                 
1204             case TT_IS_FILE_IN_DB:
1205                 TTDB_DEBUG_SYSLOG("TT_IS_FILE_IN_DB");
1206                 xdr_argument = (bool_t (*)()) xdr_tt_is_file_in_db_args;
1207                 xdr_result = (bool_t (*)()) xdr_tt_is_file_in_db_results;
1208                 local = (char *(*)()) _tt_is_file_in_db_1;
1209                 break;
1210                 
1211             case TT_IS_OBJ_IN_DB:
1212                 TTDB_DEBUG_SYSLOG("TT_IS_OBJ_IN_DB");
1213                 xdr_argument = (bool_t (*)()) xdr_tt_is_obj_in_db_args;
1214                 xdr_result = (bool_t (*)()) xdr_tt_is_obj_in_db_results;
1215                 local = (char *(*)()) _tt_is_obj_in_db_1;
1216                 break;
1217                 
1218             case TT_QUEUE_MESSAGE:
1219                 TTDB_DEBUG_SYSLOG("TT_QUEUE_MESSAGE");
1220                 xdr_argument = (bool_t (*)()) xdr_tt_queue_msg_args;
1221                 xdr_result = (bool_t (*)()) xdr_tt_db_results;
1222                 local = (char *(*)()) _tt_queue_message_1;
1223                 break;
1224                 
1225             case TT_DEQUEUE_MESSAGES:
1226                 TTDB_DEBUG_SYSLOG("TT_DEQUEUE_MESSAGES");
1227                 xdr_argument = (bool_t (*)()) xdr_tt_dequeue_msgs_args;
1228                 xdr_result = (bool_t (*)()) xdr_tt_dequeue_msgs_results;
1229                 local = (char *(*)()) _tt_dequeue_messages_1;
1230                 break;
1231                 
1232             case TTDB_FILE_NETFILE:
1233                 TTDB_DEBUG_SYSLOG("TTDB_FILE_NETFILE");
1234                 xdr_argument = (bool_t (*)()) xdr_tt_file_netfile_args;
1235                 xdr_result = (bool_t (*)()) xdr_tt_file_netfile_results;
1236                 local = (char *(*)()) _tt_file_netfile_1;
1237                 break;
1238                 
1239             case TTDB_NETFILE_FILE:
1240                 TTDB_DEBUG_SYSLOG("TTDB_NETFILE_FILE");
1241                 xdr_argument = (bool_t (*)()) xdr_tt_file_netfile_args;
1242                 xdr_result = (bool_t (*)()) xdr_tt_file_netfile_results;
1243                 local = (char *(*)()) _tt_netfile_file_1;
1244                 break;
1245
1246             case TT_GET_ALL_SESSIONS:
1247                 TTDB_DEBUG_SYSLOG("TT_GET_ALL_SESSIONS");
1248                 xdr_argument = (bool_t (*)())xdr_tt_get_all_sessions_args;
1249                 xdr_result = (bool_t (*)())xdr_tt_get_all_sessions_results;
1250                 local = (char *(*)()) _tt_get_all_sessions_1;
1251                 break;
1252
1253             case TT_GARBAGE_COLLECT:
1254                 TTDB_DEBUG_SYSLOG("TT_GARBAGE_COLLECT");
1255                 xdr_argument = (bool_t (*)())xdr_void;
1256                 xdr_result = (bool_t (*)())xdr_tt_garbage_collect_results;
1257                 local = (char *(*)()) _tt_garbage_collect_1;
1258                 break;
1259
1260             case TT_DELETE_SESSION:
1261                 TTDB_DEBUG_SYSLOG("TT_DELETE_SESSION");
1262                 xdr_argument = (bool_t (*)())xdr_tt_delete_session_args;
1263                 xdr_result = (bool_t (*)())xdr_tt_delete_session_results;
1264                 local = (char *(*)()) _tt_delete_session_1;
1265                 break;
1266
1267             default:
1268                 svcerr_noproc(transp);
1269                 UNLOCK_RPC();
1270                 return;
1271         }
1272         /* get the input arguments */
1273         memset((char *)&argument, 0, sizeof(argument));
1274         if (!svc_getargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument)) {
1275                 svcerr_decode(transp);
1276                 UNLOCK_RPC();
1277                 return;
1278         }
1279         char *(*local_t)(caddr_t, SVCXPRT *) = (char *(*)(caddr_t, SVCXPRT *))
1280                 local;
1281         
1282         /* Check global message queue unlock flag */
1283         if (msg_q_unlock_flag == TRUE) {
1284                 msg_q_unlock_flag = FALSE;
1285                 
1286                 _Tt_db_msg_q_lock locks;
1287                 locks.unsetAllLocks();
1288         }
1289         
1290         if (refresh_partition_redirection_map) {
1291                 refresh_partition_redirection_map = FALSE;      
1292                 db_pr_map->refresh();
1293         }
1294         
1295         /* call the service procedure */
1296         result = (*local_t)((caddr_t)&argument, transp);
1297
1298         
1299         /* return the results to client */
1300         if ((result != NULL) && !svc_sendreply(transp,
1301                                                (xdrproc_t)xdr_result,
1302                                                (caddr_t)result)) {
1303                 svcerr_systemerr(transp);
1304         }
1305         
1306         /* free memory */
1307         if (!svc_freeargs(transp,
1308                           (xdrproc_t)xdr_argument,
1309                           (caddr_t)&argument)) {
1310                 _tt_syslog(errstr, LOG_ERR, "svc_freeargs() == 0");
1311                 exit(1);
1312         }
1313         
1314         /* process the transaction log file if there were a transaction */
1315         if (rqstp->rq_proc == _TT_TRANSACTION) {
1316                 _tt_process_transaction();
1317         }
1318
1319         //
1320         // Free the results
1321                 switch (rqstp->rq_proc) {
1322                     case TT_GET_MIN_AUTH_LEVEL:
1323                         break;
1324                         
1325                     case TT_GET_FILE_PARTITION:
1326                         if (result) {
1327                                 if (((_tt_file_partition_results *)result)->partition) {
1328                                         free(((_tt_file_partition_results *)result)->partition);
1329                                 }
1330                                 if (((_tt_file_partition_results *)result)->network_path) {
1331                                         free(((_tt_file_partition_results *)result)->network_path);
1332                                 }
1333                         }
1334                         break;
1335                         
1336                     case TT_CREATE_FILE:
1337                         break;
1338                         
1339                     case TT_CREATE_OBJ:
1340                         break;
1341                         
1342                     case TT_REMOVE_FILE:
1343                         break;
1344                         
1345                     case TT_REMOVE_OBJ:
1346                         break;
1347                         
1348                     case TT_MOVE_FILE:
1349                         break;
1350                         
1351                     case TT_SET_FILE_PROPS:
1352                         break;
1353                         
1354                     case TT_SET_FILE_PROP:
1355                         break;
1356                         
1357                     case TT_ADD_FILE_PROP:
1358                         break;
1359                         
1360                     case TT_DELETE_FILE_PROP:
1361                         break;
1362                         
1363                     case TT_GET_FILE_PROP:
1364                         if (result) {
1365                                 _tt_free_rpc_property(((_tt_file_prop_results *)
1366                                                        result)->property);
1367                         }
1368                         break;
1369                         
1370                     case TT_GET_FILE_PROPS:
1371                         if (result) {
1372                                 _tt_free_rpc_properties(((_tt_file_props_results *)
1373                                                          result)->properties);
1374                         }
1375                         break;
1376                         
1377                     case TT_GET_FILE_OBJS:
1378                         if (result) {
1379                                 _tt_free_rpc_strings(((_tt_file_objs_results *)
1380                                                       result)->objids);
1381                         }
1382                         break;
1383                         
1384                     case TT_SET_FILE_ACCESS:
1385                         break;
1386                         
1387                     case TT_GET_FILE_ACCESS:
1388                         break;
1389                         
1390                     case TT_SET_OBJ_PROPS:
1391                         break;
1392                         
1393                     case TT_SET_OBJ_PROP:
1394                         break;
1395                         
1396                     case TT_ADD_OBJ_PROP:
1397                         break;
1398                         
1399                     case TT_DELETE_OBJ_PROP:
1400                         break;
1401                         
1402                     case TT_GET_OBJ_PROP:
1403                         if (result) {
1404                                 _tt_free_rpc_property(((_tt_obj_prop_results *)
1405                                                        result)->property);
1406                         }
1407                         break;
1408                         
1409                     case TT_GET_OBJ_PROPS:
1410                         if (result) {
1411                                 _tt_free_rpc_properties(((_tt_obj_props_results *)
1412                                                          result)->properties);
1413                         }
1414                         break;
1415                         
1416                     case TT_SET_OBJ_TYPE:
1417                         break;
1418                         
1419                     case TT_GET_OBJ_TYPE:
1420                         if (result) {
1421                                 free(((_tt_obj_type_results *)result)->otype);
1422                         }
1423                         break;
1424                         
1425                     case TT_SET_OBJ_FILE:
1426                         break;
1427                         
1428                     case TT_GET_OBJ_FILE:
1429                         if (result) {
1430                                 free(((_tt_obj_file_results *)result)->file);
1431                         }
1432                         break;
1433                         
1434                     case TT_SET_OBJ_ACCESS:
1435                         break;
1436                         
1437                     case TT_GET_OBJ_ACCESS:
1438                         break;
1439                         
1440                     case TT_IS_FILE_IN_DB:
1441                         break;
1442                         
1443                     case TT_IS_OBJ_IN_DB:
1444                         if (result && ((_tt_is_obj_in_db_results *)
1445                                        result)->forward_pointer) {
1446                                 free(((_tt_is_obj_in_db_results *)
1447                                       result)->forward_pointer);
1448                         }
1449                         break;
1450                         
1451                     case TT_QUEUE_MESSAGE:
1452                         break;
1453                         
1454                     case TT_DEQUEUE_MESSAGES:
1455                         if (result) {
1456                                 _tt_free_rpc_messages(((_tt_dequeue_msgs_results *)
1457                                                        result)->messages);
1458                         }
1459                         break;
1460                         
1461                     default:
1462                         break;
1463                 }
1464
1465         UNLOCK_RPC();
1466
1467 #if defined(OPT_AUTO_GARBAGE_COLLECT)
1468 #if !defined(OPT_GARBAGE_THREADS)
1469         if (!_tt_debug_mode) {
1470 #endif
1471                 //
1472                 // The results have been passed back to the client program.
1473                 // Now check for garbage collection at some pre-determined
1474                 // interval (_TT_GARBAGE_COLLECTION_FREQUENCY).
1475                 //
1476                 time_t  the_time_now = time(0);
1477
1478                 //
1479                 // Wait at least 5 Min. after startup.
1480                 //
1481                 if (_tt_global->next_garbage_run == -1) {
1482                   _tt_global->next_garbage_run = the_time_now + (60 * 5);
1483                 }
1484
1485                 if (the_time_now > _tt_global->next_garbage_run) {
1486                         _tt_global->next_garbage_run
1487                           = the_time_now + _TT_GARBAGE_COLLECTION_FREQUENCY;
1488
1489                         //
1490                         // Run the cleanup in parallal so the server can
1491                         // keep running.
1492                         _tt_run_garbage_collect(TRUE);  // In parallel
1493                 }
1494 #if !defined(OPT_GARBAGE_THREADS)
1495         }
1496 #endif
1497 #endif /*OPT_AUTO_GARBAGE_COLLECT*/
1498         return;
1499 }
1500
1501 void
1502 install_signal_handler()
1503 {
1504         // It's important to ignore SIGPIPES so we don't die when clients do.
1505         // SIGUSR1 is used to turn logging on or off.
1506         //
1507         // SIGHUP probably *ought* to be used to force any caches to flush
1508         // For robustness, ought to catch SIGINT/TERM so we finish the current
1509         // RPC call and write out files..
1510         //
1511
1512         _tt_sigset(SIGUSR1, &sig_handler);
1513         _tt_sigset(SIGUSR2, &sig_handler);
1514         _tt_sigset(SIGPIPE, &sig_handler);
1515
1516 #if !defined(OPT_GARBAGE_THREADS)
1517         _tt_sigset(SIGCHLD, &sig_handler);
1518 #endif
1519         return;
1520 }
1521
1522 void
1523 sig_handler(int sig)
1524 {
1525         switch (sig) {
1526               case SIGPIPE:
1527                 // If a client goes away, unlock the message q locks.
1528                 // Rationale: It's better to have potential collisions
1529                 // between old and new clients then lock up the DB
1530                 // indefinitely.
1531                 msg_q_unlock_flag = TRUE;
1532                 break;
1533                 
1534               case SIGUSR1:
1535                 // turn trace on (level 1) if it was off. turn trace off
1536                 // if it was on.
1537                 break;
1538                 
1539               case SIGUSR2:
1540                 refresh_partition_redirection_map = TRUE;       
1541                 break;
1542                 
1543 #if !defined(OPT_GARBAGE_THREADS)
1544               case SIGCHLD:
1545                 waitpid(-1, NULL, WNOHANG);     // Reap and run.
1546                 _tt_garbage_id = -1;            // Mark as done.
1547                 break;
1548 #endif
1549               default:
1550                 break;
1551         }
1552         return;
1553 }