1 /************************************************/
4 /* Jean-Marc Pigeon <jmp@safe.ca> */
5 /* Distributed under the Gnu Public */
6 /* License, see the License file in this */
9 /* Implement very sub level procedure to */
10 /* handle clement specific needs. */
12 /************************************************/
15 #include <sys/resource.h>
16 #include <sys/prctl.h>
33 #define TRALOG LOG_DEBUG
35 #define TRALOG LOG_INFO
38 /*setting the applocation version */
39 const char *curvers=VZBVERS;
40 /*sigterm request flag */
42 /*sigquit request flag */
44 /*sigint request flag */
46 /*current debug level */
48 /*flag application running background/foreground*/
49 int apl_foreground=false;
50 /*debug log in verbose mode */
52 /*base directory (where to store internal data) */
53 char *base=""; /*no prefix */
60 /************************************************/
62 /* Procedure to catch signal and do what is*/
65 /************************************************/
66 static void trapsig(int sig)
73 (void) sigfillset(&blockmask);
74 (void) sigprocmask(SIG_SETMASK,&blockmask,&oldset);
76 (void) fprintf(stderr,"subclm.c:trapsig <%s/%d> received (by pid='%d')\n",
77 sys_siglist[sig],sig,getpid());
88 (void) fprintf(stderr,"Increased debug level to '%d' (pid='%d')\n",debug,getpid());
93 (void) fprintf(stderr,"Decreased debug level to '%d' (pid='%d')\n",debug,getpid());
100 (void) fprintf(stderr,"%s, Unexpected signal <%s> received\n",
101 appname,sys_siglist[sig]);
104 /*restarting signal */
105 (void) sigemptyset(&sa.sa_mask);
106 sa.sa_handler=trapsig;
108 (void) sigprocmask(SIG_SETMASK,&oldset,(sigset_t *)0);
109 (void) sigaction(sig,&sa,(struct sigaction *)0);
114 /************************************************/
116 /* Procedure to catch signal and do what is*/
119 /************************************************/
120 static void trpmempbls(int sig)
123 #define OPPB "subclm.c:trpmempbls,"
127 (void) apl_core_dump("Program genuine memory violation");
130 (void) apl_core_dump("%s Unexpected signal <%s> received",
131 OPPB,sys_siglist[sig]);
138 /************************************************/
140 /* Procedure to check if directory is */
141 /* already existing. */
143 /************************************************/
144 int apl_isdir(char *dirpath)
151 if (stat(dirpath,&bufstat)==0) {
152 if (S_ISDIR(bufstat.st_mode)!=0) {
161 /************************************************/
163 /* Procedure to free memory used by a */
164 /* string, do not proceed if point is NULL.*/
166 /************************************************/
167 char *apl_freestr(char *str)
170 if (str!=(char *)0) {
178 /************************************************/
180 /* Procedure to extract and return current */
181 /* version number. */
183 /************************************************/
187 static char *vernum=(char *)0;
188 static char numero[30];
190 if (vernum==(char *)0) {
191 int num1,num2,num3,num4;
194 (void) sscanf(curvers,"%s %d.%d.%d.%d",revision,&num1,&num2,&num3,&num4);
195 (void) sprintf(numero,"%d.%d-%d",num1,num2,num4);
203 /************************************************/
205 /* Procedure to return the current time */
206 /* expressed with a millisecond precision. */
208 /************************************************/
209 u_long apl_getmillisec()
212 static time_t start=(time_t)0;
215 struct timeval newtime;
218 (void) gettimeofday(&newtime,(struct timezone *)0);
219 if (start==(time_t)0)
220 start=(newtime.tv_sec-1);
221 millisec=newtime.tv_sec-start;
223 millisec+=(newtime.tv_usec/1000);
229 /************************************************/
231 /* Procedure to make create a unique name */
232 /* can be used to store process data */
233 /* name return is dynamically allocated. */
235 /************************************************/
236 char *apl_uniquename(unsigned int seq)
239 #define UFTIME "%Y%m%d%H%M%S"
240 #define UNIQUE "%05d-%s-%08lx"
247 curtime=time((time_t)0);
248 tminfo=localtime(&curtime);
249 (void) strftime(asctemps,sizeof(asctemps),UFTIME,tminfo);
250 (void) asprintf(&uniquename,UNIQUE,getpid(),asctemps,apl_getmillisec()+seq);
256 /************************************************/
258 /* Procedure to return a time seen as local*/
259 /* time to a long express as YYYYMMDD */
261 /************************************************/
262 u_long apl_date(time_t curtime)
267 tm=localtime(&curtime);
268 return (tm->tm_year*10000)+(tm->tm_mon*100)+tm->tm_mday;
273 /************************************************/
275 /* Procedure to return the local time in */
276 /* HH:MM:SS format. */
277 /* Time is stored in a STATIC memeory area */
279 /************************************************/
280 char *apl_ascsystime(time_t curtime)
283 #define TTIME "%H:%M:%S"
285 static char asctemps[100];
289 tminfo=localtime(&curtime);
290 (void) strftime(asctemps,sizeof(asctemps),TTIME,tminfo);
296 /************************************************/
298 /* Procedure to return system time from an */
299 /* YYYY-MM-DDD HH:MM:SS format. */
301 /************************************************/
302 time_t apl_datetimesysasc(char *strdate,char *strtime)
305 #define DBDTOUNIX "%Y-%m-%d %H:%M:%S"
309 if ((strdate!=(char *)0)&&(strtime!=(char *)0)) {
313 (void) memset(&tm,'\000',sizeof(struct tm));
315 (void) snprintf(strdt,sizeof(strdt),"%s %s",strdate,strtime);
316 if (strptime(strdt,DBDTOUNIX,&tm)!=(char *)0) {
317 datetime=mktime(&tm);
320 (void) apl_alert(0,"subclm.c:apl_datetimesysasc Unable to convert <%s> to time_t",strdt);
328 /************************************************/
330 /* Procedure to return the local time in */
331 /* YYYY-MM-DDD format. */
332 /* date is stored in a STATIC memeory area */
334 /************************************************/
335 char *apl_ascsysdate(time_t curtime)
338 #define TDATE "%Y-%m-%d"
340 static char asctemps[100];
344 tminfo=localtime(&curtime);
345 (void) strftime(asctemps,sizeof(asctemps),TDATE,tminfo);
351 /************************************************/
353 /* Procedure to return the local time in */
354 /* YYYY-MM-DDD HH:MM:SS format. */
355 /* date is stored in a STATIC memeory area */
357 /************************************************/
358 char *apl_ascsysdatetime(time_t curtime)
361 #define TDTIME "%Y-%m-%d %H:%M:%S"
363 static char asctemps[100];
367 tminfo=localtime(&curtime);
368 (void) strftime(asctemps,sizeof(asctemps),TDTIME,tminfo);
374 /************************************************/
376 /* Procedure to transform the local system */
377 /* time in ASCII time stamp. */
378 /* Stored in STATIC memory area. */
380 /************************************************/
381 char *apl_ascsysstamp(time_t curtime)
384 #define TSTAMP "%a, %d %b %Y %H:%M:%S"
386 static char ascstamp[100];
391 tminfo=localtime(&curtime);
392 (void) strftime(asct,sizeof(asct),TSTAMP,tminfo);
393 (void) snprintf(ascstamp,sizeof(ascstamp),"%s %05ld",asct,
394 ((tminfo->tm_gmtoff/3600)*100)+
395 ((tminfo->tm_gmtoff%3600)/60));
401 /************************************************/
403 /* Procedure to display an alert in the */
406 /************************************************/
407 void apl_alert(const int dlevel,const char *fmt,...)
416 (void) vasprintf(&strloc,fmt,args);
417 if ((apl_foreground==true)||((verbose==true))) {
421 curtime=time((long *)0);
422 (void) strftime(logtime,sizeof(logtime),"%H:%M:%S",localtime(&curtime));
423 (void) fprintf(stderr,"%s %s\n",logtime,strloc);
424 (void) fflush(stderr);
427 (void) syslog(TRALOG,"%s\n",strloc);
436 /************************************************/
438 /* Procedure to display an argv list */
440 /************************************************/
441 void apl_argvtrace(const int dlevel,const char *fmt,char *argv[])
444 if ((debug>=dlevel)&&(argv[0]!=(char *)0)) {
449 for (i=1;argv[i]!=(char *)0;i++) {
452 (void) asprintf(&strloc,"%s %s",tmp,argv[i]);
456 (void) apl_alert(dlevel,fmt,tmp);
463 /************************************************/
465 /* Procedure to 'compute' a new base */
466 /* according the current directory */
467 /* return a newly allocated memory */
469 /************************************************/
470 char *apl_mkbase(char *newbase)
476 switch (newbase[0]) {
481 if (getcwd(curdir,sizeof(curdir))!=(char *)0) {
482 (void) snprintf(newpath,sizeof(newpath),"%s/%s",curdir,newbase);
483 if (chdir(newpath)<0) {
484 (void) apl_alert(0,"Unable to reach directory <%s>",newpath);
485 break; /*immediat exit */
487 (void) getcwd(newpath,sizeof(newpath));
488 if (chdir(curdir)<0) {
489 (void) apl_alert(0,"Unable to reach directory <%s>",curdir);
490 break; /*immediat exit */
502 if (ptr==(char *)0) {
503 (void) apl_alert(0,"Unable to assign new base '%s', immediat exit",newbase);
511 /************************************************/
513 /* Procedure to 'compute' an application */
514 /* directory according dir enum value */
516 /************************************************/
517 char *apl_appdir(DIRENUM dir)
526 sysbase=" "; /*something impossible */
527 apvers=apl_getapvers();
539 sysbase="/var/crash";
545 sysbase="/var/spool";
557 sysbase="/var/spool";
576 (void) asprintf(&appdir,"%s%s/%s%s",base,sysbase,apvers,subdir);
582 /************************************************/
584 /* Procedure to set the SIGV signal trap */
585 /* purpose is to CORE_DUMP in case we have */
586 /* a memory failure of some kind. */
588 /************************************************/
589 void apl_trapsegv(int onoff)
592 static struct sigaction oldsa;
595 struct sigaction newsa;
598 newsa.sa_handler=trpmempbls;
599 (void) sigemptyset(&newsa.sa_mask);
600 (void) sigaction(SIGSEGV,&newsa,&oldsa);
603 (void) sigaction(SIGSEGV,&oldsa,(struct sigaction *)0);
609 /************************************************/
611 /* Procedure to prepare a core_dump in */
612 /* the right directory. */
614 /************************************************/
615 void apl_core_dump(char *frmt,...)
623 temps=apl_ascsystime(time((time_t *)0));
624 crashdir=apl_appdir(d_crash);
625 (void) prc_core_dump(crashdir,temps,frmt,args);
631 /************************************************/
633 /* procedure to set/unset trapped signal */
635 /************************************************/
636 void apl_settrap(int set)
639 static struct sigaction oldint;
640 static struct sigaction oldterm;
641 static struct sigaction oldquit;
642 static struct sigaction oldusr1;
643 static struct sigaction oldusr2;
645 static int alldone=false;
650 (void) apl_core_dump("apl_settrap already set");
653 (void) apl_core_dump("apl_settrap not previously set");
656 (void) apl_core_dump("apl_settrap unproper set value");
660 (void) apl_trapsegv(set);
662 struct sigaction newsa;
665 newsa.sa_handler=trapsig;
666 (void) sigaction(SIGUSR2,&newsa,&oldusr2);
667 (void) sigaction(SIGUSR1,&newsa,&oldusr1);
668 (void) sigaction(SIGINT,&newsa,&oldint);
669 (void) sigaction(SIGTERM,&newsa,&oldterm);
670 (void) sigaction(SIGQUIT,&newsa,&oldquit);
673 (void) sigaction(SIGQUIT,&oldquit,(struct sigaction *)0);
674 (void) sigaction(SIGTERM,&oldterm,(struct sigaction *)0);
675 (void) sigaction(SIGINT,&oldint,(struct sigaction *)0);
676 (void) sigaction(SIGUSR1,&oldusr1,(struct sigaction *)0);
677 (void) sigaction(SIGUSR2,&oldusr2,(struct sigaction *)0);
684 /************************************************/
686 /* Procedure to set a string to lower case */
689 /************************************************/
690 char *apl_strtolower(char *str)
693 if (str!=(char *)0) {
696 for (ptr=str;*ptr!='\000';ptr++)
697 *ptr=(char)tolower((int)*ptr);
704 /************************************************/
706 /* Procedure extract line from a file, */
707 /* forget about any line starting with */
708 /* carcom character (if carcom character */
710 /* Doesn't return the '\r' and '\n' */
713 /************************************************/
714 char *apl_getstr(FILE *fichier,char *str,u_int taille,char carcom)
719 (void) memset(str,'\000',taille);
720 while ((strloc=fgets(str,taille,fichier))!=(char *)0) {
723 if (carcom!='\000') {
727 while ((ptrloc=strchr(ptrloc,carcom))!=(char *)0) {
728 if (*(ptrloc-1)=='\\') {
729 (void) memmove(ptrloc-1,ptrloc,strlen(ptrloc)+1);
738 ptrloc=strloc+strlen(strloc);
739 while (ptrloc!=(char *)0) {
758 /************************************************/
760 /* Procedure to application+version name */
762 /************************************************/
763 char *apl_getapvers()
766 static char *apvers=(char *)0;
768 if (apvers==(char *)0) {
769 static char apinfo[50];
774 (void) strcpy(version,apl_getvers());
775 if ((ptr=strchr(version,'-'))!=(char *)0)
777 (void) snprintf(apinfo,sizeof(apinfo),"%s-%s/",appname,version);
785 /************************************************/
787 /* Procedure to convert a string to a code,*/
788 /* remaining of the string is copy at the */
790 /* Return a pointer to table, never a NULL */
791 /* pointer unless the table itself is NULL */
793 /************************************************/
794 VOCTYP *apl_getvoca(const VOCTYP *table,char *str)
800 if (table!=(VOCTYP *)0) {
805 while (isspace(*sptr)!=0)
807 for (i=0;table[i].key!=(char *)0;i++) {
810 max=strlen(table[i].key);
811 if (strncasecmp(table[i].key,sptr,max)==0) {
812 if ((sptr[max]!='\000')&&(isalnum(sptr[max])!=0))
813 continue;/*it is not the right word */
815 while (isspace(*sptr)!=0)
817 (void) memmove(str,sptr,strlen(sptr)+1);
818 voc=(VOCTYP *)(table+i);
822 if (voc==(VOCTYP *)0)
823 voc=(VOCTYP *)(table+i);/*return the "unknown" info */
830 /************************************************/
832 /* Procedure to remove crlf and space AT */
833 /* the string end. */
834 /* Remove space at the string start too. */
836 /************************************************/
837 char *apl_cleanstring(char *str)
840 if (str!=(char *)0) {
847 if ((*ptr=='\n') || (*ptr=='\r') || (*ptr==' ')) {
856 while (isblank(*ptr)!=0)
859 (void) memmove(str,ptr,strlen(ptr)+1);