1 /*
2  * This file is part of the Alliance CAD System
3  * Copyright (C) Laboratoire LIP6 - D�partement ASIM
4  * Universite Pierre et Marie Curie
5  *
6  * Home page          : http://www-asim.lip6.fr/alliance/
7  * E-mail             : mailto:alliance-users@asim.lip6.fr
8  *
9  * This library is free software; you  can redistribute it and/or modify it
10  * under the terms  of the GNU Library General Public  License as published
11  * by the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * Alliance VLSI  CAD System  is distributed  in the hope  that it  will be
15  * useful, but WITHOUT  ANY WARRANTY; without even the  implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy  of the GNU General Public License along
20  * with the GNU C Library; see the  file COPYING. If not, write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * Purpose : system dependant functions
26  * Date    : 06/03/92
27  * Author  : Frederic Petrot <Frederic.Petrot@lip6.fr>
28  * Modified by Czo <Olivier.Sirol@lip6.fr> 1997,98
29  */
30 
31 #ident "$Id: mbk_sys.c,v 1.5 2012/05/14 14:20:23 alliance Exp $"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/wait.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 
43 #include "mut.h"
44 #include "mbk_sys.h"
45 
46 static char filename[BUFSIZ];
47 char MBKFOPEN_NAME[BUFSIZ];
48 char MBKFOPEN_FILTER;
49 endchld_list *HEAD_ENDCHLD=NULL;
50 endchld_list *HEAD_ENDCHLD_FREE=NULL;
51 int STAT_ENDCHLD;
52 autoackchld_list *HEAD_AUTOACKCHLD=NULL;
53 autoackchld_list *HEAD_AUTOACKCHLD_FREE=NULL;
54 int STAT_AUTOACKCHLD;
55 
56 long mbkalloc_stat = 0; /* statistics on maximun allocated memory */
57 
mbkalloc(size_t nbytes)58 void *mbkalloc(size_t nbytes)
59 {
60 void  *pt;
61 
62    mbkalloc_stat += nbytes;
63    if (!(pt = malloc(nbytes))) {
64       (void)fflush(stdout);
65       (void)fprintf(stderr,"*** mbk error ***\n");
66       (void)fprintf(stderr,"fatal mbkalloc error : not enough memory\n");
67       EXIT(1);
68    }
69    return pt;
70 }
71 
mbkrealloc(void * pt,size_t nbytes)72 void *mbkrealloc(void  *pt, size_t nbytes)
73 {
74 
75    mbkalloc_stat += nbytes;
76    if (!(pt = realloc(pt, nbytes))) {
77       (void)fflush(stdout);
78       (void)fprintf(stderr,"*** mbk error ***\n");
79       (void)fprintf(stderr,"fatal mbkrealloc error : not enough memory\n");
80       EXIT(1);
81    }
82    return pt;
83 }
84 
mbkfree(void * ptr)85 void mbkfree(void *ptr)
86 {
87    (void)free(ptr);
88 }
89 
mbkgetenv(const char * name)90 char *mbkgetenv(const char *name)
91 {
92 char *value;
93 
94    if (name == NULL)
95       fprintf(stdout, "--- mbk --- ERROR : mbkgetenv(NULL)\n");
96 
97    value = getenv(name);
98 
99    if (TRACE_GETENV) {
100       fprintf(stdout, "--- mbk --- mbkgetenv %s : %s\n",
101                       name ? name : "NULL", value ? value : "NULL");
102    }
103 
104    return value;
105 }
106 
107 
108 /* file opening :
109    defines the strategy used for searching and opening file in the
110    mbk environement. */
mbkfopen(const char * name,const char * extension,const char * mode)111 FILE* mbkfopen(const char *name, const char *extension, const char *mode)
112 {
113   FILE *ptf;
114 
115   ptf = mbkfopentrace(name, extension, mode);
116   if(( TRACE_FILE == 1 ) || (( TRACE_FILE == 3 ) && (ptf != NULL )))
117   {
118     fflush( stdout );
119     fprintf( stderr,
120              "*** mbkfopen( \"%s\", \"%s\", \"%s\" ) -> %s\n",
121              name,
122              extension ? extension : "",
123              mode,
124              ptf ? MBKFOPEN_NAME : "FAILED"
125            );
126   }
127   return ptf;
128 }
129 
mbkfopen_infos(const FILE * in,const char * filename,const char * name,const char * extension,const char * mode,const char filter)130 void mbkfopen_infos(const FILE *in, const char *filename, const char *name, const char *extension, const char *mode, const char  filter)
131 {
132   if( in )
133   {
134     strcpy( MBKFOPEN_NAME, filename );
135     MBKFOPEN_FILTER = filter;
136   }
137 
138   if( TRACE_FILE == 2 )
139   {
140     /* La methode de Czo : y parait qu'on peut debugger avec ca... */
141     fprintf( stdout,
142              "--- mbk --- mbkfopen %s : %s, (%s,%s,%s)\n",
143              in ? "ok" : "FAILED",
144              filename,
145              name,
146              extension ? extension : "",
147              mode
148            );
149   }
150 }
151 
mbkfopentrace(const char * name,const char * extension,const char * mode)152 FILE *mbkfopentrace(const char *name, const char *extension, const char *mode)
153 {
154 FILE *in=NULL;
155 FILE *insav;
156 int i;
157 
158 
159 if (!CATA_LIB || !WORK_LIB)
160     mbkenv(); /* not done yet */
161 
162 
163   if( *mode == 'w' )
164   {
165     if( OUT_FILTER && FILTER_SFX )
166     {
167       if (extension)
168         (void)sprintf( filename,
169                        "%s/%s.%s%s",
170                        WORK_LIB,
171                        name,
172                        extension,
173                        FILTER_SFX
174                      );
175       else
176         (void)sprintf(filename, "%s/%s%s", WORK_LIB, name, FILTER_SFX );
177 
178       strcpy( MBKFOPEN_NAME, filename );
179       in = mbkpopen( filename, OUT_FILTER, 'w' );
180       mbkfopen_infos( in, filename, name, extension, mode, YES );
181       if (extension)
182         (void)sprintf( filename,
183                        "%s/%s.%s",
184                        WORK_LIB,
185                        name,
186                        extension
187                      );
188       else
189         (void)sprintf(filename, "%s/%s", WORK_LIB, name );
190        if((insav = fopen(filename,READ_TEXT)) != NULL)
191          {
192           fflush( stdout );
193           fprintf( stderr,
194              "*** mbk warning : file %s already exist in the drive directory\n", filename) ;
195           fprintf( stderr, "it will be deleted\n" ) ;
196           fflush( stderr );
197           unlink(filename) ;
198           fclose(insav) ;
199          }
200       return ( in );
201     }
202     else
203     {
204       if (extension)
205         (void)sprintf( filename,
206                        "%s/%s.%s",
207                        WORK_LIB,
208                        name,
209                        extension
210                      );
211       else
212         (void)sprintf(filename, "%s/%s", WORK_LIB, name );
213 
214       strcpy( MBKFOPEN_NAME, filename );
215       in = fopen( filename, WRITE_TEXT ) ;
216       mbkfopen_infos( in, filename, name, extension, mode, NO );
217       return ( in );
218     }
219   }
220   else
221   if( *mode == 'r' )
222   {
223     if (extension) /* if extension is null, no dot is required */
224       (void)sprintf( filename,
225                      "%s/%s.%s",
226                      WORK_LIB,
227                      name,
228                      extension
229                    );
230     else
231       (void)sprintf(filename, "%s/%s", WORK_LIB, name);
232 
233     in = fopen( filename, READ_TEXT );
234     mbkfopen_infos( in, filename, name, extension, mode, NO );
235     if( in )
236     {
237       if( FILTER_SFX && IN_FILTER )
238       {
239         if (extension) /* if extension is null, no dot is required */
240           (void)sprintf( filename,
241                          "%s/%s.%s%s",
242                          WORK_LIB,
243                          name,
244                          extension,
245                          FILTER_SFX
246                        );
247         else
248           (void)sprintf(filename, "%s/%s%s", WORK_LIB, name , FILTER_SFX);
249         if((insav = fopen(filename,READ_TEXT)) != NULL)
250          {
251             fflush( stdout );
252             fprintf( stderr,
253                "*** mbk warning : file %s also exist it will be ignored\n", filename) ;
254             fflush( stderr );
255             fclose(insav) ;
256          }
257       }
258       return in;
259     }
260 
261     if( FILTER_SFX && IN_FILTER )
262     {
263       if (extension) /* if extension is null, no dot is required */
264         (void)sprintf( filename,
265                        "%s/%s.%s%s",
266                        WORK_LIB,
267                        name,
268                        extension,
269                        FILTER_SFX
270                      );
271       else
272         (void)sprintf(filename, "%s/%s%s", WORK_LIB, name, FILTER_SFX );
273 
274       in = mbkpopen( filename, IN_FILTER, 'r' );
275       mbkfopen_infos( in, filename, name, extension, mode, YES );
276       if( in )
277         return in ;
278     }
279 
280     i=0;
281 
282     while (CATA_LIB[i])
283     {
284       if (extension)
285         (void)sprintf( filename,
286                        "%s/%s.%s",
287                        CATA_LIB[i],
288                        name,
289                        extension
290                      );
291       else
292         (void)sprintf( filename,
293                        "%s/%s",
294                        CATA_LIB[i],
295                        name
296                      );
297 
298       in = fopen( filename, READ_TEXT );
299       mbkfopen_infos( in, filename, name, extension, mode, NO );
300       if( in )
301       {
302         if( FILTER_SFX && IN_FILTER )
303         {
304           if (extension) /* if extension is null, no dot is required */
305             (void)sprintf( filename,
306                            "%s/%s.%s%s",
307                            CATA_LIB[i],
308                            name,
309                            extension ,
310                            FILTER_SFX
311                          );
312           else
313             (void)sprintf(filename, "%s/%s%s", CATA_LIB[i], name ,FILTER_SFX);
314           if((insav = fopen(filename,READ_TEXT)) != NULL)
315            {
316               fflush( stdout );
317               fprintf( stderr,
318                "*** mbk warning : file %s also exist it will be ignored\n", filename) ;
319               fflush( stderr );
320               fclose(insav) ;
321              }
322         }
323         return( in );
324       }
325 
326       if( FILTER_SFX && IN_FILTER )
327       {
328         if (extension) /* if extension is null, no dot is required */
329           (void)sprintf( filename,
330                          "%s/%s.%s%s",
331                          CATA_LIB[i],
332                          name,
333                          extension,
334                          FILTER_SFX
335                        );
336         else
337           (void)sprintf(filename, "%s/%s%s", CATA_LIB[i], name, FILTER_SFX );
338 
339         in = mbkpopen( filename, IN_FILTER, 'r' );
340         mbkfopen_infos( in, filename, name, extension, mode, YES );
341         if( in )
342          {
343           return in ;
344          }
345       }
346 
347       i++;
348     }
349     return( NULL );
350   }
351   else
352   {
353     (void)fflush(stdout);
354     (void)fprintf(stderr, "*** mbk error ***\n");
355     (void)fprintf(stderr, "unknown file opening mode %s\n", mode);
356     EXIT(1);
357   }
358 
359   return NULL; /* never reached */
360 }
361 
362 /* unlink :
363    ensures that only files in the working library may be erased. */
mbkunlink(const char * name,const char * extension)364 int mbkunlink(const char *name, const char *extension)
365 {
366    if (!CATA_LIB || !WORK_LIB)
367       mbkenv(); /* not done yet */
368 
369    if (extension) /* if extension is null, no dot is required */
370       (void)sprintf(filename, "%s/%s.%s", WORK_LIB, name, extension);
371    else
372       (void)sprintf(filename, "%s/%s", WORK_LIB, name);
373 
374    return unlink(filename);
375 }
376 
377 /* filepath :
378    find the complete path of file from mbkfopen point of view. */
filepath(const char * name,const char * extension)379 char *filepath(const char *name, const char *extension)
380 {
381 FILE *in;
382 int i ;
383 
384   if (!CATA_LIB || !WORK_LIB)
385     mbkenv(); /* not done yet */
386 
387   if (extension) /* if extension is null, no dot is required */
388     (void)sprintf(filename, "%s/%s.%s", WORK_LIB, name, extension );
389   else
390     (void)sprintf(filename, "%s/%s", WORK_LIB, name );
391 
392   if ((in = fopen(filename, READ_TEXT))) {
393     (void)fclose(in);
394     return filename;
395   }
396 
397   if( FILTER_SFX && IN_FILTER )
398   {
399     if (extension) /* if extension is null, no dot is required */
400       (void)sprintf(filename, "%s/%s.%s%s", WORK_LIB, name, extension, FILTER_SFX );
401     else
402       (void)sprintf(filename, "%s/%s%s", WORK_LIB, name, FILTER_SFX );
403 
404     if ((in = fopen(filename, READ_TEXT))) {
405       (void)fclose(in);
406       return filename;
407     }
408   }
409 
410 
411   i = 0;
412   while (CATA_LIB[i]) {
413     if (extension) /* if extension is null, no dot is required */
414       (void)sprintf(filename, "%s/%s.%s", CATA_LIB[i], name, extension );
415     else
416       (void)sprintf(filename, "%s/%s", CATA_LIB[i], name );
417 
418     if ((in = fopen(filename, READ_TEXT))) {
419       (void)fclose(in);
420       return filename;
421     }
422 
423     if( FILTER_SFX && IN_FILTER )
424     {
425       if (extension) /* if extension is null, no dot is required */
426         (void)sprintf(filename, "%s/%s.%s%s", CATA_LIB[i], name, extension, FILTER_SFX );
427       else
428         (void)sprintf(filename, "%s/%s%s", CATA_LIB[i], name, FILTER_SFX );
429 
430       if ((in = fopen(filename, READ_TEXT))) {
431         (void)fclose(in);
432         return filename;
433       }
434     }
435     i++;
436   }
437   return NULL;
438 }
439 
440 /* mbkpopen : open a pipe with a filter, return a FILE*
441  * Gregoire.Avot
442  */
443 
mbkpopen(const char * nom,const char * filter,char mode)444 FILE* mbkpopen(const char *nom, const char *filter, char mode)
445 {
446   int ptf[2];
447   static int fic;
448   int pid;
449   FILE *file;
450   char **argv;
451 
452   if( mode == 'w' )
453     fic = open( nom,
454                 O_WRONLY|O_CREAT|O_TRUNC,
455                 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
456               );
457   else
458     fic = open( nom, O_RDONLY );
459 
460   if( fic == -1 )
461     return( NULL );
462 
463   if( pipe( ptf ) == -1 )
464   {
465     fflush( stdout );
466     fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" )\n", nom );
467     perror( "pipe() ");
468     EXIT(1);
469   }
470 
471 #ifndef AUTO_HAS_VFORK
472     pid = fork();
473 #else
474     pid = vfork();
475 #endif
476 
477   if( pid == -1 )
478   {
479     fflush( stdout );
480     fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" )\n", nom );
481     perror( "(v)fork() ");
482     EXIT(1);
483   }
484 
485   if( pid == 0 )
486   {
487     /* fils */
488     fflush( stdout );
489 
490     argv = decompfilter( filter );
491     if( argv == NULL )
492     {
493       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
494       fprintf( stderr, "Bad filter.\n" );
495       EXIT(1);
496     }
497 
498     if( mode == 'w' )
499     {
500       if( dup2( ptf[0], 0 ) == -1 )
501       {
502         fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
503         perror( "dup2( ptf[0], 0 ) ");
504         EXIT(1);
505       }
506 
507       if( dup2( fic, 1 ) == -1 )
508       {
509         fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
510         perror( "dup2( fic, 1 ) ");
511         EXIT(1);
512       }
513     }
514     else
515     {
516       if( dup2( ptf[1], 1 ) == -1 )
517       {
518         fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
519         perror( "dup2( ptf[1], 1 ) ");
520         EXIT(1);
521       }
522 
523       if( dup2( fic, 0 ) == -1 )
524       {
525         fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
526         perror( "dup2( fic, 0 ) ");
527         EXIT(1);
528       }
529     }
530 
531     if( close( fic ) == -1 )
532     {
533       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
534       perror( "close( fic ) ");
535       EXIT(1);
536     }
537 
538     if( close( ptf[1] ) == -1 )
539     {
540       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
541       perror( "close( ptf[1] ) ");
542       EXIT(1);
543     }
544 
545     if( close( ptf[0] ) == -1 )
546     {
547       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
548       perror( "close( ptf[0] ) ");
549       EXIT(1);
550     }
551 
552     if( execvp( argv[0], &(argv[1]) ) == -1 )
553     {
554       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) child\n", nom );
555       perror( "execvp " );
556       EXIT(1);
557     }
558   }
559 
560   mbksetautoackchld( pid );
561   close( fic );
562 
563   if( mode == 'w' )
564   {
565     if( close( ptf[0] ) == -1 )
566     {
567       fflush( stdout );
568       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) parent\n", nom );
569       perror( "close( ptf[0] ) ");
570       EXIT(1);
571     }
572 
573     file = fdopen( ptf[1], "w" );
574     if( file == NULL )
575     {
576       fflush( stdout );
577       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) parent\n", nom );
578       perror( "fdopen( ptf[1], \"w\" ) ");
579       EXIT(1);
580     }
581   }
582   else
583   {
584     if( close( ptf[1] ) == -1 )
585     {
586       fflush( stdout );
587       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) parent\n", nom );
588       perror( "close( ptf[1] ) ");
589       EXIT(1);
590     }
591 
592     file = fdopen( ptf[0], "r" );
593     if( file == NULL )
594     {
595       fflush( stdout );
596       fprintf( stderr, "*** Fatal error in mbkpopen( \"%s\" ) parent\n", nom );
597       perror( "fdopen( ptf[0], \"r\" ) ");
598       EXIT(1);
599     }
600   }
601 
602   return( file );
603 }
604 
decompfilter(const char * filter)605 char **decompfilter( const char *filter )
606 {
607   int         pos;
608   int         i;
609   char       *pt;
610   char       *fullpath;
611   char       *argv0;
612   char       *argvn;
613   chain_list *head;
614   chain_list *scan;
615   int         nbarg;
616   char      **ret;
617 
618   /* remove trailing space */
619   for( pos = 0 ; filter[pos] == ' ' && filter[pos] != 0  ; pos++ );
620   if( filter[pos] == 0 )
621     return( NULL );
622 
623   /* The full path to binairie */
624   for( i = pos ; filter[i] != ' ' && filter[i] != 0 ; i++ );
625   fullpath = (char*)mbkalloc( sizeof(char) * ( i-pos+1 ) );
626   strncpy( fullpath, filter+pos, i-pos );
627   fullpath[i-pos] = 0;
628   pos = i;
629 
630   /* The binairie himself */
631   pt = strrchr( fullpath, '/' );
632   argv0 = (char*)mbkalloc( sizeof( char ) * (strlen( fullpath ) + 1) );
633   if( pt == NULL )
634     strcpy( argv0, fullpath );
635   else
636     strcpy( argv0, pt+sizeof(char) );
637 
638   /* The arguments */
639   head = NULL;
640   nbarg=2;
641 
642   do
643   {
644     for( ; filter[pos] == ' ' && filter[pos] != 0  ; pos++ );
645     if( filter[pos] == 0 )
646       break;
647 
648     for( i = pos ; filter[i] != ' ' && filter[i] != 0 ; i++ );
649     argvn = (char*)mbkalloc( sizeof( char ) * ( i-pos+1 ) );
650     strncpy( argvn, filter+pos, i-pos );
651     argvn[i-pos] = 0;
652     pos = i;
653     head = addchain( head, argvn );
654     nbarg++;
655   }
656   while( 1 );
657 
658   head = reverse( head );
659 
660   ret = (char**)mbkalloc( sizeof(char*) * (nbarg+1) );
661 
662   ret[0] = fullpath;
663   ret[1] = argv0;
664 
665   for( scan = head, pos=2 ; scan ; scan = scan->NEXT, pos++ )
666     ret[pos] = scan->DATA;
667   ret[pos] = NULL;
668 
669   freechain( head );
670 
671   return( ret );
672 }
673 
mbkackchld(int sig)674 void mbkackchld( int sig )
675 {
676   int               pid;
677   int               status;
678   endchld_list     *new;
679   int               err;
680   autoackchld_list *scanauto, *prevauto;
681 
682   /* Le handlert d'interruption SIGCHLD. Il doit avoir �t� configur� pour ne
683    * pas �tre interrompu par lui m�me. */
684 
685   if( sig != SIGCHLD )
686   {
687     fflush( stdout );
688     fprintf( stderr,
689              "*** mbk warning : call of mbkackchld with signal %d\n",
690              (int)sig
691            );
692     return;
693   }
694 
695   do
696   {
697     errno = 0;
698     pid = waitpid( -1, &status, WNOHANG );
699     err = errno ;
700     if( pid > 0 )
701     {
702       for( scanauto = HEAD_AUTOACKCHLD, prevauto=NULL ;
703            scanauto ;
704            scanauto = scanauto->NEXT
705          )
706       {
707         if( scanauto->PID == pid )
708           break;
709         prevauto = scanauto ;
710       }
711 
712       if( scanauto )
713       {
714         /* Process was previously put in the list auto acknowledge. */
715         if( prevauto )
716           prevauto->NEXT = scanauto->NEXT;
717         else
718           HEAD_AUTOACKCHLD = scanauto->NEXT;
719 
720         mbkfreeautoackchld( scanauto );
721       }
722       else
723       {
724         /* Put process in the waiting queue to be read by user */
725         new           = mbkgetendchld();
726         new->NEXT     = HEAD_ENDCHLD;
727         HEAD_ENDCHLD = new;
728         new->PID      = pid;
729         new->STATUS   = status;
730       }
731     }
732   }
733   while( pid != 0 && err != ECHILD );
734 
735 }
736 
737 /* Sur les architectures multipro, on peut avoir un malloc() interrompu par
738  * un signal. Si ou alloue une structure endchld_list avec un malloc dans le
739  * handler, on aura une r�entrance du malloc. Cette caract�ristiques n'est pour
740  * l'instant pas support�e. */
741 
mbkgetendchld(void)742 endchld_list* mbkgetendchld( void )
743 {
744   endchld_list *new;
745 
746   /* Cette fonction ne doit �tre appell�e qu'� partir du handler du signal
747    * SIGCHLD. Si cela devait changer, il faudrait la prot�ger contre la
748    * r�ception de ce signal */
749 
750   if( ! HEAD_ENDCHLD_FREE )
751   {
752     fflush( stdout );
753     fprintf( stderr,
754              "\n*** mbk ERROR : Not enought free slot in mbkgetfreeendchld().\n"
755            );
756     exit(1);
757   }
758 
759   new = HEAD_ENDCHLD_FREE ;
760   HEAD_ENDCHLD_FREE = HEAD_ENDCHLD_FREE->NEXT ;
761 
762   STAT_ENDCHLD++;
763   return( new );
764 }
765 
mbkfreeendchld(endchld_list * bloc)766 void mbkfreeendchld( endchld_list *bloc )
767 {
768   sigset_t  set;
769 
770   /* Cette fonction est appell�e � partir de mbkwaitpid(). Il peut y avoir une
771    * corruption de la liste si un signal SIGCHLD intervient entre les deux
772    * lignes puisque le handler appellera mbkgetendchld... */
773 
774   /* On masque temporairement le signal emb�tant */
775   sigemptyset( &set );
776   sigaddset( &set, SIGCHLD );
777   sigprocmask( SIG_BLOCK, &set, NULL );
778 
779 
780   bloc->NEXT = HEAD_ENDCHLD_FREE ;
781   HEAD_ENDCHLD_FREE = bloc ;
782 
783   STAT_ENDCHLD--;
784   /* On le demasque. Si il y en a un qui est arriv� entre temps, il sera pris
785    * en compte maintenant. */
786   /* sigrelse(SIGCHLD); (non d�fini sous SunOs) */
787   sigprocmask( SIG_UNBLOCK, &set, NULL );
788 }
789 
mbkinitendchld()790 void mbkinitendchld( )
791 {
792   endchld_list *bloc;
793   int n;
794 
795   /* L�, pas de probl�mes : le handler n'est pas encore positionn� quand cette
796    * fonction est appell�e. */
797   bloc = (endchld_list*)mbkalloc( sizeof( endchld_list ) * ENDCHLD_MAX );
798   n = ENDCHLD_MAX - 1;
799   bloc[n].NEXT = NULL ;
800   while( n > 0 )
801   {
802     n-- ;
803     bloc[n].NEXT = &( bloc[n+1] );
804   }
805   HEAD_ENDCHLD_FREE = &(bloc[0]);
806   STAT_ENDCHLD=0;
807 }
808 
mbkgetautoackchld(void)809 autoackchld_list* mbkgetautoackchld( void )
810 {
811   autoackchld_list *new;
812 
813   if( ! HEAD_AUTOACKCHLD_FREE )
814   {
815     fflush( stdout );
816     fprintf( stderr,
817              "\n*** mbk ERROR : Not enought free slot in mbkgetautoackchld().\n"
818            );
819     exit(1);
820   }
821 
822   new = HEAD_AUTOACKCHLD_FREE ;
823   HEAD_AUTOACKCHLD_FREE = HEAD_AUTOACKCHLD_FREE->NEXT ;
824 
825   STAT_AUTOACKCHLD++;
826   return( new );
827 }
828 
mbkfreeautoackchld(autoackchld_list * bloc)829 void mbkfreeautoackchld( autoackchld_list *bloc )
830 {
831   bloc->NEXT = HEAD_AUTOACKCHLD_FREE ;
832   HEAD_AUTOACKCHLD_FREE = bloc ;
833   STAT_AUTOACKCHLD--;
834 }
835 
mbkinitautoackchld(void)836 void mbkinitautoackchld( void )
837 {
838   autoackchld_list *bloc;
839   int n;
840 
841   bloc=(autoackchld_list*)mbkalloc( sizeof( autoackchld_list ) * ENDCHLD_MAX );
842   n = AUTOACKCHLD_MAX - 1;
843   bloc[n].NEXT = NULL ;
844   while( n > 0 )
845   {
846     n-- ;
847     bloc[n].NEXT = &( bloc[n+1] );
848   }
849   HEAD_AUTOACKCHLD_FREE = &(bloc[0]);
850   STAT_AUTOACKCHLD=0;
851 }
852 
mbksetautoackchld(int pid)853 void mbksetautoackchld( int pid )
854 {
855   endchld_list     *scan, *prev ;
856   autoackchld_list *new;
857   sigset_t  set;
858 
859   /* Fonction utilisateur : on met dans la liste HEAD_AUTOACKCHLD un num�ro de
860    * pid. D�s qu'un processus fils se termine ave ce pid, il sera
861    * automatiquement supprim�. */
862 
863   /* Dans le d�roulement normal du programme, on touche ici � des structures
864    * qui sont modifi�es par le handler SIGCHLD. On �vite de mettre le bazard en
865    * blindant le morceau de code. */
866 
867   sigemptyset( &set );
868   sigaddset( &set, SIGCHLD );
869   sigprocmask( SIG_BLOCK, &set, NULL );
870 
871   prev = NULL;
872   for( scan = HEAD_ENDCHLD ; scan ; scan = scan->NEXT )
873   {
874     if( scan->PID == pid )
875       break;
876     prev = scan;
877   }
878 
879   if( scan )
880   {
881     /* Cas o� le processus que l'on demande d'acquiter automatiquement est d�j�
882      * termin�. Dans ce cas on le supprime de la file d'attente des processus
883      * termin�s */
884 
885     if( prev )
886       prev->NEXT = scan->NEXT ;
887     else
888       HEAD_ENDCHLD = scan->NEXT ;
889 
890     mbkfreeendchld( scan );
891   }
892   else
893   {
894     /* On ne voudra jamais savoir ce qu'est devenu le processus fils pid. On le
895      * met dans la liste des processus � acquiter automatiquement */
896     new         = mbkgetautoackchld();
897     new->PID    = pid;
898     new->NEXT   = HEAD_AUTOACKCHLD ;
899     HEAD_AUTOACKCHLD = new ;
900   }
901   sigprocmask( SIG_UNBLOCK, &set, NULL );
902 }
903