]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/lad.c
lad: Add Timeout waiting for Response FIFO
[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>
50 #include <time.h>
52 #include <ti/ipc/MessageQ.h>
53 #include <_MessageQ.h>
54 #include <ti/ipc/NameServer.h>
55 #include <_NameServer.h>
56 #include <ti/ipc/GateMP.h>
57 #include <_GateMP_daemon.h>
58 #include <_MultiProc.h>
60 #include <GateHWSpinlock.h>
62 #include <ladclient.h>
63 #include <_lad.h>
65 #ifndef DAEMON
66 #define DAEMON        1           /* 1 = run as a daemon; 0 = run as app */
67 #endif
69 #define READ_BUF_SIZE 50
71 Bool logFile = FALSE;
72 FILE *logPtr = NULL;
73 struct timeval start_tv;
75 static String commandFIFOFile = LAD_COMMANDFIFO;
76 static FILE *commandFIFOFilePtr = NULL;
78 #if defined(GATEMP_SUPPORT)
79 static Bool gatempEnabled = FALSE;
80 #endif
82 /* LAD client info arrays */
83 static Bool clientConnected[LAD_MAXNUMCLIENTS];
84 static UInt clientPID[LAD_MAXNUMCLIENTS];
85 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
86 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
88 /* local internal routines */
89 static Bool isDaemonRunning(Char *pidName);
90 static LAD_ClientHandle assignClientId(Void);
91 static Void cleanupFifos(Void);
92 static Void cleanupDepartedClients(Void);
93 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
94 static Void disconnectFromLAD(Int clientId);
95 static Void doDisconnect(Int clientId);
97 struct LAD_CommandObj cmd;
98 union LAD_ResponseObj rsp;
100 #define LAD_USAGE "\
101 Usage:\n\
102     lad_<platform> [options] \n\
103 \n\
104 Options:\n\
105     h            : print this help message\n\
106     g            : enable GateMP support \n\
107     l <logfile>  : name of logfile for LAD\n\
108     n <nprocs>   : total number of processors in the system\n\
109     p <oct value>: set LAD's directory permissions\n\
110     r <nreserve> : number of reserved queues\n\
111     s <synctype> : type of Ipc_ProcSync (ALL|PAIR|NONE)\n\
112     b <value>    : Processor's base cluster id \n\
113 \n\
114 Examples:\n\
115     lad_<platform> -h\n\
116     lad_<platform> -l log.txt\n\
117     lad_<platform> -l log.txt -p 777\n\
118     lad_<platform> -g -l log.txt\n\
119     lad_<platform> -l log.txt -b 10\n\
120 \n"
122 /*
123  *  ======== main ========
124  */
125 int main(int argc, char * argv[])
127     MessageQ_Handle handle;
128     Ipc_Config ipcCfg;
129     UInt16 *procIdPtr;
130     Int statusIO;
131     Int clientId;
132     Int command;
133     Int flags;
134     Int i;
135     Int n;
136     Int c;
137 #if defined(GATEMP_SUPPORT)
138     Int status;
139     UInt16 procId;
140 #endif
141     String tmpString;
142 #if DAEMON
143     pid_t pid;
144     pid_t sid;
145 #endif
147     /* change to LAD's root directory */
148     if ((chdir(LAD_ROOTDIR)) < 0) {
149         /* if can't change directory assume it needs to be created, do it */
150         if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
151             fprintf(stderr,
152                     "\nERROR: Failed to create LAD's root directory!\n");
153             exit(EXIT_FAILURE);
154         }
155     }
157 #ifndef IPC_BUILDOS_ANDROID
158     if (isDaemonRunning(argv[0])) {
159         printf("Multiple instances of LAD are not supported!\n");
160         exit(EXIT_FAILURE);
161     }
162 #endif
164     /* change to LAD's working directory */
165     if ((chdir(LAD_WORKINGDIR)) < 0) {
167         /* if can't change directory assume it needs to be created, do it */
168         if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
169             fprintf(stderr,
170                     "\nERROR: Failed to create LAD's working directory!\n");
171             exit(EXIT_FAILURE);
172         }
173         /* now change to the new directory */
174         if ((chdir(LAD_WORKINGDIR)) < 0) {
175             fprintf(stderr,
176                     "\nERROR: Failed to change to LAD's working directory!\n");
177             exit(EXIT_FAILURE);
178         }
179     } else {
180         cleanupFifos();
181     }
183     /* process command line args */
184     while (1) {
185         c = getopt(argc, argv, "b:ghl:n:p:r:s:");
186         if (c == -1) {
187             break;
188         }
190         switch (c) {
191             case 'g':
192 #if defined(GATEMP_SUPPORT)
193                 printf("\nGateMP support enabled on host\n");
194                 gatempEnabled = TRUE;
195 #else
196                 printf("\nGateMP is not supported for this device\n");
197 #endif
198                 break;
199             case 'b':
200                 printf("\nSet LAD's base cluster id to %s\n", optarg);
201                 _MultiProc_cfg.id = atoi(optarg);
202                 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
203                 break;
204             case 'h':
205                 printf("%s", LAD_USAGE);
206                 exit(0);
207                 break;
208             case 'l':
209                 logPtr = fopen(optarg, "w");
210                 if (logPtr == NULL) {
211                     fprintf(stderr, "\nERROR: unable to open log file %s\n",
212                             optarg);
213                     exit(EXIT_FAILURE);
214                 }
215                 else {
216                     logFile = TRUE;
217                     gettimeofday(&start_tv, NULL);
218                     printf("\nOpened log file: %s\n", optarg);
219                     /* close log file upon LAD termination */
220                     flags = fcntl(fileno(logPtr), F_GETFD);
221                     if (flags != -1) {
222                         fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
223                     }
224                 }
225                 break;
226             case 'n':
227                 printf("\nSet LAD's number of processors to %s\n", optarg);
228                 _MultiProc_cfg.numProcessors = atoi(optarg);
229                 break;
230             case 'p':
231                 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
232                 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
233                 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
234                 break;
235             case 'r':
236                 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
237                 _MessageQ_setNumReservedEntries(atoi(optarg));
238                 break;
239             case 's':
240                 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
241                        optarg);
243                 Ipc_getConfig(&ipcCfg);
245                 if (!strcmp(optarg, "ALL")) {
246                     ipcCfg.procSync = Ipc_ProcSync_ALL;
247                 }
248                 else if (!strcmp(optarg, "PAIR")) {
249                     ipcCfg.procSync = Ipc_ProcSync_PAIR;
250                 }
251                 else if (!strcmp(optarg, "NONE")) {
252                     ipcCfg.procSync = Ipc_ProcSync_NONE;
253                 }
254                 else {
255                     fprintf(stderr,
256                             "Error: bad synchronization specified, must be "
257                             "ALL|PAIR|NONE\n");
258                     exit(EXIT_FAILURE);
259                 }
261                 Ipc_setConfig(&ipcCfg);
262                 break;
263             default:
264                 fprintf (stderr, "\nUnrecognized argument\n");
265                 exit(EXIT_FAILURE);
266         }
267     }
269     /* Check to ensure id and baseId are not invalid */
270     printf ("\nnumProcessors = %d id = %d baseId = %d\n",
271             _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
272             _MultiProc_cfg.baseIdOfCluster);
274     if (_MultiProc_cfg.id == 0xFFFF ||
275         _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
276          fprintf(stderr, "\nBase cluster id is set to an INVALID value\n");
277          fprintf(stderr,
278                  "Use -b option to set value or modify the MultiProcCfg file\n"
279                 );
280          exit(EXIT_FAILURE);
281     }
282     if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
283         _MultiProc_cfg.numProcessors) {
284         fprintf(stderr,
285                 "\nNumber of processors (%d) must be >= base cluster id + "
286                 "number of processors in cluster (%d + %d)\n",
287                 _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
288                 _MultiProc_cfg.numProcsInCluster);
289         exit(EXIT_FAILURE);
290     }
293 #if DAEMON
294     /* fork off a child process */
295     pid = fork();
297     /* if fork of child failed then exit immediately; no child created */
298     if (pid < 0) {
299         fprintf(stderr, "\nERROR: Failed to fork child process!");
300         exit(EXIT_FAILURE);
301     }
303     /* if pid > 0 this is the parent; time to die ... */
304     if (pid > 0) {
305         printf("\nSpawned daemon: %s\n\n", argv[0]);
306         exit(EXIT_SUCCESS);
307     }
309     /* child continues from here (pid == 0) ... */
311     /* change file mode mask */
312     umask(0);
314     /* create new session ID for the child */
315     sid = setsid();
317     /* exit with failure code if failed to get session ID... */
318     if (sid < 0) {
319         fprintf(stderr, "\nERROR: Failed to acquire new session ID!");
320         exit(EXIT_FAILURE);
321     }
323     /* disassociate from the standard file descriptors */
324     close(STDIN_FILENO);
325     close(STDOUT_FILENO);
326     close(STDERR_FILENO);
328 #endif
330     LOG0("\nInitializing LAD... ")
332     /* TODO:L make sure LAD is not already running? */
334     /* initialize client info arrays */
335     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
336         clientConnected[i] = FALSE;
337         responseFIFOFilePtr[i] = NULL;
338     }
340     /* if command FIFO exists from previous LAD session delete it now */
341     unlink(commandFIFOFile);
343     /* create command FIFO */
344     statusIO = mkfifo(commandFIFOFile, 0777);
345     if (statusIO != 0) {
346         LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
347             errno)
348         return(0);
349     }
351     /* set FIFO permissions to read/write */
352     chmod(commandFIFOFile, 0666);
354     /* Setup modules relevant for GateMP if necessary */
355 #if defined(GATEMP_SUPPORT)
356     if (gatempEnabled) {
357         /* Set up NameServer for resource manager process */
358         status = NameServer_setup();
359         if (status < 0) {
360             LOG0("\nERROR: unable to setup NameServer\n")
361             return(0);
362         }
364         status = GateHWSpinlock_start();
365         if (status < 0) {
366             LOG0("\nERROR: unable to start GateHWSpinlock\n");
367             return(0);
368         }
370         /* Set up GateMP */
371         status = GateMP_setup();
372         if (status < 0) {
373             LOG0("\nERROR: unable to setup GateMP\n")
374             NameServer_destroy();
375             return(0);
376         }
377     }
378 #endif
380 opencommandFIFO:
382     /* now open file for FIFO - will block until writer arrives... */
383     LOG1("\n    opening FIFO: %s\n", commandFIFOFile)
384     commandFIFOFilePtr = fopen(commandFIFOFile, "r");
385     if (commandFIFOFilePtr == NULL) {
386         LOG0("\nERROR: unable to open command FIFO\n")
387         unlink(commandFIFOFile);
388 #if defined(GATEMP_SUPPORT)
389         if (gatempEnabled) {
390             GateMP_destroy();
391             NameServer_destroy();
392         }
393 #endif
394         return(0);
395     }
397     /* COMMAND PROCESSING LOOP */
398     while (1) {
399         LOG0("Retrieving command...\n")
401         /* read the next command packet */
402         n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
404         /*
405          * if last client closes FIFO then it must be closed and reopened ...
406          */
407         if (!n) {
408             LOG1("   EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
409             fclose(commandFIFOFilePtr);
411             goto opencommandFIFO;
412         }
414         /* cleanup for any connected/started clients that have departed */
415         cleanupDepartedClients();
417         command = cmd.cmd;
418         clientId = cmd.clientId;
420         /* process individual commands */
421         switch (command) {
422           /*
423            * Since cmd is a union of rcv and snd structs, don't write
424            * any snd elements before all rcv elements have been referenced
425            * (either saved in separate variables or passed to a function).
426            *
427            * cmd.cmd has already been saved in 'command'
428            * cmd.clientId has already been saved in 'clientId'
429            */
430           case LAD_CONNECT:
431             connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
432                          cmd.args.connect.protocol, NULL);
434             break;
436           case LAD_DISCONNECT:
437             disconnectFromLAD(clientId);
439             break;
441           case LAD_IPC_GETCONFIG:
442             Ipc_getConfig(&rsp.ipcConfig);
443             break;
445           case LAD_NAMESERVER_SETUP:
446             LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
448             rsp.status = NameServer_setup();
450             LOG1("    status = %d\n", rsp.status)
451             LOG0("DONE\n")
453             break;
455           case LAD_NAMESERVER_DESTROY:
456             LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
458             rsp.status = NameServer_destroy();
460             LOG1("    status = %d\n", rsp.status)
461             LOG0("DONE\n")
463             break;
465           case LAD_NAMESERVER_PARAMS_INIT:
466             LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
468             NameServer_Params_init(&rsp.params);
470             LOG0("DONE\n")
472             break;
474           case LAD_NAMESERVER_CREATE:
475             LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
477             rsp.handle = NameServer_create(cmd.args.create.name,
478                                                &cmd.args.create.params);
480             LOG1("    handle = %p\n", rsp.handle)
481             LOG0("DONE\n")
483             break;
485           case LAD_NAMESERVER_DELETE:
486             LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
487                     cmd.args.nsdelete.handle)
489             rsp.nsdelete.handle = cmd.args.nsdelete.handle;
490             rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
492             LOG1("    status = %d\n", rsp.nsdelete.status)
493             LOG0("DONE\n")
495             break;
497           case LAD_NAMESERVER_ADD:
498             LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
499             LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
500             LOG1(" 0x%x)...\n", cmd.args.add.len)
502             rsp.entryPtr = NameServer_add(
503                 cmd.args.add.handle,
504                 cmd.args.add.name,
505                 cmd.args.add.buf,
506                 cmd.args.add.len);
508             LOG1("    entryPtr = %p\n", rsp.entryPtr)
509             LOG0("DONE\n")
511             break;
513           case LAD_NAMESERVER_GET:
514             LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
515                     cmd.args.get.handle, cmd.args.get.name)
516             LOG0(")...\n")
518             if (cmd.args.get.procId[0] == (UInt16)-1) {
519                 procIdPtr = NULL;
520             }
521             else {
522                 procIdPtr = cmd.args.get.procId;
523             }
524             rsp.get.status = NameServer_get(
525                 cmd.args.get.handle,
526                 cmd.args.get.name,
527                 rsp.get.buf,
528                 &cmd.args.get.len,
529                 procIdPtr);
530             rsp.get.len = cmd.args.get.len;
532             LOG1("    value = 0x%x\n", rsp.get.len)
533             LOG1("    status = %d\n", rsp.get.status)
534             LOG0("DONE\n")
536             break;
538           case LAD_NAMESERVER_ADDUINT32:
539             LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
540                     "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
541                     cmd.args.addUInt32.name, cmd.args.addUInt32.val)
543             rsp.entryPtr = NameServer_addUInt32(
544                 cmd.args.addUInt32.handle,
545                 cmd.args.addUInt32.name,
546                 cmd.args.addUInt32.val);
548             LOG1("    entryPtr = %p\n", rsp.entryPtr)
549             LOG0("DONE\n")
551             break;
553           case LAD_NAMESERVER_GETUINT32:
554             LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
555                     "(%p, '%s')...\n", cmd.args.getUInt32.handle,
556                     cmd.args.getUInt32.name)
558             if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
559                 procIdPtr = NULL;
560             }
561             else {
562                 procIdPtr = cmd.args.getUInt32.procId;
563             }
564             rsp.getUInt32.status = NameServer_getUInt32(
565                 cmd.args.getUInt32.handle,
566                 cmd.args.getUInt32.name,
567                 &rsp.getUInt32.val,
568                 procIdPtr);
570             LOG1("    value = 0x%x\n", rsp.getUInt32.val)
571             LOG1("    status = %d\n", rsp.getUInt32.status)
572             LOG0("DONE\n")
574             break;
576           case LAD_NAMESERVER_GETLOCAL:
577             rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
578                 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
579             rsp.get.len = cmd.args.getLocal.len;
580             break;
582           case LAD_NAMESERVER_GETLOCALUINT32:
583             rsp.getUInt32.status = NameServer_getLocalUInt32(
584                 cmd.args.getLocalUInt32.handle,
585                 cmd.args.getLocalUInt32.name,
586                 &rsp.getUInt32.val);
587             break;
589           case LAD_NAMESERVER_REMOVE:
590             LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
592             rsp.status = NameServer_remove(cmd.args.remove.handle,
593                                                cmd.args.remove.name);
595             LOG1("    status = %d\n", rsp.status)
596             LOG0("DONE\n")
598             break;
600           case LAD_NAMESERVER_REMOVEENTRY:
601             LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
603             rsp.status = NameServer_removeEntry(
604                 cmd.args.removeEntry.handle,
605                 cmd.args.removeEntry.entryPtr);
607             LOG1("    status = %d\n", rsp.status)
608             LOG0("DONE\n")
610             break;
612           case LAD_NAMESERVER_ATTACH:
613             rsp.status = NameServer_attach(cmd.args.attach.procId);
614             break;
616           case LAD_NAMESERVER_DETACH:
617             rsp.status = NameServer_detach(cmd.args.detach.procId);
618             break;
620           case LAD_MESSAGEQ_GETCONFIG:
621             LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
623             MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
624             rsp.messageQGetConfig.status = 0;
626             LOG1("    status = %d\n", rsp.messageQGetConfig.status)
627             LOG0("DONE\n")
629             break;
631           case LAD_MESSAGEQ_SETUP:
632             LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
634             rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
635             rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
637             LOG1("    status = %d\n", rsp.setup.status)
638             LOG0("DONE\n")
640             break;
642           case LAD_MESSAGEQ_DESTROY:
643             LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
645             rsp.status = MessageQ_destroy();
647             LOG1("    status = %d\n", rsp.status)
648             LOG0("DONE\n")
650             break;
652           case LAD_MESSAGEQ_CREATE:
653             LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
654                     cmd.args.messageQCreate.name,
655                     &cmd.args.messageQCreate.params);
657             tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
658                 cmd.args.messageQCreate.name;
660             handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
661             rsp.messageQCreate.serverHandle = handle;
663             if (handle) {
664                 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
665                 MessageQ_setQueueOwner(handle, clientPID[clientId]);
666                 rsp.messageQCreate.status = 0;
667             }
668             else {
669                 rsp.messageQCreate.status = -1;
670             }
672             LOG1("    status = %d\n", rsp.messageQCreate.status)
673             LOG0("DONE\n")
675             break;
677           case LAD_MESSAGEQ_ANNOUNCE:
678             LOG2("LAD_MESSAGEQ_ANNOUNCE: calling MessageQ_announce(%p, %p)...\n",
679                     cmd.args.messageQAnnounce.name,
680                     cmd.args.messageQAnnounce.serverHandle);
682             tmpString = (cmd.args.messageQAnnounce.name[0] == '\0') ? NULL :
683                 cmd.args.messageQAnnounce.name;
685             rsp.messageQAnnounce.status =
686                 MessageQ_announce(tmpString, (MessageQ_Handle *)&cmd.args.messageQAnnounce.serverHandle);
688             LOG1("    status = %d\n", rsp.messageQAnnounce.status)
689             LOG0("DONE\n")
691             break;
692           case LAD_MESSAGEQ_DELETE:
693             LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
695             rsp.messageQDelete.status =
696                 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
698             LOG1("    status = %d\n", rsp.messageQDelete.status)
699             LOG0("DONE\n")
701             break;
703           case LAD_MESSAGEQ_MSGINIT:
704             LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
706             MessageQ_msgInit(&rsp.msgInit.msg);
707             rsp.msgInit.status = 0;
709             LOG1("    status = %d\n", rsp.msgInit.status)
710             LOG0("DONE\n")
712             break;
714           case LAD_MULTIPROC_GETCONFIG:
715             LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
717             MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
718             rsp.multiprocGetConfig.status = 0;
720             LOG1("    status = %d\n", rsp.multiprocGetConfig.status)
721             LOG0("DONE\n")
723             break;
725 #if defined(GATEMP_SUPPORT)
726           case LAD_GATEMP_ATTACH:
727             procId = cmd.args.attach.procId;
728             LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
730             rsp.status = GateMP_attach(procId);
732             LOG1("    status = %d\n", rsp.status)
733             LOG0("DONE\n")
735             break;
737           case LAD_GATEMP_DETACH:
738             procId = cmd.args.detach.procId;
739             LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
741             rsp.status = GateMP_detach(procId);
743             LOG1("    status = %d\n", rsp.status)
744             LOG0("DONE\n")
746             break;
748           case LAD_GATEMP_START:
749             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
751             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
752             rsp.gateMPStart.status = GateMP_S_SUCCESS;
754             LOG1("    status = %d\n", rsp.gateMPStart.status)
755             LOG0("DONE\n")
757             break;
759           case LAD_GATEMP_GETNUMRESOURCES:
760             LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
762             rsp.gateMPGetNumResources.value = GateMP_getNumResources(
763                                           cmd.args.gateMPGetNumResources.type);
764             rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
766             LOG1("    status = %d\n", rsp.gateMPGetNumResources.status)
767             LOG0("DONE\n")
769             break;
771           case LAD_GATEMP_GETFREERESOURCE:
772             LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
774             rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
775                                           cmd.args.gateMPGetFreeResource.type);
776             rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
778             LOG1("    status = %d\n", rsp.gateMPGetFreeResource.status)
779             LOG0("DONE\n")
781             break;
783           case LAD_GATEMP_RELEASERESOURCE:
784             LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
786             rsp.gateMPReleaseResource.status = GateMP_releaseResource(
787                                           cmd.args.gateMPReleaseResource.id,
788                                           cmd.args.gateMPReleaseResource.type);
790             LOG1("    status = %d\n", rsp.gateMPReleaseResource.status)
791             LOG0("DONE\n")
793             break;
795           case LAD_GATEMP_ISSETUP:
796             LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
798             rsp.gateMPIsSetup.result = GateMP_isSetup();
799             rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
801             LOG1("    status = %d\n", rsp.gateMPIsSetup.status)
802             LOG0("DONE\n")
804             break;
806           case LAD_GATEHWSPINLOCK_GETCONFIG:
807             LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
809             GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
810             rsp.gateHWSpinlockGetConfig.status = 0;
812             LOG1("    status = %d\n", rsp.gateHWSpinlockGetConfig.status)
813             LOG0("DONE\n")
815             break;
816 #endif
818           case LAD_EXIT:
819             goto exitNow;
821             break;
823           default:
824             LOG1("\nUnrecognized command: 0x%x\n", command)
826             break;
827         }
829         switch (command) {
830           case LAD_CONNECT:
831           case LAD_DISCONNECT:
832             break;
834           case LAD_IPC_GETCONFIG:
835           case LAD_NAMESERVER_SETUP:
836           case LAD_NAMESERVER_DESTROY:
837           case LAD_NAMESERVER_PARAMS_INIT:
838           case LAD_NAMESERVER_CREATE:
839           case LAD_NAMESERVER_DELETE:
840           case LAD_NAMESERVER_ADD:
841           case LAD_NAMESERVER_GET:
842           case LAD_NAMESERVER_ADDUINT32:
843           case LAD_NAMESERVER_GETUINT32:
844           case LAD_NAMESERVER_GETLOCAL:
845           case LAD_NAMESERVER_GETLOCALUINT32:
846           case LAD_NAMESERVER_REMOVE:
847           case LAD_NAMESERVER_REMOVEENTRY:
848           case LAD_NAMESERVER_ATTACH:
849           case LAD_NAMESERVER_DETACH:
850           case LAD_MESSAGEQ_GETCONFIG:
851           case LAD_MESSAGEQ_SETUP:
852           case LAD_MESSAGEQ_DESTROY:
853           case LAD_MESSAGEQ_CREATE:
854           case LAD_MESSAGEQ_ANNOUNCE:
855           case LAD_MESSAGEQ_DELETE:
856           case LAD_MESSAGEQ_MSGINIT:
857           case LAD_MULTIPROC_GETCONFIG:
858 #if defined(GATEMP_SUPPORT)
859           case LAD_GATEMP_ATTACH:
860           case LAD_GATEMP_DETACH:
861           case LAD_GATEMP_START:
862           case LAD_GATEMP_GETNUMRESOURCES:
863           case LAD_GATEMP_GETFREERESOURCE:
864           case LAD_GATEMP_RELEASERESOURCE:
865           case LAD_GATEMP_ISSETUP:
866           case LAD_GATEHWSPINLOCK_GETCONFIG:
867 #endif
869             LOG0("Sending response...\n");
871             fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
872             fflush(responseFIFOFilePtr[clientId]);
874             break;
876           default:
877             break;
878         }
879     }
881 exitNow:
882 #if defined(GATEMP_SUPPORT)
883     if (gatempEnabled) {
884         GateMP_destroy();
885         NameServer_destroy();
886     }
887 #endif
888     if (logFile) {
889         LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
890         fclose(logPtr);
891     }
892     unlink(commandFIFOFile);
894     return(0);
899 /*
900  *  ======== isDaemonRunning ========
901  */
902 static Bool isDaemonRunning(Char *pidName)
904     DIR *dir;
905     pid_t pid;
906     Int dirNum;
907     FILE *fp;
908     struct dirent * next;
909     Bool isRunning = FALSE;
910     Char filename [READ_BUF_SIZE];
911     Char buffer [READ_BUF_SIZE];
912     Char *bptr = buffer;
913     Char *name;
915     pid = getpid();
916     dir = opendir("/proc");
917     if (!dir) {
918         printf("Warning: Cannot open /proc filesystem\n");
919         return isRunning;
920     }
922     name = strrchr(pidName, '/');
923     if (name) {
924         pidName = (name + 1);
925     }
927     while ((next = readdir(dir)) != NULL) {
928         /* If it isn't a number, we don't want it */
929         if (!isdigit(*next->d_name)) {
930             continue;
931         }
933         dirNum = strtol(next->d_name, NULL, 10);
934         if (dirNum == pid) {
935             continue;
936         }
938         snprintf(filename, READ_BUF_SIZE, "/proc/%s/cmdline", next->d_name);
939         if (!(fp = fopen(filename, "r"))) {
940             continue;
941         }
942         if (fgets(buffer, READ_BUF_SIZE, fp) == NULL) {
943             fclose(fp);
944             continue;
945         }
946         fclose (fp);
948         name = strrchr(buffer, '/');
949         if (name && (name + 1)) {
950             bptr = name + 1;
951         }
952         else {
953             bptr = buffer;
954         }
956         /* Buffer should contain the entire command line */
957         if (strcmp(bptr, pidName) == 0) {
958             isRunning = TRUE;
959             break;
960         }
961     }
962     closedir (dir);
964     return isRunning;
967 /*
968  *  ======== assignClientId ========
969  */
970 static LAD_ClientHandle assignClientId(Void)
972     Int clientId = -1;
973     Int i;
975     /* scan connection status flags to acquire a clientId */
976     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
977         /* if slot open then provisionally select this clientId */
978         if (clientConnected[i] == FALSE) {
979              clientId = i;
980              break;
981         }
982     }
984     return(clientId);
987 /*
988  *  ======== cleanupFifos ========
989  */
990 static void cleanupFifos(Void)
992     DIR *dir;
993     struct dirent entry;
994     struct dirent *result;
995     size_t dirnamelen;
996     size_t maxcopy;
997     Char pathname[PATH_MAX];
998     Char *namep;
1000     if ((dir = opendir(LAD_WORKINGDIR)) == NULL)
1001         return;
1003     dirnamelen = snprintf(pathname, sizeof(pathname), "%s/", LAD_WORKINGDIR);
1004     if (dirnamelen >= sizeof(pathname)) {
1005         closedir(dir);
1006         return;
1007     }
1008     namep = pathname + dirnamelen;
1009     maxcopy = PATH_MAX - dirnamelen;
1010     while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
1011         /* Delete old FIFOs left over */
1012         if ((entry.d_type == DT_FIFO) && (strlen(entry.d_name) < maxcopy)) {
1013             strncpy(namep, entry.d_name, maxcopy);
1014             unlink(pathname);
1015         }
1016     }
1017     closedir(dir);
1020 /*
1021  *  ======== cleanupDepartedClients ========
1022  */
1023 static Void cleanupDepartedClients(Void)
1025     Int killStat;
1026     Int i;
1028     /* scan all connections to verify client processes still exist... */
1029     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
1031         /* if connected... */
1032         if (clientConnected[i] == TRUE) {
1034             /* check if the client process (PID) still exists */
1035             /*
1036              * NOTE - calling kill with signal value of 0 will perform
1037              * error checking, but not actually send a signal.  Will use this
1038              * error check to see if PID still exists.  An alternative was
1039              * to call getpgid.  This worked, but is apparently limited to
1040              * USE_XOPEN_EXTENDED configurations.
1041              */
1042             killStat = kill(clientPID[i], 0);
1043             if ((killStat == -1) && (errno == ESRCH)) {
1045                 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
1047                 /* will always need to do the disconnect... */
1048                 LOG0("\nDoing DISCONNECT on behalf of client...")
1049                 doDisconnect(i);
1051                 MessageQ_cleanupOwner(clientPID[i]);
1052 //                NameServer_cleanupOwner(clientPID[i]);
1054                 LOG0("DONE\n")
1055             }
1056         }
1057     }
1061 /*
1062  *  ======== connectToLAD ========
1063  */
1064 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
1066     Int clientId = -1;
1067     Bool connectDenied = FALSE;
1068     Int status = LAD_SUCCESS;
1069     time_t currentTime;
1070     time_t startTime;
1071     struct stat statBuf;
1072     double delta = 0;
1073     int filePtrFd = 0;
1074     FILE * filePtr;
1075     Int statusIO;
1077     /*
1078      * TODO:L here, and everywhere parse FIFO strings: should
1079      * add full error checking for incomplete or corrupted
1080      * strings? Since LAD to ladclient comms are "closed", and
1081      * tested, the likelihood of problems seems very low.
1082      * But should still consider doing full error checking
1083      * and, hopefully, recovery.
1084      */
1085     LOG0("\nLAD_CONNECT: \n")
1086     LOG1("    client FIFO name = %s\n", clientName)
1087     LOG1("    client PID = %d\n", pid)
1089     /* first check for proper communication protocol */
1090     if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
1092         /* if no match then reject the request */
1093         LOG0("    ERROR: mismatch in communication protocol!\n")
1094         LOG1("        LAD protocol = %s\n", LAD_PROTOCOLVERSION)
1095         LOG1("        client protocol = %s\n", clientProto)
1096         status = LAD_INVALIDVERSION;
1098         /* set flag so know to close FIFO after response */
1099         connectDenied = TRUE;
1101         /* now jump forward a bit to send response */
1102         goto openResponseFIFO;
1103     }
1105     /* determine this client's ID */
1106     clientId = assignClientId();
1108     /* if failed to acquire an ID then exit early */
1109     if (clientId == -1) {
1110         LOG0("    no free handle; too many connections!\n")
1111         status = LAD_ACCESSDENIED;
1113         /* set flag so know to close FIFO after response */
1114         connectDenied = TRUE;
1115     }
1116     else {
1117         LOG1("    assigned client handle = %d\n", clientId)
1119         /* save the client's FIFO name for when disconnect */
1120         strcpy(clientFIFOName[clientId], clientName);
1121     }
1123 openResponseFIFO:
1125     /* create the dedicated response FIFO to the client */
1126     statusIO = mkfifo(clientName, 0777);
1127     if (statusIO != 0) {
1129         LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
1131         status = LAD_IOFAILURE;
1133         /* send no response; connection request will timeout */
1134         goto doneconnect;
1135     }
1137     LOG1("    FIFO %s created\n", clientName)
1139     /* set FIFO permissions to read/write */
1140     chmod(clientName, 0666);
1142     startTime = time ((time_t *) 0);
1143     while (delta <= LAD_RESPONSEFIFOTIMEOUT) {
1144         /* open a file for writing to FIFO, non-blocking so we can timeout */
1145         filePtrFd = open(clientName, O_WRONLY | O_TRUNC | O_NONBLOCK);
1146         if (filePtrFd != -1) {
1147             break;
1148         }
1149         LOG1("\nWARN: Client %s has not yet opened, will retry\n", clientName)
1150         usleep(100);
1151         currentTime = time ((time_t *) 0);
1152         delta = difftime(currentTime, startTime);
1153     }
1155     if (delta > LAD_RESPONSEFIFOTIMEOUT) {
1156         LOG1("\nERROR: timed out waiting for Client to open response FIFO %s\n", clientName);
1157         unlink(clientName);
1158         status = LAD_IOFAILURE;
1159         goto doneconnect;
1160     }
1162     filePtr = fopen(clientName, "w");
1164     close(filePtrFd);
1166     if (filePtr == NULL) {
1167         LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
1169         /* if failed open, still need to delete the FIFO */
1170         unlink(clientName);
1172         status = LAD_IOFAILURE;
1174         /* send no response; connection request will timeout */
1175         goto doneconnect;
1176     }
1178     LOG1("    FIFO %s opened for writing\n", clientName)
1180     /*
1181      * set "this client is connected" flag; this client ID is now "owned", and
1182      * is no longer provisional
1183      */
1184     if (connectDenied == FALSE) {
1185         responseFIFOFilePtr[clientId] = filePtr;
1186         clientPID[clientId] = pid;
1187         clientConnected[clientId] = TRUE;
1188     }
1190     rsp.connect.assignedId = clientId;
1191     rsp.status = status;
1193     /* put response to FIFO */
1194     fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1195     fflush(filePtr);
1197     LOG0("    sent response\n")
1199     /* if connection was denied, must now close FIFO */
1200     if (connectDenied == TRUE) {
1201         LOG1("    connect denied; closing FIFO %s\n", clientName)
1202         fclose(filePtr);
1203         unlink(clientName);
1204     }
1206     LOG0("DONE\n")
1208 doneconnect:
1209     if (clientIdPtr != NULL) {
1210         *clientIdPtr = clientId;
1211     }
1213     return(status);
1217 /*
1218  *  ======== disconnectFromLAD ========
1219  */
1220 static Void disconnectFromLAD(Int clientId)
1222     LOG0("\nLAD_DISCONNECT: ")
1224     LOG1("\n    client handle = %x", clientId)
1225     doDisconnect(clientId);
1227     LOG0("DONE\n")
1229     return;
1233 /*
1234  *  ======== doDisconnect ========
1235  */
1236 static Void doDisconnect(Int clientId)
1238     /* set "this client is not connected" flag */
1239     clientConnected[clientId] = FALSE;
1241     /* close and remove the response FIFO */
1242     LOG2("\n    closing FIFO %s (filePtr=%p)\n",
1243         clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1244     fclose(responseFIFOFilePtr[clientId]);
1246     LOG1("    done, unlinking %s\n", clientFIFOName[clientId]);
1247     unlink(clientFIFOName[clientId]);