Inserting VZGOT development tree within GIT
[safe/jmp/vzgot] / lib / unicnt.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 /*      UNICNT:                                 */
28 /*                                              */
29 /************************************************/
30 #include        <sys/mount.h>
31 #include        <sys/syscall.h>
32 #include        <sys/time.h>
33 #include        <sys/wait.h>
34 #include        <time.h>
35 #include        <signal.h>
36 #include        <stdio.h>
37 #include        <string.h>
38 #include        <syslog.h>
39 #include        <errno.h>
40 #include        <fcntl.h>
41 #include        <unistd.h>
42
43 #include        "lowtyp.h"
44 #include        "dbgmem.h"
45 #include        "subapl.h"
46 #include        "unicnt.h"
47
48 /*container filesystem                          */
49 #define ROOTFS  "rootfs"        /*container root*/
50 #define OLDROOT ".oldroot"      /*for pivot_root*/
51 #define CLONPID "first.pid"     /*cont process 1*/
52 #define MTAB    "/etc/mtab"     /*mtab file     */
53 /*
54 \f
55 */
56 /************************************************/
57 /*                                              */
58 /*      Defining pivot_root system call         */
59 /*                                              */
60 /************************************************/
61 static int pivot_root(const char * new_root,const char * put_old)
62
63 {
64 #ifndef __NR_pivot_root
65 #pragma message ("the pivot_root syscall is not available within \"sys/syscall.h\"")
66 #pragma message ("-> The pivot_root system call will generate an alert")
67 (void) apl_alert(0,"%s need the pivot_root system call!!!.",appname);
68 errno=ENOSYS;
69 return -1;
70 #else
71 return(syscall(__NR_pivot_root, new_root, put_old));
72 #endif
73 }
74 /*
75 \f
76 */
77 /************************************************/
78 /*                                              */
79 /*      Returning the container path.           */
80 /*      contpath array is dynamically assigned  */
81 /*      need to be freed when not need anymore. */
82 /*                                              */
83 /************************************************/
84 static char *getcontpath(char *contname)
85
86 {
87 char *contpath;
88 char *vzpath;
89
90 contpath=(char *)0;
91 vzpath=apl_appdir(d_vzgot);
92 (void) asprintf(&contpath,"%s/%s",vzpath,contname);
93 (void) free(vzpath);
94 return contpath;
95 }
96 /*
97 \f
98 */
99 /************************************************/
100 /*                                              */
101 /*      Check is the container is here with     */
102 /*      all needed parts.                       */
103 /*                                              */
104 /************************************************/
105 int cnt_iscontgood(char *contname)
106
107 {
108 int isgood;
109 char *contpath;
110 int phase;
111 int proceed;
112
113 isgood=true;
114 phase=0;
115 proceed=true;
116 contpath=getcontpath(contname);
117 while (proceed==true) {
118   switch (phase) {
119     case 0      :       /*is container existing?*/
120       if (contpath!=(char *)0) {/*always.       */
121         char *rootpath; 
122
123         (void) asprintf(&rootpath,"%s/%s",contpath,ROOTFS);
124         if (apl_isdir(rootpath)<0) {
125           (void) apl_alert(0,"%s, rootfs directory missing within container \"cont\" directory",
126                              appname,contname);
127           isgood=false;
128           phase=999;    /*trouble trouble       */
129           }
130         (void) free(rootpath);
131         }
132       break;
133     case 1      :       /*check/make oldroot dir*/
134       if (contpath!=(char *)0) {/*always.       */
135         char *oldpath;
136
137         (void) asprintf(&oldpath,"%s/%s",contpath,OLDROOT);
138         if (apl_isdir(oldpath)<0) {
139           if (mkdir(oldpath,0700)<0) {
140             (void) apl_alert(0,"%s, unable to make %s directory for container <%s> (error=%s)",
141                                 appname,OLDROOT,contname,strerror(errno));
142             isgood=false;
143             phase=999;  /*trouble trouble       */
144             }
145           }
146         (void) free(oldpath);
147         }
148       break;
149     default     :       /*SAFE Guard            */
150       proceed=false;
151       break;
152     }
153   phase++;
154   }
155 (void) free(contpath);
156 return isgood;
157 }
158 /*
159 \f
160 */
161 /************************************************/
162 /*                                              */
163 /*      procedure to set an initial mtab        */
164 /*      contents WITHIN the clone rootfs        */
165 /*                                              */
166 /************************************************/
167 static int setmtab(char *contname)
168
169 {
170 int done;
171 FILE *fichier;
172 int phase;
173 int proceed;
174
175 done=false;
176 fichier=(FILE *)0;
177 phase=0;
178 proceed=true;
179 while (proceed==true) {
180   switch (phase) {
181     case 0      :       /*removing mtab file    */
182       if (unlink(MTAB)<0) {
183         switch (errno)  {
184           case ENOENT   :/* file not existing:-}*/
185             break;
186           default       :
187             (void) apl_alert(0,"%s, Unable to remove %s from container <%s> rootfs (error=<%s>)",
188                                 appname,MTAB,contname,strerror(errno));
189             phase=999;  /*trouble trouble       */
190             break;
191           }
192         }
193       break;
194     case 1      :       /*creating new MTAB file*/
195       if ((fichier=fopen(MTAB,"w"))==(FILE *)0) {
196         (void) apl_alert(0,"%s, Unable to create %s within container <%s> rootfs (error=<%s>)",
197                             appname,MTAB,contname,strerror(errno));
198         phase=999;      /*trouble trouble       */
199         }
200       break;
201     case 2      :       /*inserting contents    */
202       if (fprintf(fichier,"%s / roofs rw 0 0\n",appname)<0) {
203         (void) apl_alert(0,"%s, Unable to write %s file in container <%s> (error=<%s>)",
204                             appname,MTAB,contname,strerror(errno));
205         phase=999;      /*trouble trouble       */
206         }
207       (void) fclose(fichier);
208       break;
209     case 3      :       /*everything fine       */
210       done=true;
211       break;
212     default     :       /*SAFE Guard            */
213       proceed=false;
214       break;
215     }
216   phase++;
217   }
218 return done;
219 }
220 /*
221 \f
222 */
223 /************************************************/
224 /*                                              */
225 /*      procedure to pivot the container root   */
226 /*      file system.                            */
227 /*                                              */
228 /************************************************/
229 int cnt_pivot(int foreground,char *contname)
230
231 {
232 int done;
233 char *contpath;
234 int phase;
235 int proceed;
236
237 done=false;
238 contpath=getcontpath(contname);
239 phase=0;
240 proceed=true;
241 while (proceed==true) {
242   switch (phase) {
243     case 0      :       /*binding container file*/
244       if (mount(contpath,contpath,0,MS_BIND,0)<0) {
245         (void) apl_alert(0,"%s, unable to bind container <%s> directory (error=%s)",
246                                 appname,contname,strerror(errno));
247         phase=999;      /*trouble trouble       */
248         }
249       break;
250     case 1      :       /*moving to rootfs      */
251       (void) cnt_setstdio(foreground,contname,"container.log");
252       if (chdir(contpath)<0) {
253         (void) apl_alert(0,"%s, unable to reach container <%s> directory (error=%s)",
254                                 appname,contname,strerror(errno));
255         phase=999;      /*trouble trouble       */
256         }
257       break;
258     case 2      :       /*moving to rootfs      */
259       if (pivot_root(".",OLDROOT)<0) {
260         (void) apl_alert(0,"%s, unable to pivot container <%s> root (error=%s)",
261                                 appname,contname,strerror(errno));
262         phase=999;      /*trouble trouble       */
263         }
264       break;
265     case 3      :       /*umounting previous fs */
266       if (umount2(OLDROOT,MNT_DETACH)<0) {
267         (void) apl_alert(0,"%s, unable to unmount container <%s> oldroot (error=%s)",
268                                 appname,contname,strerror(errno));
269         phase=999;      /*trouble trouble       */
270         }
271       break;
272     case 4      :       /* chrooting to rootfs  */
273       if (chdir(ROOTFS)<0) {
274         (void) apl_alert(0,"%s, unable to reach container <%s> rootfs (error=%s)",
275                                 appname,contname,strerror(errno));
276         phase=999;      /*trouble trouble       */
277         }
278       break;
279     case 5      :       /* everything fine      */
280       if (chroot(".")<0) {
281         (void) apl_alert(0,"%s, unable to rootfs container <%s> (error=%s)",
282                                 appname,contname,strerror(errno));
283         phase=999;      /*trouble trouble       */
284         }
285       break;
286     case 6      :       /* everything fine      */
287       (void) setmtab(contname); /*initiat mtab  */
288       (void) fprintf(stdout,"%s container chroot done\n",apl_ascsystime(time((time_t *)0)));
289       (void) fflush(stdout);
290       done=true;
291       break;
292     default     :       /*SAFE Guard            */
293       proceed=false;
294       break;
295     }
296   phase++;
297   }
298 (void) free(contpath);
299 return done;
300 }
301 /*
302 \f
303 */
304 /************************************************/
305 /*                                              */
306 /*      procedure to set a file with the clone  */
307 /*      ip number.                              */
308 /*                                              */
309 /************************************************/
310 int cnt_setclonepid(char *contname,pid_t cpid)
311
312 {
313 int done;
314 FILE *fichier;
315 char *filename;
316 char *contpath;
317 int phase;
318 int proceed;
319
320 done=false;
321 fichier=(FILE *)0;
322 filename=(char *)0;
323 contpath=getcontpath(contname);
324 (void) asprintf(&filename,"%s/%s",contpath,CLONPID);
325 phase=0;
326 proceed=true;
327 while (proceed==true) {
328   switch (phase) {
329     case 0      :       /*opening the file      */
330       if ((fichier=fopen(filename,"w"))==(FILE *)0) {
331         (void) apl_alert(0,"%s, Unable to open pidfile <%s> (error=<%s>)",
332                             appname,filename,strerror(errno));
333         phase=999;      /*trouble trouble       */
334         }
335       break;
336     case 1      :       /*writing  PID in it    */
337       if (fprintf(fichier,"%05d\n",cpid)<0) {
338         (void) apl_alert(0,"%s, Unable to write pidfile in container <%s> (error=<%s>)",
339                             appname,contname,strerror(errno));
340         phase=999;      /*trouble trouble       */
341         }
342       (void) fclose(fichier);
343       break;
344     case 2      :       /*everything fine       */
345       done=true;
346       break;
347     default     :       /*SAFE Guard            */
348       proceed=false;
349       break;
350     }
351   phase++;
352   }
353 (void) free(filename);
354 (void) free(contpath);
355 return done;
356 }
357 /*
358 \f
359 */
360 /************************************************/
361 /*                                              */
362 /*      procedure to get the clone pid stored   */
363 /*      within the clonpid file                 */
364 /*                                              */
365 /************************************************/
366 pid_t cnt_getclonepid(char *contname)
367
368 {
369 pid_t clonepid;
370 FILE *fichier;
371 char *filename;
372 char *contpath;
373
374 clonepid=(pid_t)0;
375 contpath=getcontpath(contname);
376 (void) asprintf(&filename,"%s/%s",contpath,CLONPID);
377 if ((fichier=fopen(filename,"r"))!=(FILE *)0) {
378   char strloc[80];
379
380   (void) fgets(strloc,sizeof(strloc)-1,fichier);
381   (void) sscanf(strloc,"%d",&clonepid);
382   (void) fclose(fichier);
383   }
384 (void) free(filename);
385 (void) free(contpath);
386 return clonepid;
387 }
388 /*
389 \f
390 */
391 /************************************************/
392 /*                                              */
393 /*      procedure to remove the file with the   */
394 /*      clone pid.                              */
395 /*                                              */
396 /************************************************/
397 int cnt_rmclonepid(char *contname)
398
399 {
400 int done;
401 char *filename;
402 char *contpath;
403
404 done=true;
405 filename=(char *)0;
406 contpath=getcontpath(contname);
407 (void) asprintf(&filename,"%s/%s",contpath,CLONPID);
408 if (unlink(filename)<0) {
409   (void) apl_alert(0,"%s, Unable to remove pidfile in container <%s> (error=<%s>)",
410                      appname,contname,strerror(errno));
411   done=false;
412   }
413 (void) free(filename);
414 (void) free(contpath);
415 return done;
416 }
417 /*
418 \f
419 */
420 /************************************************/
421 /*                                              */
422 /*      procedure to initialize the HOST side   */
423 /*                                              */
424 /************************************************/
425 int cnt_initscript(char *scriptname,const char *fmt,...)
426
427 {
428 #define BSIZE   2048
429
430 int status;
431 va_list args;
432 FILE *canal;
433 char *varlibpath;
434 char *parmlst;
435 char *cmd;
436 int phase;
437 int proceed;
438
439 status=0;
440 va_start(args,fmt);
441 canal=(FILE *)0;
442 varlibpath=apl_appdir(d_varlib);
443 (void) vasprintf(&parmlst,fmt,args);
444 (void) asprintf(&cmd,"%s/shell/%s %s",varlibpath,scriptname,parmlst);
445 phase=0;
446 proceed=true;
447 while (proceed==true) {
448   switch (phase) {
449     case 0      :       /*opening pip channel   */
450       if ((canal=popen(cmd,"r"))==(FILE *)0) {
451         (void) apl_alert(0,"%s, Unable to pipe cmd <%s> (error=<%s>)",
452                             appname,cmd,strerror(errno));
453         status=1;
454         phase=999;      /*trouble trouble       */      
455         }
456       break;
457     case 1      :       /*do we have feed back  */
458       if (canal!=(FILE *)0) {   /*always        */
459         char buffer[BSIZE];
460
461         while (fgets(buffer,BSIZE,canal)!=(char *)0) {
462           (void) apl_cleanstring(buffer);
463           if ((debug>0)&&(verbose==true))
464             (void) apl_alert(0,"%s, pipe say: <%s>",appname,buffer);
465           else {
466             (void) fprintf(stdout,"%s\n",buffer);
467             (void) fflush(stdout);
468             }
469           }
470         }
471       break;
472     case 2      :       /*closing pip           */
473       status=pclose(canal);/*get pipe status    */
474       break;
475     default     :       /*SAFE Guard            */
476       proceed=false;
477       break;
478     }
479   phase++;
480   }
481 (void) free(cmd);
482 (void) free(parmlst);
483 (void) free(varlibpath);
484 va_end(args);
485 return status;
486 }
487 /*
488 \f
489 */
490 /************************************************/
491 /*                                              */
492 /*      procedure to extract the container      */
493 /*      architecture available in the 'arch'    */
494 /*      file.                                   */
495 /*                                              */
496 /************************************************/
497 char *cnt_getarch(char *contname)
498
499 {
500 static char *availarch[]={
501         "i386","i686","x86_64",(char *)0
502         };
503
504 char *arch;
505 FILE *fichier;
506 char *contpath;
507 char *filename;
508 int phase;
509 int proceed;
510 char buffer[200];
511
512 arch=(char *)0;
513 fichier=(FILE *)0;
514 filename=(char *)0;
515 contpath=getcontpath(contname);
516 (void) asprintf(&filename,"%s/%s",contpath,"arch");
517 phase=0;
518 proceed=true;
519 while (proceed==true) {
520   switch (phase) {
521     case 0      :       /*let open the file     */
522       if ((fichier=fopen(filename,"r"))==(FILE *)0) {
523         (void) apl_alert(0,"%s Unable to open file <%s> (error=<%s>)",
524                            appname,filename,strerror(errno));
525         phase=999;      /*trouble trouble       */
526         }
527       break;
528     case 1      :       /*reading first line    */
529       if (apl_getstr(fichier,buffer,sizeof(buffer),'#')==(char *)0) {
530         (void) apl_alert(0,"%s Unable to read file <%s> (file empty?)",
531                            appname,filename);
532         phase=999;      /*trouble trouble       */
533         }
534       (void) fclose(fichier);
535       break;
536     case 2      :       /*scanning line         */
537       (void) apl_cleanstring(buffer);
538       if (strlen(buffer)>0) {   /*always?       */
539         int i;
540
541         for (i=0;availarch[i]!=(char *)0;i++) {
542           if (strcmp(availarch[i],buffer)==0) {
543             arch=strdup(availarch[i]);
544             proceed=false;      /*found arch    */
545             break;
546             }
547           }
548         }
549       break;
550     case 3      :       /*scanning line         */
551       (void) apl_alert(0,"%s file <%s>, arch <%s> unknown, setting default",
552                            appname,filename,buffer);
553       break;
554     default     :       /*SAFE Guard            */
555       proceed=false;
556       break;
557     }
558   phase++;
559   }
560 (void) free(filename);
561 (void) free(contpath);
562 if (arch==(char *)0) {
563   arch=strdup(availarch[0]);
564   }
565 return arch;
566 }
567 /*
568 \f
569 */
570 /************************************************/
571 /*                                              */
572 /*      procedure to extract the container      */
573 /*      distribution type available in the      */
574 /*      'dist' file.                            */
575 /*                                              */
576 /************************************************/
577 char *cnt_getdist(char *contname)
578
579 {
580 char *dist;
581 FILE *fichier;
582 char *contpath;
583 char *filename;
584 int phase;
585 int proceed;
586 char buffer[200];
587
588 dist=(char *)0;
589 fichier=(FILE *)0;
590 filename=(char *)0;
591 contpath=getcontpath(contname);
592 (void) asprintf(&filename,"%s/%s",contpath,"dist");
593 phase=0;
594 proceed=true;
595 while (proceed==true) {
596   switch (phase) {
597     case 0      :       /*let open the file     */
598       if ((fichier=fopen(filename,"r"))==(FILE *)0) {
599         (void) apl_alert(0,"%s Unable to open file <%s> (error=<%s>)",
600                            appname,filename,strerror(errno));
601         phase=999;      /*trouble trouble       */
602         }
603       break;
604     case 1      :       /*reading first line    */
605       if (apl_getstr(fichier,buffer,sizeof(buffer),'#')==(char *)0) {
606         (void) apl_alert(0,"%s Unable to read file <%s> (file empty?)",
607                            appname,filename);
608         phase=999;      /*trouble trouble       */
609         }
610       (void) fclose(fichier);
611       break;
612     case 2      :       /*scanning line         */
613       (void) apl_cleanstring(buffer);
614       dist=strdup(buffer);
615       break;
616     default     :       /*SAFE Guard            */
617       proceed=false;
618       break;
619     }
620   phase++;
621   }
622 (void) free(filename);
623 (void) free(contpath);
624 if (dist==(char *)0) {
625   dist=strdup("unknown");
626   }
627 return dist;
628 }
629 /*
630 \f
631 */
632 /************************************************/
633 /*                                              */
634 /*      procedure to assign a new STDOUT/STDERR */
635 /*      and close STDIN. Done ONLY if the       */
636 /*      process is in background mode.          */
637 /*                                              */
638 /************************************************/
639 void cnt_setstdio(int foreground,char *contname,char *outname)
640
641 {
642 #define OPIO    "unicnt.c:cnt_setstdio,"
643
644 if (foreground==0) {
645   int newstdout;
646   int newstderr;
647   int phase;
648   int proceed;
649   char *contpath;
650   char *filename;
651
652   newstdout=-1;
653   newstderr=-1;
654   phase=0;
655   proceed=true;
656   contpath=getcontpath(contname);
657   (void) asprintf(&filename,"%s/%s.stdout",contpath,outname);
658   while (proceed==true) {
659     switch (phase) {
660       case 0    :       /*open the new stdout   */
661         (void) unlink(filename);
662         if ((newstdout=open(filename,O_CREAT|O_RDWR|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP))<0) {
663           (void) apl_alert(0,"%s, Unable to open <%s> (error=<%s>)",
664                               OPIO,filename,strerror(errno));
665           phase=999;    /*trouble trouble       */
666           }
667         break;
668       case 1    :       /*open the new stderr   */
669         (void) free(filename);
670         (void) asprintf(&filename,"%s/%s.stderr",contpath,outname);
671         (void) unlink(filename);
672         if ((newstderr=open(filename,O_CREAT|O_RDWR|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP))<0) {
673           (void) apl_alert(0,"%s, Unable to open <%s> (error=<%s>)",
674                               OPIO,filename,strerror(errno));
675           (void) close(newstdout);
676           phase=999;    /*trouble trouble       */
677           }
678         break;
679       case 2    :       /*duplicating stdout    */
680         if (dup2(newstdout,1)<0) {
681           (void) apl_alert(0,"%s, Unable to dup2 stdout (error=<%s>)",
682                               OPIO,strerror(errno));
683           (void) close(newstderr);
684           (void) close(newstdout);
685           phase=999;
686           }
687         break;
688       case 3    :       /*duplicating stderr    */
689         (void) close(newstdout);
690         if (dup2(newstderr,2)<0) {
691           (void) apl_alert(0,"%s, Unable to dup2 stderr (error=<%s>)",
692                               OPIO,strerror(errno));
693           (void) close(newstderr);
694           phase=999;
695           }
696         break;
697       case 4    :       /*setting new std       */
698         if ((stdout=fdopen(1,"w"))==(FILE *)0) {
699           (void) apl_alert(0,"%s, Unable to fdopen stdout (error=<%s>)",
700                               OPIO,strerror(errno));
701           }
702         if ((stderr=fdopen(2,"w"))==(FILE *)0) {
703           (void) apl_alert(0,"%s, Unable to fdopen stderr (error=<%s>)",
704                               OPIO,strerror(errno));
705           }
706         (void) fclose(stdin);
707         break;
708       case 5    :       /*write time stamp      */
709         (void) fprintf(stdout,"stdout start: %s\n",apl_ascsysdatetime(time((time_t *)0)));
710         (void) fprintf(stderr,"stderr start: %s\n",apl_ascsysdatetime(time((time_t *)0)));
711         (void) fflush(stdout);
712         (void) fflush(stderr);
713         break;
714       default   :       /*SAFE Guard            */
715         proceed=false;
716         break;
717       }
718     phase++;
719     }
720   (void) free(filename);
721   (void) free(contpath);
722   }
723 }
724 /*
725 \f
726 */
727 /************************************************/
728 /*                                              */
729 /*      Procedure to wait for entry on the      */
730 /*      container console and forward it        */
731 /*      on the Master_container console file.   */
732 /*      A Management expiration is done         */
733 /*      according time.                         */
734 /*                                              */
735 /************************************************/
736 int cnt_mstconsole(char *contname,pid_t cntpid)
737
738 {
739 #define OPCO    "unicnt.c:cnt_console,"
740
741 #define RLX     5       /*number of sec         */
742 int status;
743 int nbr;
744 int cconsole;
745 int mconsole;
746 struct timeval relax;
747 fd_set reading;
748 char *contpath;
749 char *filename;
750 int phase;
751 int proceed;
752 char buffer[1000];
753
754 status=0;
755 nbr=0;
756 cconsole=0;
757 mconsole=0;
758 relax.tv_sec=RLX;       /*sec relax time        */
759 relax.tv_usec=0;
760 FD_ZERO(&reading);
761 contpath=getcontpath(contname);
762 (void) asprintf(&filename,"%s/%s",contpath,"console");
763 phase=0;
764 proceed=true;
765 while (proceed==true) {
766   switch (phase) {
767     case 0      :       /*opening the M-Console*/
768       if ((mconsole=open(filename,O_CREAT|O_WRONLY|O_TRUNC,S_IRUSR|S_IWUSR))<0) {
769         (void) apl_alert(0,"%s, Unable to open mconsole <%s> (error=<%s>)",
770                               OPCO,filename,strerror(errno));
771         phase=999;
772         status=-1;
773         }
774       break;
775     case 1      :       /*opening the C-Console*/
776       (void) free(filename);
777       (void) asprintf(&filename,"%s/rootfs/dev/%s",contpath,"console");
778       if ((cconsole=open(filename,O_RDWR|O_ASYNC))<0) {
779         (void) apl_alert(0,"%s, Unable to open cconsole <%s> (error=<%s>)",
780                               OPCO,filename,strerror(errno));
781         (void) close(mconsole);
782         phase=999;
783         status=-1;
784         }
785       break;
786     case 2      :       /*waiting event         */
787       relax.tv_sec=RLX; /*sec relax time        */
788       relax.tv_usec=0;
789       FD_ZERO(&reading);
790       FD_SET(cconsole,&reading);
791       switch ((nbr=select(cconsole+1,&reading,(fd_set *)0,(fd_set *)0,&relax))) {
792         case    -1    :
793           switch (errno) {
794             case EINTR: /*received a signal, lets see...*/
795               break;    /*getting out fast              */
796             default   :
797               (void) apl_alert(0,"%s, unexpected select event (error=<%s>)",
798                                   OPCO,strerror(errno));
799               break;
800             }
801           break;
802         case      0   : /*timeout child lost ?  */
803           switch (waitpid(cntpid,0,WNOHANG)) {
804             case -1   : /*exiting               */
805               (void) apl_alert(0,"Unexpect error on waitpid (error=<%s>)",strerror(errno));
806               status=-1;
807               break;
808             case 0    : /*process still up!     */
809               phase--;  /*lets wait for console */
810               break;
811             default   : /*process exited!       */
812                         /*going to next phase   */
813               break;
814             }
815           break;
816         default       : /*data ready in cconsole*/
817           if ((nbr=read(cconsole,buffer,sizeof(buffer)))>0) {
818             (void) write(mconsole,buffer,nbr);
819             }           /*forwarded to mconsole */
820           phase--;      /*stay put on phase     */
821           break;
822         }
823       break;
824     case 3      :       /*closing console       */
825       (void) close(mconsole);
826       (void) close(cconsole);
827       break;
828     default     :       /*SAFE Guard            */
829       proceed=false;
830       break;
831     }
832   phase++;
833   }
834 (void) free(filename);
835 (void) free(contpath);
836 return status;
837 }