/* UNIX Daemon Server Programming Sample Program Levent Karakas May 2001 To compile: gcc -o ../bin/bancsig bancserial.c daemonize.c To run: ./bancsig To test daemon: ps -ef|grep bancsig (or ps -aux on BSD systems) To test log: tail -f /var/log/bancsig.log To test signal: kill -HUP `cat /var/lock/bancsig.lock` To terminate: kill `cat /var/lock/bancsig.lock` */ // AT, @hitec.fr // 20 nov 2009. // This daemon check last modified time of DATANEEDEDFILE. // If less than LIFE seconds, do its job // otherwise delete DATANEEDEDFILE. // // Its job : Read 3 sensors linked to serial ports. // Update 3 files (MYFILE0...) with read values. // (Could be improved to update also the 3 units.) #include #include #include #include #include #include #include #define RUNNING_DIR "/var/run" #define LOCK_FILE "/var/run/bancsig.pid" #define LOG_FILE "/var/log/bancsig.log" ///////// LAST MODIFIED TIME ///////////// #include // Needed to check last access time #include #define DATANEEDEDFILE "/home/etalon/public_html/safedir/pleaseKeepValUpdated" #define LIFE 5 // (secondes) age maxi du fichier DATANEEDEDFILE // avant l arret des lectures et sa destruction ////////////////////////////////////////// /* baudrate settings are defined in , which is included by */ #define BAUDRATE0 B2400 #define BAUDRATE1 B9600 #define BAUDRATE2 B9600 /* change this definition for the correct port */ #define MODEMDEVICE0 "/dev/ttyS0" #define MODEMDEVICE1 "/dev/ttyS1" #define MODEMDEVICE2 "/dev/ttyS2" /* Define target files where to store values*/ #define MYFILE0 "/usr/lib/bancsig/tmpfs/value0" #define MYFILE1 "/usr/lib/bancsig/tmpfs/value1" #define MYFILE2 "/usr/lib/bancsig/tmpfs/value2" ////////////////////////////////////////// void log_message(filename,message) char *filename; char *message; { FILE *logfile; logfile=fopen(filename,"a"); if(!logfile) return; fprintf(logfile,"%s\n",message); fclose(logfile); } void signal_handler(sig) int sig; { switch(sig) { case SIGHUP: log_message(LOG_FILE,"hangup signal catched"); break; case SIGTERM: //log_message(LOG_FILE,"terminate signal catched"); log_message(LOG_FILE,"Try to destroy pid file"); unlink(LOCK_FILE); exit(0); break; } } void daemonize() { int i,lfp; char str[10]; if(getppid()==1) return; /* already a daemon */ i=fork(); if (i<0) exit(1); /* fork error */ if (i>0) exit(0); /* parent exits */ /* child (daemon) continues */ setsid(); /* obtain a new process group */ for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */ i=open("/dev/null",O_RDWR); dup(i); dup(i); /* handle standart I/O */ umask(027); /* set newly created file permissions */ chdir(RUNNING_DIR); /* change running directory */ lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640); if (lfp<0) exit(1); /* can not open */ if (lockf(lfp,F_TLOCK,0)<0) exit(0); /* can not lock */ /* first instance continues */ sprintf(str,"%d\n",getpid()); write(lfp,str,strlen(str)); /* record pid to lockfile */ signal(SIGCHLD,SIG_IGN); /* ignore child */ signal(SIGTSTP,SIG_IGN); /* ignore tty signals */ signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGHUP,signal_handler); /* catch hangup signal */ signal(SIGTERM,signal_handler); /* catch kill signal */ } main() { int fd0, fd1, fd2 ; // descripteurs de fichiers int res0, res1, res2; char buf0[64], buf1[64], buf2[64], out[64]; FILE *fp0, *fp1, *fp2; // Pointeurs fichiers destination struct stat buf; // statistiques sur le fichier (dont last modified time) time_t ltime; // Local time // ---------------------- DAEMONIZE -------------------------- daemonize(); // ---------------------- INITS ------------------------------ // Open ports // ---------- fd0 = openPort(MODEMDEVICE0, BAUDRATE0); fd1 = openPort(MODEMDEVICE1, BAUDRATE1); fd2 = openPort(MODEMDEVICE2, BAUDRATE2); // ---------------------- LOOP ------------------------------- while (1) { // Control if data needed (check age of file) // ------------------------------------------ if (!stat(DATANEEDEDFILE, &buf)) { // File exists, stats are now in buf // Save local present time in ltime time(<ime); // Compute file age if ((int)difftime(ltime,buf.st_mtime) <= LIFE) { // ALIVE : Do the job // ------------------ // Start outputs to ports (requetes de demande des valeurs des instruments) // ---------------------- write(fd0, "30\r", 3); // <-- Pour le METRIX write(fd1, "*PGR\r", 5); // <-- Pour les CONDEC write(fd2, "*PGR\r", 5); // <-- Pour les CONDEC // Wait... usleep(200000); // 200ms important ! sinon réponse pas prete dans le buffer // Start readings on ports // ----------------------- res0 = read(fd0,buf0,64); res1 = read(fd1,buf1,64); res2 = read(fd2,buf2,64); buf0[res0]=0; /* set end of string, so we can printf */ buf1[res1]=0; buf2[res2]=0; // Clean and output results // ------------------------ // Device 0 if (cleanNumeric(buf0, out)) { //printf("dev0: %s\n", out); fp0 = fopen(MYFILE0, "w"); fprintf(fp0, "%s\n", out); fclose(fp0); chmod(MYFILE0, 0644); } // Device 1 if (cleanNumeric(buf1, out)) { fp1 = fopen(MYFILE1, "w"); fprintf(fp1, "%s\n", out); fclose(fp1); chmod(MYFILE1, 0644); } // Device 2 if (cleanNumeric(buf2, out)) { fp2 = fopen(MYFILE2, "w"); fprintf(fp2, "%s\n", out); fclose(fp2); chmod(MYFILE2, 0644); } } // FIN if ALIVE ? else { // DEAD, on supprime le fichier remove(DATANEEDEDFILE); //if (remove(DATANEEDEDFILE) == -1) // printf("Error deleting the file.\n"); } } // Wait a little... // ---------------- usleep(100000); } // END of while(1) // ---------------------- END ---------------------------------- } /* EOF */