From f0a51386cd95ccd44b9dd6a1640f95fc8b8f9649 Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Tue, 9 Jul 2024 02:18:23 -0400 Subject: [PATCH] Adding uniprc module --- app/maild.c | 26 ++++- lib/Makefile | 6 +- lib/subrou.c | 28 ++++- lib/subrou.h | 9 +- lib/unipar.c | 2 +- lib/unipar.h | 2 +- lib/uniprc.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/uniprc.h | 39 +++++++ 8 files changed, 398 insertions(+), 10 deletions(-) create mode 100644 lib/uniprc.c create mode 100644 lib/uniprc.h diff --git a/app/maild.c b/app/maild.c index 6666fd8..7e2ba5e 100644 --- a/app/maild.c +++ b/app/maild.c @@ -6,17 +6,27 @@ /********************************************************/ #include #include +#include #include "subrou.h" #include "unipar.h" +#include "uniprc.h" /* */ /********************************************************/ /* */ +/* Program main task */ /* */ /********************************************************/ +static void task() + +{ +(void) rou_alert(0,"JMPDBG starting task"); +(void) sleep(5); +(void) rou_alert(0,"JMPDBG task completed"); +} /* */ @@ -47,12 +57,22 @@ while (proceed==true) { phase=999; //no need to go further } break; - case 1 : //initialising process + case 1 : //Need to go in background mode? + if (foreground==false) + if (prc_divedivedive()!=(pid_t)0) + proceed=false;//Dive mode + break; + case 2 : //initialising process (void) rou_modesubrou(true); - (void) uni_modeunipar(true); + (void) par_modeunipar(true); + (void) prc_modeuniprc(true); + break; + case 3 : //doing main tash + (void) task(); break; default : //end of task - (void) uni_modeunipar(false); + (void) prc_modeuniprc(false); + (void) par_modeunipar(false); (void) rou_modesubrou(false); proceed=false; break; diff --git a/lib/Makefile b/lib/Makefile index f530df6..d0a2cec 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -16,7 +16,7 @@ clean : #Equivalences #-------------------------------------------------------------------- OBJS= \ - unipar.o \ + unipar.o uniprc.o \ subrou.o objs : $(OBJS) @@ -25,6 +25,10 @@ objs : $(OBJS) #-------------------------------------------------------------------- #Dependances +uniprc.o: \ + subrou.h \ + uniprc.h uniprc.c + unipar.o: \ subrou.h \ unipar.h unipar.c diff --git a/lib/subrou.c b/lib/subrou.c index 4dfdcae..aca5e46 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -14,7 +14,7 @@ //version definition #define VERSION "0.1" -#define RELEASE "8" +#define RELEASE "9" //Public variables PUBLIC int debug=0; //debug level @@ -48,6 +48,32 @@ return VERSION"."RELEASE; */ /********************************************************/ /* */ +/* procedure to allocate a path within the root */ +/* directory if needed */ +/* */ +/********************************************************/ +char *rou_apppath(const char *path) + +{ +char *root; +char *newpath; +int taille; +char loc[3]; + +root=""; +newpath=(char *)0; +if (rootdir!=(char *)0) + root=rootdir; +taille=snprintf(loc,sizeof(loc),"%s%s",root,path); +newpath=(char *)calloc(taille+3,sizeof(char)); +(void) sprintf(newpath,"%s%s",root,path); +return newpath; +} +/* + +*/ +/********************************************************/ +/* */ /* Subroutine to log event on syslog */ /* */ /********************************************************/ diff --git a/lib/subrou.h b/lib/subrou.h index 316319a..021f142 100644 --- a/lib/subrou.h +++ b/lib/subrou.h @@ -23,6 +23,12 @@ extern char *appname; //application "official" name //--- Routines implemented within subrou.c --------- +//return program version +extern const char *rou_getversion(); + +//to compute an application path with the root directory +extern char *rou_apppath(const char *path); + //to display message on console (verbose mode) or //via syslog (LOG_INFO) using variable argument list macros void rou_valert(const int dlevel,const char *fmt,va_list ap); @@ -31,9 +37,6 @@ void rou_valert(const int dlevel,const char *fmt,va_list ap); //via syslog (LOG_DAEMON) extern void rou_alert(const int dlevel,const char *fmt,...); -//return program version -extern const char *rou_getversion(); - //homework to be done before starting/stoping module. extern int rou_modesubrou(_Bool mode); diff --git a/lib/unipar.c b/lib/unipar.c index 551387c..2c9b3ca 100644 --- a/lib/unipar.c +++ b/lib/unipar.c @@ -165,7 +165,7 @@ return params; /* return zero if everything right */ /* */ /********************************************************/ -int uni_modeunipar(_Bool mode) +int par_modeunipar(_Bool mode) { #define OPEP "unipar.c:uni_modeunipar" diff --git a/lib/unipar.h b/lib/unipar.h index 29530af..097bf09 100644 --- a/lib/unipar.h +++ b/lib/unipar.h @@ -24,6 +24,6 @@ extern ARGTYP *par_freeparams(ARGTYP *params); extern ARGTYP *par_getparams(int argc,char * const argv[],const char *optstring); //homework to be done before starting/stoping module. -extern int uni_modeunipar(_Bool mode); +extern int par_modeunipar(_Bool mode); #endif diff --git a/lib/uniprc.c b/lib/uniprc.c new file mode 100644 index 0000000..f07cef6 --- /dev/null +++ b/lib/uniprc.c @@ -0,0 +1,296 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/********************************************************/ +/* */ +/* Module for low level subroutine */ +/* */ +/********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "subrou.h" +#include "uniprc.h" + + +//directory to set lock +#define DIRLOCK "/var/run/"APPNAME + +static _Bool modopen; //boolean module open/close +/* + +*/ +/********************************************************/ +/* */ +/* 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 +} diff --git a/lib/uniprc.h b/lib/uniprc.h new file mode 100644 index 0000000..0bea404 --- /dev/null +++ b/lib/uniprc.h @@ -0,0 +1,39 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/************************************************/ +/* */ +/* Unit level process management */ +/* declaration */ +/* */ +/************************************************/ +#ifndef UNIPRC +#define UNIPRC + +#include +#include + +#include "subrou.h" + +#define LCK_UNLOCK 0 /*unlocking request */ +#define LCK_LOCK 1 /*locking requets */ + +//To allow application to core dump is memory is +//big trouble need to be investigated +extern void prc_allow_core_dump(); + +//To do an on purpose application memory core dump +//with an explication message +extern void prc_core_dump(const char *fmt,...); + +//routine to check if a proces is still up and running +extern _Bool prc_checkprocess(pid_t pidnumber); + +//lock application (to avoid running multiple daemon) +extern _Bool prc_locking(const char *lockname,int lock,int tentative); + +//procedure to put application in deamon mode +extern pid_t prc_divedivedive(); + +//homework to be done before starting/stoping module. +extern int prc_modeuniprc(_Bool mode); + +#endif -- 2.47.3