Linux/Android: Refactor MessageQ_create to Register Later with NameServer
[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 <ctype.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <signal.h>
48 #include <unistd.h>
49 #include <dirent.h>
51 #include <ti/ipc/MessageQ.h>
52 #include <_MessageQ.h>
53 #include <ti/ipc/NameServer.h>
54 #include <_NameServer.h>
55 #include <ti/ipc/GateMP.h>
56 #include <_GateMP_daemon.h>
57 #include <_MultiProc.h>
59 #include <GateHWSpinlock.h>
61 #include <ladclient.h>
62 #include <_lad.h>
64 #define DAEMON        1           /* 1 = run as a daemon; 0 = run as app */
66 #define READ_BUF_SIZE 50
68 Bool logFile = FALSE;
69 FILE *logPtr = NULL;
70 struct timeval start_tv;
72 static String commandFIFOFile = LAD_COMMANDFIFO;
73 static FILE *commandFIFOFilePtr = NULL;
75 #if defined(GATEMP_SUPPORT)
76 static Bool gatempEnabled = FALSE;
77 #endif
79 /* LAD client info arrays */
80 static Bool clientConnected[LAD_MAXNUMCLIENTS];
81 static UInt clientPID[LAD_MAXNUMCLIENTS];
82 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
83 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
85 /* local internal routines */
86 static Bool isDaemonRunning(Char *pidName);
87 static LAD_ClientHandle assignClientId(Void);
88 static Void cleanupFifos(Void);
89 static Void cleanupDepartedClients(Void);
90 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
91 static Void disconnectFromLAD(Int clientId);
92 static Void doDisconnect(Int clientId);
94 struct LAD_CommandObj cmd;
95 union LAD_ResponseObj rsp;
97 #define LAD_USAGE "\
98 Usage:\n\
99     lad_<platform> [options] \n\
100 \n\
101 Options:\n\
102     h            : print this help message\n\
103     g            : enable GateMP support \n\
104     l <logfile>  : name of logfile for LAD\n\
105     n <nprocs>   : total number of processors in the system\n\
106     p <oct value>: set LAD's directory permissions\n\
107     r <nreserve> : number of reserved queues\n\
108     s <synctype> : type of Ipc_ProcSync (ALL|PAIR|NONE)\n\
109     b <value>    : Processor's base cluster id \n\
110 \n\
111 Examples:\n\
112     lad_<platform> -h\n\
113     lad_<platform> -l log.txt\n\
114     lad_<platform> -l log.txt -p 777\n\
115     lad_<platform> -g -l log.txt\n\
116     lad_<platform> -l log.txt -b 10\n\
117 \n"
119 /*
120  *  ======== main ========
121  */
122 int main(int argc, char * argv[])
124     MessageQ_Handle handle;
125     Ipc_Config ipcCfg;
126     UInt16 *procIdPtr;
127     Int statusIO;
128     Int clientId;
129     Int command;
130     Int flags;
131     Int i;
132     Int n;
133     Int c;
134 #if defined(GATEMP_SUPPORT)
135     Int status;
136     UInt16 procId;
137 #endif
138     String tmpString;
139 #if DAEMON
140     pid_t pid;
141     pid_t sid;
142 #endif
144     /* change to LAD's root directory */
145     if ((chdir(LAD_ROOTDIR)) < 0) {
146         /* if can't change directory assume it needs to be created, do it */
147         if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
148             fprintf(stderr,
149                     "\nERROR: Failed to create LAD's root directory!\n");
150             exit(EXIT_FAILURE);
151         }
152     }
154     if (isDaemonRunning(argv[0])) {
155         printf("Multiple instances of LAD are not supported!\n");
156         exit(EXIT_FAILURE);
157     }
159     /* change to LAD's working directory */
160     if ((chdir(LAD_WORKINGDIR)) < 0) {
162         /* if can't change directory assume it needs to be created, do it */
163         if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
164             fprintf(stderr,
165                     "\nERROR: Failed to create LAD's working directory!\n");
166             exit(EXIT_FAILURE);
167         }
168         /* now change to the new directory */
169         if ((chdir(LAD_WORKINGDIR)) < 0) {
170             fprintf(stderr,
171                     "\nERROR: Failed to change to LAD's working directory!\n");
172             exit(EXIT_FAILURE);
173         }
174     } else {
175         cleanupFifos();
176     }
178     /* process command line args */
179     while (1) {
180         c = getopt(argc, argv, "b:ghl:n:p:r:s:");
181         if (c == -1) {
182             break;
183         }
185         switch (c) {
186             case 'g':
187 #if defined(GATEMP_SUPPORT)
188                 printf("\nGateMP support enabled on host\n");
189                 gatempEnabled = TRUE;
190 #else
191                 printf("\nGateMP is not supported for this device\n");
192 #endif
193                 break;
194             case 'b':
195                 printf("\nSet LAD's base cluster id to %s\n", optarg);
196                 _MultiProc_cfg.id = atoi(optarg);
197                 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
198                 break;
199             case 'h':
200                 printf("%s", LAD_USAGE);
201                 exit(0);
202                 break;
203             case 'l':
204                 logPtr = fopen(optarg, "w");
205                 if (logPtr == NULL) {
206                     fprintf(stderr, "\nERROR: unable to open log file %s\n",
207                             optarg);
208                     exit(EXIT_FAILURE);
209                 }
210                 else {
211                     logFile = TRUE;
212                     gettimeofday(&start_tv, NULL);
213                     printf("\nOpened log file: %s\n", optarg);
214                     /* close log file upon LAD termination */
215                     flags = fcntl(fileno(logPtr), F_GETFD);
216                     if (flags != -1) {
217                         fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
218                     }
219                 }
220                 break;
221             case 'n':
222                 printf("\nSet LAD's number of processors to %s\n", optarg);
223                 _MultiProc_cfg.numProcessors = atoi(optarg);
224                 break;
225             case 'p':
226                 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
227                 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
228                 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
229                 break;
230             case 'r':
231                 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
232                 _MessageQ_setNumReservedEntries(atoi(optarg));
233                 break;
234             case 's':
235                 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
236                        optarg);
238                 Ipc_getConfig(&ipcCfg);
240                 if (!strcmp(optarg, "ALL")) {
241                     ipcCfg.procSync = Ipc_ProcSync_ALL;
242                 }
243                 else if (!strcmp(optarg, "PAIR")) {
244                     ipcCfg.procSync = Ipc_ProcSync_PAIR;
245                 }
246                 else if (!strcmp(optarg, "NONE")) {
247                     ipcCfg.procSync = Ipc_ProcSync_NONE;
248                 }
249                 else {
250                     fprintf(stderr,
251                             "Error: bad synchronization specified, must be "
252                             "ALL|PAIR|NONE\n");
253                     exit(EXIT_FAILURE);
254                 }
256                 Ipc_setConfig(&ipcCfg);
257                 break;
258             default:
259                 fprintf (stderr, "\nUnrecognized argument\n");
260                 exit(EXIT_FAILURE);
261         }
262     }
264     /* Check to ensure id and baseId are not invalid */
265     printf ("\nnumProcessors = %d id = %d baseId = %d\n",
266             _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
267             _MultiProc_cfg.baseIdOfCluster);
269     if (_MultiProc_cfg.id == 0xFFFF ||
270         _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
271          fprintf(stderr, "\nBase cluster id is set to an INVALID value\n");
272          fprintf(stderr,
273                  "Use -b option to set value or modify the MultiProcCfg file\n"
274                 );
275          exit(EXIT_FAILURE);
276     }
277     if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
278         _MultiProc_cfg.numProcessors) {
279         fprintf(stderr,
280                 "\nNumber of processors (%d) must be >= base cluster id + "
281                 "number of processors in cluster (%d + %d)\n",
282                 _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
283                 _MultiProc_cfg.numProcsInCluster);
284         exit(EXIT_FAILURE);
285     }
288 #if DAEMON
289     /* fork off a child process */
290     pid = fork();
292     /* if fork of child failed then exit immediately; no child created */
293     if (pid < 0) {
294         fprintf(stderr, "\nERROR: Failed to fork child process!");
295         exit(EXIT_FAILURE);
296     }
298     /* if pid > 0 this is the parent; time to die ... */
299     if (pid > 0) {
300         printf("\nSpawned daemon: %s\n\n", argv[0]);
301         exit(EXIT_SUCCESS);
302     }
304     /* child continues from here (pid == 0) ... */
306     /* change file mode mask */
307     umask(0);
309     /* create new session ID for the child */
310     sid = setsid();
312     /* exit with failure code if failed to get session ID... */
313     if (sid < 0) {
314         fprintf(stderr, "\nERROR: Failed to acquire new session ID!");
315         exit(EXIT_FAILURE);
316     }
318     /* disassociate from the standard file descriptors */
319     close(STDIN_FILENO);
320     close(STDOUT_FILENO);
321     close(STDERR_FILENO);
323 #endif
325     LOG0("\nInitializing LAD... ")
327     /* TODO:L make sure LAD is not already running? */
329     /* initialize client info arrays */
330     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
331         clientConnected[i] = FALSE;
332         responseFIFOFilePtr[i] = NULL;
333     }
335     /* if command FIFO exists from previous LAD session delete it now */
336     unlink(commandFIFOFile);
338     /* create command FIFO */
339     statusIO = mkfifo(commandFIFOFile, 0777);
340     if (statusIO != 0) {
341         LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
342             errno)
343         return(0);
344     }
346     /* set FIFO permissions to read/write */
347     chmod(commandFIFOFile, 0666);
349     /* Setup modules relevant for GateMP if necessary */
350 #if defined(GATEMP_SUPPORT)
351     if (gatempEnabled) {
352         /* Set up NameServer for resource manager process */
353         status = NameServer_setup();
354         if (status < 0) {
355             LOG0("\nERROR: unable to setup NameServer\n")
356             return(0);
357         }
359         status = GateHWSpinlock_start();
360         if (status < 0) {
361             LOG0("\nERROR: unable to start GateHWSpinlock\n");
362             return(0);
363         }
365         /* Set up GateMP */
366         status = GateMP_setup();
367         if (status < 0) {
368             LOG0("\nERROR: unable to setup GateMP\n")
369             NameServer_destroy();
370             return(0);
371         }
372     }
373 #endif
375 opencommandFIFO:
377     /* now open file for FIFO - will block until writer arrives... */
378     LOG1("\n    opening FIFO: %s\n", commandFIFOFile)
379     commandFIFOFilePtr = fopen(commandFIFOFile, "r");
380     if (commandFIFOFilePtr == NULL) {
381         LOG0("\nERROR: unable to open command FIFO\n")
382         unlink(commandFIFOFile);
383 #if defined(GATEMP_SUPPORT)
384         if (gatempEnabled) {
385             GateMP_destroy();
386             NameServer_destroy();
387         }
388 #endif
389         return(0);
390     }
392     /* COMMAND PROCESSING LOOP */
393     while (1) {
394         LOG0("Retrieving command...\n")
396         /* read the next command packet */
397         n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
399         /*
400          * if last client closes FIFO then it must be closed and reopened ...
401          */
402         if (!n) {
403             LOG1("   EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
404             fclose(commandFIFOFilePtr);
406             goto opencommandFIFO;
407         }
409         /* cleanup for any connected/started clients that have departed */
410         cleanupDepartedClients();
412         command = cmd.cmd;
413         clientId = cmd.clientId;
415         /* process individual commands */
416         switch (command) {
417           /*
418            * Since cmd is a union of rcv and snd structs, don't write
419            * any snd elements before all rcv elements have been referenced
420            * (either saved in separate variables or passed to a function).
421            *
422            * cmd.cmd has already been saved in 'command'
423            * cmd.clientId has already been saved in 'clientId'
424            */
425           case LAD_CONNECT:
426             connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
427                          cmd.args.connect.protocol, NULL);
429             break;
431           case LAD_DISCONNECT:
432             disconnectFromLAD(clientId);
434             break;
436           case LAD_IPC_GETCONFIG:
437             Ipc_getConfig(&rsp.ipcConfig);
438             break;
440           case LAD_NAMESERVER_SETUP:
441             LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
443             rsp.status = NameServer_setup();
445             LOG1("    status = %d\n", rsp.status)
446             LOG0("DONE\n")
448             break;
450           case LAD_NAMESERVER_DESTROY:
451             LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
453             rsp.status = NameServer_destroy();
455             LOG1("    status = %d\n", rsp.status)
456             LOG0("DONE\n")
458             break;
460           case LAD_NAMESERVER_PARAMS_INIT:
461             LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
463             NameServer_Params_init(&rsp.params);
465             LOG0("DONE\n")
467             break;
469           case LAD_NAMESERVER_CREATE:
470             LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
472             rsp.handle = NameServer_create(cmd.args.create.name,
473                                                &cmd.args.create.params);
475             LOG1("    handle = %p\n", rsp.handle)
476             LOG0("DONE\n")
478             break;
480           case LAD_NAMESERVER_DELETE:
481             LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
482                     cmd.args.nsdelete.handle)
484             rsp.nsdelete.handle = cmd.args.nsdelete.handle;
485             rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
487             LOG1("    status = %d\n", rsp.nsdelete.status)
488             LOG0("DONE\n")
490             break;
492           case LAD_NAMESERVER_ADD:
493             LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
494             LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
495             LOG1(" 0x%x)...\n", cmd.args.add.len)
497             rsp.entryPtr = NameServer_add(
498                 cmd.args.add.handle,
499                 cmd.args.add.name,
500                 cmd.args.add.buf,
501                 cmd.args.add.len);
503             LOG1("    entryPtr = %p\n", rsp.entryPtr)
504             LOG0("DONE\n")
506             break;
508           case LAD_NAMESERVER_GET:
509             LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
510                     cmd.args.get.handle, cmd.args.get.name)
511             LOG0(")...\n")
513             if (cmd.args.get.procId[0] == (UInt16)-1) {
514                 procIdPtr = NULL;
515             }
516             else {
517                 procIdPtr = cmd.args.get.procId;
518             }
519             rsp.get.status = NameServer_get(
520                 cmd.args.get.handle,
521                 cmd.args.get.name,
522                 rsp.get.buf,
523                 &cmd.args.get.len,
524                 procIdPtr);
525             rsp.get.len = cmd.args.get.len;
527             LOG1("    value = 0x%x\n", rsp.get.len)
528             LOG1("    status = %d\n", rsp.get.status)
529             LOG0("DONE\n")
531             break;
533           case LAD_NAMESERVER_ADDUINT32:
534             LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
535                     "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
536                     cmd.args.addUInt32.name, cmd.args.addUInt32.val)
538             rsp.entryPtr = NameServer_addUInt32(
539                 cmd.args.addUInt32.handle,
540                 cmd.args.addUInt32.name,
541                 cmd.args.addUInt32.val);
543             LOG1("    entryPtr = %p\n", rsp.entryPtr)
544             LOG0("DONE\n")
546             break;
548           case LAD_NAMESERVER_GETUINT32:
549             LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
550                     "(%p, '%s')...\n", cmd.args.getUInt32.handle,
551                     cmd.args.getUInt32.name)
553             if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
554                 procIdPtr = NULL;
555             }
556             else {
557                 procIdPtr = cmd.args.getUInt32.procId;
558             }
559             rsp.getUInt32.status = NameServer_getUInt32(
560                 cmd.args.getUInt32.handle,
561                 cmd.args.getUInt32.name,
562                 &rsp.getUInt32.val,
563                 procIdPtr);
565             LOG1("    value = 0x%x\n", rsp.getUInt32.val)
566             LOG1("    status = %d\n", rsp.getUInt32.status)
567             LOG0("DONE\n")
569             break;
571           case LAD_NAMESERVER_GETLOCAL:
572             rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
573                 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
574             rsp.get.len = cmd.args.getLocal.len;
575             break;
577           case LAD_NAMESERVER_GETLOCALUINT32:
578             rsp.getUInt32.status = NameServer_getLocalUInt32(
579                 cmd.args.getLocalUInt32.handle,
580                 cmd.args.getLocalUInt32.name,
581                 &rsp.getUInt32.val);
582             break;
584           case LAD_NAMESERVER_REMOVE:
585             LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
587             rsp.status = NameServer_remove(cmd.args.remove.handle,
588                                                cmd.args.remove.name);
590             LOG1("    status = %d\n", rsp.status)
591             LOG0("DONE\n")
593             break;
595           case LAD_NAMESERVER_REMOVEENTRY:
596             LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
598             rsp.status = NameServer_removeEntry(
599                 cmd.args.removeEntry.handle,
600                 cmd.args.removeEntry.entryPtr);
602             LOG1("    status = %d\n", rsp.status)
603             LOG0("DONE\n")
605             break;
607           case LAD_NAMESERVER_ATTACH:
608             rsp.status = NameServer_attach(cmd.args.attach.procId);
609             break;
611           case LAD_NAMESERVER_DETACH:
612             rsp.status = NameServer_detach(cmd.args.detach.procId);
613             break;
615           case LAD_MESSAGEQ_GETCONFIG:
616             LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
618             MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
619             rsp.messageQGetConfig.status = 0;
621             LOG1("    status = %d\n", rsp.messageQGetConfig.status)
622             LOG0("DONE\n")
624             break;
626           case LAD_MESSAGEQ_SETUP:
627             LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
629             rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
630             rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
632             LOG1("    status = %d\n", rsp.setup.status)
633             LOG0("DONE\n")
635             break;
637           case LAD_MESSAGEQ_DESTROY:
638             LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
640             rsp.status = MessageQ_destroy();
642             LOG1("    status = %d\n", rsp.status)
643             LOG0("DONE\n")
645             break;
647           case LAD_MESSAGEQ_CREATE:
648             LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
649                     cmd.args.messageQCreate.name,
650                     &cmd.args.messageQCreate.params);
652             tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
653                 cmd.args.messageQCreate.name;
655             handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
656             rsp.messageQCreate.serverHandle = handle;
658             if (handle) {
659                 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
660                 MessageQ_setQueueOwner(handle, clientPID[clientId]);
661                 rsp.messageQCreate.status = 0;
662             }
663             else {
664                 rsp.messageQCreate.status = -1;
665             }
667             LOG1("    status = %d\n", rsp.messageQCreate.status)
668             LOG0("DONE\n")
670             break;
672           case LAD_MESSAGEQ_ANNOUNCE:
673             LOG2("LAD_MESSAGEQ_ANNOUNCE: calling MessageQ_announce(%p, %p)...\n",
674                     cmd.args.messageQAnnounce.name,
675                     cmd.args.messageQAnnounce.serverHandle);
677             tmpString = (cmd.args.messageQAnnounce.name[0] == '\0') ? NULL :
678                 cmd.args.messageQAnnounce.name;
680             rsp.messageQAnnounce.status =
681                 MessageQ_announce(tmpString, (MessageQ_Handle *)&cmd.args.messageQAnnounce.serverHandle);
683             LOG1("    status = %d\n", rsp.messageQAnnounce.status)
684             LOG0("DONE\n")
686             break;
687           case LAD_MESSAGEQ_DELETE:
688             LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
690             rsp.messageQDelete.status =
691                 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
693             LOG1("    status = %d\n", rsp.messageQDelete.status)
694             LOG0("DONE\n")
696             break;
698           case LAD_MESSAGEQ_MSGINIT:
699             LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
701             MessageQ_msgInit(&rsp.msgInit.msg);
702             rsp.msgInit.status = 0;
704             LOG1("    status = %d\n", rsp.msgInit.status)
705             LOG0("DONE\n")
707             break;
709           case LAD_MULTIPROC_GETCONFIG:
710             LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
712             MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
713             rsp.multiprocGetConfig.status = 0;
715             LOG1("    status = %d\n", rsp.multiprocGetConfig.status)
716             LOG0("DONE\n")
718             break;
720 #if defined(GATEMP_SUPPORT)
721           case LAD_GATEMP_ATTACH:
722             procId = cmd.args.attach.procId;
723             LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
725             rsp.status = GateMP_attach(procId);
727             LOG1("    status = %d\n", rsp.status)
728             LOG0("DONE\n")
730             break;
732           case LAD_GATEMP_DETACH:
733             procId = cmd.args.detach.procId;
734             LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
736             rsp.status = GateMP_detach(procId);
738             LOG1("    status = %d\n", rsp.status)
739             LOG0("DONE\n")
741             break;
743           case LAD_GATEMP_START:
744             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
746             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
747             rsp.gateMPStart.status = GateMP_S_SUCCESS;
749             LOG1("    status = %d\n", rsp.gateMPStart.status)
750             LOG0("DONE\n")
752             break;
754           case LAD_GATEMP_GETNUMRESOURCES:
755             LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
757             rsp.gateMPGetNumResources.value = GateMP_getNumResources(
758                                           cmd.args.gateMPGetNumResources.type);
759             rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
761             LOG1("    status = %d\n", rsp.gateMPGetNumResources.status)
762             LOG0("DONE\n")
764             break;
766           case LAD_GATEMP_GETFREERESOURCE:
767             LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
769             rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
770                                           cmd.args.gateMPGetFreeResource.type);
771             rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
773             LOG1("    status = %d\n", rsp.gateMPGetFreeResource.status)
774             LOG0("DONE\n")
776             break;
778           case LAD_GATEMP_RELEASERESOURCE:
779             LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
781             rsp.gateMPReleaseResource.status = GateMP_releaseResource(
782                                           cmd.args.gateMPReleaseResource.id,
783                                           cmd.args.gateMPReleaseResource.type);
785             LOG1("    status = %d\n", rsp.gateMPReleaseResource.status)
786             LOG0("DONE\n")
788             break;
790           case LAD_GATEMP_ISSETUP:
791             LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
793             rsp.gateMPIsSetup.result = GateMP_isSetup();
794             rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
796             LOG1("    status = %d\n", rsp.gateMPIsSetup.status)
797             LOG0("DONE\n")
799             break;
801           case LAD_GATEHWSPINLOCK_GETCONFIG:
802             LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
804             GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
805             rsp.gateHWSpinlockGetConfig.status = 0;
807             LOG1("    status = %d\n", rsp.gateHWSpinlockGetConfig.status)
808             LOG0("DONE\n")
810             break;
811 #endif
813           case LAD_EXIT:
814             goto exitNow;
816             break;
818           default:
819             LOG1("\nUnrecognized command: 0x%x\n", command)
821             break;
822         }
824         switch (command) {
825           case LAD_CONNECT:
826           case LAD_DISCONNECT:
827             break;
829           case LAD_IPC_GETCONFIG:
830           case LAD_NAMESERVER_SETUP:
831           case LAD_NAMESERVER_DESTROY:
832           case LAD_NAMESERVER_PARAMS_INIT:
833           case LAD_NAMESERVER_CREATE:
834           case LAD_NAMESERVER_DELETE:
835           case LAD_NAMESERVER_ADD:
836           case LAD_NAMESERVER_GET:
837           case LAD_NAMESERVER_ADDUINT32:
838           case LAD_NAMESERVER_GETUINT32:
839           case LAD_NAMESERVER_GETLOCAL:
840           case LAD_NAMESERVER_GETLOCALUINT32:
841           case LAD_NAMESERVER_REMOVE:
842           case LAD_NAMESERVER_REMOVEENTRY:
843           case LAD_NAMESERVER_ATTACH:
844           case LAD_NAMESERVER_DETACH:
845           case LAD_MESSAGEQ_GETCONFIG:
846           case LAD_MESSAGEQ_SETUP:
847           case LAD_MESSAGEQ_DESTROY:
848           case LAD_MESSAGEQ_CREATE:
849           case LAD_MESSAGEQ_ANNOUNCE:
850           case LAD_MESSAGEQ_DELETE:
851           case LAD_MESSAGEQ_MSGINIT:
852           case LAD_MULTIPROC_GETCONFIG:
853 #if defined(GATEMP_SUPPORT)
854           case LAD_GATEMP_ATTACH:
855           case LAD_GATEMP_DETACH:
856           case LAD_GATEMP_START:
857           case LAD_GATEMP_GETNUMRESOURCES:
858           case LAD_GATEMP_GETFREERESOURCE:
859           case LAD_GATEMP_RELEASERESOURCE:
860           case LAD_GATEMP_ISSETUP:
861           case LAD_GATEHWSPINLOCK_GETCONFIG:
862 #endif
864             LOG0("Sending response...\n");
866             fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
867             fflush(responseFIFOFilePtr[clientId]);
869             break;
871           default:
872             break;
873         }
874     }
876 exitNow:
877 #if defined(GATEMP_SUPPORT)
878     if (gatempEnabled) {
879         GateMP_destroy();
880         NameServer_destroy();
881     }
882 #endif
883     if (logFile) {
884         LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
885         fclose(logPtr);
886     }
887     unlink(commandFIFOFile);
889     return(0);
894 /*
895  *  ======== isDaemonRunning ========
896  */
897 static Bool isDaemonRunning(Char *pidName)
899     DIR *dir;
900     pid_t pid;
901     Int dirNum;
902     FILE *fp;
903     struct dirent * next;
904     Bool isRunning = FALSE;
905     Char filename [READ_BUF_SIZE];
906     Char buffer [READ_BUF_SIZE];
907     Char *bptr = buffer;
908     Char *name;
910     pid = getpid();
911     dir = opendir("/proc");
912     if (!dir) {
913         printf("Warning: Cannot open /proc filesystem\n");
914         return isRunning;
915     }
917     name = strrchr(pidName, '/');
918     if (name) {
919         pidName = (name + 1);
920     }
922     while ((next = readdir(dir)) != NULL) {
923         /* If it isn't a number, we don't want it */
924         if (!isdigit(*next->d_name)) {
925             continue;
926         }
928         dirNum = strtol(next->d_name, NULL, 10);
929         if (dirNum == pid) {
930             continue;
931         }
933         snprintf(filename, READ_BUF_SIZE, "/proc/%s/cmdline", next->d_name);
934         if (!(fp = fopen(filename, "r"))) {
935             continue;
936         }
937         if (fgets(buffer, READ_BUF_SIZE, fp) == NULL) {
938             fclose(fp);
939             continue;
940         }
941         fclose (fp);
943         name = strrchr(buffer, '/');
944         if (name && (name + 1)) {
945             bptr = name + 1;
946         }
947         else {
948             bptr = buffer;
949         }
951         /* Buffer should contain the entire command line */
952         if (strcmp(bptr, pidName) == 0) {
953             isRunning = TRUE;
954             break;
955         }
956     }
957     closedir (dir);
959     return isRunning;
962 /*
963  *  ======== assignClientId ========
964  */
965 static LAD_ClientHandle assignClientId(Void)
967     Int clientId = -1;
968     Int i;
970     /* scan connection status flags to acquire a clientId */
971     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
972         /* if slot open then provisionally select this clientId */
973         if (clientConnected[i] == FALSE) {
974              clientId = i;
975              break;
976         }
977     }
979     return(clientId);
982 /*
983  *  ======== cleanupFifos ========
984  */
985 static void cleanupFifos(Void)
987     DIR *dir;
988     struct dirent entry;
989     struct dirent *result;
990     size_t dirnamelen;
991     size_t maxcopy;
992     Char pathname[PATH_MAX];
993     Char *namep;
995     if ((dir = opendir(LAD_WORKINGDIR)) == NULL)
996         return;
998     dirnamelen = snprintf(pathname, sizeof(pathname), "%s/", LAD_WORKINGDIR);
999     if (dirnamelen >= sizeof(pathname)) {
1000         closedir(dir);
1001         return;
1002     }
1003     namep = pathname + dirnamelen;
1004     maxcopy = PATH_MAX - dirnamelen;
1005     while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
1006         /* Delete old FIFOs left over */
1007         if ((entry.d_type == DT_FIFO) && (strlen(entry.d_name) < maxcopy)) {
1008             strncpy(namep, entry.d_name, maxcopy);
1009             unlink(pathname);
1010         }
1011     }
1012     closedir(dir);
1015 /*
1016  *  ======== cleanupDepartedClients ========
1017  */
1018 static Void cleanupDepartedClients(Void)
1020     Int killStat;
1021     Int i;
1023     /* scan all connections to verify client processes still exist... */
1024     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
1026         /* if connected... */
1027         if (clientConnected[i] == TRUE) {
1029             /* check if the client process (PID) still exists */
1030             /*
1031              * NOTE - calling kill with signal value of 0 will perform
1032              * error checking, but not actually send a signal.  Will use this
1033              * error check to see if PID still exists.  An alternative was
1034              * to call getpgid.  This worked, but is apparently limited to
1035              * USE_XOPEN_EXTENDED configurations.
1036              */
1037             killStat = kill(clientPID[i], 0);
1038             if ((killStat == -1) && (errno == ESRCH)) {
1040                 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
1042                 /* will always need to do the disconnect... */
1043                 LOG0("\nDoing DISCONNECT on behalf of client...")
1044                 doDisconnect(i);
1046                 MessageQ_cleanupOwner(clientPID[i]);
1047 //                NameServer_cleanupOwner(clientPID[i]);
1049                 LOG0("DONE\n")
1050             }
1051         }
1052     }
1056 /*
1057  *  ======== connectToLAD ========
1058  */
1059 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
1061     Int clientId = -1;
1062     Bool connectDenied = FALSE;
1063     Int status = LAD_SUCCESS;
1064     FILE * filePtr;
1065     Int statusIO;
1067     /*
1068      * TODO:L here, and everywhere parse FIFO strings: should
1069      * add full error checking for incomplete or corrupted
1070      * strings? Since LAD to ladclient comms are "closed", and
1071      * tested, the likelihood of problems seems very low.
1072      * But should still consider doing full error checking
1073      * and, hopefully, recovery.
1074      */
1075     LOG0("\nLAD_CONNECT: \n")
1076     LOG1("    client FIFO name = %s\n", clientName)
1077     LOG1("    client PID = %d\n", pid)
1079     /* first check for proper communication protocol */
1080     if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
1082         /* if no match then reject the request */
1083         LOG0("    ERROR: mismatch in communication protocol!\n")
1084         LOG1("        LAD protocol = %s\n", LAD_PROTOCOLVERSION)
1085         LOG1("        client protocol = %s\n", clientProto)
1086         status = LAD_INVALIDVERSION;
1088         /* set flag so know to close FIFO after response */
1089         connectDenied = TRUE;
1091         /* now jump forward a bit to send response */
1092         goto openResponseFIFO;
1093     }
1095     /* determine this client's ID */
1096     clientId = assignClientId();
1098     /* if failed to acquire an ID then exit early */
1099     if (clientId == -1) {
1100         LOG0("    no free handle; too many connections!\n")
1101         status = LAD_ACCESSDENIED;
1103         /* set flag so know to close FIFO after response */
1104         connectDenied = TRUE;
1105     }
1106     else {
1107         LOG1("    assigned client handle = %d\n", clientId)
1109         /* save the client's FIFO name for when disconnect */
1110         strcpy(clientFIFOName[clientId], clientName);
1111     }
1113 openResponseFIFO:
1115     /* create the dedicated response FIFO to the client */
1116     statusIO = mkfifo(clientName, 0777);
1117     if (statusIO != 0) {
1119         LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
1121         status = LAD_IOFAILURE;
1123         /* send no response; connection request will timeout */
1124         goto doneconnect;
1125     }
1127     LOG1("    FIFO %s created\n", clientName)
1129     /* set FIFO permissions to read/write */
1130     chmod(clientName, 0666);
1132     filePtr = fopen(clientName, "w");
1133     if (filePtr == NULL) {
1134         LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
1136         /* if failed open, still need to delete the FIFO */
1137         unlink(clientName);
1139         status = LAD_IOFAILURE;
1141         /* send no response; connection request will timeout */
1142         goto doneconnect;
1143     }
1145     LOG1("    FIFO %s opened for writing\n", clientName)
1147     /*
1148      * set "this client is connected" flag; this client ID is now "owned", and
1149      * is no longer provisional
1150      */
1151     if (connectDenied == FALSE) {
1152         responseFIFOFilePtr[clientId] = filePtr;
1153         clientPID[clientId] = pid;
1154         clientConnected[clientId] = TRUE;
1155     }
1157     rsp.connect.assignedId = clientId;
1158     rsp.status = status;
1160     /* put response to FIFO */
1161     fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1162     fflush(filePtr);
1164     LOG0("    sent response\n")
1166     /* if connection was denied, must now close FIFO */
1167     if (connectDenied == TRUE) {
1168         LOG1("    connect denied; closing FIFO %s\n", clientName)
1169         fclose(filePtr);
1170         unlink(clientName);
1171     }
1173     LOG0("DONE\n")
1175 doneconnect:
1176     if (clientIdPtr != NULL) {
1177         *clientIdPtr = clientId;
1178     }
1180     return(status);
1184 /*
1185  *  ======== disconnectFromLAD ========
1186  */
1187 static Void disconnectFromLAD(Int clientId)
1189     LOG0("\nLAD_DISCONNECT: ")
1191     LOG1("\n    client handle = %x", clientId)
1192     doDisconnect(clientId);
1194     LOG0("DONE\n")
1196     return;
1200 /*
1201  *  ======== doDisconnect ========
1202  */
1203 static Void doDisconnect(Int clientId)
1205     /* set "this client is not connected" flag */
1206     clientConnected[clientId] = FALSE;
1208     /* close and remove the response FIFO */
1209     LOG2("\n    closing FIFO %s (filePtr=%p)\n",
1210         clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1211     fclose(responseFIFOFilePtr[clientId]);
1213     LOG1("    done, unlinking %s\n", clientFIFOName[clientId]);
1214     unlink(clientFIFOName[clientId]);