Don't use fstat for readable pipe chars in dtexec.
[oweals/cde.git] / cde / programs / dtudcexch / importbdf.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: importbdf.c /main/5 1996/06/27 10:40:33 ageorge $ */
24 /*
25  *  (c) Copyright 1995 FUJITSU LIMITED
26  *  This is source code modified by FUJITSU LIMITED under the Joint
27  *  Development Agreement for the CDEnext PST.
28  *  This is unpublished proprietary source code of FUJITSU LIMITED
29  *
30  *  Authors: Seiya Miyazaki     FUJITSU LIMITED
31  *           Hiroyuki Chiba     FUJITSU LIMITED
32  *
33  */
34
35
36
37 #include        <stdio.h>
38 #include        <fcntl.h>
39 #include        <signal.h>
40 #include        <sys/types.h>
41 #include        <sys/stat.h>
42 #ifndef SVR4
43 #if !defined( SYSV )
44 #include        <sys/resource.h>
45 #endif
46 #include        <sys/wait.h>
47 #else
48 #include        <wait.h>
49 #endif
50
51 #include        <unistd.h>
52
53 #include        <X11/Xmd.h>
54 #include        <X11/Xproto.h>
55 #include        "bdfgpf.h"
56 #include        "FaLib.h"
57
58 #include        <errno.h>
59
60 #define UNLINK_TMPFILE( file ){ \
61         if ( unlink( file ) != 0 ) { \
62                 exit(-1) ; \
63         } \
64 }
65
66 static impFileConvInit();
67 static impGetGpfInf();
68 static impReadBdfHeaderAndPut();
69 static impMergePtn();
70 static impModifyPtn();
71 static impInsertPtn();
72 static impWriteSnf();
73 static int impWritePtnToBdf();
74 static int impPutDefaultChars();
75 static int impReadBdfToMemory();
76
77 extern  int  expCheckCode();
78
79
80 static struct ptobhead WriteGpf;
81
82 static char     *targ_file = NULL;      /* UDC_file_name */
83
84
85 static void
86 sigint_out()
87 {
88         if (WriteGpf.out_file) {
89                 UNLINK_TMPFILE( WriteGpf.out_file );
90         }
91         exit( 0 );
92 }
93
94
95
96
97 int
98 ImpBDFCodeList( bdf_name, code_num, code_list )
99 char    *bdf_name ;
100 int     *code_num ;
101 int     **code_list ;
102 {
103         int     *glyph_list ;
104         FILE    *bdfp ;
105         char    *p ;
106         char    buf[2048] ;
107         int     cnt ;
108
109         /* open BDF file */
110         if( (bdfp = fopen( bdf_name, "r" )) == NULL ){
111             return(-1);
112         }
113
114         /* get number of characters in BDF file */
115         while ( 1 ) {
116             if( fgets( buf, BUFSIZE, bdfp ) == NULL) {
117                 return (BDF_INVAL);
118             }
119             p = buf;
120             SCAN_TO_NONSP( p )
121             if ( !strncmp( p, CHARS, (unsigned int)strlen( CHARS ) ) ) {
122                 if ( ( sscanf( p, "CHARS %d", code_num ) ) != 1 ) {
123                     return  BDF_INVAL;
124                 }
125                 break ;
126             } 
127         }
128
129         /* alloc memory for codes */
130         if( (glyph_list = (int *)calloc( *code_num, (unsigned int)sizeof(int) )) == NULL ){
131             return(-1);
132         }
133
134         /* get codes of BDF file */
135         cnt = 0 ;
136         while( cnt < *code_num ) {
137             if (fgets(buf, BUFSIZE, bdfp ) == NULL) {
138                 return (BDF_INVAL);
139             }
140             p = buf;
141             SCAN_TO_NONSP( p )
142             if (!strncmp(p, ENDFONT, (unsigned int)ENDFONTsz)) {
143                 break;
144             }else if (!strncmp(p, ENCODING, (unsigned int)ENCODINGsz)) {
145                 if ((sscanf(p, "ENCODING %d", &glyph_list[cnt] )) != 1) {
146                     return(BDF_INVAL);
147                 }
148                 cnt ++ ;
149             }
150         }
151         if( cnt != *code_num ){
152                 return(-1) ;
153         }
154
155         /* close BDF file */
156         if( fclose( bdfp ) ){
157             return(-1);
158         }
159
160         *code_list = glyph_list ;
161
162         return(0) ;
163 }
164
165
166
167 int
168 ImpBDFCodeListFree( code_list )
169 int     **code_list ;
170 {
171         free( *code_list ) ;
172         return(0) ;
173 }
174
175
176
177 int
178 ImpBDFCheck( bdf_name, gpf_name )
179 char    *bdf_name ;     /* BDF file name        */
180 char    *gpf_name ;     /* GPF file name        */
181 {
182         /* parameter check */
183         if( bdf_name == NULL || gpf_name == NULL ){
184                 return(-1) ;
185         }
186         return(0) ;
187 }
188
189
190
191
192 int
193 ImpBDFtoGpf( bdf_name, gpf_name, bdf_codenum, bdf_codelist)
194 char    *bdf_name ;
195 char    *gpf_name ;
196 int     bdf_codenum ;
197 int     *bdf_codelist ;
198 {
199         int     rtn ;
200         int     exit_stat;
201         struct btophead ReadGpf;
202         struct btophead ReadUdc;
203         struct stat             statbuf;
204         char            buf[BUFSIZE];
205
206         int     chk_fd;
207
208         ReadGpf.in_file = ReadUdc.in_file = WriteGpf.out_file = NULL;
209
210         if (!( bdftopcf = get_cmd_path( getenv( "PATH" ), BDFTOPCF_CMD ))) {
211                 bdftopcf = BDFTOPCF;
212         }
213         if (!( oakgtobdf = get_cmd_path( getenv( "PATH" ), SNFTOBDF_CMD ))) {
214                 oakgtobdf = SNFTOBDF;
215         }
216         if (!( bdftosnf = get_cmd_path( getenv( "PATH" ), BDFTOSNF_CMD ))) {
217                 bdftosnf = BDFTOSNF;
218         }
219
220         /* 
221         * set input/output file name
222         */
223
224         ReadUdc.in_file = bdf_name ;
225         ReadUdc.code_category = ALL_CODE ;
226         ReadUdc.start_code    = MIN_CODE ;
227         ReadUdc.end_code      = MAX_CODE ;
228
229         ReadGpf.in_file = gpf_name ;
230         ReadGpf.code_category = ALL_CODE ;
231         ReadGpf.start_code    = MIN_CODE ;
232         ReadGpf.end_code      = MAX_CODE ;
233
234         /*
235         * get real file name of GPF file
236         */
237         if ((targ_file = GetRealFileName( ReadGpf.in_file )) == NULL){
238                 return(-1);
239         }
240
241         /*
242         * WriteGpf.snf_file = ReadGpf.in_file
243         */
244         WriteGpf.snf_file = targ_file;
245
246         signal( SIGHUP , (void(*)())sigint_out );
247         signal( SIGINT , (void(*)())sigint_out );
248         signal( SIGQUIT, (void(*)())sigint_out );
249         signal( SIGTERM, (void(*)())sigint_out );
250
251         /*
252          * impFileConvInit() 
253          *
254          * SNFTOBDF, BDFTOSNF
255          *
256          *  (ReadGpf.in_file)  -->  SNFTOBDF ==H 
257          *                                     H
258          *                                      oakaddp  <-- (ReadUdc.in_file)
259          *                                     H
260          * (WriteGpf.out_file) <--  BDFTOSNF ==H
261          *
262          */
263
264         /*
265         * make a temporary file by BDF format corresponded to target GPF file
266         */
267         if ( rtn = impFileConvInit( &ReadUdc, &ReadGpf, &WriteGpf ) ) {
268                 if ( WriteGpf.out_file ) {
269                         UNLINK_TMPFILE( WriteGpf.out_file );
270                 }
271                 return(-1) ;
272         }
273
274         /*
275         * get informations from import file in BDF format
276         */
277         if ( rtn = ReadBdfHeader( &ReadUdc, buf ) ) {
278                 if ( WriteGpf.out_file ) {
279                         UNLINK_TMPFILE( WriteGpf.out_file );
280                 }
281                 return(-1) ;
282         }
283
284         /*
285         * get informations from target file in BDF format
286         */
287
288         if ( rtn = impGetGpfInf( &ReadGpf, &WriteGpf, buf, bdf_codenum ) ) {
289                 if ( WriteGpf.out_file ) {
290                         UNLINK_TMPFILE( WriteGpf.out_file );
291                 }
292                 return(-1) ;
293         }
294
295         /* wait for dtgpftobdf */
296         fclose( ReadGpf.input );
297         wait( 0 );
298
299         /*
300         * merge the UDC glyphs into GPF file (in BDF format)
301         */
302         if ( ( rtn = impMergePtn( &ReadUdc, &ReadGpf, buf,
303                                   bdf_codenum, bdf_codelist  ) ) ) {
304                 if ( WriteGpf.out_file ) {
305                         UNLINK_TMPFILE( WriteGpf.out_file );
306                 }
307                 return(-1) ;
308         }
309
310         /*
311         * write the UDC data into GPF output file (in BDF format)
312         */
313         if ( ( rtn = impWriteSnf( &ReadGpf, &WriteGpf ) ) ) {
314                 if ( WriteGpf.out_file ) {
315                         UNLINK_TMPFILE( WriteGpf.out_file );
316                 }
317                 return(-1) ;
318         }
319
320         /*
321         * convert temporary file into GPF format
322         */
323         fclose( ReadUdc.input );
324         fclose( WriteGpf.output );
325         wait( &exit_stat );
326 #if !defined( SVR4 ) && !defined( SYSV )
327         if ( !WIFEXITED(exit_stat) ) {
328 #else
329         if ( ! ( WIFEXITED(exit_stat) && !WEXITSTATUS(exit_stat) ) ) {
330 #endif
331                 UNLINK_TMPFILE( WriteGpf.out_file );
332                 return(-1) ;
333         }
334         signal( SIGHUP , SIG_IGN );
335         signal( SIGINT , SIG_IGN );
336         signal( SIGQUIT, SIG_IGN );
337         signal( SIGTERM, SIG_IGN );
338
339         sleep( 1 );
340         if ( ( stat( WriteGpf.out_file, &statbuf ) ) || ( statbuf.st_size == 0 )
341             ) {
342                 UNLINK_TMPFILE( WriteGpf.out_file );
343                 return(-1) ;
344         }
345         if ( stat( WriteGpf.snf_file, &statbuf ) ) {
346                 UNLINK_TMPFILE( WriteGpf.out_file );
347                 return( -1 );
348         }
349         /*
350         * convert the temporary file to target file
351         */
352         return( Make_NewFefFile( WriteGpf.snf_file, WriteGpf.out_file,
353             FONT_FILE_PARM, (uid_t)statbuf.st_uid, (gid_t)statbuf.st_gid, "ImpBDFtoGpf()" ));
354 }
355
356
357 /*
358 * sub functions
359 */
360
361 static
362 impFileConvInit(r_udc, r_gpf, w_gpf )
363 struct btophead *r_udc;
364 struct btophead *r_gpf;
365 struct ptobhead *w_gpf;
366 {
367         int     fd[2], snf_fd, permission;
368         char    buf[BUFSIZE];
369         int     pfd[2], ofd;
370
371         FontInfoRec     *finf;
372         char    *optlist[5] = {0,0,0,0,0};
373         char    *ep ;
374         int     i ;
375         struct  stat    statbuf ;
376
377
378
379         if ( ( r_udc->input = fopen(r_udc->in_file, "r")) == NULL ) {
380                 return  GPF_OPEN_IN;
381         }
382
383         /*
384         * case of SNF file
385         */
386         if ( ChkPcfFontFile( w_gpf->snf_file ) ) {
387                 /* snf */
388                 if ( ( snf_fd = open( w_gpf->snf_file, O_RDONLY ) ) >= 0 ) {
389                         COMM_SNF_FILEVERSION( snf_fd, finf, buf, permission ) ;
390                         if( permission < 0 ) {
391                                 return  BDF_INVAL;
392                         }
393                 } else {
394                         return  BDF_OPEN_IN;
395                 }
396         }
397
398         if (pipe(fd) != 0) {
399                 return  PIPE_ERROR;
400         }
401         switch ( fork() ) {
402         case    0:
403                 close( fd[0] );
404                 close( 1 );
405                 if ( dup( fd[1] ) < 0 ) {
406                         return  DUP_ERROR;
407                 }
408
409                 close( fd[1] );
410
411                 /* gpf -> bdf */
412                 execl( oakgtobdf, oakgtobdf, r_gpf->in_file, 0 );
413                 return  EXEC_ERROR;
414
415         case    -1:
416                 return  FORK_ERROR;
417
418         default:
419                 break;
420         }
421         close( fd[1] );
422         if ( ( r_gpf->input = (FILE *)fdopen( fd[0], "r" ) ) == NULL ) {
423                 return  FDOPEN_ERROR;
424         }
425
426         if ( !( w_gpf->out_file = GetTmpPath( targ_file ) ) ) {
427                 return  MKTMP_ERROR;
428         }
429
430         if ( pipe( pfd ) != 0 ) {
431                 return  PIPE_ERROR;
432         }
433         switch ( fork() ) {
434         case    0:
435                 if ( ( ofd = open( w_gpf->out_file, O_WRONLY | O_CREAT, 0664 ) ) < 0 ) {
436                         return  BDF_OPEN_OUT;
437                 }
438                 close( 0 );
439                 if ( dup(pfd[0]) < 0 ) {
440                         return  DUP_ERROR;
441                 }
442                 close( pfd[0] );
443                 close( pfd[1] );
444                 close( 1 );
445                 if( dup( ofd ) < 0 ) {
446                         return  DUP_ERROR;
447                 }
448                 close( ofd );
449                 /*
450                 * case of PCF file format
451                 */
452                 if ( ChkPcfFontFile( w_gpf->snf_file ) == 0 ) {
453                         execl( bdftopcf, bdftopcf, 0 );
454                         return  EXEC_ERROR;
455                 }
456                 /*
457                 * case of SNF file format
458                 */
459                 COMM_SNF_EXECLBDFTOSNF( permission, buf, w_gpf->snf_file ) ;
460                 return  EXEC_ERROR;
461
462         case    -1:
463                 return  FORK_ERROR;
464                                 
465         default:
466                 break;
467         }
468         close( pfd[0] );
469         if ( ( w_gpf->output = (FILE *)fdopen( pfd[1], "w" ) ) == NULL ) {
470                 return  FDOPEN_ERROR;
471         }
472         return  0;
473 }
474
475
476
477
478
479 static
480 impGetGpfInf( r_gpf, w_gpf, buf, bdf_codenum )
481 struct btophead *r_gpf;
482 struct ptobhead *w_gpf;
483 char            *buf;
484 int             bdf_codenum ;
485 {
486         int         nchar, rtn;
487
488         if ( ( rtn = impReadBdfHeaderAndPut( r_gpf, w_gpf, buf ) ) ) {
489                 return  rtn;
490         }
491
492         nchar = r_gpf->num_chars + bdf_codenum ;
493
494         if ( ( r_gpf->code = (int *)malloc( sizeof(int) * nchar ) ) == NULL ) {
495                 return  MALLOC_ERROR;
496         }
497
498         if ( ( r_gpf->ptn = (char **)malloc( sizeof(char *) * nchar ) ) == NULL ) {
499                 return  MALLOC_ERROR;
500         }
501
502         return  ReadBdfToMemory( r_gpf, buf ) ;
503 }
504
505
506
507 static
508 impReadBdfHeaderAndPut(r_gpf, w_gpf, buf)
509 struct btophead *r_gpf;
510 struct ptobhead *w_gpf;
511 char    *buf;
512 {
513         char    *p;
514         unsigned int    getstat = 0;
515
516         while ( 1 ) {
517                 if ( fgets( buf, BUFSIZE, r_gpf->input ) == NULL ) {
518                         return  BDF_INVAL;
519                 }
520                 p = buf;
521                 SCAN_TO_NONSP( p )
522                     if ( !strncmp( p, SIZE, (unsigned int)strlen( SIZE ) ) ) {
523                         if ( ( sscanf( p, "SIZE %f%d",
524                             &(r_gpf->bdf_point), &(r_gpf->bdf_xdpi))) != 2 ) {
525                                 return  BDF_INVAL;
526                         }
527                         fprintf( w_gpf->output, "%s", buf );
528                         getstat |= 0x01;
529
530                 } else if ( !strncmp( p, FONTBOUNDINGBOX, (unsigned int)strlen( FONTBOUNDINGBOX ) ) ) {
531                         if ( ( sscanf( p, "FONTBOUNDINGBOX %d %d %d %d",
532                             &(r_gpf->bdf_width), &(r_gpf->bdf_height),
533                             &(r_gpf->bdf_x), &(r_gpf->bdf_y) ) ) != 4 ) {
534                                 return  BDF_INVAL;
535                         }
536                         fprintf( w_gpf->output, "%s", buf );
537                         getstat |= 0x02;
538
539                 } else if ( !strncmp( p, CHARS, (unsigned int)strlen( CHARS ) ) ) {
540                         if ( ( sscanf( p, "CHARS %d", &( r_gpf->num_chars ) ) ) != 1 ) {
541                                 return  BDF_INVAL;
542                         }
543                         getstat |= 0x04;
544                         break;
545                 } else {
546                         fprintf( w_gpf->output, "%s", buf );
547                 }
548         }
549
550         if ( getstat != 0x07 ) {
551                 return  BDF_INVAL;
552         }
553         return  0;
554 }
555
556
557 static
558 impMergePtn(r_udc, r_gpf, buf, bdf_codenum, bdf_codelist )
559 struct  btophead *r_udc;
560 struct  btophead *r_gpf;
561 char    *buf;
562 int     bdf_codenum ;
563 int     *bdf_codelist ;
564 {
565         int     code, rtn, msize, i, j;
566         char    *ptn;
567
568         if ( ( r_udc->bdf_width != r_gpf->bdf_width )
569             || ( r_udc->bdf_height != r_gpf->bdf_height )
570             ) {
571                 r_udc->zoomf = 1;
572
573                 msize = ( r_udc->bdf_width + 7 ) / 8 * r_udc->bdf_height;
574
575                 if ( ( ptn = (char *)malloc( msize ) ) == NULL ) {
576                         return  MALLOC_ERROR;
577                 }
578                 r_udc->ptn = &ptn;
579
580         } else {
581                 r_udc->zoomf = 0;
582         }
583
584         for ( i = 0; i < r_udc->num_chars; i++ ) {
585                 if ( ( rtn = GetBdfCode( r_udc, buf, &code ) ) < 0 ) {
586                         return  rtn;
587                 } else if ( rtn == FILE_END ) {
588                         break;
589                 }
590
591                 if( expCheckCode( code, bdf_codenum, bdf_codelist ) ) {
592                         continue ;
593                 }
594
595                 for ( j = 0; j < r_gpf->num_chars; j++ ) {
596                         if ( r_gpf->code[j] == code ) {
597                                 if ( ( rtn = impModifyPtn( r_udc, r_gpf, buf, j ) ) ) {
598                                         return  rtn;
599                                 }
600                                 break;
601                         } else if ( r_gpf->code[j] > code ) {
602                                 if ( ( rtn = impInsertPtn( r_udc, r_gpf, buf, code, j ) ) ) {
603                                         return  rtn;
604                                 }
605                                 break;
606                         }
607                 }
608                 if ( j == r_gpf->num_chars ) {
609                         if ( ( rtn = impInsertPtn( r_udc, r_gpf, buf, code, j ) ) ) {
610                                 return  rtn;
611                         }
612                 }
613         }
614         return  0;
615 }
616
617 static
618 impModifyPtn( r_udc, r_gpf, buf, ix )
619 struct btophead *r_udc;
620 struct btophead *r_gpf;
621 char    *buf;
622 int     ix;
623 {
624         int     mwidth, msize, rtn;
625
626         mwidth = ( r_udc->bdf_width + 7 ) / 8;
627         msize = mwidth * r_udc->bdf_height;
628
629         if ( r_udc->zoomf ) {
630                 if ( ( rtn = GetBdfPtn( r_udc, buf, r_udc->ptn[0], mwidth, msize ) ) ) {
631                         return  rtn;
632                 }
633                 if ( ( rtn = PtnZoom( r_gpf->ptn[ix], r_udc->ptn[0],
634                     r_udc->bdf_width, r_udc->bdf_height,
635                     r_gpf->bdf_width, r_gpf->bdf_height ) ) ) {
636                         return  rtn;
637                 }
638         } else {
639                 if ( ( rtn = GetBdfPtn( r_udc, buf, r_gpf->ptn[ix], mwidth, msize ) ) ) {
640                         return  rtn;
641                 }
642         }
643         return  0;
644 }
645
646 static
647 impInsertPtn( r_udc, r_gpf, buf, code, ix )
648 struct btophead *r_udc;
649 struct btophead *r_gpf;
650 char    *buf;
651 int     code;
652 int     ix;
653 {
654         int     mwidth, msize, rtn, i;
655
656         for ( i = r_gpf->num_chars; i > ix; i-- ) {
657                 r_gpf->code[i] = r_gpf->code[i-1];
658                 r_gpf->ptn[i] = r_gpf->ptn[i-1];
659         }
660         r_gpf->code[ix] = code;
661
662         r_gpf->num_chars++;
663
664         mwidth = (r_gpf->bdf_width + 7) / 8;
665         msize = mwidth * r_gpf->bdf_height;
666
667         if ( ( r_gpf->ptn[ix] = (char *)malloc( msize ) ) == NULL ) {
668                 return  MALLOC_ERROR;
669         }
670
671         if ( r_udc->zoomf ) {
672                 mwidth = (r_udc->bdf_width + 7) / 8;
673                 msize = mwidth * r_udc->bdf_height;
674                 if ( ( rtn = GetBdfPtn( r_udc, buf, r_udc->ptn[0], mwidth, msize ) ) ) {
675                         return  rtn;
676                 }
677                 if ( ( rtn = PtnZoom( r_gpf->ptn[ix], r_udc->ptn[0],
678                     r_udc->bdf_width, r_udc->bdf_height,
679                     r_gpf->bdf_width, r_gpf->bdf_height ) ) ) {
680                         return  rtn;
681                 }
682         } else {
683                 if ( ( rtn = GetBdfPtn( r_udc, buf, r_gpf->ptn[ix], mwidth, msize ) ) ) {
684                         return  rtn;
685                 }
686         }
687         return(0);
688 }
689
690 static
691 impWriteSnf( r_gpf, w_gpf )
692 struct btophead *r_gpf;
693 struct ptobhead *w_gpf;
694 {
695         w_gpf->zoomf = 0;
696         w_gpf->num_chars  = r_gpf->num_chars;
697         w_gpf->code       = r_gpf->code;
698         w_gpf->ptn        = r_gpf->ptn;
699         w_gpf->bdf_width  = r_gpf->bdf_width;
700         w_gpf->bdf_height = r_gpf->bdf_height;
701         w_gpf->bdf_x      = r_gpf->bdf_x;
702         w_gpf->bdf_y      = r_gpf->bdf_y;
703         w_gpf->bdf_point  = r_gpf->bdf_point;
704         w_gpf->bdf_xdpi   = r_gpf->bdf_xdpi;
705
706         return  WritePtnToBdf( w_gpf );
707 }
708