chkfontpath-2.0.3/000075500000000000000000000000001213403266700140275ustar00rootroot00000000000000chkfontpath-2.0.3/.indent000064400000000000000000000002011213403266700153020ustar00rootroot00000000000000-bad -bap -bbb -nbc -bbo -bl -bli0 -bls -ce -cdw -cli8 -cs -di8 -nfc1 -nfca -i8 -lp -saf -sai -saw -sob -ss -pcs -nprs -psl -ts8 chkfontpath-2.0.3/Makefile000064400000000000000000000006171213403266700154730ustar00rootroot00000000000000PROGNAME = chkfontpath VERSION = 2.0.0 CFLAGS := $(RPM_OPT_FLAGS) $(shell getconf LFS_CFLAGS) -DVERSION=\"$(VERSION)\" INSTALL = install DESTDIR = sbindir=/usr/sbin mandir=/usr/share/man SUBDIRS = man all: $(PROGNAME) install: $(INSTALL) -D -m755 $(PROGNAME) $(DESTDIR)$(sbindir)/$(PROGNAME) $(INSTALL) -D -m644 $(PROGNAME).8 $(DESTDIR)$(mandir)/man8/$(PROGNAME).8 clean: $(RM) $(PROGNAME) chkfontpath-2.0.3/chkfontpath.8000064400000000000000000000047611213403266700164410ustar00rootroot00000000000000.de FN \fI\|\\$1\|\fP .. .TH CHKFONTPATH 8 "Thu Jan 28 2002" "ALT Linux" "ALT Linux" .UC 4 .SH NAME chkfontpath \- simple interface for adding, removing, and listing directories in the X font server's path .SH SYNOPSIS \fBchkfontpath\fR [\fI-lqfh\fR] [\fI-a name of directory to add\fR] [\fI-r name of directory to remove\fR] .SH DESCRIPTION .PP \fBchkfontpath\fR provides a simple method of configuring the directories contained in the X font server's path. As of Red Hat 6.0, all fonts in X are served via this separate font server process, not through the main X server process. This speeds up font rendering, and also allows use of font servers which are not running on the local host. .PP \fBchkfontpath\fR is mainly used by \fBrpm\fR in its \fB%post\fR and \fB%postun\fR sections to add and remove new directories to the server's config file at installation and de-installation time of packages containing fonts. .PP .TP \fB-a\fR, \fB--add=name of directory to add\fR Add a directory to the font path. .TP \fB-r\fR, \fB--remove=name of directory to remove\fR Remove a directory from the font path. .TP \fB-l\fR, \fB--list\fR List all directories in the font path. .TP \fB-q\fR, \fB--quiet\fR Quiet operation; don't display any output to the screen, even when there is an error during operation. .TP \fB-f\fR, \fB--first\fR Requires usage of the \fBadd\fR command; puts the specified directory first in the font path, rather than last. .TP \fB-h\fR, \fB--help\fR Show detailed help on the command line. .PP When directories are added to the path, some sanity checking is performed to make sure you are not adding a directory without the file \fBfonts.dir\fR contained in it, which the server needs to be able to render fonts properly. When a path is succesfully added or removed, the \fBxfs\fR process is restarted if it is currently running. .PD .SH "RETURN CODES" \fBchkfontpath\fR returns 0 on success, or 1 on error. .PD .SH FILES .PD 0 .TP .TP .FN /etc/X11/fs/config Configuration file for the X font server (xfs). .PD .SH "SEE ALSO" .BR xfs (1), fslsfonts (1) .SH AUTHOR .nf Written by Preston Brown Rewritten by Dmitry V. Levin .fi .SH "REPORTING BUGS" Report bugs to http://bugs.altlinux.ru/. .SH COPYRIGHT Copyright \(co 1999-2001 Red Hat, Inc. Copyright \(co 2002 Dmitry V. Levin .BR All rights reserved. .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. chkfontpath-2.0.3/chkfontpath.c000064400000000000000000000414151213403266700165110ustar00rootroot00000000000000 /* * chkfontpath - utility for manipulating X Font Server font paths * * Copyright (C) 1998-2001 Red Hat, Inc. * Author: Preston Brown * * Copyright (C) 2002, 2007 Dmitry V. Levin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* Copyright 1987, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. * Copyright 1990, 1991 Network Computing Devices; * Portions Copyright 1987 by Digital Equipment Corporation * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the names of Network Computing Devices, * or Digital not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Network Computing Devices, or Digital * make no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, OR DIGITAL BE * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $NCDXorg: @(#)config.c,v 4.6 1991/07/09 14:08:09 lemke Exp $ * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #define CONFIG_FILE "/etc/X11/fs/config" static int is_quiet = 0, is_verbose = 0; static void __attribute__((__noreturn__)) __attribute__((__format__(__printf__, 2, 3))) failure(int errnum, const char *fmt, ...) { if (!is_quiet) { va_list args; fflush(stdout); fprintf(stderr, "%s: ", program_invocation_short_name); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); if (errnum) fprintf(stderr, ": %s", strerror(errnum)); putc('\n', stderr); fflush(stderr); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } static void __attribute__((__format__(__printf__, 1, 2))) verbose(const char *fmt, ...) { if (is_verbose) { va_list args; fflush(stdout); fprintf(stderr, "%s: ", program_invocation_short_name); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); putc('\n', stderr); fflush(stderr); } } static char *config_mem, *orig_mem; static size_t config_size, catalogue_begin, catalogue_end; struct stat config_stat; enum read_state { read_normal = 0, read_dnl, read_eq, read_begin, read_catalogue }; inline static int is_eol(char c) { return (c == '\n') || (c == '\r') || (c == '\f'); } inline static int is_param(char c) { return isalnum(c) || ('-' == c); } inline static int is_catspace(char c) { return isspace(c) || (',' == c); } inline static void skip_whitespace(size_t * offset) { while ((*offset < config_size) && is_catspace(config_mem[*offset])) (*offset)++; } static size_t next_eq(size_t offset) { int nesting = 0; for (; offset < config_size; ++offset) { if ('(' == config_mem[offset]) ++nesting; else if (')' == config_mem[offset]) --nesting; else if (('=' == config_mem[offset]) && !nesting) return offset; } return 0; } static const char **font_list; static size_t font_count; static int add_before; static void register_path(const char *path) { if ('/' != *path) { verbose("ignoring invalid font path: %s", path); return; } font_list = (const char **) realloc(font_list, sizeof(char *) * (1 + font_count)); if (!font_list) failure(errno, "realloc"); font_list[font_count++] = path; } static void parse_catalogue(char *data) { char *path; for (path = data; *data; ++data) { if (is_catspace(*data)) { if (path) { *data = '\0'; register_path(path); path = 0; } continue; } if (!path) path = data; } if (path) register_path(path); } static void parse_config(void) { size_t offset = 0; skip_whitespace(&offset); while (offset < config_size) { int skip = 0; char *param; size_t offset_zero, eq, val = 0; /* get parameter name */ for (param = config_mem + offset; (offset < config_size) && is_param(config_mem[offset]); ++offset) ; offset_zero = offset; /* check for junk */ if (('=' != config_mem[offset]) && !isspace(config_mem[offset])) { /* report about trash found */ config_mem[offset_zero] = '\0'; verbose("syntax error near parameter \"%s\" at offset %lu", param, (unsigned long) offset); /* eat garbage */ if (offset < config_size) ++offset; while ((offset < config_size) && !isspace(config_mem[offset]) && ('=' != config_mem[offset])) ++offset; } skip_whitespace(&offset); config_mem[offset_zero] = '\0'; if ('=' != config_mem[offset]) { verbose("missing \"=\" after parameter \"%s\" at offset %lu", param, (unsigned long) offset); skip = 1; } else ++offset; skip_whitespace(&offset); /* find next assignment to guess where the value ends */ if ((eq = next_eq(offset))) { /* back up over whitespace */ for (val = eq - 1; (val >= offset) && is_catspace(config_mem[val]); --val) ; /* back over parm name */ for (; (val >= offset) && is_param(config_mem[val]); --val) ; if (val <= offset) { verbose("missing value for parameter \"%s\" at offset %lu", param, (unsigned long) offset); continue; } config_mem[val] = '\0'; } else if (offset >= config_size) { verbose("missing value for parameter \"%s\" at offset %lu", param, (unsigned long) offset); continue; } else /* probably reached end of values */ { for (val = config_size; val > 0 && isspace(config_mem[val - 1]); --val) ; } /* match parm name */ if (!skip && !strcmp(param, "catalogue")) { catalogue_begin = offset; catalogue_end = val; for (catalogue_end = val; (catalogue_end > offset) && isspace(config_mem[catalogue_end - 1]); --catalogue_end) ; config_mem[catalogue_end] = '\0'; parse_catalogue(config_mem + offset); } if (val) offset = val + 1; else /* last setting */ break; } } static void read_config(const char *config) { int fd; size_t offset; fd = open(config, O_RDONLY); if (fd < 0) failure(errno, "error opening config file: %s", config); if (fstat(fd, &config_stat)) failure(errno, "error accessing config file: %s", config); if (!S_ISREG(config_stat.st_mode)) failure(0, "error accessing config file: %s: bad file type 0%o", config, config_stat.st_mode >> 12); config_size = config_stat.st_size; orig_mem = (char *) mmap(0, config_size, PROT_READ, MAP_SHARED, fd, 0); if (orig_mem == MAP_FAILED) failure(0, "error accessing config file: %s: mmap", config); close(fd); config_mem = malloc(1 + config_size); if (!config_mem) failure(errno, "malloc"); memcpy(config_mem, orig_mem, config_size); config_mem[config_size] = '\0'; /* Strip comments in the same way X11 fs do it. */ for (offset = 0; offset < config_size; ++offset) { if ('#' != config_mem[offset]) continue; if (!offset || ('\\' != config_mem[offset - 1])) while ((offset < config_size) && !is_eol(config_mem[offset])) config_mem[offset++] = ' '; } /* Parse config in the same way X11 fs do it. */ parse_config(); } static void xwrite(int fd, const char *buffer, size_t count, const char *fname) { size_t offset = 0; while (count > 0) { ssize_t block = write(fd, &buffer[offset], count); if (block < 0) { if (errno == EINTR) continue; failure(errno, "error writing %s", fname); } if (!block) break; offset += block; count -= block; } if (count > 0) failure(errno, "error writing %s", fname); } static void write_catalogue(int fd, const char *config) { size_t i; for (i = 0; i < font_count; ++i) { size_t len = strlen(font_list[i]); if (i) xwrite(fd, "\t", 1, config); xwrite(fd, font_list[i], len, config); if (i + 1 < font_count) xwrite(fd, ",\n", 2, config); } } static void write_config(const char *config, const char *config_tmp) { int fd_tmp; unlink(config_tmp); fd_tmp = open(config_tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd_tmp < 0) failure(errno, "error opening %s for writing", config_tmp); if (catalogue_begin) { xwrite(fd_tmp, orig_mem, catalogue_begin, config_tmp); } else { const char param[] = "catalogue = "; xwrite(fd_tmp, param, sizeof(param) - 1, config_tmp); } write_catalogue(fd_tmp, config_tmp); if (catalogue_end < config_size) { if (!is_eol(orig_mem[catalogue_end])) xwrite(fd_tmp, "\n", 1, config_tmp); xwrite(fd_tmp, orig_mem + catalogue_end, config_size - catalogue_end, config_tmp); } else { xwrite(fd_tmp, "\n", 1, config_tmp); } /* set permissions on the new file */ if (fchown(fd_tmp, -1, config_stat.st_gid) || fchmod(fd_tmp, config_stat.st_mode & ~(config_stat.st_gid ? 07137 : 07133))) failure(errno, "fchown/fchmod failed for %s", config_tmp); close(fd_tmp); if (unlink(config)) failure(errno, "unlink: %s", config); if (rename(config_tmp, config)) failure(errno, "error renaming %s to %s", config_tmp, config); } static void add_path_to_list(const char *add_font) { char *fixDir = strdup(add_font); if (!fixDir) failure(errno, "strdup"); else { const char suffix[] = ":unscaled"; size_t fixDirLen = strlen(fixDir); size_t prefixLen, i; int isUnscaled = 0; if ('/' != *fixDir) failure(0, "invalid font path \"%s\" will not be added", fixDir); /* check for ":unscaled" suffix */ if (fixDirLen > sizeof(suffix) && !strcmp(fixDir + fixDirLen - sizeof(suffix) + 1, suffix)) { /* strip suffix */ isUnscaled = 1; fixDir[fixDirLen - sizeof(suffix) + 1] = '\0'; fixDirLen -= sizeof(suffix) - 1; } for (; '/' == fixDir[fixDirLen - 1]; --fixDirLen) fixDir[fixDirLen - 1] = '\0'; { const char suffix[] = "/fonts.dir"; char fontsdir[fixDirLen + sizeof(suffix)]; memcpy(fontsdir, fixDir, fixDirLen); memcpy(fontsdir + fixDirLen, suffix, sizeof(suffix)); if (access(fontsdir, R_OK) < 0) failure(errno, "invalid font path \"%s\" will not be added: cannot access %s", fixDir, fontsdir); } prefixLen = strrchr(fixDir, '/') - fixDir + 1; for (i = 0; i < font_count; ++i) { if (strncmp(font_list[i], fixDir, prefixLen)) continue; if (!strncmp(font_list[i], fixDir, fixDirLen)) { if ((!isUnscaled && (font_list[i][fixDirLen] == '\0')) || (isUnscaled && !strcmp(font_list[i] + fixDirLen, suffix))) failure(0, "path %s already in font list", fixDir); } } if (isUnscaled) strcat(fixDir, suffix); font_list = (const char **) realloc(font_list, sizeof(char *) * (1 + font_count)); if (!font_list) failure(errno, "realloc"); if (add_before) { memmove(font_list + 1, font_list, sizeof(char *) * font_count); font_list[0] = fixDir; ++font_count; } else { font_list[font_count++] = fixDir; } } } static void remove_path_from_list(const char *del_font) { char *font = strdup(del_font); if (!font) failure(errno, "strdup"); else { size_t len = strlen(font); size_t i; int found = 0; for (; '/' == font[len - 1]; --len) font[len - 1] = '\0'; for (i = 0; i < font_count; ++i) { if (!strncmp(font_list[i], font, len) && ((font_list[i][len] == '\0') || !strcmp(font_list[i] + len, ":unscaled"))) { found = 1; if (i + 1 < font_count) memmove(font_list + i, font_list + i + 1, sizeof(char *) * (font_count - i - 1)); --font_count; --i; } } if (!found) failure(0, "path %s not found in font list", font); free(font); } } static void restart_x11_fs(void) { struct stat st; /* Stat /proc/version to see if /proc is mounted. */ if (!stat("/proc/version", &st)) if (system("/etc/init.d/xfs condreload >/dev/null 2>&1")) ; /* don't care */ } static void listPaths(void) { if (font_count == 0) puts("No directories found in font path."); else { int i; puts("Directories found in font path:"); for (i = 0; i < font_count; ++i) printf("%d: %s\n", i + 1, font_list[i]); } } const char *argp_program_version = "chkfontpath-" VERSION; const char *argp_program_bug_address = "http://bugs.altlinux.ru/"; /* Program documentation. */ static char doc[] = "Utility for adding, removing, and listing directories in the X font server's path."; static char exclusive_doc[] = "options --add, --remove and --list are mutually exclusive.\n"; /* The options we understand. */ static struct argp_option options[] = { {"add", 'a', "DIRECTORY", 0, "Add directory to font path", 1}, {"remove", 'r', "DIRECTORY", 0, "Remove directory from font path", 1}, {"list", 'l', 0, 0, "List all directories in font path", 2}, {"first", 'f', 0, 0, "Make --add to put the directory first (not last) in the path", 3}, {"config", 'c', "FILE", 0, "Config file to use (instead of " CONFIG_FILE ")", 4}, {"verbose", 'v', 0, 0, "Produce verbose output", 10}, {"quiet", 'q', 0, 0, "Don't produce any output", 10}, {0} }; static int list; static const char *add_font, *del_font; static const char *config_file = CONFIG_FILE; /* Parse a single option. */ static error_t parse_opt(int key, char *arg, struct argp_state *state) { switch (key) { case 'l': if (add_font || del_font) { fprintf(stderr, exclusive_doc); argp_usage(state); } list = 1; break; case 'f': add_before = 1; break; case 'q': is_quiet = 1; is_verbose = 0; break; case 'v': is_quiet = 0; is_verbose = 1; break; case 'a': if (list || del_font) { fprintf(stderr, exclusive_doc); argp_usage(state); } add_font = arg; break; case 'r': if (list || add_font) { fprintf(stderr, exclusive_doc); argp_usage(state); } del_font = arg; break; case 'c': config_file = arg; break; case ARGP_KEY_ARG: fprintf(stderr, "unexpected arguments.\n"); argp_usage(state); break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = { options, parse_opt, 0, doc }; int main(int argc, char **__restrict argv) { argp_parse(&argp, argc, argv, 0, 0, 0); read_config(config_file); if (add_font) add_path_to_list(add_font); else if (del_font) remove_path_from_list(del_font); if (add_font || del_font) { unsigned len = strlen(config_file); char tmp_file[len + 2]; memcpy(tmp_file, config_file, len); tmp_file[len++] = '-'; tmp_file[len] = '\0'; write_config(config_file, tmp_file); restart_x11_fs(); } else { listPaths(); } return EXIT_SUCCESS; }