Inserting VZGOT development tree within GIT
[safe/jmp/vzgot] / lib / subprc.c
1 /************************************************/
2 /*                                              */
3 /*      Copyright:                              */
4 /*       Jean-Marc Pigeon <jmp@safe.ca>  2009   */
5 /*                                              */
6 /************************************************/
7 /* This program is free software; you can       */
8 /* redistribute it and/or modify it under the   */
9 /* terms of the GNU General Public License as   */
10 /* published by the Free Software Foundation    */
11 /* version 2 of the License                     */
12 /*                                              */
13 /* This program is distributed in the hope that */
14 /* it will be useful, but WITHOUT ANY WARRANTY; */
15 /* without even the implied warranty of         */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR  */
17 /* PURPOSE.  See the GNU General Public License */
18 /* for more details.                            */
19 /*                                              */
20 /* You should have received a copy of the GNU   */
21 /* General Public License along with this       */
22 /* program; if not, write to the Free Software  */
23 /* Foundation, Inc., 51 Franklin Street,        */
24 /* Fifth Floor, Boston, MA  02110-1301, USA.    */
25 /************************************************/
26 /*                                              */
27 /*      SUBPRC:                                 */
28 /*      take care of all low level process      */
29 /*      handling.                               */
30 /*                                              */
31 /************************************************/
32 #include        <unistd.h>
33 #include        <stdlib.h>
34 #include        <stdio.h>
35 #include        <string.h>
36 #include        <signal.h>
37 #include        <errno.h>
38 #include        <sys/resource.h>
39 #include        <sys/prctl.h>
40 #include        <sys/time.h>
41 #include        "dbgmem.h"
42 #include        "lowtyp.h"
43 #include        "utlvec.h"
44 #include        "subprc.h"
45
46 #define DEVNULL "/dev/null"
47
48 /*Process command override structure (proc)     */
49 typedef struct  {
50         int max;        /*title max size        */
51         char **newargv; /*newly set argv list   */
52         char *title;    /*title storage area    */
53         }TITLTYP;
54
55 /*storage area for /proc title display          */
56 static  TITLTYP *title=(TITLTYP *)0;
57 /*
58 \f
59 */
60 /************************************************/
61 /*                                              */
62 /*      Procedure to catch a SIGALRM signal     */
63 /*                                              */
64 /************************************************/
65 static void trppace(int sig)
66
67 {
68 #define OPTR    "subprc.c:trppace,"
69
70 static u_long tics=(u_long)0;
71
72 switch (sig) {
73   case SIGALRM   :
74     tics++;
75     break;
76   default        :
77     (void) fprintf(stderr,"%s Unexpected signal <%s> received\n",
78                           OPTR,sys_siglist[sig]);
79     (void) fflush(stderr);
80     break;
81   }
82 }
83 /*
84 \f
85 */
86 /************************************************/
87 /*                                              */
88 /*      Procedure to free used title memory     */
89 /*                                              */
90 /************************************************/
91 char **prc_cleantitle()
92
93 {
94 if (title!=(TITLTYP *)0) {
95   title->newargv=(char **)vec_freelstlst((void **)title->newargv,VECFREE);
96   if (environ!=(char **)0) {
97     int i;
98
99     for (i=0;environ[i]!=(char *)0;i++) {
100       (void) free(environ[i]);
101       environ[i]=(char *)0;
102       }
103     (void) free(environ);
104     environ=(char **)0;
105     }
106   (void) free(title);
107   title=(TITLTYP *)0;
108   }
109 return (char **)0;
110 }
111 /*
112 \f
113 */
114 /************************************************/
115 /*                                              */
116 /*      Procedure to find and limit space to    */
117 /*      be used as status information available */
118 /*      from proc (ps ax)                       */
119 /*                                              */
120 /************************************************/
121 char **prc_preptitle(int argc,char *argv[],char *env[])
122
123 {
124 extern char **environ;
125
126 char *lastend;
127
128 lastend=(char *)0;
129 (void) prc_cleantitle();
130 title=(TITLTYP *)calloc(1,sizeof(TITLTYP));
131 if (argv!=(char **)0) {
132   int i;
133
134   title->title=argv[0];
135   title->newargv=(char **)vec_addlstlst((void **)title->newargv,(void *)strdup(argv[0]));
136   for (i=1;argv[i]!=(char *)0;i++) {
137     char *valeur;
138
139     lastend=argv[i]+strlen(argv[i]);
140     valeur=strdup(argv[i]);
141     title->newargv=(char **)vec_addlstlst((void **)title->newargv,(void *)valeur);
142     argv[i]=(char *)0;
143     }
144   }
145 if (env!=(char **)0) {
146   int i;
147
148   environ=(char **)0;
149   for (i=0;env[i]!=(char *)0;i++) {
150     char *valeur;
151
152     lastend=env[i]+strlen(env[i]);
153     valeur=strdup(env[i]);
154     (void) putenv(valeur);
155     }
156   }
157 title->max=lastend-title->title;
158 return title->newargv;
159 }
160 /*
161 \f
162 */
163 /************************************************/
164 /*                                              */
165 /*      Procedure to update title information.  */
166 /*      title information is available via the  */
167 /*      "ps" command.                           */
168 /*                                              */
169 /************************************************/
170 void prc_settitle(const char *fmt,...)
171
172 {
173 va_list args;
174
175 va_start(args,fmt);
176 if ((title!=(TITLTYP *)0)&&(title->title!=(char *)0)) {
177   (void) bzero(title->title,title->max);
178   (void) vsnprintf(title->title,title->max,fmt,args);
179   }
180 va_end(args);
181 }
182 /*
183 \f
184 */
185 /************************************************/
186 /*                                              */
187 /*      Procedure to put a process in background*/
188 /*      mode.                                   */
189 /*                                              */
190 /************************************************/
191 void prc_divedivedive(int foreground)
192
193 {
194 #define OPDI    "dbgprc.c:prc_divedivedive,"
195
196 if (foreground==0) {
197   switch (fork()) {
198     case -1     :
199       (void) fprintf(stderr,"%s, Unable to dive! (error=<%s>)",
200                              OPDI,strerror(errno));
201       /*lets continue if foregorund mode                */
202       break;
203     case  0     :
204       /*we are now in background mode           */
205       if (foreground==0)        /*always        */
206         (void) setsid();
207       break;
208     default     :
209       /*waiting for ballast to fill up :-}}     */
210       (void) sleep(1);  
211       (void) exit(0);   /*just exit             */
212       break;            /*never reached         */
213     }
214   }
215 }
216 /*
217 \f
218 */
219 /************************************************/
220 /*                                              */
221 /*      Procedure to start or stop a 'Pacemaker'*/
222 /*      within the application.                 */
223 /*                                              */
224 /************************************************/
225 void prc_pace(u_long millisec,int onoff)
226
227 {
228 int static done=false;
229 struct sigaction oldsa;
230
231 if (onoff==true) {
232   if (done==false) {
233     struct sigaction newsa;
234     struct itimerval period;
235
236     newsa.sa_flags=0;
237     newsa.sa_handler=trppace;
238     (void) sigemptyset(&newsa.sa_mask);
239     (void) sigaction(SIGALRM,&newsa,&oldsa);
240     period.it_value.tv_sec=millisec/1000;
241     period.it_value.tv_usec=millisec*1000;
242     period.it_interval.tv_sec=period.it_value.tv_sec;
243     period.it_interval.tv_usec=period.it_value.tv_usec;
244     (void) setitimer(ITIMER_REAL,&period,(struct itimerval *)0);
245     done=true;
246     }
247   }
248 else {
249   if (done==true) {
250     struct itimerval period;
251
252     period.it_value.tv_sec=0;
253     period.it_value.tv_usec=0;
254     period.it_interval.tv_sec=period.it_value.tv_sec;
255     period.it_interval.tv_usec=period.it_value.tv_usec;
256     (void) setitimer(ITIMER_REAL,&period,(struct itimerval *)0);
257     (void) sigaction(SIGALRM,&oldsa,(struct sigaction *)0);
258     done=false;
259     }
260   }
261 }