1:/*---------------------------------------------------------------------------
   2: 
   3:  FILENAME:
   4:        template2.c
   5: 
   6:  PURPOSE:
   7:        Provide the 2nd radlib template process entry point.
   8: 
   9:  REVISION HISTORY:
  10:        Date            Engineer        Revision        Remarks
  11:        01/01/2004      Your Name       0               Original
  12: 
  13:  NOTES:
  14:        All references to "template" should be replaced by a meaningful
  15:        process name, including the file names and data structures.
  16: 
  17:----------------------------------------------------------------------------*/
  18:
  19:// System include files
  20:#include <sys/types.h>
  21:#include <sys/wait.h>
  22:#include <unistd.h>
  23:
  24:// radlib include files
  25:
  26:// Local include files
  27:#include "template.h"
  28:
  29:
  30:// global memory declarations
  31:
  32:// global memory referenced
  33:
  34:// static (local) memory declarations
  35:
  36:// declare the process work area
  37:static TEMPLATE_WORK    templateWork;
  38:
  39:
  40:// methods
  41:
  42:static void msgHandler
  43:(
  44:    char        *srcQueueName,
  45:    UINT        msgType,
  46:    void        *msg,
  47:    UINT        length,
  48:    void        *userData
  49:)
  50:{
  51:    STIM        stim;
  52:
  53:    stim.type           = STIM_QMSG;
  54:    stim.srcQueueName   = srcQueueName;
  55:    stim.msgType        = msgType;
  56:    stim.msg            = msg;
  57:    stim.length         = length;
  58:
  59:    radStatesProcess (templateWork.stateMachine, &stim);
  60:
  61:    return;
  62:}
  63:
  64:static void evtHandler
  65:(
  66:    UINT        eventsRx,
  67:    UINT        rxData,
  68:    void        *userData
  69:)
  70:{
  71:    STIM        stim;
  72:
  73:    stim.type           = STIM_EVENT;
  74:    stim.eventsRx       = eventsRx;
  75:    stim.eventData      = rxData;
  76:
  77:    radStatesProcess (templateWork.stateMachine, &stim);
  78:
  79:    return;
  80:}
  81:
  82:// process initialization
  83:static int templateSysInit (void)
  84:{
  85:    char            devPath[256], temp[32];
  86:    char            *installPath;
  87:    struct stat     fileData;
  88:    FILE            *pidfile;
  89:
  90:    // get the install path
  91:    installPath = getenv ("APPLICATION_RUN_DIRECTORY");
  92:    if (installPath == NULL)
  93:    {
  94:        installPath = ".";
  95:    }
  96:    chdir (installPath);
  97:
  98:
  99:    // check for our pid file, don't run if it is there
 100:    sprintf (devPath, "%s/%s", installPath, TEMPLATE2_LOCK_FILENAME);
 101:    if (stat (devPath, &fileData) == 0)
 102:    {
 103:        printf ("lock file %s exists, older copy may be running - aborting!\n",
 104:                devPath);
 105:        return -1;
 106:    }
 107:
 108:
 109:    // create our device directory if it is not there
 110:    sprintf (devPath, "%s/dev", installPath);
 111:    if (stat (devPath, &fileData) != 0)
 112:    {
 113:        if (mkdir (devPath, 0755) != 0)
 114:        {
 115:            printf ("Cannot create device dir: %s - aborting!\n",
 116:                    devPath);
 117:            return -1;
 118:        }
 119:    }
 120:
 121:    return 0;
 122:}
 123:
 124:// system exit
 125:static int templateSysExit (void)
 126:{
 127:    char            devPath[256];
 128:    char            *installPath;
 129:    struct stat     fileData;
 130:
 131:    // get the install path
 132:    installPath = getenv ("APPLICATION_RUN_DIRECTORY");
 133:    if (installPath == NULL)
 134:    {
 135:        installPath = ".";
 136:    }
 137:
 138:    // delete our pid file
 139:    sprintf (devPath, "%s/%s", installPath, TEMPLATE2_LOCK_FILENAME);
 140:    if (stat (devPath, &fileData) == 0)
 141:    {
 142:        printf ("\nlock file %s exists, deleting it...\n",
 143:                devPath);
 144:        if (unlink (devPath) == -1)
 145:        {
 146:            printf ("lock file %s delete failed!\n",
 147:                    devPath);
 148:        }
 149:    }
 150:
 151:    return 0;
 152:}
 153:
 154:static void defaultSigHandler (int signum)
 155:{
 156:    switch (signum)
 157:    {
 158:        case SIGPIPE:
 159:            // if you are using sockets or pipes, you will need to catch this
 160:            // we have a far end socket disconnection, we'll handle it in the
 161:            // "read/write" code
 162:            signal (signum, defaultSigHandler);
 163:            break;
 164:
 165:        case SIGILL:
 166:        case SIGBUS:
 167:        case SIGFPE:
 168:        case SIGSEGV:
 169:        case SIGXFSZ:
 170:        case SIGSYS:
 171:            // unrecoverable signal - we must exit right now!
 172:            radMsgLog (PRI_CATASTROPHIC, "template2d: recv sig %d: bailing out!", signum);
 173:            abort ();
 174:        
 175:        case SIGCHLD:
 176:            wait (NULL);
 177:            signal (signum, defaultSigHandler);
 178:            break;
 179:
 180:        default:
 181:            // can we allow the process to exit normally?
 182:            if (radProcessGetExitFlag())
 183:            {
 184:                // NO! - we gotta bail here!
 185:                radMsgLog (PRI_HIGH, "template2d: recv sig %d: exiting now!", signum);
 186:                exit (0);                
 187:            }
 188:            
 189:            // we can allow the process to exit normally...
 190:            radMsgLog (PRI_HIGH, "template2d: recv sig %d: exiting!", signum);
 191:        
 192:            radProcessSetExitFlag ();
 193:        
 194:            signal (signum, defaultSigHandler);
 195:            break;
 196:    }
 197:
 198:    return;
 199:}
 200:
 201:
 202:// the main entry point for the template process
 203:int main (int argc, char *argv[])
 204:{
 205:    void            (*alarmHandler)(int);
 206:    STIM            stim;
 207:    int             i;
 208:    char            qname[256], cfgname[256], instance[32], value[32];
 209:    char            pidName[256];
 210:    char            *installPath;
 211:    CF_ID           configFileId;
 212:    struct stat     fileStatus;
 213:    FILE            *pidfile;
 214:
 215:
 216:    // initialize some system stuff first
 217:    if (templateSysInit () == -1)
 218:    {
 219:        radMsgLogInit (PROC_NAME_TEMPLATE2, TRUE, TRUE);
 220:        radMsgLog (PRI_CATASTROPHIC, "system init failed!\n");
 221:        radMsgLogExit ();
 222:        exit (1);
 223:    }
 224:
 225:    // create some file paths for later use
 226:    installPath = getenv ("APPLICATION_RUN_DIRECTORY");
 227:    if (installPath == NULL)
 228:    {
 229:        installPath = ".";
 230:    }
 231:    sprintf (qname, "%s/dev/%s", installPath, PROC_NAME_TEMPLATE2);
 232:    sprintf (cfgname, "%s/%s", installPath, TEMPLATE_CONFIG_FILENAME);
 233:    sprintf (pidName, "%s/%s", installPath, TEMPLATE2_LOCK_FILENAME);
 234:
 235:    memset (&templateWork, 0, sizeof (templateWork));
 236:
 237:
 238:
 239:    // call the global radlib system init function
 240:    if (radSystemInit (TEMPLATE_SYSTEM_ID) == ERROR)
 241:    {
 242:        radMsgLogInit (PROC_NAME_TEMPLATE2, TRUE, TRUE);
 243:        radMsgLog (PRI_CATASTROPHIC, "%s: radSystemInit failed!");
 244:        radMsgLogExit ();
 245:        exit (1);
 246:    }
 247:
 248:
 249:    // call the radlib process init function
 250:    if (radProcessInit (PROC_NAME_TEMPLATE2,
 251:                        qname,
 252:                        0,                          // no timers
 253:                        TRUE,                       // TRUE => daemon
 254:                        msgHandler,
 255:                        evtHandler,
 256:                        NULL)
 257:            == ERROR)
 258:    {
 259:        radMsgLogInit (PROC_NAME_TEMPLATE2, TRUE, TRUE);
 260:        radMsgLog (PRI_CATASTROPHIC, "radProcessInit failed: %s",
 261:                   PROC_NAME_TEMPLATE2);
 262:        radMsgLogExit ();
 263:
 264:        radSystemExit (TEMPLATE_SYSTEM_ID);
 265:
 266:        exit (1);
 267:    }
 268:
 269:    // save our process pid and create the lock file 
 270:    templateWork.myPid = getpid ();
 271:    pidfile = fopen (pidName, "w");
 272:    if (pidfile == NULL)
 273:    {
 274:        radMsgLog (PRI_CATASTROPHIC, "lock file create failed!\n");
 275:
 276:        radProcessExit ();
 277:        radSystemExit (TEMPLATE_SYSTEM_ID);
 278:
 279:        exit (1);
 280:    }
 281:    fprintf (pidfile, "%d", templateWork.myPid);
 282:    fclose (pidfile);
 283:
 284:
 285:    // save the current alarm signal handler, set all signal handlers
 286:    // to the default handler, then set the alarm handler back to original
 287:    alarmHandler = radProcessSignalGetHandler (SIGALRM);
 288:    radProcessSignalCatchAll (defaultSigHandler);
 289:    radProcessSignalCatch (SIGALRM, alarmHandler);
 290:
 291:
 292:    // create our state machine - where all run-time work is done
 293:    templateWork.stateMachine = radStatesInit (&templateWork);
 294:    if (templateWork.stateMachine == NULL)
 295:    {
 296:        radMsgLog (PRI_HIGH, "radStatesInit failed");
 297:
 298:        radProcessExit ();
 299:        radSystemExit (TEMPLATE_SYSTEM_ID);
 300:
 301:        exit (1);
 302:    }
 303:
 304:    if (radStatesAddHandler (templateWork.stateMachine, TEMPLATE_STATE_IDLE,
 305:                             template2IdleState)
 306:            == ERROR)
 307:    {
 308:        radMsgLog (PRI_HIGH, "radStatesAddHandler failed");
 309:        radStatesExit (templateWork.stateMachine);
 310:
 311:        radProcessExit ();
 312:        radSystemExit (TEMPLATE_SYSTEM_ID);
 313:
 314:        exit (1);
 315:    }
 316:    if (radStatesAddHandler (templateWork.stateMachine, TEMPLATE_STATE_RUN,
 317:                             template2RunState)
 318:            == ERROR)
 319:    {
 320:        radMsgLog (PRI_HIGH, "radStatesAddHandler failed");
 321:        radStatesExit (templateWork.stateMachine);
 322:
 323:        radProcessExit ();
 324:        radSystemExit (TEMPLATE_SYSTEM_ID);
 325:
 326:        exit (1);
 327:    }
 328:    if (radStatesAddHandler (templateWork.stateMachine, TEMPLATE_STATE_ERROR,
 329:                             template2ErrorState)
 330:            == ERROR)
 331:    {
 332:        radMsgLog (PRI_HIGH, "radStatesAddHandler failed");
 333:        radStatesExit (templateWork.stateMachine);
 334:
 335:        radProcessExit ();
 336:        radSystemExit (TEMPLATE_SYSTEM_ID);
 337:
 338:        exit (1);
 339:    }
 340:
 341:    radStatesSetState (templateWork.stateMachine, TEMPLATE_STATE_IDLE);
 342:
 343:
 344:    // initialize the radlib message router interface
 345:    if (radMsgRouterInit (".") == ERROR)
 346:    {
 347:        radMsgLog (PRI_HIGH, "radMsgRouterInit failed");
 348:        radStatesExit (templateWork.stateMachine);
 349:
 350:        radProcessExit ();
 351:        radSystemExit (TEMPLATE_SYSTEM_ID);
 352:
 353:        exit (1);
 354:    }
 355:
 356:    radMsgRouterMessageRegister (TEMPLATE_MSGID_USER_REQUEST);
 357:
 358:
 359:    radMsgLog (PRI_STATUS, "running ...");
 360:
 361:
 362:    // dummy up a stimulus to get the state machine running
 363:    stim.type = STIM_DUMMY;
 364:    radStatesProcess (templateWork.stateMachine, &stim);
 365:
 366:
 367:    while (!templateWork.exiting)
 368:    {
 369:        // wait on timers, events, file descriptors, msgs, everything!
 370:        if (radProcessWait (0) == ERROR)
 371:        {
 372:            templateWork.exiting = TRUE;
 373:        }
 374:    }
 375:
 376:
 377:    radMsgLog (PRI_STATUS, "exiting normally...");
 378:
 379:    radStatesExit (templateWork.stateMachine);
 380:    templateSysExit ();
 381:
 382:    radProcessExit ();
 383:    radSystemExit (TEMPLATE_SYSTEM_ID);
 384:
 385:    exit (0);
 386:}
 387: