00001 #define CD_MAIN
00002 #include "auc-cd.h"
00003
00004 #include <stdio.h>
00005 #include <fcntl.h>
00006 #include <signal.h>
00007 #include <unistd.h>
00008
00009 const char *cdOrKb;
00010 using namespace std;
00011
00012
00013
00014
00015
00016
00017 void runCommander();
00018 void setSignals();
00019 void signal_handler(int);
00020 void usage();
00021
00022 using namespace boost::interprocess;
00023 using namespace std;
00024
00025 void aucClientServer() {
00026
00027 int i,lfp;
00028 char str[10];
00029
00030 thisConfig->daemonProcess = fork();
00031 if (thisConfig->daemonProcess < 0) {
00032 puts("Can't initialize process!");
00033 exit(1);
00034 }
00035 if (thisConfig->runCommander && getpid() == thisConfig->shellProcess)
00036 {setSignals(); runCommander();}
00037 setsid();
00038 i=open("/dev/null",O_RDWR); dup(i); dup(i);
00039 umask(027);
00040 chdir(RUNNING_DIR);
00041 lfp=open(CD_LOCK_FILE,O_RDWR|O_CREAT,0640);
00042 if (lfp<0) {puts("Can't open lockfile!"); exit(1);}
00043 if (lockf(lfp,F_TLOCK,0)<0)
00044 {puts("Can't lock lockfile!"); exit(0);}
00045 shared_memory_object shm(open_only, "auc-cd-global", read_write);
00046 mapped_region aucCDglobal(shm, read_write);
00047 gm = (auc_cd_global *)aucCDglobal.get_address();
00048 if (strcmp(gm->id,"auc-cd"))
00049 {theseLogs.logN(0,"Daemon couldn't identify global memory. Bye."); exit(1);}
00050 gm->daemon_pid = getpid();
00051 sprintf(str,"%d",getpid());
00052 theseLogs.logN(1,"auc-cd running (%s)",str);
00053 strcat(str,"\n");
00054 write(lfp,str,strlen(str));
00055 setSignals();
00056
00057 theseLogs.init("auc-cd");
00058 theseLogs.logN(0,CD_NAME " " CD_VERSION " compiled on " __DATE__ " @ " __TIME__);
00059 theseLogs.logN(3,"Cliever processing(%d) begins for devices on port %s to MD at %s.",getpid(),thisConfig->telemetryPortStr.c_str(),thisConfig->mdAddress.c_str());
00060
00061 try {
00062
00063 if (*cdOrKb == 'd') {
00064 theseLogs.logN(0,"Creating CLIPS Environment.");
00065 #ifdef MD_MAND
00066 DACLIPS::init();
00067 #endif
00068 }
00069
00070 boost::thread cliever(runCliever);
00071 boost::thread dataLayer(runDataLayer);
00072
00073 if (!dataLayer.joinable() || !cliever.joinable()) {
00074 if (!dataLayer.joinable())
00075 theseLogs.logN(0,"Failed to start data layer, auc-cd process will terminate.");
00076 if (!cliever.joinable())
00077 theseLogs.logN(0,"Failed to start client-server, auc-cd process will terminate.");
00078 }
00079 else {
00080 theseLogs.logN(0,"Cliever started OK.");
00081 dataLayer.join();
00082 theseLogs.logN(0,"auc-cd EOJ.");
00083 }
00084
00085 }
00086 catch (std::exception &e)
00087 {
00088 theseLogs.logN(1,"Exception: %s",e.what());
00089 }
00090 catch (...) {
00091 theseLogs.logN(0,"General fault.");
00092 }
00093
00094 exit(thisCliever->rc);
00095
00096 }
00097 int main(int const argc, const char ** const argv)
00098 {
00099 const char *exeName,*banner = "\n" CD_NAME " " CD_VERSION " compiled on " __DATE__ " @ " __TIME__ " (%d)\n";
00100 int mthParm, rc = OK;
00101
00102 exeName = (strcspn(argv[0],"./") == strlen(argv[0])) ? argv[0] : strrchr(argv[0],'/') + 1;
00103 cdOrKb = exeName;
00104 thisCliever = NULL;
00105
00106
00107 struct shm_remove
00108 {
00109 shm_remove() { shared_memory_object::remove("auc-cd-global"); }
00110 ~shm_remove() { shared_memory_object::remove("auc-cd-global"); }
00111 } remover;
00112
00113 shared_memory_object shm(create_only, "auc-cd-global", read_write);
00114 shm.truncate(CD_GLOBAL_SIZE);
00115 mapped_region aucCDglobal(shm, read_write);
00116 memset(aucCDglobal.get_address(), 0, aucCDglobal.get_size());
00117 gm = (auc_cd_global *)aucCDglobal.get_address();
00118 strcpy(gm->id,"auc-cd");
00119 strcmp(gm->id,"auc-cd");
00120
00121
00122 thisConfig = new clientDaemonConfig();
00123 thisConfig->shellProcess = getpid();
00124 strcpy(thisConfig->origCmd,argv[0]);
00125
00126 if (argc < 2 || argc > 7) usage();
00127
00128 thisConfig->telemetryPort = atoi(argv[1]);
00129 if (thisConfig->telemetryPort < 1000 || thisConfig->telemetryPort > 65535)
00130 {
00131 std::cerr << "The <telemetry-udp-port> value is invalid.\n";
00132 exit(1);
00133 }
00134 thisConfig->telemetryPortStr = std::string(argv[1]);
00135 for (mthParm=2;mthParm < argc;mthParm++) {
00136 if (*argv[mthParm] == '*') {
00137 thisConfig->runCommander = false;
00138 }
00139 else
00140 if (!strncmp(argv[mthParm],"device=",7)) {
00141 thisConfig->deviceName = std::string(argv[mthParm]+8);
00142 }
00143 else
00144 if (!strncmp(argv[mthParm],"logs=",4)) {
00145 strcpy(thisConfig->logPath,argv[mthParm]+5);
00146 }
00147 else
00148 if (!strncmp(argv[mthParm],"mdIP=",4)) {
00149 thisConfig->mdAddress = std::string(argv[mthParm]+5);
00150 }
00151 else usage();
00152 }
00153
00154 if (thisConfig->runCommander) printf(banner,thisConfig->shellProcess);
00155 aucClientServer();
00156 while(!gm->graceful) sleep(2);
00157
00158 }
00159 void runCommander() {
00160
00161 char msg[128];
00162 int i;
00163 mdCommander commander;
00164
00165 theseLogs.init("auc-cd-ui");
00166 theseLogs.logN(0,"Interactive command processor started.");
00167 commander.driver();
00168 if (thisConfig->terminateRequest) {
00169 theseLogs.logN(0,"Interactive shutdown requested.");
00170 puts("auc-cd operator issued terminate command.");
00171 kill(gm->daemon_pid,SIGTERM);
00172 } else {
00173 theseLogs.logN(0,"Interactive command processor ended.");
00174 sprintf(msg,"Commander terminated, auc-cd continues (%d).",gm->daemon_pid);
00175 puts(msg);
00176 }
00177
00178 theseLogs.logN(1,"Closing out I/O for shell process (%d)",thisConfig->shellProcess);
00179 for (i=getdtablesize();i>=0;--i) close(i);
00180
00181 exit(0);
00182
00183 }
00184 void setSignals() {
00185
00186 signal(SIGCHLD,SIG_IGN);
00187 signal(SIGTSTP,SIG_IGN);
00188 signal(SIGTTOU,SIG_IGN);
00189 signal(SIGTTIN,SIG_IGN);
00190 signal(SIGSEGV,signal_handler);
00191 signal(SIGUSR1,signal_handler);
00192 signal(SIGHUP,signal_handler);
00193 signal(SIGTERM,signal_handler);
00194
00195 }
00196 void signal_handler(int sig)
00197 {
00198 switch(sig) {
00199 case SIGSEGV:
00200 break;
00201 case SIGUSR1:
00202 break;
00203 case SIGHUP:
00204 theseLogs.logN(0,"hangup signal caught, currently auc-cd ignores this.");
00205 break;
00206 case SIGTERM:
00207 theseLogs.logN(0,"terminate signal caught, auc-cd will shutdown.");
00208 cdShutdown termEvent;
00209 termEvent.send();
00210 break;
00211 }
00212
00213 }
00214 void usage() {
00215
00216 std::cerr << "Usage: " << cdOrKb << " <udp-port> ['*'] [device=TEST] [mdIP=" MD_DEFAULT_IP "] [logs=\\tmp]\n\n where \n\n"
00217 "\t <udp-port> is required, must be the first parameter, and must be 1000 or greater. \n"
00218 "\t The other parameters are optional and non-positional and take the shown defaults. \n"
00219 "\t '*', if present, indicates skip the command loop (string quotes may be required). \n";
00220 exit(1);
00221 }