## root/clib/appinit.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following definitions.

1. appinit_start
2. appinit_stop
3. appinit_waitfor
4. appinit_register_name
5. appinit_get_name
6. appinit_remove_name
7. appinit_get_sname

    /* Application initialization/notification API.
       Rick Smereka, Copyright (C) 2002-2004.

       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2 of the License, or
       (at your option) any later version.

       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.

       You should have received a copy of the GNU General Public License
       along with this program; if not, get a copy via the Internet at
       http://gnu.org/copyleft/gpl.html or write to the Free Software
       Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       MA 02111-1307 USA

       You can contact the author via email at rsmereka@future-lab.com

       This API notifies other applications that the running program
       is initializing. Notification is done through a lock file.
       This API should be used by any program that depends on other
       applications to be running before starting-up. This API also
       provides a storage location for the application name in case
       this name is required by another API outside of the main
       program module.

       Original Linux version. May/2002, Rick Smereka

       Ported to 32-bit Windows. Jun/2002, Rick Smereka

       Added functions to register and obtain the application name.
       Ported to QNX 4.x. Jul/2002, Rick Smereka

       Ported to Debian Linux. Nov/2002, Rick Smereka

       Fixed bug in function 'appinit_get_name' that ignored whether
       'appinit_apname' was NULL. Changed all logging calls from
       'log_file_date' to 'logman'. Mar/2004, Rick Smereka */

    #include "stdhead.h"
    #include "appinit.h"

    /* global module data */

    char *appinit_apname = (char *)NULL;

    /* private function */

    static int appinit_get_sname(char *, char *);

    int appinit_start(char *sname)
    {
       /* Indicate that the application is starting up by creating
          a zero byte lock file. The parameter 'sname' should be a
          unique name to identify the application and is usually
          the 'socloc' service name when dealing with a socket
          server. Function returns 'TRUE' upon success, 'FALSE'
          otherwise. */

       char *nsname, mname[] = "appinit_start";

       logman("%s:enter:sname=%s", mname, sname);

       if (sname == (char *)NULL || !strlen(sname))
          {
          logman("%s:exit:null or empty[sname]", mname);
          return(FALSE);
          }

       if ((nsname = (char *)malloc(strlen(sname) + 5)) == (char *)NULL)
          {
          logman("%s:exit:alloc fail[nsname]", mname);
          return(FALSE);
          }

       if (!appinit_get_sname(sname, nsname))
          {
          logman("%s:exit:bad rc[FALSE] from appinit_get_sname", mname);
          free(nsname);
          return(FALSE);
          }

       if (exist(nsname))
          {
          logman("%s:exit:lock file %s already exists", mname, nsname);
          free(nsname);
          return(FALSE);
          }

       if (!zcreate(nsname))
          {
          logman("%s:exit:bad rc[FALSE] from zcreate", mname);
          free(nsname);
          return(FALSE);
          }

       free(nsname);
       logman("%s:normal exit[TRUE]", mname);
       return(TRUE);
    }

    int appinit_stop(char *sname)
    {
       /* Indicate that the application has completed its
          initialization by deleting the zero byte lock file.
          The parameter 'sname' must be the same name used to
          call 'appinit_start'. Function returns 'TRUE' upon
          success, 'FALSE' otherwise. */

       char *nsname, mname[] = "appinit_stop";

       logman("%s:enter:sname=%s", mname, sname);

       if (sname == (char *)NULL || !strlen(sname))
          {
          logman("%s:exit:null or empty[sname]", mname);
          return(FALSE);
          }

       if ((nsname = (char *)malloc(strlen(sname) + 5)) == (char *)NULL)
          {
          logman("%s:exit:alloc fail[nsname]", mname);
          return(FALSE);
          }

       if (!appinit_get_sname(sname, nsname))
          {
          logman("%s:exit:bad rc[FALSE] from appinit_get_sname", mname);
          free(nsname);
          return(FALSE);
          }

       if (!exist(nsname))
          {
          logman("%s:exit:lock file %s not present", mname, nsname);
          free(nsname);
          return(FALSE);
          }

       unlink(nsname);
       free(nsname);
       logman("%s:normal exit[TRUE]", mname);
       return(TRUE);
    }

    int appinit_waitfor(char *sname, int min_timeout)
    {
       /* Check for a lock file using the name 'sname'. Wait
          up to 'min_timeout' minutes for the lock file to be
          removed. Function returns 'TRUE' if the lock file
          no longer exists, 'FALSE' otherwise. */

       time_t nowtime, target_time;
       char *nsname, mname[] = "appinit_waitfor";

       logman("%s:enter:sname=%s", mname, sname);

       if (sname == (char *)NULL || !strlen(sname))
          {
          logman("%s:exit:null or empty[sname]", mname);
          return(FALSE);
          }

       if (min_timeout <= 0)
          {
          logman("%s:exit:out of range[min_timeout]", mname);
          return(FALSE);
          }

       if ((nsname = (char *)malloc(strlen(sname) + 5)) == (char *)NULL)
          {
          logman("%s:exit:alloc fail[nsname]", mname);
          return(FALSE);
          }

       if (!appinit_get_sname(sname, nsname))
          {
          logman("%s:exit:bad rc[FALSE] from appinit_get_sname", mname);
          free(nsname);
          return(FALSE);
          }

       nowtime = time(NULL);
       target_time = nowtime + (min_timeout * 60);

       do
          {
          if (!exist(nsname))
             {
             logman("%s:normal exit[TRUE],lock file %s is not present",
                           mname, nsname);
             free(nsname);
             return(TRUE);
             }

    #ifdef OS_UNIX
          /* use 'sleep' under Unix systems to block process */

          sleep(2);
    #endif

          nowtime = time(NULL);
          }
       while(nowtime < target_time);

       free(nsname);
       logman("%s:exit[FALSE]:time expired", mname);
       return(FALSE);
    }

    int appinit_register_name(char *apname)
    {
       /* Load the passed 'apname' into the module global
          'appinit_apname'. Function returns 'TRUE' upon
          success, 'FALSE' otherwise. */

       char mname[] = "appinit_register_name";
       int len, ret = FALSE;

       logman("%s:enter", mname);

       if (apname == (char *)NULL || !strlen(apname))
          {
          logman("%s:exit[FALSE]:null or empty[apname]", mname);
          return(ret);
          }

       len = strlen(apname);

       /* if name already allocated, de-allocate it */

       if (appinit_apname != (char *)NULL)
          if (!appinit_remove_name())
             {
             logman("%s:exit[FALSE]:bad rc from appinit_remove_name",
                           mname);
             return(ret);
             }

       if ((appinit_apname = (char *)malloc(len + 1)) == (char *)NULL)
          {
          logman("%s:exit[FALSE]:alloc fail[appinit_apname]", mname);
          return(ret);
          }

       strcpy(appinit_apname, apname);
       ret = TRUE;
       logman("%s:normal exit[TRUE]", mname);
       return(ret);
    }

    int appinit_get_name(char *apname)
    {
       /* Obtain the application name which must already be defined
          by calling the function 'appinit_register_name'. Function
          returns 'TRUE' upon success with the application name
          loaded into 'apname' (which must already be allocated to
          sufficient size), 'FALSE' otherwise. */

       char mname[] = "appinit_get_name";
       int ret = FALSE;

       logman("%s:enter", mname);

       if (apname == (char *)NULL)
          {
          logman("%s:exit[FALSE]:null[apname]", mname);
          return(ret);
          }

       apname[0] = EOS;

       if (appinit_apname == (char *)NULL || !strlen(appinit_apname))
          return(FALSE);

       strcpy(apname, appinit_apname);
       logman("%s:normal exit[TRUE]", mname);
       ret = TRUE;
       return(ret);
    }

    int appinit_remove_name(void)
    {
       /* De-allocate the current application name ('appinit_apname').
          Function returns 'TRUE' upon success, 'FALSE' otherwise. */

       char mname[] = "appinit_remove_name";
       int ret = FALSE;

       logman("%s:enter", mname);

       if (appinit_apname == (char *)NULL || !strlen(appinit_apname))
          {
          logman("%s:exit[FALSE]:no application name present", mname);
          return(ret);
          }

       free(appinit_apname);
       appinit_apname = (char *)NULL;
       logman("%s:normal exit[TRUE]", mname);
       ret = TRUE;
       return(ret);
    }

    static int appinit_get_sname(char *oldname, char *newname)
    {
       /* Translate an application name. The lock file extension
          will be appended to the name. In addition, any QNX 4.x
          nameloc name (starting with '/') will have its leading
          slash removed. Function will load the translated name
          into 'newname' which must already be allocated by the
          caller to sufficient size. Function returns 'TRUE'
          upon success, 'FALSE' otherwise. */

       char mname[] = "appinit_get_sname";

       logman("%s:enter:oldname=%s", mname, oldname);

       if (oldname == (char *)NULL || !strlen(oldname))
          {
          logman("%s:exit:null or empty[oldname]", mname);
          return(FALSE);
          }

       if (newname == (char *)NULL)
          {
          logman("%s:exit:null[newname]", mname);
          return(FALSE);
          }

       newname[0] = EOS;

    #ifdef IPC_QNX
       if (oldname[0] == '/')
          sprintf(newname, "%s.lck", &oldname[1]);
       else
          sprintf(newname, "%s.lck", oldname);
    #else
       sprintf(newname, "%s.lck", oldname);
    #endif

       logman("%s:normal exit[TRUE]:newname=%s", mname, newname);
       return(TRUE);
    }

/* [<][>][^][v][top][bottom][index][help] */