]> SAFE projects GIT repository - jmp/mailleur/commitdiff
Adding uniprc module
authorJean-Marc Pigeon (Delson) <jmp@safe.ca>
Tue, 9 Jul 2024 06:18:23 +0000 (02:18 -0400)
committerJean-Marc Pigeon (Delson) <jmp@safe.ca>
Tue, 9 Jul 2024 06:18:23 +0000 (02:18 -0400)
app/maild.c
lib/Makefile
lib/subrou.c
lib/subrou.h
lib/unipar.c
lib/unipar.h
lib/uniprc.c [new file with mode: 0644]
lib/uniprc.h [new file with mode: 0644]

index 6666fd876c52a2b06938e03c690c8fb6aa7a3aad..7e2ba5e9a32ca2238cc116cc700e2101677c833b 100644 (file)
@@ -6,17 +6,27 @@
 /********************************************************/
 #include       <stdlib.h>
 #include       <stdio.h>
+#include       <unistd.h>
 
 #include       "subrou.h"
 #include       "unipar.h"
+#include       "uniprc.h"
 
 /*
 \f
 */
 /********************************************************/
 /*                                                     */
+/*      Program main task                               */
 /*                                                     */
 /********************************************************/
+static void task()
+
+{
+(void) rou_alert(0,"JMPDBG starting task");
+(void) sleep(5);
+(void) rou_alert(0,"JMPDBG task completed");
+}
 /*
 \f
 */
@@ -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;
index f530df6df3d72e488a70368727609c7e6be7eb77..d0a2cec202acf49270c84d13ba72fed3a093d42d 100644 (file)
@@ -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
index 4dfdcaeb8771d3571e56cd98a13507ecee25a665..aca5e46e51dcd9043d6b500bce352e183ea08c9c 100644 (file)
@@ -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;
+}
+/*
+\f
+*/
+/********************************************************/
+/*                                                     */
 /*     Subroutine to log event on syslog               */
 /*                                                     */
 /********************************************************/
index 316319af40a8bf2f5090d294e231f43e8a33d32a..021f142a61b8b0b4b8e86f0eb4a9f76cd2a2c331 100644 (file)
@@ -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);
 
index 551387ca3133d8abd65cba43cee43cebea95c6c8..2c9b3ca2d5dbbae127b7111a8355ef9f99a33634 100644 (file)
@@ -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"
index 29530af82be9bf845375bb7d4b3de19ceea9635f..097bf0944262061a95174b58c7bdcb9b6540e824 100644 (file)
@@ -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 (file)
index 0000000..f07cef6
--- /dev/null
@@ -0,0 +1,296 @@
+// 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
+}
diff --git a/lib/uniprc.h b/lib/uniprc.h
new file mode 100644 (file)
index 0000000..0bea404
--- /dev/null
@@ -0,0 +1,39 @@
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/************************************************/
+/*                                             */
+/*     Unit level process management           */
+/*      declaration                             */
+/*                                             */
+/************************************************/
+#ifndef        UNIPRC
+#define UNIPRC
+
+#include        <stdbool.h>
+#include        <stdio.h>
+
+#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