Add FD_CLOEXEC flag for sockets, /dev/mem and LAD pipes
[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     UInt16 procId;
131 #endif
132     String tmpString;
133 #if DAEMON
134     pid_t pid;
135     pid_t sid;
136 #endif
138     /* change to LAD's root directory */
139     if ((chdir(LAD_ROOTDIR)) < 0) {
140         /* if can't change directory assume it needs to be created, do it */
141         if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
142             printf("\nERROR: Failed to create LAD's root directory!\n");
143             exit(EXIT_FAILURE);
144         }
145     }
147     /* change to LAD's working directory */
148     if ((chdir(LAD_WORKINGDIR)) < 0) {
150         /* if can't change directory assume it needs to be created, do it */
151         if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
152             printf("\nERROR: Failed to create LAD's working directory!\n");
153             exit(EXIT_FAILURE);
154         }
155         /* now change to the new directory */
156         if ((chdir(LAD_WORKINGDIR)) < 0) {
157             printf("\nERROR: Failed to change to LAD's working directory!\n");
158             exit(EXIT_FAILURE);
159         }
160     }
162     /* process command line args */
163     while (1) {
164         c = getopt(argc, argv, "b:ghl:n:p:r:s:");
165         if (c == -1) {
166             break;
167         }
169         switch (c) {
170             case 'g':
171 #if defined(GATEMP_SUPPORT)
172                 printf("\nGateMP support enabled on host\n");
173                 gatempEnabled = TRUE;
174 #else
175                 printf("\nGateMP is not supported for this device\n");
176 #endif
177                 break;
178             case 'b':
179                 printf("\nSet LAD's base cluster id to %s\n", optarg);
180                 _MultiProc_cfg.id = atoi(optarg);
181                 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
182                 break;
183             case 'h':
184                 printf("%s", LAD_USAGE);
185                 exit(0);
186                 break;
187             case 'l':
188                 logPtr = fopen(optarg, "w");
189                 if (logPtr == NULL) {
190                     printf("\nERROR: unable to open log file %s\n", optarg);
191                     exit(EXIT_FAILURE);
192                 }
193                 else {
194                     logFile = TRUE;
195                     gettimeofday(&start_tv, NULL);
196                     printf("\nOpened log file: %s\n", optarg);
197                     /* close log file upon LAD termination */
198                     flags = fcntl(fileno(logPtr), F_GETFD);
199                     if (flags != -1) {
200                         fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
201                     }
202                 }
203                 break;
204             case 'n':
205                 printf("\nSet LAD's number of processors to %s\n", optarg);
206                 _MultiProc_cfg.numProcessors = atoi(optarg);
207                 break;
208             case 'p':
209                 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
210                 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
211                 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
212                 break;
213             case 'r':
214                 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
215                 _MessageQ_setNumReservedEntries(atoi(optarg));
216                 break;
217             case 's':
218                 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
219                        optarg);
221                 Ipc_getConfig(&ipcCfg);
223                 if (!strcmp(optarg, "ALL")) {
224                     ipcCfg.procSync = Ipc_ProcSync_ALL;
225                 }
226                 else if (!strcmp(optarg, "PAIR")) {
227                     ipcCfg.procSync = Ipc_ProcSync_PAIR;
228                 }
229                 else if (!strcmp(optarg, "NONE")) {
230                     ipcCfg.procSync = Ipc_ProcSync_NONE;
231                 }
232                 else {
233                     printf("Error: bad synchronization specified, must be "
234                            "ALL|PAIR|NONE\n");
235                     exit(EXIT_FAILURE);
236                 }
238                 Ipc_setConfig(&ipcCfg);
239                 break;
240             default:
241                 fprintf (stderr, "\nUnrecognized argument\n");
242                 exit(EXIT_FAILURE);
243         }
244     }
246     /* Check to ensure id and baseId are not invalid */
247     printf ("\nnumProcessors = %d id = %d baseId = %d\n",
248             _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
249             _MultiProc_cfg.baseIdOfCluster);
251     if (_MultiProc_cfg.id == 0xFFFF ||
252         _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
253          printf("\nBase cluster id is set to an INVALID value\n");
254          printf("Use -b option to set value or modify the MultiProcCfg file\n");
255          exit(EXIT_FAILURE);
256     }
257     if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
258         _MultiProc_cfg.numProcessors) {
259         printf("\nNumber of processors (%d) must be >= base cluster id + "
260                "number of processors in cluster (%d + %d)\n",
261                _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
262                _MultiProc_cfg.numProcsInCluster);
263          exit(EXIT_FAILURE);
264     }
267 #if DAEMON
268     /* fork off a child process */
269     pid = fork();
271     /* if fork of child failed then exit immediately; no child created */
272     if (pid < 0) {
273         printf("\nERROR: Failed to fork child process!");
274         exit(EXIT_FAILURE);
275     }
277     /* if pid > 0 this is the parent; time to die ... */
278     if (pid > 0) {
279         printf("\nSpawned daemon: %s\n\n", argv[0]);
280         exit(EXIT_SUCCESS);
281     }
283     /* child continues from here (pid == 0) ... */
285     /* change file mode mask */
286     umask(0);
288     /* create new session ID for the child */
289     sid = setsid();
291     /* exit with failure code if failed to get session ID... */
292     if (sid < 0) {
293         printf("\nERROR: Failed to acquire new session ID!");
294         exit(EXIT_FAILURE);
295     }
297     /* disassociate from the standard file descriptors */
298     close(STDIN_FILENO);
299     close(STDOUT_FILENO);
300     close(STDERR_FILENO);
302 #endif
304     LOG0("\nInitializing LAD... ")
306     /* TODO:L make sure LAD is not already running? */
308     /* initialize client info arrays */
309     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
310         clientConnected[i] = FALSE;
311         responseFIFOFilePtr[i] = NULL;
312     }
314     /* if command FIFO exists from previous LAD session delete it now */
315     unlink(commandFIFOFile);
317     /* create command FIFO */
318     statusIO = mkfifo(commandFIFOFile, 0777);
319     if (statusIO != 0) {
320         LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
321             errno)
322         return(0);
323     }
325     /* set FIFO permissions to read/write */
326     chmod(commandFIFOFile, 0666);
328     /* Setup modules relevant for GateMP if necessary */
329 #if defined(GATEMP_SUPPORT)
330     if (gatempEnabled) {
331         /* Set up NameServer for resource manager process */
332         status = NameServer_setup();
333         if (status < 0) {
334             LOG0("\nERROR: unable to setup NameServer\n")
335             return(0);
336         }
338         status = GateHWSpinlock_start();
339         if (status < 0) {
340             LOG0("\nERROR: unable to start GateHWSpinlock\n");
341             return(0);
342         }
344         /* Set up GateMP */
345         status = GateMP_setup();
346         if (status < 0) {
347             LOG0("\nERROR: unable to setup GateMP\n")
348             NameServer_destroy();
349             return(0);
350         }
351     }
352 #endif
354 opencommandFIFO:
356     /* now open file for FIFO - will block until writer arrives... */
357     LOG1("\n    opening FIFO: %s\n", commandFIFOFile)
358     commandFIFOFilePtr = fopen(commandFIFOFile, "r");
359     if (commandFIFOFilePtr == NULL) {
360         LOG0("\nERROR: unable to open command FIFO\n")
361         unlink(commandFIFOFile);
362 #if defined(GATEMP_SUPPORT)
363         if (gatempEnabled) {
364             GateMP_destroy();
365             NameServer_destroy();
366         }
367 #endif
368         return(0);
369     }
371     /* COMMAND PROCESSING LOOP */
372     while (1) {
373         LOG0("Retrieving command...\n")
375         /* read the next command packet */
376         n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
378         /*
379          * if last client closes FIFO then it must be closed and reopened ...
380          */
381         if (!n) {
382             LOG1("   EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
383             fclose(commandFIFOFilePtr);
385             goto opencommandFIFO;
386         }
388         /* cleanup for any connected/started clients that have departed */
389         cleanupDepartedClients();
391         command = cmd.cmd;
392         clientId = cmd.clientId;
394         /* process individual commands */
395         switch (command) {
396           /*
397            * Since cmd is a union of rcv and snd structs, don't write
398            * any snd elements before all rcv elements have been referenced
399            * (either saved in separate variables or passed to a function).
400            *
401            * cmd.cmd has already been saved in 'command'
402            * cmd.clientId has already been saved in 'clientId'
403            */
404           case LAD_CONNECT:
405             connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
406                          cmd.args.connect.protocol, NULL);
408             break;
410           case LAD_DISCONNECT:
411             disconnectFromLAD(clientId);
413             break;
415           case LAD_RPROC_SETID:
416             rsp.status = MultiProc_rprocSetId(cmd.args.rprocSetId.procId,
417                     cmd.args.rprocSetId.rprocId);
418             break;
420           case LAD_IPC_GETCONFIG:
421             Ipc_getConfig(&rsp.ipcConfig);
422             break;
424           case LAD_NAMESERVER_SETUP:
425             LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
427             rsp.status = NameServer_setup();
429             LOG1("    status = %d\n", rsp.status)
430             LOG0("DONE\n")
432             break;
434           case LAD_NAMESERVER_DESTROY:
435             LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
437             rsp.status = NameServer_destroy();
439             LOG1("    status = %d\n", rsp.status)
440             LOG0("DONE\n")
442             break;
444           case LAD_NAMESERVER_PARAMS_INIT:
445             LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
447             NameServer_Params_init(&rsp.params);
449             LOG0("DONE\n")
451             break;
453           case LAD_NAMESERVER_CREATE:
454             LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
456             rsp.handle = NameServer_create(cmd.args.create.name,
457                                                &cmd.args.create.params);
459             LOG1("    handle = %p\n", rsp.handle)
460             LOG0("DONE\n")
462             break;
464           case LAD_NAMESERVER_DELETE:
465             LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
466                     cmd.args.nsdelete.handle)
468             rsp.nsdelete.handle = cmd.args.nsdelete.handle;
469             rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
471             LOG1("    status = %d\n", rsp.nsdelete.status)
472             LOG0("DONE\n")
474             break;
476           case LAD_NAMESERVER_ADD:
477             LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
478             LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
479             LOG1(" 0x%x)...\n", cmd.args.add.len)
481             rsp.entryPtr = NameServer_add(
482                 cmd.args.add.handle,
483                 cmd.args.add.name,
484                 cmd.args.add.buf,
485                 cmd.args.add.len);
487             LOG1("    entryPtr = %p\n", rsp.entryPtr)
488             LOG0("DONE\n")
490             break;
492           case LAD_NAMESERVER_GET:
493             LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
494                     cmd.args.get.handle, cmd.args.get.name)
495             LOG0(")...\n")
497             if (cmd.args.get.procId[0] == (UInt16)-1) {
498                 procIdPtr = NULL;
499             }
500             else {
501                 procIdPtr = cmd.args.get.procId;
502             }
503             rsp.get.status = NameServer_get(
504                 cmd.args.get.handle,
505                 cmd.args.get.name,
506                 rsp.get.buf,
507                 &cmd.args.get.len,
508                 procIdPtr);
509             rsp.get.len = cmd.args.get.len;
511             LOG1("    value = 0x%x\n", rsp.get.len)
512             LOG1("    status = %d\n", rsp.get.status)
513             LOG0("DONE\n")
515             break;
517           case LAD_NAMESERVER_ADDUINT32:
518             LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
519                     "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
520                     cmd.args.addUInt32.name, cmd.args.addUInt32.val)
522             rsp.entryPtr = NameServer_addUInt32(
523                 cmd.args.addUInt32.handle,
524                 cmd.args.addUInt32.name,
525                 cmd.args.addUInt32.val);
527             LOG1("    entryPtr = %p\n", rsp.entryPtr)
528             LOG0("DONE\n")
530             break;
532           case LAD_NAMESERVER_GETUINT32:
533             LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
534                     "(%p, '%s')...\n", cmd.args.getUInt32.handle,
535                     cmd.args.getUInt32.name)
537             if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
538                 procIdPtr = NULL;
539             }
540             else {
541                 procIdPtr = cmd.args.getUInt32.procId;
542             }
543             rsp.getUInt32.status = NameServer_getUInt32(
544                 cmd.args.getUInt32.handle,
545                 cmd.args.getUInt32.name,
546                 &rsp.getUInt32.val,
547                 procIdPtr);
549             LOG1("    value = 0x%x\n", rsp.getUInt32.val)
550             LOG1("    status = %d\n", rsp.getUInt32.status)
551             LOG0("DONE\n")
553             break;
555           case LAD_NAMESERVER_GETLOCAL:
556             rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
557                 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
558             rsp.get.len = cmd.args.getLocal.len;
559             break;
561           case LAD_NAMESERVER_GETLOCALUINT32:
562             rsp.getUInt32.status = NameServer_getLocalUInt32(
563                 cmd.args.getLocalUInt32.handle,
564                 cmd.args.getLocalUInt32.name,
565                 &rsp.getUInt32.val);
566             break;
568           case LAD_NAMESERVER_REMOVE:
569             LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
571             rsp.status = NameServer_remove(cmd.args.remove.handle,
572                                                cmd.args.remove.name);
574             LOG1("    status = %d\n", rsp.status)
575             LOG0("DONE\n")
577             break;
579           case LAD_NAMESERVER_REMOVEENTRY:
580             LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
582             rsp.status = NameServer_removeEntry(
583                 cmd.args.removeEntry.handle,
584                 cmd.args.removeEntry.entryPtr);
586             LOG1("    status = %d\n", rsp.status)
587             LOG0("DONE\n")
589             break;
591           case LAD_NAMESERVER_ATTACH:
592             rsp.status = NameServer_attach(cmd.args.attach.procId);
593             break;
595           case LAD_NAMESERVER_DETACH:
596             rsp.status = NameServer_detach(cmd.args.detach.procId);
597             break;
599           case LAD_MESSAGEQ_GETCONFIG:
600             LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
602             MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
603             rsp.messageQGetConfig.status = 0;
605             LOG1("    status = %d\n", rsp.messageQGetConfig.status)
606             LOG0("DONE\n")
608             break;
610           case LAD_MESSAGEQ_SETUP:
611             LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
613             rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
614             rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
616             LOG1("    status = %d\n", rsp.setup.status)
617             LOG0("DONE\n")
619             break;
621           case LAD_MESSAGEQ_DESTROY:
622             LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
624             rsp.status = MessageQ_destroy();
626             LOG1("    status = %d\n", rsp.status)
627             LOG0("DONE\n")
629             break;
631           case LAD_MESSAGEQ_CREATE:
632             LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
633                     cmd.args.messageQCreate.name,
634                     &cmd.args.messageQCreate.params);
636             tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
637                 cmd.args.messageQCreate.name;
639             handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
640             rsp.messageQCreate.serverHandle = handle;
642             if (handle) {
643                 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
644                 MessageQ_setQueueOwner(handle, clientPID[clientId]);
645                 rsp.messageQCreate.status = 0;
646             }
647             else {
648                 rsp.messageQCreate.status = -1;
649             }
651             LOG1("    status = %d\n", rsp.messageQCreate.status)
652             LOG0("DONE\n")
654             break;
656           case LAD_MESSAGEQ_DELETE:
657             LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
659             rsp.messageQDelete.status =
660                 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
662             LOG1("    status = %d\n", rsp.messageQDelete.status)
663             LOG0("DONE\n")
665             break;
667           case LAD_MESSAGEQ_MSGINIT:
668             LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
670             MessageQ_msgInit(&rsp.msgInit.msg);
671             rsp.msgInit.status = 0;
673             LOG1("    status = %d\n", rsp.msgInit.status)
674             LOG0("DONE\n")
676             break;
678           case LAD_MULTIPROC_GETCONFIG:
679             LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
681             MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
682             rsp.multiprocGetConfig.status = 0;
684             LOG1("    status = %d\n", rsp.multiprocGetConfig.status)
685             LOG0("DONE\n")
687             break;
689 #if defined(GATEMP_SUPPORT)
690           case LAD_GATEMP_ATTACH:
691             procId = cmd.args.attach.procId;
692             LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
694             rsp.status = GateMP_attach(procId);
696             LOG1("    status = %d\n", rsp.status)
697             LOG0("DONE\n")
699             break;
701           case LAD_GATEMP_DETACH:
702             procId = cmd.args.detach.procId;
703             LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
705             rsp.status = GateMP_detach(procId);
707             LOG1("    status = %d\n", rsp.status)
708             LOG0("DONE\n")
710             break;
712           case LAD_GATEMP_START:
713             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
715             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
716             rsp.gateMPStart.status = GateMP_S_SUCCESS;
718             LOG1("    status = %d\n", rsp.gateMPStart.status)
719             LOG0("DONE\n")
721             break;
723           case LAD_GATEMP_GETNUMRESOURCES:
724             LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
726             rsp.gateMPGetNumResources.value = GateMP_getNumResources(
727                                           cmd.args.gateMPGetNumResources.type);
728             rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
730             LOG1("    status = %d\n", rsp.gateMPGetNumResources.status)
731             LOG0("DONE\n")
733             break;
735           case LAD_GATEMP_GETFREERESOURCE:
736             LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
738             rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
739                                           cmd.args.gateMPGetFreeResource.type);
740             rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
742             LOG1("    status = %d\n", rsp.gateMPGetFreeResource.status)
743             LOG0("DONE\n")
745             break;
747           case LAD_GATEMP_RELEASERESOURCE:
748             LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
750             rsp.gateMPReleaseResource.status = GateMP_releaseResource(
751                                           cmd.args.gateMPReleaseResource.id,
752                                           cmd.args.gateMPReleaseResource.type);
754             LOG1("    status = %d\n", rsp.gateMPReleaseResource.status)
755             LOG0("DONE\n")
757             break;
759           case LAD_GATEMP_ISSETUP:
760             LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
762             rsp.gateMPIsSetup.result = GateMP_isSetup();
763             rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
765             LOG1("    status = %d\n", rsp.gateMPIsSetup.status)
766             LOG0("DONE\n")
768             break;
770           case LAD_GATEHWSPINLOCK_GETCONFIG:
771             LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
773             GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
774             rsp.gateHWSpinlockGetConfig.status = 0;
776             LOG1("    status = %d\n", rsp.gateHWSpinlockGetConfig.status)
777             LOG0("DONE\n")
779             break;
780 #endif
782           case LAD_EXIT:
783             goto exitNow;
785             break;
787           default:
788             LOG1("\nUnrecognized command: 0x%x\n", command)
790             break;
791         }
793         switch (command) {
794           case LAD_CONNECT:
795           case LAD_DISCONNECT:
796             break;
798           case LAD_RPROC_SETID:
799           case LAD_IPC_GETCONFIG:
800           case LAD_NAMESERVER_SETUP:
801           case LAD_NAMESERVER_DESTROY:
802           case LAD_NAMESERVER_PARAMS_INIT:
803           case LAD_NAMESERVER_CREATE:
804           case LAD_NAMESERVER_DELETE:
805           case LAD_NAMESERVER_ADD:
806           case LAD_NAMESERVER_GET:
807           case LAD_NAMESERVER_ADDUINT32:
808           case LAD_NAMESERVER_GETUINT32:
809           case LAD_NAMESERVER_GETLOCAL:
810           case LAD_NAMESERVER_GETLOCALUINT32:
811           case LAD_NAMESERVER_REMOVE:
812           case LAD_NAMESERVER_REMOVEENTRY:
813           case LAD_NAMESERVER_ATTACH:
814           case LAD_NAMESERVER_DETACH:
815           case LAD_MESSAGEQ_GETCONFIG:
816           case LAD_MESSAGEQ_SETUP:
817           case LAD_MESSAGEQ_DESTROY:
818           case LAD_MESSAGEQ_CREATE:
819           case LAD_MESSAGEQ_DELETE:
820           case LAD_MESSAGEQ_MSGINIT:
821           case LAD_MULTIPROC_GETCONFIG:
822 #if defined(GATEMP_SUPPORT)
823           case LAD_GATEMP_ATTACH:
824           case LAD_GATEMP_DETACH:
825           case LAD_GATEMP_START:
826           case LAD_GATEMP_GETNUMRESOURCES:
827           case LAD_GATEMP_GETFREERESOURCE:
828           case LAD_GATEMP_RELEASERESOURCE:
829           case LAD_GATEMP_ISSETUP:
830           case LAD_GATEHWSPINLOCK_GETCONFIG:
831 #endif
833             LOG0("Sending response...\n");
835             fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
836             fflush(responseFIFOFilePtr[clientId]);
838             break;
840           default:
841             break;
842         }
843     }
845 exitNow:
846 #if defined(GATEMP_SUPPORT)
847     if (gatempEnabled) {
848         GateMP_destroy();
849         NameServer_destroy();
850     }
851 #endif
852     if (logFile) {
853         LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
854         fclose(logPtr);
855     }
856     unlink(commandFIFOFile);
858     return(0);
863 /*
864  *  ======== assignClientId ========
865  */
866 static LAD_ClientHandle assignClientId(Void)
868     Int clientId = -1;
869     Int i;
871     /* scan connection status flags to acquire a clientId */
872     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
873         /* if slot open then provisionally select this clientId */
874         if (clientConnected[i] == FALSE) {
875              clientId = i;
876              break;
877         }
878     }
880     return(clientId);
884 /*
885  *  ======== cleanupDepartedClients ========
886  */
887 static Void cleanupDepartedClients(Void)
889     Int killStat;
890     Int i;
892     /* scan all connections to verify client processes still exist... */
893     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
895         /* if connected... */
896         if (clientConnected[i] == TRUE) {
898             /* check if the client process (PID) still exists */
899             /*
900              * NOTE - calling kill with signal value of 0 will perform
901              * error checking, but not actually send a signal.  Will use this
902              * error check to see if PID still exists.  An alternative was
903              * to call getpgid.  This worked, but is apparently limited to
904              * USE_XOPEN_EXTENDED configurations.
905              */
906             killStat = kill(clientPID[i], 0);
907             if ((killStat == -1) && (errno == ESRCH)) {
909                 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
911                 /* will always need to do the disconnect... */
912                 LOG0("\nDoing DISCONNECT on behalf of client...")
913                 doDisconnect(i);
915                 MessageQ_cleanupOwner(clientPID[i]);
916 //                NameServer_cleanupOwner(clientPID[i]);
918                 LOG0("DONE\n")
919             }
920         }
921     }
925 /*
926  *  ======== connectToLAD ========
927  */
928 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
930     Int clientId = -1;
931     Bool connectDenied = FALSE;
932     Int status = LAD_SUCCESS;
933     FILE * filePtr;
934     Int statusIO;
936     /*
937      * TODO:L here, and everywhere parse FIFO strings: should
938      * add full error checking for incomplete or corrupted
939      * strings? Since LAD to ladclient comms are "closed", and
940      * tested, the likelihood of problems seems very low.
941      * But should still consider doing full error checking
942      * and, hopefully, recovery.
943      */
944     LOG0("\nLAD_CONNECT: \n")
945     LOG1("    client FIFO name = %s\n", clientName)
946     LOG1("    client PID = %d\n", pid)
948     /* first check for proper communication protocol */
949     if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
951         /* if no match then reject the request */
952         LOG0("    ERROR: mismatch in communication protocol!\n")
953         LOG1("        LAD protocol = %s\n", LAD_PROTOCOLVERSION)
954         LOG1("        client protocol = %s\n", clientProto)
955         status = LAD_INVALIDVERSION;
957         /* set flag so know to close FIFO after response */
958         connectDenied = TRUE;
960         /* now jump forward a bit to send response */
961         goto openResponseFIFO;
962     }
964     /* determine this client's ID */
965     clientId = assignClientId();
967     /* if failed to acquire an ID then exit early */
968     if (clientId == -1) {
969         LOG0("    no free handle; too many connections!\n")
970         status = LAD_ACCESSDENIED;
972         /* set flag so know to close FIFO after response */
973         connectDenied = TRUE;
974     }
975     else {
976         LOG1("    assigned client handle = %d\n", clientId)
978         /* save the client's FIFO name for when disconnect */
979         strcpy(clientFIFOName[clientId], clientName);
980     }
982 openResponseFIFO:
984     /* if response FIFO exists from previous LAD session delete it now */
985     unlink(clientName);
987     /* create the dedicated response FIFO to the client */
988     statusIO = mkfifo(clientName, 0777);
989     if (statusIO != 0) {
991         LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
993         status = LAD_IOFAILURE;
995         /* send no response; connection request will timeout */
996         goto doneconnect;
997     }
999     LOG1("    FIFO %s created\n", clientName)
1001     /* set FIFO permissions to read/write */
1002     chmod(clientName, 0666);
1004     filePtr = fopen(clientName, "w");
1005     if (filePtr == NULL) {
1006         LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
1008         /* if failed open, still need to delete the FIFO */
1009         unlink(clientName);
1011         status = LAD_IOFAILURE;
1013         /* send no response; connection request will timeout */
1014         goto doneconnect;
1015     }
1017     LOG1("    FIFO %s opened for writing\n", clientName)
1019     /*
1020      * set "this client is connected" flag; this client ID is now "owned", and
1021      * is no longer provisional
1022      */
1023     if (connectDenied == FALSE) {
1024         responseFIFOFilePtr[clientId] = filePtr;
1025         clientPID[clientId] = pid;
1026         clientConnected[clientId] = TRUE;
1027     }
1029     rsp.connect.assignedId = clientId;
1030     rsp.status = status;
1032     /* put response to FIFO */
1033     fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1034     fflush(filePtr);
1036     LOG0("    sent response\n")
1038     /* if connection was denied, must now close FIFO */
1039     if (connectDenied == TRUE) {
1040         LOG1("    connect denied; closing FIFO %s\n", clientName)
1041         fclose(filePtr);
1042         unlink(clientName);
1043     }
1045     LOG0("DONE\n")
1047 doneconnect:
1048     if (clientIdPtr != NULL) {
1049         *clientIdPtr = clientId;
1050     }
1052     return(status);
1056 /*
1057  *  ======== disconnectFromLAD ========
1058  */
1059 static Void disconnectFromLAD(Int clientId)
1061     LOG0("\nLAD_DISCONNECT: ")
1063     LOG1("\n    client handle = %x", clientId)
1064     doDisconnect(clientId);
1066     LOG0("DONE\n")
1068     return;
1072 /*
1073  *  ======== doDisconnect ========
1074  */
1075 static Void doDisconnect(Int clientId)
1077     /* set "this client is not connected" flag */
1078     clientConnected[clientId] = FALSE;
1080     /* close and remove the response FIFO */
1081     LOG2("\n    closing FIFO %s (filePtr=%p)\n",
1082         clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1083     fclose(responseFIFOFilePtr[clientId]);
1085     LOG1("    done, unlinking %s\n", clientFIFOName[clientId]);
1086     unlink(clientFIFOName[clientId]);