Add new command-line options to LAD to override static defaults
[ipc/ipcdev.git] / linux / src / daemon / lad.c
1 /*
2  * Copyright (c) 2012-2015, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== lad.c ========
34  */
36 #include <ti/ipc/Std.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <sys/stat.h>
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <signal.h>
47 #include <unistd.h>
49 #include <ti/ipc/MessageQ.h>
50 #include <_MessageQ.h>
51 #include <ti/ipc/NameServer.h>
52 #include <_NameServer.h>
53 #include <ti/ipc/GateMP.h>
54 #include <_GateMP_daemon.h>
55 #include <_MultiProc.h>
57 #include <GateHWSpinlock.h>
59 #include <ladclient.h>
60 #include <_lad.h>
62 #define DAEMON        1           /* 1 = run as a daemon; 0 = run as app */
64 Bool logFile = FALSE;
65 FILE *logPtr = NULL;
66 struct timeval start_tv;
68 static String commandFIFOFile = LAD_COMMANDFIFO;
69 static FILE *commandFIFOFilePtr = NULL;
71 #if defined(GATEMP_SUPPORT)
72 static Bool gatempEnabled = FALSE;
73 #endif
75 /* LAD client info arrays */
76 static Bool clientConnected[LAD_MAXNUMCLIENTS];
77 static UInt clientPID[LAD_MAXNUMCLIENTS];
78 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
79 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
81 /* local internal routines */
82 static LAD_ClientHandle assignClientId(Void);
83 static Void cleanupDepartedClients(Void);
84 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
85 static Void disconnectFromLAD(Int clientId);
86 static Void doDisconnect(Int clientId);
88 struct LAD_CommandObj cmd;
89 union LAD_ResponseObj rsp;
91 #define LAD_USAGE "\
92 Usage:\n\
93     lad_<platform> [options] \n\
94 \n\
95 Options:\n\
96     h            : print this help message\n\
97     g            : enable GateMP support \n\
98     l <logfile>  : name of logfile for LAD\n\
99     n <nprocs>   : total number of processors in the system\n\
100     p <oct value>: set LAD's directory permissions\n\
101     r <nreserve> : number of reserved queues\n\
102     s <synctype> : type of Ipc_ProcSync (ALL|PAIR|NONE)\n\
103     b <value>    : Processor's base cluster id \n\
104 \n\
105 Examples:\n\
106     lad_<platform> -h\n\
107     lad_<platform> -l log.txt\n\
108     lad_<platform> -l log.txt -p 777\n\
109     lad_<platform> -g -l log.txt\n\
110     lad_<platform> -l log.txt -b 10\n\
111 \n"
113 /*
114  *  ======== main ========
115  */
116 int main(int argc, char * argv[])
118     MessageQ_Handle handle;
119     Ipc_Config ipcCfg;
120     UInt16 *procIdPtr;
121     Int statusIO;
122     Int clientId;
123     Int command;
124     Int flags;
125     Int i;
126     Int n;
127     Int c;
128 #if defined(GATEMP_SUPPORT)
129     Int status;
130 #endif
131     String tmpString;
132 #if DAEMON
133     pid_t pid;
134     pid_t sid;
135 #endif
137     /* change to LAD's root directory */
138     if ((chdir(LAD_ROOTDIR)) < 0) {
139         /* if can't change directory assume it needs to be created, do it */
140         if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
141             printf("\nERROR: Failed to create LAD's root directory!\n");
142             exit(EXIT_FAILURE);
143         }
144     }
146     /* change to LAD's working directory */
147     if ((chdir(LAD_WORKINGDIR)) < 0) {
149         /* if can't change directory assume it needs to be created, do it */
150         if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
151             printf("\nERROR: Failed to create LAD's working directory!\n");
152             exit(EXIT_FAILURE);
153         }
154         /* now change to the new directory */
155         if ((chdir(LAD_WORKINGDIR)) < 0) {
156             printf("\nERROR: Failed to change to LAD's working directory!\n");
157             exit(EXIT_FAILURE);
158         }
159     }
161     /* process command line args */
162     while (1) {
163         c = getopt(argc, argv, "b:ghl:n:p:r:s:");
164         if (c == -1) {
165             break;
166         }
168         switch (c) {
169             case 'g':
170 #if defined(GATEMP_SUPPORT)
171                 printf("\nGateMP support enabled on host\n");
172                 gatempEnabled = TRUE;
173 #else
174                 printf("\nGateMP is not supported for this device\n");
175 #endif
176                 break;
177             case 'b':
178                 printf("\nSet LAD's base cluster id to %s\n", optarg);
179                 _MultiProc_cfg.id = atoi(optarg);
180                 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
181                 break;
182             case 'h':
183                 printf("%s", LAD_USAGE);
184                 exit(0);
185                 break;
186             case 'l':
187                 logPtr = fopen(optarg, "w");
188                 if (logPtr == NULL) {
189                     printf("\nERROR: unable to open log file %s\n", optarg);
190                     exit(EXIT_FAILURE);
191                 }
192                 else {
193                     logFile = TRUE;
194                     gettimeofday(&start_tv, NULL);
195                     printf("\nOpened log file: %s\n", optarg);
196                     /* close log file upon LAD termination */
197                     flags = fcntl(fileno(logPtr), F_GETFD);
198                     if (flags != -1) {
199                         fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
200                     }
201                 }
202                 break;
203             case 'n':
204                 printf("\nSet LAD's number of processors to %s\n", optarg);
205                 _MultiProc_cfg.numProcessors = atoi(optarg);
206                 break;
207             case 'p':
208                 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
209                 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
210                 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
211                 break;
212             case 'r':
213                 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
214                 _MessageQ_setNumReservedEntries(atoi(optarg));
215                 break;
216             case 's':
217                 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
218                        optarg);
220                 Ipc_getConfig(&ipcCfg);
222                 if (!strcmp(optarg, "ALL")) {
223                     ipcCfg.procSync = Ipc_ProcSync_ALL;
224                 }
225                 else if (!strcmp(optarg, "PAIR")) {
226                     ipcCfg.procSync = Ipc_ProcSync_PAIR;
227                 }
228                 else if (!strcmp(optarg, "NONE")) {
229                     ipcCfg.procSync = Ipc_ProcSync_NONE;
230                 }
231                 else {
232                     printf("Error: bad synchronization specified, must be "
233                            "ALL|PAIR|NONE\n");
234                     exit(EXIT_FAILURE);
235                 }
237                 Ipc_setConfig(&ipcCfg);
238                 break;
239             default:
240                 fprintf (stderr, "\nUnrecognized argument\n");
241                 exit(EXIT_FAILURE);
242         }
243     }
245     /* Check to ensure id and baseId are not invalid */
246     printf ("\nnumProcessors = %d id = %d baseId = %d\n",
247             _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
248             _MultiProc_cfg.baseIdOfCluster);
250     if (_MultiProc_cfg.id == 0xFFFF ||
251         _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
252          printf("\nBase cluster id is set to an INVALID value\n");
253          printf("Use -b option to set value or modify the MultiProcCfg file\n");
254          exit(EXIT_FAILURE);
255     }
256     if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
257         _MultiProc_cfg.numProcessors) {
258         printf("\nNumber of processors (%d) must be >= base cluster id + "
259                "number of processors in cluster (%d + %d)\n",
260                _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
261                _MultiProc_cfg.numProcsInCluster);
262          exit(EXIT_FAILURE);
263     }
266 #if DAEMON
267     /* fork off a child process */
268     pid = fork();
270     /* if fork of child failed then exit immediately; no child created */
271     if (pid < 0) {
272         printf("\nERROR: Failed to fork child process!");
273         exit(EXIT_FAILURE);
274     }
276     /* if pid > 0 this is the parent; time to die ... */
277     if (pid > 0) {
278         printf("\nSpawned daemon: %s\n\n", argv[0]);
279         exit(EXIT_SUCCESS);
280     }
282     /* child continues from here (pid == 0) ... */
284     /* change file mode mask */
285     umask(0);
287     /* create new session ID for the child */
288     sid = setsid();
290     /* exit with failure code if failed to get session ID... */
291     if (sid < 0) {
292         printf("\nERROR: Failed to acquire new session ID!");
293         exit(EXIT_FAILURE);
294     }
296     /* disassociate from the standard file descriptors */
297     close(STDIN_FILENO);
298     close(STDOUT_FILENO);
299     close(STDERR_FILENO);
301 #endif
303     LOG0("\nInitializing LAD... ")
305     /* TODO:L make sure LAD is not already running? */
307     /* initialize client info arrays */
308     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
309         clientConnected[i] = FALSE;
310         responseFIFOFilePtr[i] = NULL;
311     }
313     /* if command FIFO exists from previous LAD session delete it now */
314     unlink(commandFIFOFile);
316     /* create command FIFO */
317     statusIO = mkfifo(commandFIFOFile, 0777);
318     if (statusIO != 0) {
319         LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
320             errno)
321         return(0);
322     }
324     /* set FIFO permissions to read/write */
325     chmod(commandFIFOFile, 0666);
327     /* Setup modules relevant for GateMP if necessary */
328 #if defined(GATEMP_SUPPORT)
329     if (gatempEnabled) {
330         /* Set up NameServer for resource manager process */
331         status = NameServer_setup();
332         if (status < 0) {
333             LOG0("\nERROR: unable to setup NameServer\n")
334             return(0);
335         }
337         status = GateHWSpinlock_start();
338         if (status < 0) {
339             LOG0("\nERROR: unable to start GateHWSpinlock\n");
340             return(0);
341         }
343         /* Set up GateMP */
344         status = GateMP_setup();
345         if (status < 0) {
346             LOG0("\nERROR: unable to setup GateMP\n")
347             NameServer_destroy();
348             return(0);
349         }
350     }
351 #endif
353 opencommandFIFO:
355     /* now open file for FIFO - will block until writer arrives... */
356     LOG1("\n    opening FIFO: %s\n", commandFIFOFile)
357     commandFIFOFilePtr = fopen(commandFIFOFile, "r");
358     if (commandFIFOFilePtr == NULL) {
359         LOG0("\nERROR: unable to open command FIFO\n")
360         unlink(commandFIFOFile);
361 #if defined(GATEMP_SUPPORT)
362         if (gatempEnabled) {
363             GateMP_destroy();
364             NameServer_destroy();
365         }
366 #endif
367         return(0);
368     }
370     /* COMMAND PROCESSING LOOP */
371     while (1) {
372         LOG0("Retrieving command...\n")
374         /* read the next command packet */
375         n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
377         /*
378          * if last client closes FIFO then it must be closed and reopened ...
379          */
380         if (!n) {
381             LOG1("   EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
382             fclose(commandFIFOFilePtr);
384             goto opencommandFIFO;
385         }
387         /* cleanup for any connected/started clients that have departed */
388         cleanupDepartedClients();
390         command = cmd.cmd;
391         clientId = cmd.clientId;
393         /* process individual commands */
394         switch (command) {
395           /*
396            * Since cmd is a union of rcv and snd structs, don't write
397            * any snd elements before all rcv elements have been referenced
398            * (either saved in separate variables or passed to a function).
399            *
400            * cmd.cmd has already been saved in 'command'
401            * cmd.clientId has already been saved in 'clientId'
402            */
403           case LAD_CONNECT:
404             connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
405                          cmd.args.connect.protocol, NULL);
407             break;
409           case LAD_DISCONNECT:
410             disconnectFromLAD(clientId);
412             break;
414           case LAD_RPROC_SETID:
415             rsp.status = MultiProc_rprocSetId(cmd.args.rprocSetId.procId,
416                     cmd.args.rprocSetId.rprocId);
417             break;
419           case LAD_IPC_GETCONFIG:
420             Ipc_getConfig(&rsp.ipcConfig);
421             break;
423           case LAD_NAMESERVER_SETUP:
424             LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
426             rsp.status = NameServer_setup();
428             LOG1("    status = %d\n", rsp.status)
429             LOG0("DONE\n")
431             break;
433           case LAD_NAMESERVER_DESTROY:
434             LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
436             rsp.status = NameServer_destroy();
438             LOG1("    status = %d\n", rsp.status)
439             LOG0("DONE\n")
441             break;
443           case LAD_NAMESERVER_PARAMS_INIT:
444             LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
446             NameServer_Params_init(&rsp.params);
448             LOG0("DONE\n")
450             break;
452           case LAD_NAMESERVER_CREATE:
453             LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
455             rsp.handle = NameServer_create(cmd.args.create.name,
456                                                &cmd.args.create.params);
458             LOG1("    handle = %p\n", rsp.handle)
459             LOG0("DONE\n")
461             break;
463           case LAD_NAMESERVER_DELETE:
464             LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
465                     cmd.args.nsdelete.handle)
467             rsp.nsdelete.handle = cmd.args.nsdelete.handle;
468             rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
470             LOG1("    status = %d\n", rsp.nsdelete.status)
471             LOG0("DONE\n")
473             break;
475           case LAD_NAMESERVER_ADD:
476             LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
477             LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
478             LOG1(" 0x%x)...\n", cmd.args.add.len)
480             rsp.entryPtr = NameServer_add(
481                 cmd.args.add.handle,
482                 cmd.args.add.name,
483                 cmd.args.add.buf,
484                 cmd.args.add.len);
486             LOG1("    entryPtr = %p\n", rsp.entryPtr)
487             LOG0("DONE\n")
489             break;
491           case LAD_NAMESERVER_GET:
492             LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
493                     cmd.args.get.handle, cmd.args.get.name)
494             LOG0(")...\n")
496             if (cmd.args.get.procId[0] == (UInt16)-1) {
497                 procIdPtr = NULL;
498             }
499             else {
500                 procIdPtr = cmd.args.get.procId;
501             }
502             rsp.get.status = NameServer_get(
503                 cmd.args.get.handle,
504                 cmd.args.get.name,
505                 rsp.get.buf,
506                 &cmd.args.get.len,
507                 procIdPtr);
508             rsp.get.len = cmd.args.get.len;
510             LOG1("    value = 0x%x\n", rsp.get.len)
511             LOG1("    status = %d\n", rsp.get.status)
512             LOG0("DONE\n")
514             break;
516           case LAD_NAMESERVER_ADDUINT32:
517             LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
518                     "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
519                     cmd.args.addUInt32.name, cmd.args.addUInt32.val)
521             rsp.entryPtr = NameServer_addUInt32(
522                 cmd.args.addUInt32.handle,
523                 cmd.args.addUInt32.name,
524                 cmd.args.addUInt32.val);
526             LOG1("    entryPtr = %p\n", rsp.entryPtr)
527             LOG0("DONE\n")
529             break;
531           case LAD_NAMESERVER_GETUINT32:
532             LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
533                     "(%p, '%s')...\n", cmd.args.getUInt32.handle,
534                     cmd.args.getUInt32.name)
536             if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
537                 procIdPtr = NULL;
538             }
539             else {
540                 procIdPtr = cmd.args.getUInt32.procId;
541             }
542             rsp.getUInt32.status = NameServer_getUInt32(
543                 cmd.args.getUInt32.handle,
544                 cmd.args.getUInt32.name,
545                 &rsp.getUInt32.val,
546                 procIdPtr);
548             LOG1("    value = 0x%x\n", rsp.getUInt32.val)
549             LOG1("    status = %d\n", rsp.getUInt32.status)
550             LOG0("DONE\n")
552             break;
554           case LAD_NAMESERVER_GETLOCAL:
555             rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
556                 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
557             rsp.get.len = cmd.args.getLocal.len;
558             break;
560           case LAD_NAMESERVER_GETLOCALUINT32:
561             rsp.getUInt32.status = NameServer_getLocalUInt32(
562                 cmd.args.getLocalUInt32.handle,
563                 cmd.args.getLocalUInt32.name,
564                 &rsp.getUInt32.val);
565             break;
567           case LAD_NAMESERVER_REMOVE:
568             LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
570             rsp.status = NameServer_remove(cmd.args.remove.handle,
571                                                cmd.args.remove.name);
573             LOG1("    status = %d\n", rsp.status)
574             LOG0("DONE\n")
576             break;
578           case LAD_NAMESERVER_REMOVEENTRY:
579             LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
581             rsp.status = NameServer_removeEntry(
582                 cmd.args.removeEntry.handle,
583                 cmd.args.removeEntry.entryPtr);
585             LOG1("    status = %d\n", rsp.status)
586             LOG0("DONE\n")
588             break;
590           case LAD_NAMESERVER_ATTACH:
591             rsp.status = NameServer_attach(cmd.args.attach.procId);
592             break;
594           case LAD_NAMESERVER_DETACH:
595             rsp.status = NameServer_detach(cmd.args.detach.procId);
596             break;
598           case LAD_MESSAGEQ_GETCONFIG:
599             LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
601             MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
602             rsp.messageQGetConfig.status = 0;
604             LOG1("    status = %d\n", rsp.messageQGetConfig.status)
605             LOG0("DONE\n")
607             break;
609           case LAD_MESSAGEQ_SETUP:
610             LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
612             rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
613             rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
615             LOG1("    status = %d\n", rsp.setup.status)
616             LOG0("DONE\n")
618             break;
620           case LAD_MESSAGEQ_DESTROY:
621             LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
623             rsp.status = MessageQ_destroy();
625             LOG1("    status = %d\n", rsp.status)
626             LOG0("DONE\n")
628             break;
630           case LAD_MESSAGEQ_CREATE:
631             LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
632                     cmd.args.messageQCreate.name,
633                     &cmd.args.messageQCreate.params);
635             tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
636                 cmd.args.messageQCreate.name;
638             handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
639             rsp.messageQCreate.serverHandle = handle;
641             if (handle) {
642                 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
643                 MessageQ_setQueueOwner(handle, clientPID[clientId]);
644                 rsp.messageQCreate.status = 0;
645             }
646             else {
647                 rsp.messageQCreate.status = -1;
648             }
650             LOG1("    status = %d\n", rsp.messageQCreate.status)
651             LOG0("DONE\n")
653             break;
655           case LAD_MESSAGEQ_DELETE:
656             LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
658             rsp.messageQDelete.status =
659                 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
661             LOG1("    status = %d\n", rsp.messageQDelete.status)
662             LOG0("DONE\n")
664             break;
666           case LAD_MESSAGEQ_MSGINIT:
667             LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
669             MessageQ_msgInit(&rsp.msgInit.msg);
670             rsp.msgInit.status = 0;
672             LOG1("    status = %d\n", rsp.msgInit.status)
673             LOG0("DONE\n")
675             break;
677           case LAD_MULTIPROC_GETCONFIG:
678             LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
680             MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
681             rsp.multiprocGetConfig.status = 0;
683             LOG1("    status = %d\n", rsp.multiprocGetConfig.status)
684             LOG0("DONE\n")
686             break;
688 #if defined(GATEMP_SUPPORT)
689           case LAD_GATEMP_START:
690             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
692             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
693             rsp.gateMPStart.status = GateMP_S_SUCCESS;;
695             LOG1("    status = %d\n", rsp.gateMPStart.status)
696             LOG0("DONE\n")
698             break;
700           case LAD_GATEMP_GETNUMRESOURCES:
701             LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
703             rsp.gateMPGetNumResources.value = GateMP_getNumResources(
704                                           cmd.args.gateMPGetNumResources.type);
705             rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
707             LOG1("    status = %d\n", rsp.gateMPGetNumResources.status)
708             LOG0("DONE\n")
710             break;
712           case LAD_GATEMP_GETFREERESOURCE:
713             LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
715             rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
716                                           cmd.args.gateMPGetFreeResource.type);
717             rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
719             LOG1("    status = %d\n", rsp.gateMPGetFreeResource.status)
720             LOG0("DONE\n")
722             break;
724           case LAD_GATEMP_RELEASERESOURCE:
725             LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
727             rsp.gateMPReleaseResource.status = GateMP_releaseResource(
728                                           cmd.args.gateMPReleaseResource.id,
729                                           cmd.args.gateMPReleaseResource.type);
731             LOG1("    status = %d\n", rsp.gateMPReleaseResource.status)
732             LOG0("DONE\n")
734             break;
736           case LAD_GATEMP_ISSETUP:
737             LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
739             rsp.gateMPIsSetup.result = GateMP_isSetup();
740             rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
742             LOG1("    status = %d\n", rsp.gateMPIsSetup.status)
743             LOG0("DONE\n")
745             break;
747           case LAD_GATEHWSPINLOCK_GETCONFIG:
748             LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
750             GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
751             rsp.gateHWSpinlockGetConfig.status = 0;
753             LOG1("    status = %d\n", rsp.gateHWSpinlockGetConfig.status)
754             LOG0("DONE\n")
756             break;
757 #endif
759           case LAD_EXIT:
760             goto exitNow;
762             break;
764           default:
765             LOG1("\nUnrecognized command: 0x%x\n", command)
767             break;
768         }
770         switch (command) {
771           case LAD_CONNECT:
772           case LAD_DISCONNECT:
773             break;
775           case LAD_RPROC_SETID:
776           case LAD_IPC_GETCONFIG:
777           case LAD_NAMESERVER_SETUP:
778           case LAD_NAMESERVER_DESTROY:
779           case LAD_NAMESERVER_PARAMS_INIT:
780           case LAD_NAMESERVER_CREATE:
781           case LAD_NAMESERVER_DELETE:
782           case LAD_NAMESERVER_ADD:
783           case LAD_NAMESERVER_GET:
784           case LAD_NAMESERVER_ADDUINT32:
785           case LAD_NAMESERVER_GETUINT32:
786           case LAD_NAMESERVER_GETLOCAL:
787           case LAD_NAMESERVER_GETLOCALUINT32:
788           case LAD_NAMESERVER_REMOVE:
789           case LAD_NAMESERVER_REMOVEENTRY:
790           case LAD_NAMESERVER_ATTACH:
791           case LAD_NAMESERVER_DETACH:
792           case LAD_MESSAGEQ_GETCONFIG:
793           case LAD_MESSAGEQ_SETUP:
794           case LAD_MESSAGEQ_DESTROY:
795           case LAD_MESSAGEQ_CREATE:
796           case LAD_MESSAGEQ_DELETE:
797           case LAD_MESSAGEQ_MSGINIT:
798           case LAD_MULTIPROC_GETCONFIG:
799 #if defined(GATEMP_SUPPORT)
800           case LAD_GATEMP_START:
801           case LAD_GATEMP_GETNUMRESOURCES:
802           case LAD_GATEMP_GETFREERESOURCE:
803           case LAD_GATEMP_RELEASERESOURCE:
804           case LAD_GATEMP_ISSETUP:
805           case LAD_GATEHWSPINLOCK_GETCONFIG:
806 #endif
808             LOG0("Sending response...\n");
810             fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
811             fflush(responseFIFOFilePtr[clientId]);
813             break;
815           default:
816             break;
817         }
818     }
820 exitNow:
821 #if defined(GATEMP_SUPPORT)
822     if (gatempEnabled) {
823         GateMP_destroy();
824         NameServer_destroy();
825     }
826 #endif
827     if (logFile) {
828         LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
829         fclose(logPtr);
830     }
831     unlink(commandFIFOFile);
833     return(0);
838 /*
839  *  ======== assignClientId ========
840  */
841 static LAD_ClientHandle assignClientId(Void)
843     Int clientId = -1;
844     Int i;
846     /* scan connection status flags to acquire a clientId */
847     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
848         /* if slot open then provisionally select this clientId */
849         if (clientConnected[i] == FALSE) {
850              clientId = i;
851              break;
852         }
853     }
855     return(clientId);
859 /*
860  *  ======== cleanupDepartedClients ========
861  */
862 static Void cleanupDepartedClients(Void)
864     Int killStat;
865     Int i;
867     /* scan all connections to verify client processes still exist... */
868     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
870         /* if connected... */
871         if (clientConnected[i] == TRUE) {
873             /* check if the client process (PID) still exists */
874             /*
875              * NOTE - calling kill with signal value of 0 will perform
876              * error checking, but not actually send a signal.  Will use this
877              * error check to see if PID still exists.  An alternative was
878              * to call getpgid.  This worked, but is apparently limited to
879              * USE_XOPEN_EXTENDED configurations.
880              */
881             killStat = kill(clientPID[i], 0);
882             if ((killStat == -1) && (errno == ESRCH)) {
884                 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
886                 /* will always need to do the disconnect... */
887                 LOG0("\nDoing DISCONNECT on behalf of client...")
888                 doDisconnect(i);
890                 MessageQ_cleanupOwner(clientPID[i]);
891 //                NameServer_cleanupOwner(clientPID[i]);
893                 LOG0("DONE\n")
894             }
895         }
896     }
900 /*
901  *  ======== connectToLAD ========
902  */
903 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
905     Int clientId = -1;
906     Bool connectDenied = FALSE;
907     Int status = LAD_SUCCESS;
908     FILE * filePtr;
909     Int statusIO;
911     /*
912      * TODO:L here, and everywhere parse FIFO strings: should
913      * add full error checking for incomplete or corrupted
914      * strings? Since LAD to ladclient comms are "closed", and
915      * tested, the likelihood of problems seems very low.
916      * But should still consider doing full error checking
917      * and, hopefully, recovery.
918      */
919     LOG0("\nLAD_CONNECT: \n")
920     LOG1("    client FIFO name = %s\n", clientName)
921     LOG1("    client PID = %d\n", pid)
923     /* first check for proper communication protocol */
924     if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
926         /* if no match then reject the request */
927         LOG0("    ERROR: mismatch in communication protocol!\n")
928         LOG1("        LAD protocol = %s\n", LAD_PROTOCOLVERSION)
929         LOG1("        client protocol = %s\n", clientProto)
930         status = LAD_INVALIDVERSION;
932         /* set flag so know to close FIFO after response */
933         connectDenied = TRUE;
935         /* now jump forward a bit to send response */
936         goto openResponseFIFO;
937     }
939     /* determine this client's ID */
940     clientId = assignClientId();
942     /* if failed to acquire an ID then exit early */
943     if (clientId == -1) {
944         LOG0("    no free handle; too many connections!\n")
945         status = LAD_ACCESSDENIED;
947         /* set flag so know to close FIFO after response */
948         connectDenied = TRUE;
949     }
950     else {
951         LOG1("    assigned client handle = %d\n", clientId)
953         /* save the client's FIFO name for when disconnect */
954         strcpy(clientFIFOName[clientId], clientName);
955     }
957 openResponseFIFO:
959     /* if response FIFO exists from previous LAD session delete it now */
960     unlink(clientName);
962     /* create the dedicated response FIFO to the client */
963     statusIO = mkfifo(clientName, 0777);
964     if (statusIO != 0) {
966         LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
968         status = LAD_IOFAILURE;
970         /* send no response; connection request will timeout */
971         goto doneconnect;
972     }
974     LOG1("    FIFO %s created\n", clientName)
976     /* set FIFO permissions to read/write */
977     chmod(clientName, 0666);
979     filePtr = fopen(clientName, "w");
980     if (filePtr == NULL) {
981         LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
983         /* if failed open, still need to delete the FIFO */
984         unlink(clientName);
986         status = LAD_IOFAILURE;
988         /* send no response; connection request will timeout */
989         goto doneconnect;
990     }
992     LOG1("    FIFO %s opened for writing\n", clientName)
994     /*
995      * set "this client is connected" flag; this client ID is now "owned", and
996      * is no longer provisional
997      */
998     if (connectDenied == FALSE) {
999         responseFIFOFilePtr[clientId] = filePtr;
1000         clientPID[clientId] = pid;
1001         clientConnected[clientId] = TRUE;
1002     }
1004     rsp.connect.assignedId = clientId;
1005     rsp.status = status;
1007     /* put response to FIFO */
1008     fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1009     fflush(filePtr);
1011     LOG0("    sent response\n")
1013     /* if connection was denied, must now close FIFO */
1014     if (connectDenied == TRUE) {
1015         LOG1("    connect denied; closing FIFO %s\n", clientName)
1016         fclose(filePtr);
1017         unlink(clientName);
1018     }
1020     LOG0("DONE\n")
1022 doneconnect:
1023     if (clientIdPtr != NULL) {
1024         *clientIdPtr = clientId;
1025     }
1027     return(status);
1031 /*
1032  *  ======== disconnectFromLAD ========
1033  */
1034 static Void disconnectFromLAD(Int clientId)
1036     LOG0("\nLAD_DISCONNECT: ")
1038     LOG1("\n    client handle = %x", clientId)
1039     doDisconnect(clientId);
1041     LOG0("DONE\n")
1043     return;
1047 /*
1048  *  ======== doDisconnect ========
1049  */
1050 static Void doDisconnect(Int clientId)
1052     /* set "this client is not connected" flag */
1053     clientConnected[clientId] = FALSE;
1055     /* close and remove the response FIFO */
1056     LOG2("\n    closing FIFO %s (filePtr=%p)\n",
1057         clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1058     fclose(responseFIFOFilePtr[clientId]);
1060     LOG1("    done, unlinking %s\n", clientFIFOName[clientId]);
1061     unlink(clientFIFOName[clientId]);