--- /dev/null
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/********************************************************/
+/* */
+/* Module for low level subroutine */
+/* */
+/********************************************************/
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "subrou.h"
+#include "uniprc.h"
+
+
+//directory to set lock
+#define DIRLOCK "/var/run/"APPNAME
+
+static _Bool modopen; //boolean module open/close
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to allow process core DUMP */
+/* to trace origin of problem */
+/* */
+/* NOTE: */
+/* On linux to have a working coredump, you MUST */
+/* add to /etc/sysctl.conf */
+/* fs.suid_dumpable=1 */
+/* kernel.core_uses_pid=1 */
+/* kernel.core_pattern=./core.%e.%p */
+/* */
+/********************************************************/
+void prc_allow_core_dump()
+
+{
+struct rlimit limites;
+
+if (getrlimit(RLIMIT_CORE,&limites)<0) {
+ (void) fprintf(stderr,"getrlimit error='%s'",strerror(errno));
+ }
+limites.rlim_cur=limites.rlim_max;
+if (setrlimit(RLIMIT_CORE,&limites)<0) {
+ (void) fprintf(stderr,"setrlimit error='%s'",strerror(errno));
+ }
+(void) prctl(PR_SET_DUMPABLE,1,0,0,0);/*to allow core-dump */
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* procedure to check if a process is */
+/* still up and running. */
+/* */
+/********************************************************/
+_Bool prc_checkprocess(pid_t pidnum)
+
+{
+#define SIGCHECK 0 //signal to check if process
+ //is existing.
+ //
+_Bool status;
+
+status=false;
+switch(pidnum) {
+ case (pid_t)0 : /*0 means no process */
+ status=false;
+ break;
+ case (pid_t)1 : /*init process always OK*/
+ status=true;
+ break;
+ default : /*standard process */
+ if (kill(pidnum,SIGCHECK)==0)
+ status=true;
+ break;
+ }
+return status;
+#undef SIGCHECK
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to set/unset a lock */
+/* return true if successful, */
+/* false otherwise. */
+/* */
+/********************************************************/
+_Bool prc_locking(const char *lockname,int lock,int tentative)
+
+{
+#define OPEP "uniprc.c:lck_locking,"
+
+_Bool done;
+char *fullname;
+struct stat bufstat;
+int phase;
+_Bool proceed;
+
+done=false;
+fullname=(char *)0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //setting lock filename
+ if (lockname==(const char *)0) {
+ (void) rou_alert(9,"%s lockname is missing (bug?)",OPEP);
+ phase=999; //big trouble, No need to go further
+ }
+ break;
+ case 1 : //creating the lock directory if needed
+ int status;
+ char cmd[100];
+
+ fullname=rou_apppath(DIRLOCK);
+ (void) snprintf(cmd,sizeof(cmd),"mkdir -p %s",fullname);
+ if ((status=system(cmd))!=0) {
+ (void) rou_alert(9,"Unable to create <%s> directory (system?/bug?)",
+ fullname);
+ phase=999; //big trouble, No need to go further
+ }
+ (void) free(fullname);
+ break;
+ case 2 : //setting lock filename
+ const char *fname;
+ char *name;
+
+ if ((fname=strrchr(lockname,'/'))==(char *)0)
+ fname=lockname;
+ else
+ fname++;
+ name=(char *)calloc(sizeof(DIRLOCK)+strlen(fname)+10,sizeof(char));
+ (void) sprintf(name,"%s/%s.lock",DIRLOCK,fname);
+ fullname=rou_apppath(name);
+ (void) free(name);
+ break;
+ case 3 : //checking if link already exist
+ if (stat(fullname,&bufstat)<0) {
+ phase++; //no need to check lock contents
+ }
+ break;
+ case 4 : //making lockname
+ if (S_ISREG(bufstat.st_mode)!=0) {
+ FILE *fichier;
+
+ if ((fichier=fopen(fullname,"r"))!=(FILE *)0) {
+ pid_t pid;
+ char strloc[80];
+
+ (void) fgets(strloc,sizeof(strloc)-1,fichier);
+ (void) fclose(fichier);
+ if (sscanf(strloc,"%lu",(u_long *)(&pid))==1) {
+ (void) rou_alert(2,"Locking, check %d process active",pid);
+ if (prc_checkprocess(pid)==false) {
+ (void) rou_alert(2,"Locking, removing pid=%d unactive lock",pid);
+ (void) unlink(fullname);
+ }
+ else {
+ if (lock==LCK_LOCK) {
+ (void) rou_alert(0,"lock check, found %d process still active",pid);
+ phase=999; //no need to go further
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 5 : //do we need to unlock ?
+ if (lock==LCK_UNLOCK) {
+ (void) rou_alert(9,"%s Request unlocking <%s>",OPEP,fullname);
+ (void) unlink(fullname);
+ done=true;
+ phase=999; //No need to go further
+ }
+ break;
+ case 6 : //making lockname
+ (void) rou_alert(6,"%s Request locking <%s>",OPEP,fullname);
+ while (tentative>0) {
+ int handle;
+
+ tentative--;
+ if ((handle=open(fullname,O_RDWR|O_EXCL|O_CREAT,0640))>=0) {
+ char numid[30];
+
+ (void) snprintf(numid,sizeof(numid),"%d\n",getpid());
+ (void) write(handle,numid,strlen(numid));
+ (void) close(handle);
+ done=true;
+ break; //breaking "tentative" loop
+ }
+ else {
+ (void) rou_alert(3,"Trying one more second to lock <%s> (error=<%s>)",
+ fullname,strerror(errno));
+ (void) sleep(1);
+ }
+ }
+ break;
+ default : //SAFE Guard
+ if (done==false)
+ (void) rou_alert(2,"Unable to set <%s> lock (config?)",lockname);
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+if (fullname!=(char *)0)
+ (void) free(fullname);
+return done;
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* */
+/* Procedure to put a process in background */
+/* mode. */
+/* Return the child process id. */
+/* */
+/********************************************************/
+pid_t prc_divedivedive()
+
+{
+#define OPEP "uniprc:rou_divedivedive,"
+pid_t childpid;
+
+childpid=(pid_t)0;
+switch (childpid=fork()) {
+ case -1 :
+ (void) fprintf(stderr,"%s, Unable to dive! (error=<%s>)",
+ OPEP,strerror(errno));
+ break;
+ case 0 :
+ //we are now in background mode
+ (void) setsid();
+ break;
+ default :
+ //waiting for ballast to fill up :-}}
+ (void) sleep(1);
+ break;
+ }
+return childpid;
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to "open/close" module and do */
+/* homework purpose */
+/* return zero if everything right */
+/* */
+/********************************************************/
+int prc_modeuniprc(_Bool mode)
+
+{
+#define OPEP "unipar.c:uni_modeuniprc"
+
+int status;
+
+status=0;
+if (mode!=modopen) {
+ (void) rou_modesubrou(mode);
+ switch ((int)mode) {
+ case true :
+ (void) prc_allow_core_dump();
+ break;
+ case false :
+ break;
+ default :
+ (void) fprintf(stderr,"Calling %s with wrong mode='%d' (Bug?!):",
+ OPEP,(int)mode);
+ status=-1;
+ break;
+ }
+ modopen=mode;
+ }
+return status;
+#undef OPEP
+}