rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / x11 / installalias / src / installalias.c
blob130b7d9a02deea7597d1d53d118d32d116dbcbfe
1 /*
2 * Copyright (c) 1993, 2009, Oracle and/or its affiliates. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
23 /* Code copied from libXfont is:
25 Copyright 1991, 1998 The Open Group
27 Permission to use, copy, modify, distribute, and sell this software and its
28 documentation for any purpose is hereby granted without fee, provided that
29 the above copyright notice appear in all copies and that both that
30 copyright notice and this permission notice appear in supporting
31 documentation.
33 The above copyright notice and this permission notice shall be included in
34 all copies or substantial portions of the Software.
36 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
40 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 Except as contained in this notice, the name of The Open Group shall not be
44 used in advertising or otherwise to promote the sale, use or other dealings
45 in this Software without prior written authorization from The Open Group.
50 * Ensure that a fonts.alias file only contains aliases for fonts that exist
51 * We do this by first reading in the fonts.dir file and then for
52 * each entry in the fonts.alias file we verify that the alias can
53 * be resolved. Most this of this code is borrowed from
54 * libXfont with minor modifications.
56 #include <X11/fonts/fntfilst.h>
57 #include <stdio.h>
58 #include <sys/types.h>
59 #include <errno.h>
60 #include <sys/stat.h>
61 #include <ctype.h>
62 #include <limits.h>
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <X11/keysym.h>
67 #define EBadFontPath 0
68 #define EBadFontName 0
69 #define EAllocError 0
70 #define Success 1
72 pointer serverClient;
73 static char *programName;
75 static int lexc(FILE *file);
77 void
78 ErrorF (const char * f, ...)
80 va_list args;
82 va_start(args, f);
83 fprintf(stderr, "%s: ", programName);
84 vfprintf(stderr, f, args);
85 va_end(args);
88 /* Provide pseudo renderers for font file formats we may find in fonts.dir
89 files during installation, but which libXfont does not support */
90 /* ARGSUSED */
91 static int
92 PseudoOpenScalable (FontPathElementPtr fpe, FontPtr *ppFont, int flags,
93 FontEntryPtr entry, char *fileName, FontScalablePtr vals,
94 fsBitmapFormat format, fsBitmapFormatMask fmask,
95 FontPtr non_cachable_font)
97 return 1;
100 /* ARGSUSED */
101 static int
102 PseudoGetInfoScalable (FontPathElementPtr fpe, FontInfoPtr info,
103 FontEntryPtr entry, FontNamePtr fontName,
104 char *fileName, FontScalablePtr vals)
106 return 1;
109 static FontRendererRec PseudoRenderers[] = {
110 { ".spd", 4, NULL, PseudoOpenScalable, NULL, PseudoGetInfoScalable, 0 }
113 static void
114 PseudoFontFileRegisterFpeFunctions (void)
116 int i;
118 for (i = 0; i < (sizeof(PseudoRenderers) / sizeof(FontRendererRec)); i++) {
119 FontFileRegisterRenderer(&PseudoRenderers[i]);
124 ProcessFontsDirectory (
125 char *directory,
126 FontDirectoryPtr *pdir)
128 char file_name[MAXFONTNAMELEN];
129 char font_name[MAXFONTNAMELEN];
130 char dir_file[MAXFONTNAMELEN];
131 FILE *file;
132 int count, i;
133 struct stat statb;
135 FontDirectoryPtr dir = NullFontDirectory;
137 i = strlcpy(dir_file, directory, sizeof(dir_file));
138 if (directory[i - 1] != '/')
139 strlcat(dir_file, "/", sizeof(dir_file));
140 strlcat(dir_file, FontDirFile, sizeof(dir_file));
141 file = fopen(dir_file, "r");
142 if (file) {
143 if (fstat (fileno(file), &statb) == -1)
144 return EBadFontPath;
145 count = fscanf(file, "%d\n", &i);
146 if ((count == EOF) || (count != 1)) {
147 fclose(file);
148 return EBadFontPath;
150 dir = FontFileMakeDir(directory, i);
151 if (dir == NULL) {
152 fclose(file);
153 return EBadFontPath;
155 dir->dir_mtime = statb.st_mtime;
156 while ((count = fscanf(file, "%1024s %[^\n]\n", file_name, font_name))
157 != EOF) {
158 if (count != 2) {
159 FontFileFreeDir (dir);
160 fclose(file);
161 return EBadFontPath;
163 if (!FontFileAddFontFile (dir, font_name, file_name))
165 FontFileFreeDir (dir);
166 fclose(file);
167 return EBadFontPath;
170 fclose(file);
171 } else if (errno != ENOENT) {
172 return EBadFontPath;
174 if (!dir)
175 return EBadFontPath;
177 *pdir = dir;
178 return Success;
181 #define NAME 0
182 #define NEWLINE 1
183 #define DONE 2
184 #define EALLOC 3
185 #define FileClosed 4
187 #define QUOTE 0
188 #define WHITE 1
189 #define NORMAL 2
190 #define END 3
191 #define NL 4
193 static int charClass;
195 static int
196 lexAlias(
197 FILE *file,
198 char **lexToken)
200 int c;
201 char *t;
202 enum state {
203 Begin, Normal, Quoted
204 } state;
205 int count;
207 static char *tokenBuf = (char *) NULL;
208 static unsigned int tokenSize = 0;
210 t = tokenBuf;
211 count = 0;
212 state = Begin;
213 for (;;) {
214 if (count == tokenSize) {
215 unsigned int nsize;
216 char *nbuf;
218 nsize = tokenSize ? (tokenSize << 1) : 64;
219 nbuf = realloc(tokenBuf, nsize);
220 if (!nbuf)
221 return EALLOC;
222 tokenBuf = nbuf;
223 tokenSize = nsize;
224 t = tokenBuf + count;
226 c = lexc(file);
227 switch (charClass) {
228 case QUOTE:
229 switch (state) {
230 case Begin:
231 case Normal:
232 state = Quoted;
233 break;
234 case Quoted:
235 state = Normal;
236 break;
238 break;
239 case WHITE:
240 switch (state) {
241 case Begin:
242 continue;
243 case Normal:
244 *t = '\0';
245 *lexToken = tokenBuf;
246 return NAME;
247 case Quoted:
248 break;
250 /* fall through */
251 case NORMAL:
252 switch (state) {
253 case Begin:
254 state = Normal;
256 *t++ = c;
257 ++count;
258 break;
259 case END:
260 case NL:
261 switch (state) {
262 case Begin:
263 *lexToken = (char *) NULL;
264 return charClass == END ? DONE : NEWLINE;
265 default:
266 *t = '\0';
267 *lexToken = tokenBuf;
268 ungetc(c, file);
269 return NAME;
275 static int
276 lexc(FILE *file)
278 int c;
280 c = getc(file);
281 switch (c) {
282 case EOF:
283 charClass = END;
284 break;
285 case '\\':
286 c = getc(file);
287 if (c == EOF)
288 charClass = END;
289 else
290 charClass = NORMAL;
291 break;
292 case '"':
293 charClass = QUOTE;
294 break;
295 case ' ':
296 case '\t':
297 charClass = WHITE;
298 break;
299 case '\n':
300 charClass = NL;
301 break;
302 default:
303 charClass = NORMAL;
304 break;
306 return c;
309 static inline unsigned char
310 ISOLatin1ToLower(unsigned char source)
312 if (source >= XK_A && source <= XK_Z)
313 return source + (XK_a - XK_A);
314 if (source >= XK_Agrave && source <= XK_Odiaeresis)
315 return source + (XK_agrave - XK_Agrave);
316 if (source >= XK_Ooblique && source <= XK_Thorn)
317 return source + (XK_oslash - XK_Ooblique);
318 return source;
321 static void
322 copyISOLatin1Lowered(char *dest, char *source, int length)
324 int i;
325 for (i = 0; i < length; i++, source++, dest++)
326 *dest = ISOLatin1ToLower(*source);
327 *dest = '\0';
330 static int
331 ReadAliases(
332 FILE *file,
333 char *alias,
334 char *font_name)
336 int token;
337 char *lexToken;
338 int status = Success;
340 while (status == Success) {
341 token = lexAlias(file, &lexToken);
342 switch (token) {
343 case NEWLINE:
344 break;
345 case DONE:
346 fclose(file);
347 return FileClosed;
348 case EALLOC:
349 status = EAllocError;
350 break;
351 case NAME:
352 strlcpy(alias, lexToken, MAXFONTNAMELEN);
353 token = lexAlias(file, &lexToken);
354 switch (token) {
355 case NEWLINE:
356 break;
357 case DONE:
358 status = EBadFontPath;
359 break;
360 case EALLOC:
361 status = EAllocError;
362 break;
363 case NAME:
364 copyISOLatin1Lowered(alias, alias, strlen(alias));
365 copyISOLatin1Lowered(font_name, lexToken, strlen(lexToken));
366 return status;
370 fclose(file);
371 return FileClosed;
374 #define FontAliasEntry 8
376 static int
377 OpenAndVerifyFont (
378 char *name,
379 int namelen,
380 FontDirectoryPtr dir)
382 char lowerName[MAXFONTNAMELEN];
383 char *p;
384 FontNameRec tmpName;
385 FontEntryPtr entry;
386 FontScalableRec vals;
387 FontBitmapEntryPtr bitmap;
388 FontBCEntryPtr bc;
389 int ret = 0;
390 Bool isxlfd;
391 Bool scaleAlias;
393 if (namelen >= MAXFONTNAMELEN)
394 return EAllocError;
395 copyISOLatin1Lowered (lowerName, name, namelen);
396 lowerName[namelen] = '\0';
397 tmpName.name = lowerName;
398 tmpName.length = namelen;
399 tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
400 /* Match XLFD patterns */
401 if (tmpName.ndashes == 14 &&
402 FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO))
404 isxlfd = TRUE;
405 tmpName.length = strlen (lowerName);
406 entry = FontFileFindNameInDir (&dir->scalable, &tmpName);
407 if (entry) {
408 return Success;
411 else
413 isxlfd = FALSE;
415 /* Match non XLFD pattern */
416 if (entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName))
418 switch (entry->type) {
419 case FONT_ENTRY_BITMAP:
420 bitmap = &entry->u.bitmap;
421 ret = Success;
422 break;
423 case FONT_ENTRY_ALIAS:
424 if (entry->u.alias.resolved) {
425 strlcpy(name, entry->u.alias.resolved, MAXFONTNAMELEN);
426 ret = FontAliasEntry;
427 } else {
428 ret = EBadFontName;
430 break;
431 case FONT_ENTRY_BC:
432 bc = &entry->u.bc;
433 entry = bc->entry;
434 break;
435 default:
436 ret = EBadFontName;
439 else
441 scaleAlias = FALSE;
442 if (isxlfd)
444 FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_ZERO);
445 tmpName.length = strlen (lowerName);
446 scaleAlias = TRUE;
448 else
450 p = lowerName + tmpName.length;
451 while (p > lowerName && isdigit(p[-1]))
452 p--;
453 if (*p)
455 vals.point = atoi(p) * 10;
456 if (p[-1] == '-')
457 p--;
458 if (p > lowerName)
460 *p = '\0';
461 vals.pixel = 0;
462 vals.x = 0;
463 vals.y = 0;
464 vals.width = 0;
465 tmpName.length = p - lowerName;
466 scaleAlias = TRUE;
470 if (scaleAlias &&
471 (entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) &&
472 entry->type == FONT_ENTRY_ALIAS)
474 if (entry->u.alias.resolved) {
475 strlcpy(name, entry->u.alias.resolved, MAXFONTNAMELEN);
476 return FontAliasEntry;
477 } else {
478 return EBadFontName;
482 else
484 ret = EBadFontName;
487 return ret;
490 #define TempFileSuffix "_TMPFILE"
492 static void
493 ProcessAliasFile(
494 FontDirectoryPtr dir,
495 const char *aliasfilename)
497 char alias[MAXFONTNAMELEN];
498 char font_name[MAXFONTNAMELEN];
499 char save_font_name[MAXFONTNAMELEN];
500 char aliasfile[MAXFONTNAMELEN];
501 char tmpfile[MAXFONTNAMELEN];
502 char outfile[MAXFONTNAMELEN];
504 FILE *file, *newfile;
505 int ret;
506 struct stat statb;
507 int retvalue;
508 int containsSpace = 0;
510 strlcpy(aliasfile, dir->directory, sizeof(aliasfile));
511 strlcat(aliasfile, aliasfilename, sizeof(aliasfile));
512 file = fopen(aliasfile, "r");
513 if (!file)
514 return; /* fail silently -- if no alias file, we're done */
515 else
516 if (fstat (fileno(file), &statb) == -1)
517 return;
519 strlcpy(tmpfile, aliasfile, sizeof(tmpfile));
520 strlcat(tmpfile, TempFileSuffix, sizeof(tmpfile));
521 newfile = fopen(tmpfile, "w");
523 if (!newfile) {
524 ErrorF("Can't create new alias file %s\n", tmpfile);
525 return;
528 while ((ret = ReadAliases(file, alias, font_name)) != FileClosed) {
529 strlcpy(save_font_name, font_name, sizeof(save_font_name));
530 while ((retvalue = OpenAndVerifyFont(font_name,strlen(font_name), dir))
531 == FontAliasEntry) {
532 continue;
534 if (strcmp(alias,save_font_name) == 0) {
535 /* 4258475: don't add if the names are the same */
536 #ifdef DEBUG
537 fprintf(stderr,"%s\t%s aliased to itself!\n", alias, save_font_name);
538 #endif
539 } else if (retvalue == Success) {
540 /* add this alias to list of known aliases */
541 if (strchr(alias, ' '))
542 containsSpace = 1;
544 if (!FontFileAddFontAlias (dir, alias, save_font_name))
545 #ifdef DEBUG
546 fprintf(stderr, "installalias: unable to add alias to list\n");
547 #else
548 ; /* do nothing -- fail silently */
549 #endif /* DEBUG */
550 if (containsSpace) {
551 containsSpace = 0;
552 fprintf(newfile, "\"%s\"\t\"%s\"\n",alias, save_font_name);
553 } else {
554 fprintf(newfile, "%s\t\"%s\"\n",alias, save_font_name);
557 #ifdef DEBUG
558 else
559 fprintf(stderr,"%s\t%s not found\n", alias, save_font_name);
560 #endif /* DEBUG */
562 fclose(newfile);
563 fclose(file);
564 strlcpy(outfile, dir->directory, sizeof(outfile));
565 strlcat(outfile, "fonts.alias", sizeof(outfile));
566 ret = rename(tmpfile, outfile);
567 if (ret < 0) {
568 ErrorF("Unable to rename %s to %s.\n", tmpfile, outfile);
570 return;
574 GetDefaultPointSize (void)
576 return 120;
579 /* ARGSUSED */
580 FontResolutionPtr GetClientResolutions (int *num)
582 return 0;
585 /* ARGSUSED */
586 int RegisterFPEFunctions ( NameCheckFunc name_func,
587 InitFpeFunc init_func,
588 FreeFpeFunc free_func,
589 ResetFpeFunc reset_func,
590 OpenFontFunc open_func,
591 CloseFontFunc close_func,
592 ListFontsFunc list_func,
593 StartLfwiFunc start_lfwi_func,
594 NextLfwiFunc next_lfwi_func,
595 WakeupFpeFunc wakeup_func,
596 ClientDiedFunc client_died,
597 LoadGlyphsFunc load_glyphs,
598 StartLaFunc start_list_alias_func,
599 NextLaFunc next_list_alias_func,
600 SetPathFunc set_path_func )
602 return 0;
605 void
606 InitFontFileFunctions(void)
608 FontFileRegisterFpeFunctions();
609 PseudoFontFileRegisterFpeFunctions();
610 return;
614 main(int argc, char **argv)
617 FontDirectoryPtr dir;
618 const char *aliasFileName = "fonts.alias";
619 char *defaultDirectoryList[] = { ".", NULL };
620 char **directoryList = defaultDirectoryList;
621 int directoryCount = 1;
622 int i = 0, ret;
624 programName = argv[0];
626 InitFontFileFunctions();
628 if (argc > 1) {
629 aliasFileName = argv[1];
632 if (argc > 2) {
633 directoryCount = argc;
634 directoryList = argv;
635 i = 2;
638 for (/* i initialized above */ ; i < directoryCount; i++) {
639 ret = ProcessFontsDirectory(directoryList[i], &dir);
640 if (ret == Success) {
641 ProcessAliasFile(dir, aliasFileName);
642 } else {
643 char curdir[PATH_MAX];
644 const char *directory = directoryList[i];
645 if (strcmp(directory, ".") == 0) {
646 getcwd(curdir, sizeof(curdir));
647 directory = curdir;
649 ErrorF("failed to process fonts.dir file in %s\n", directory);
650 exit (1);
653 exit (0);