]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/lad.c
55c549fa0babb8adfb536af2e50663e5bc6c9083
[ipc/ipcdev.git] / linux / src / daemon / lad.c
1 /*
2  * Copyright (c) 2012-2014, 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/types.h>
45 #include <signal.h>
46 #include <unistd.h>
48 #include <ti/ipc/MessageQ.h>
49 #include <_MessageQ.h>
50 #include <ti/ipc/NameServer.h>
51 #include <_NameServer.h>
52 #include <ti/ipc/GateMP.h>
53 #include <_GateMP_daemon.h>
55 #include <GateHWSpinlock.h>
57 #include <ladclient.h>
58 #include <_lad.h>
60 #define DAEMON        1           /* 1 = run as a daemon; 0 = run as app */
62 Bool logFile = FALSE;
63 FILE *logPtr = NULL;
65 static String commandFIFOFile = LAD_COMMANDFIFO;
66 static FILE *commandFIFOFilePtr = NULL;
68 static Bool gatempEnabled = FALSE;
70 /* LAD client info arrays */
71 static Bool clientConnected[LAD_MAXNUMCLIENTS];
72 static UInt clientPID[LAD_MAXNUMCLIENTS];
73 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
74 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
76 /* local internal routines */
77 static LAD_ClientHandle assignClientId(Void);
78 static Void cleanupDepartedClients(Void);
79 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
80 static Void disconnectFromLAD(Int clientId);
81 static Void doDisconnect(Int clientId);
83 struct LAD_CommandObj cmd;
84 union LAD_ResponseObj rsp;
86 #define LAD_USAGE "\
87 Usage:\n\
88     lad_<platform> [options] \n\
89 \n\
90 Options:\n\
91     h            : print this help message\n\
92     g            : enable GateMP support \n\
93     l <logfile>  : name of logfile for LAD\n\
94 \n\
95 Examples:\n\
96     lad_<platform> -h\n\
97     lad_<platform> -l log.txt\n\
98     lad_<platform> -g -l log.txt\n\
99 \n"
101 /*
102  *  ======== main ========
103  */
104 int main(int argc, char * argv[])
106     MessageQ_Handle handle;
107     UInt16 *procIdPtr;
108     Int statusIO;
109     Int clientId;
110     Int command;
111     Int flags;
112     Int i;
113     Int n;
114     Int c;
115     Int status;
116     String tmpString;
117 #if DAEMON
118     pid_t pid;
119     pid_t sid;
120 #endif
122     /* change to LAD's working directory */
123     if ((chdir(LAD_WORKINGDIR)) < 0) {
125         /* if can't change directory assume it needs to be created, do it */
126         if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
127             printf("\nERROR: Failed to create LAD's working directory!\n");
128             exit(EXIT_FAILURE);
129         }
130         /* now change to the new directory */
131         if ((chdir(LAD_WORKINGDIR)) < 0) {
132             printf("\nERROR: Failed to change to LAD's working directory!\n");
133             exit(EXIT_FAILURE);
134         }
135     }
137     /* process command line args */
138     while (1) {
139         c = getopt(argc, argv, "ghl:");
140         if (c == -1) {
141             break;
142         }
144         switch (c) {
145             case 'g':
146 #if defined(GATEMP_SUPPORT)
147                 printf("\nGateMP support enabled on host\n");
148                 gatempEnabled = TRUE;
149 #else
150                 printf("\nGateMP is not supported for this device\n");
151 #endif
152                 break;
153             case 'h':
154                 printf("%s", LAD_USAGE);
155                 exit(0);
156                 break;
157             case 'l':
158                 logPtr = fopen(optarg, "w");
159                 if (logPtr == NULL) {
160                     printf("\nERROR: unable to open log file %s\n", optarg);
161                     exit(EXIT_FAILURE);
162                 }
163                 else {
164                     logFile = TRUE;
165                     printf("\nOpened log file: %s", optarg);
166                     /* close log file upon LAD termination */
167                     flags = fcntl(fileno(logPtr), F_GETFD);
168                     if (flags != -1) {
169                         fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
170                     }
171                 }
172                 break;
173             default:
174                 fprintf (stderr, "\nUnrecognized argument\n");
175                 exit(EXIT_FAILURE);
176         }
177     }
179 #if DAEMON
180     /* fork off a child process */
181     pid = fork();
183     /* if fork of child failed then exit immediately; no child created */
184     if (pid < 0) {
185         printf("\nERROR: Failed to fork child process!");
186         exit(EXIT_FAILURE);
187     }
189     /* if pid > 0 this is the parent; time to die ... */
190     if (pid > 0) {
191         printf("\nSpawned daemon: %s\n\n", argv[0]);
192         exit(EXIT_SUCCESS);
193     }
195     /* child continues from here (pid == 0) ... */
197     /* change file mode mask */
198     umask(0);
200     /* create new session ID for the child */
201     sid = setsid();
203     /* exit with failure code if failed to get session ID... */
204     if (sid < 0) {
205         printf("\nERROR: Failed to acquire new session ID!");
206         exit(EXIT_FAILURE);
207     }
209     /* disassociate from the standard file descriptors */
210     close(STDIN_FILENO);
211     close(STDOUT_FILENO);
212     close(STDERR_FILENO);
214 #endif
216     LOG0("\nInitializing LAD... ")
218     /* TODO:L make sure LAD is not already running? */
220     /* initialize client info arrays */
221     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
222         clientConnected[i] = FALSE;
223         responseFIFOFilePtr[i] = NULL;
224     }
226     /* if command FIFO exists from previous LAD session delete it now */
227     unlink(commandFIFOFile);
229     /* create command FIFO */
230     statusIO = mkfifo(commandFIFOFile, 0777);
231     if (statusIO != 0) {
232         LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
233             errno)
234         return(0);
235     }
237     /* set FIFO permissions to read/write */
238     chmod(commandFIFOFile, 0666);
240     /* Setup modules relevant for GateMP if necessary */
241 #if defined(GATEMP_SUPPORT)
242     if (gatempEnabled) {
243         /* Set up NameServer for resource manager process */
244         status = NameServer_setup();
245         if (status < 0) {
246             LOG0("\nERROR: unable to setup NameServer\n")
247             return(0);
248         }
250         status = GateHWSpinlock_start();
251         if (status < 0) {
252             LOG0("\nERROR: unable to start GateHWSpinlock\n");
253             return(0);
254         }
256         /* Set up GateMP */
257         status = GateMP_setup();
258         if (status < 0) {
259             LOG0("\nERROR: unable to setup GateMP\n")
260             NameServer_destroy();
261             return(0);
262         }
263     }
264 #endif
266 opencommandFIFO:
268     /* now open file for FIFO - will block until writer arrives... */
269     LOG1("\n    opening FIFO: %s\n", commandFIFOFile)
270     commandFIFOFilePtr = fopen(commandFIFOFile, "r");
271     if (commandFIFOFilePtr == NULL) {
272         LOG0("\nERROR: unable to open command FIFO\n")
273         unlink(commandFIFOFile);
274 #if defined(GATEMP_SUPPORT)
275         if (gatempEnabled) {
276             GateMP_destroy();
277             NameServer_destroy();
278         }
279 #endif
280         return(0);
281     }
283     /* COMMAND PROCESSING LOOP */
284     while (1) {
285         LOG0("Retrieving command...\n")
287         /* read the next command packet */
288         n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
290         /*
291          * if last client closes FIFO then it must be closed and reopened ...
292          */
293         if (!n) {
294             LOG1("   EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
295             fclose(commandFIFOFilePtr);
297             goto opencommandFIFO;
298         }
300         /* cleanup for any connected/started clients that have departed */
301         cleanupDepartedClients();
303         command = cmd.cmd;
304         clientId = cmd.clientId;
306         /* process individual commands */
307         switch (command) {
308           /*
309            * Since cmd is a union of rcv and snd structs, don't write
310            * any snd elements before all rcv elements have been referenced
311            * (either saved in separate variables or passed to a function).
312            *
313            * cmd.cmd has already been saved in 'command'
314            * cmd.clientId has already been saved in 'clientId'
315            */
316           case LAD_CONNECT:
317             connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
318                          cmd.args.connect.protocol, NULL);
320             break;
322           case LAD_DISCONNECT:
323             disconnectFromLAD(clientId);
325             break;
327           case LAD_NAMESERVER_SETUP:
328             LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
330             rsp.status = NameServer_setup();
332             LOG1("    status = %d\n", rsp.status)
333             LOG0("DONE\n")
335             break;
337           case LAD_NAMESERVER_DESTROY:
338             LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
340             rsp.status = NameServer_destroy();
342             LOG1("    status = %d\n", rsp.status)
343             LOG0("DONE\n")
345             break;
347           case LAD_NAMESERVER_PARAMS_INIT:
348             LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
350             NameServer_Params_init(&rsp.params);
352             LOG0("DONE\n")
354             break;
356           case LAD_NAMESERVER_CREATE:
357             LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
359             rsp.handle = NameServer_create(cmd.args.create.name,
360                                                &cmd.args.create.params);
362             LOG1("    handle = %p\n", rsp.handle)
363             LOG0("DONE\n")
365             break;
367           case LAD_NAMESERVER_DELETE:
368             LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n", cmd.args.delete.handle)
370             rsp.delete.handle = cmd.args.delete.handle;
371             rsp.delete.status = NameServer_delete(&rsp.delete.handle);
373             LOG1("    status = %d\n", rsp.status)
374             LOG0("DONE\n")
376             break;
378           case LAD_NAMESERVER_ADD:
379             LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
380             LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
381             LOG1(" 0x%x)...\n", cmd.args.add.len)
383             rsp.entryPtr = NameServer_add(
384                 cmd.args.add.handle,
385                 cmd.args.add.name,
386                 cmd.args.add.buf,
387                 cmd.args.add.len);
389             LOG1("    entryPtr = %p\n", rsp.entryPtr)
390             LOG0("DONE\n")
392             break;
394           case LAD_NAMESERVER_GET:
395             LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
396                 cmd.args.get.handle, cmd.args.get.name)
397             LOG0(")...\n")
399             if (cmd.args.get.procId[0] == (UInt16)-1) {
400                 procIdPtr = NULL;
401             }
402             else {
403                 procIdPtr = cmd.args.get.procId;
404             }
405             rsp.status = NameServer_get(
406                 cmd.args.get.handle,
407                 cmd.args.get.name,
408                 rsp.get.buf,
409                 &cmd.args.get.len,
410                 procIdPtr);
411             rsp.get.len = cmd.args.get.len;
413             LOG1("    value = 0x%x\n", rsp.get.len)
414             LOG1("    status = %d\n", rsp.status)
415             LOG0("DONE\n")
417             break;
419           case LAD_NAMESERVER_ADDUINT32:
420             LOG1("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32(%p, ", cmd.args.addUInt32.handle)
421             LOG2("'%s', 0x%x)...\n", cmd.args.addUInt32.name, cmd.args.addUInt32.val)
423             rsp.entryPtr = NameServer_addUInt32(
424                 cmd.args.addUInt32.handle,
425                 cmd.args.addUInt32.name,
426                 cmd.args.addUInt32.val);
428             LOG1("    entryPtr = %p\n", rsp.entryPtr)
429             LOG0("DONE\n")
431             break;
433           case LAD_NAMESERVER_GETUINT32:
434             LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32(%p, '%s')...\n", cmd.args.getUInt32.handle, cmd.args.getUInt32.name)
436             if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
437                 procIdPtr = NULL;
438             }
439             else {
440                 procIdPtr = cmd.args.getUInt32.procId;
441             }
442             rsp.status = NameServer_getUInt32(
443                 cmd.args.getUInt32.handle,
444                 cmd.args.getUInt32.name,
445                 &rsp.getUInt32.val,
446                 procIdPtr);
448             LOG1("    value = 0x%x\n", rsp.getUInt32.val)
449             LOG1("    status = %d\n", rsp.status)
450             LOG0("DONE\n")
452             break;
454           case LAD_NAMESERVER_REMOVE:
455             LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
457             rsp.status = NameServer_remove(cmd.args.remove.handle,
458                                                cmd.args.remove.name);
460             LOG1("    status = %d\n", rsp.status)
461             LOG0("DONE\n")
463             break;
465           case LAD_NAMESERVER_REMOVEENTRY:
466             LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
468             rsp.status = NameServer_removeEntry(
469                 cmd.args.removeEntry.handle,
470                 cmd.args.removeEntry.entryPtr);
472             LOG1("    status = %d\n", rsp.status)
473             LOG0("DONE\n")
475             break;
477           case LAD_MESSAGEQ_GETCONFIG:
478             LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
480             MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
481             rsp.messageQGetConfig.status = 0;
483             LOG1("    status = %d\n", rsp.messageQGetConfig.status)
484             LOG0("DONE\n")
486             break;
488           case LAD_MESSAGEQ_SETUP:
489             LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
491             rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
492             rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
494             LOG1("    status = %d\n", rsp.setup.status)
495             LOG0("DONE\n")
497             break;
499           case LAD_MESSAGEQ_DESTROY:
500             LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
502             rsp.status = MessageQ_destroy();
504             LOG1("    status = %d\n", rsp.status)
505             LOG0("DONE\n")
507             break;
509           case LAD_MESSAGEQ_CREATE:
510             LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
511                     cmd.args.messageQCreate.name,
512                     &cmd.args.messageQCreate.params);
514             tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
515                 cmd.args.messageQCreate.name;
517             handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
518             rsp.messageQCreate.serverHandle = handle;
520             if (handle) {
521                 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
522                 MessageQ_setQueueOwner(handle, clientPID[clientId]);
523                 rsp.messageQCreate.status = 0;
524             }
525             else {
526                 rsp.messageQCreate.status = -1;
527             }
529             LOG1("    status = %d\n", rsp.messageQCreate.status)
530             LOG0("DONE\n")
532             break;
534           case LAD_MESSAGEQ_DELETE:
535             LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
537             rsp.messageQDelete.status =
538                 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
540             LOG1("    status = %d\n", rsp.messageQDelete.status)
541             LOG0("DONE\n")
543             break;
545           case LAD_MESSAGEQ_MSGINIT:
546             LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
548             MessageQ_msgInit(&rsp.msgInit.msg);
549             rsp.msgInit.status = 0;
551             LOG1("    status = %d\n", rsp.msgInit.status)
552             LOG0("DONE\n")
554             break;
556           case LAD_MULTIPROC_GETCONFIG:
557             LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
559             MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
560             rsp.multiprocGetConfig.status = 0;
562             LOG1("    status = %d\n", rsp.multiprocGetConfig.status)
563             LOG0("DONE\n")
565             break;
567 #if defined(GATEMP_SUPPORT)
568           case LAD_GATEMP_START:
569             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
571             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
572             rsp.gateMPStart.status = GateMP_S_SUCCESS;;
574             LOG1("    status = %d\n", rsp.gateMPStart.status)
575             LOG0("DONE\n")
577             break;
579           case LAD_GATEMP_GETNUMRESOURCES:
580             LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
582             rsp.gateMPGetNumResources.value = GateMP_getNumResources(
583                                           cmd.args.gateMPGetNumResources.type);
584             rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
586             LOG1("    status = %d\n", rsp.gateMPGetNumResources.status)
587             LOG0("DONE\n")
589             break;
591           case LAD_GATEMP_GETFREERESOURCE:
592             LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
594             rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
595                                           cmd.args.gateMPGetFreeResource.type);
596             rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
598             LOG1("    status = %d\n", rsp.gateMPGetFreeResource.status)
599             LOG0("DONE\n")
601             break;
603           case LAD_GATEMP_RELEASERESOURCE:
604             LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
606             rsp.gateMPReleaseResource.status = GateMP_releaseResource(
607                                           cmd.args.gateMPReleaseResource.id,
608                                           cmd.args.gateMPReleaseResource.type);
610             LOG1("    status = %d\n", rsp.gateMPReleaseResource.status)
611             LOG0("DONE\n")
613             break;
615           case LAD_GATEMP_ISSETUP:
616             LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
618             rsp.gateMPIsSetup.result = GateMP_isSetup();
619             rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
621             LOG1("    status = %d\n", rsp.gateMPIsSetup.status)
622             LOG0("DONE\n")
624             break;
626           case LAD_GATEHWSPINLOCK_GETCONFIG:
627             LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
629             GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
630             rsp.gateHWSpinlockGetConfig.status = 0;
632             LOG1("    status = %d\n", rsp.gateHWSpinlockGetConfig.status)
633             LOG0("DONE\n")
635             break;
636 #endif
638           case LAD_EXIT:
639             goto exitNow;
641             break;
643           default:
644             LOG1("\nUnrecognized command: 0x%x\n", command)
646             break;
647         }
649         switch (command) {
650           case LAD_CONNECT:
651           case LAD_DISCONNECT:
652             break;
654           case LAD_NAMESERVER_SETUP:
655           case LAD_NAMESERVER_DESTROY:
656           case LAD_NAMESERVER_PARAMS_INIT:
657           case LAD_NAMESERVER_CREATE:
658           case LAD_NAMESERVER_DELETE:
659           case LAD_NAMESERVER_ADD:
660           case LAD_NAMESERVER_GET:
661           case LAD_NAMESERVER_ADDUINT32:
662           case LAD_NAMESERVER_GETUINT32:
663           case LAD_NAMESERVER_REMOVE:
664           case LAD_NAMESERVER_REMOVEENTRY:
665           case LAD_MESSAGEQ_GETCONFIG:
666           case LAD_MESSAGEQ_SETUP:
667           case LAD_MESSAGEQ_DESTROY:
668           case LAD_MESSAGEQ_CREATE:
669           case LAD_MESSAGEQ_DELETE:
670           case LAD_MESSAGEQ_MSGINIT:
671           case LAD_MULTIPROC_GETCONFIG:
672 #if defined(GATEMP_SUPPORT)
673           case LAD_GATEMP_START:
674           case LAD_GATEMP_GETNUMRESOURCES:
675           case LAD_GATEMP_GETFREERESOURCE:
676           case LAD_GATEMP_RELEASERESOURCE:
677           case LAD_GATEMP_ISSETUP:
678           case LAD_GATEHWSPINLOCK_GETCONFIG:
679 #endif
681             LOG0("Sending response...\n");
683             fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
684             fflush(responseFIFOFilePtr[clientId]);
686             break;
688           default:
689             break;
690         }
691     }
693 exitNow:
694 #if defined(GATEMP_SUPPORT)
695     if (gatempEnabled) {
696         GateMP_destroy();
697         NameServer_destroy();
698     }
699 #endif
700     if (logFile) {
701         LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
702         fclose(logPtr);
703     }
704     unlink(commandFIFOFile);
706     return(0);
711 /*
712  *  ======== assignClientId ========
713  */
714 static LAD_ClientHandle assignClientId(Void)
716     Int clientId = -1;
717     Int i;
719     /* scan connection status flags to acquire a clientId */
720     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
721         /* if slot open then provisionally select this clientId */
722         if (clientConnected[i] == FALSE) {
723              clientId = i;
724              break;
725         }
726     }
728     return(clientId);
732 /*
733  *  ======== cleanupDepartedClients ========
734  */
735 static Void cleanupDepartedClients(Void)
737     Int killStat;
738     Int i;
740     /* scan all connections to verify client processes still exist... */
741     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
743         /* if connected... */
744         if (clientConnected[i] == TRUE) {
746             /* check if the client process (PID) still exists */
747             /*
748              * NOTE - calling kill with signal value of 0 will perform
749              * error checking, but not actually send a signal.  Will use this
750              * error check to see if PID still exists.  An alternative was
751              * to call getpgid.  This worked, but is apparently limited to
752              * USE_XOPEN_EXTENDED configurations.
753              */
754             killStat = kill(clientPID[i], 0);
755             if ((killStat == -1) && (errno == ESRCH)) {
757                 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
759                 /* will always need to do the disconnect... */
760                 LOG0("\nDoing DISCONNECT on behalf of client...")
761                 doDisconnect(i);
763                 MessageQ_cleanupOwner(clientPID[i]);
764 //                NameServer_cleanupOwner(clientPID[i]);
766                 LOG0("DONE\n")
767             }
768         }
769     }
773 /*
774  *  ======== connectToLAD ========
775  */
776 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
778     Int clientId = -1;
779     Bool connectDenied = FALSE;
780     Int status = LAD_SUCCESS;
781     FILE * filePtr;
782     Int statusIO;
784     /*
785      * TODO:L here, and everywhere parse FIFO strings: should
786      * add full error checking for incomplete or corrupted
787      * strings? Since LAD to ladclient comms are "closed", and
788      * tested, the likelihood of problems seems very low.
789      * But should still consider doing full error checking
790      * and, hopefully, recovery.
791      */
792     LOG0("\nLAD_CONNECT: \n")
793     LOG1("    client FIFO name = %s\n", clientName)
794     LOG1("    client PID = %d\n", pid)
796     /* first check for proper communication protocol */
797     if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
799         /* if no match then reject the request */
800         LOG0("    ERROR: mismatch in communication protocol!\n")
801         LOG1("        LAD protocol = %s\n", LAD_PROTOCOLVERSION)
802         LOG1("        client protocol = %s\n", clientProto)
803         status = LAD_INVALIDVERSION;
805         /* set flag so know to close FIFO after response */
806         connectDenied = TRUE;
808         /* now jump forward a bit to send response */
809         goto openResponseFIFO;
810     }
812     /* determine this client's ID */
813     clientId = assignClientId();
815     /* if failed to acquire an ID then exit early */
816     if (clientId == -1) {
817         LOG0("    no free handle; too many connections!\n")
818         status = LAD_ACCESSDENIED;
820         /* set flag so know to close FIFO after response */
821         connectDenied = TRUE;
822     }
823     else {
824         LOG1("    assigned client handle = %d\n", clientId)
826         /* save the client's FIFO name for when disconnect */
827         strcpy(clientFIFOName[clientId], clientName);
828     }
830 openResponseFIFO:
832     /* if response FIFO exists from previous LAD session delete it now */
833     unlink(clientName);
835     /* create the dedicated response FIFO to the client */
836     statusIO = mkfifo(clientName, 0777);
837     if (statusIO != 0) {
839         LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
841         status = LAD_IOFAILURE;
843         /* send no response; connection request will timeout */
844         goto doneconnect;
845     }
847     LOG1("    FIFO %s created\n", clientName)
849     /* set FIFO permissions to read/write */
850     chmod(clientName, 0666);
852     filePtr = fopen(clientName, "w");
853     if (filePtr == NULL) {
854         LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
856         /* if failed open, still need to delete the FIFO */
857         unlink(clientName);
859         status = LAD_IOFAILURE;
861         /* send no response; connection request will timeout */
862         goto doneconnect;
863     }
865     LOG1("    FIFO %s opened for writing\n", clientName)
867     /*
868      * set "this client is connected" flag; this client ID is now "owned", and
869      * is no longer provisional
870      */
871     if (connectDenied == FALSE) {
872         responseFIFOFilePtr[clientId] = filePtr;
873         clientPID[clientId] = pid;
874         clientConnected[clientId] = TRUE;
875     }
877     rsp.connect.assignedId = clientId;
878     rsp.status = status;
880     /* put response to FIFO */
881     fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
882     fflush(filePtr);
884     LOG0("    sent response\n")
886     /* if connection was denied, must now close FIFO */
887     if (connectDenied == TRUE) {
888         LOG1("    connect denied; closing FIFO %s\n", clientName)
889         fclose(filePtr);
890         unlink(clientName);
891     }
893     LOG0("DONE\n")
895 doneconnect:
896     if (clientIdPtr != NULL) {
897         *clientIdPtr = clientId;
898     }
900     return(status);
904 /*
905  *  ======== disconnectFromLAD ========
906  */
907 static Void disconnectFromLAD(Int clientId)
909     LOG0("\nLAD_DISCONNECT: ")
911     LOG1("\n    client handle = %x", clientId)
912     doDisconnect(clientId);
914     LOG0("DONE\n")
916     return;
920 /*
921  *  ======== doDisconnect ========
922  */
923 static Void doDisconnect(Int clientId)
925     /* set "this client is not connected" flag */
926     clientConnected[clientId] = FALSE;
928     /* close and remove the response FIFO */
929     LOG2("\n    closing FIFO %s (filePtr=%p)\n",
930         clientFIFOName[clientId], responseFIFOFilePtr[clientId])
931     fclose(responseFIFOFilePtr[clientId]);
933     LOG1("    done, unlinking %s\n", clientFIFOName[clientId]);
934     unlink(clientFIFOName[clientId]);