Improved 003b
Likewise, Eugene Konev ported the 003b patch but lost the comments.
Version with comments attached.
--
Don't say I didn't warn you.
$Id: 003b_xfs_fixes.diff 2151 2005-01-24 16:54:48Z branden $
This patch by Branden Robinson, Matthieu Herrb, and Nikita V. Youshchenko.
os/utils.c:
- Handle pid files the way most other Unix daemons do. Use Matthieu
Herrb's version of StorePid(), which refuses to open pre-existing pid
files, and is more careful with the type of Pid_t.
- Allow the user to specify the pid filename on the command line with a
"-pid" option (courtesy of Nikita V. Youshchenko).
- Add RemovePid() function which removes the process ID file, and
register it with atexit() so that it is automatically invoked when xfs
exits.
- Sort options in usage message alphabetically.
- Refer to "user ID" and "process ID" in diagnostic messages, not
"userid" and "process-id".
- Remove duplicate unconditional #include of stdlib.h.
- Wrap long lines.
- Whitespace police.
xfs.man:
- Document the new "-pid" option (courtesy of Nikita V. Youshchenko).
- Add "FUTURE DIRECTIONS" section.
- Perform massive cleanup and reformatting.
Not submitted upstream yet.
Index: xc/programs/xfs/os/utils.c
===================================================================
--- xc.orig/programs/xfs/os/utils.c 2005-03-01 00:35:18.000000000 +0700
+++ xc/programs/xfs/os/utils.c 2005-07-03 13:48:14.000000000 +0800
@@ -3,7 +3,7 @@
* misc os utilities
*/
/*
-
+
Copyright 1990, 1991, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
@@ -27,7 +27,7 @@
in this Software without prior written authorization from The Open Group.
* Copyright 1990, 1991 Network Computing Devices;
- * Portions Copyright 1987 by Digital Equipment Corporation
+ * 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
@@ -90,8 +90,6 @@
#define SIGNALS_RESET_WHEN_CAUGHT
#endif
-#include <stdlib.h>
-
extern char *configfilename;
static Bool dropPriv = FALSE; /* whether or not to drop root privileges */
#ifdef DEFAULT_DAEMON
@@ -116,7 +114,8 @@
static char *pidFile = XFSPIDDIR "/xfs.pid";
static int pidFd;
static FILE *pidFilePtr;
-static int StorePid (void);
+static long StorePid (void);
+static void RemovePid (void);
/* ARGSUSED */
SIGVAL
@@ -219,7 +218,9 @@
static void
usage(void)
{
- fprintf(stderr, "usage: %s [-config config_file] [-port tcp_port] [-droppriv] [-daemon] [-nodaemon] [-user user_name] [-ls listen_socket]\n",
+ fprintf(stderr, "usage: %s [-config config_file] [-daemon] [-droppriv]"
+ " [-ls listen_socket] [-nodaemon] [-pid pid_file]"
+ " [-port tcp_port] [-user user_name]\n",
progname);
exit(1);
}
@@ -242,7 +243,7 @@
*
* [] denotes optional and ... denotes repitition.
*
- * The string must be _exactly_ in the above format.
+ * The string must be _exactly_ in the above format.
*/
void
@@ -260,7 +261,7 @@
count++;
ptr++;
}
-
+
OldListenCount = count + 1;
OldListen = (OldListenRec *) malloc (
OldListenCount * sizeof (OldListenRec));
@@ -349,6 +350,11 @@
configfilename = argv[++i];
else
usage();
+ } else if (!strcmp(argv[i], "-pid")) {
+ if (argv[i + 1])
+ pidFile = argv[++i];
+ else
+ usage();
}
#ifdef MEMBUG
else if ( strcmp( argv[i], "-alloc") == 0)
@@ -392,7 +398,7 @@
FSalloc (unsigned long amount)
{
register pointer ptr;
-
+
if ((long)amount < 0)
return 0;
if (amount == 0)
@@ -462,21 +468,21 @@
FatalError("out of memory\n");
return 0;
}
-
+
/*****************
* FSfree
- * calls free
- *****************/
+ * calls free
+ *****************/
void
FSfree(pointer ptr)
{
#ifdef MEMBUG
if (ptr)
- ffree((char *)ptr);
+ ffree((char *)ptr);
#else
if (ptr)
- free((char *)ptr);
+ free((char *)ptr);
#endif
}
@@ -511,11 +517,12 @@
}
#endif /* QNX4 */
if (setuid(pwent->pw_uid)) {
- FatalError("fatal: couldn't set userid to %s user\n", user);
+ FatalError("fatal: couldn't set user ID to %s user\n", user);
}
}
} else if (dropPriv || userId) {
- FatalError("fatal: -droppriv or -user flag specified, but xfs not run as root\n");
+ FatalError("fatal: -droppriv or -user flag specified, but xfs not"
+ " invoked by root user\n");
}
}
@@ -523,48 +530,76 @@
void
SetDaemonState(void)
{
- int oldpid;
+ long oldpid;
if (becomeDaemon) {
BecomeDaemon();
if ((oldpid = StorePid ())) {
if (oldpid == -1)
- ErrorF ("error opening process-id file %s\n", pidFile);
+ ErrorF ("error opening process ID file %s\n", pidFile);
else
ErrorF ("process-id file %s indicates another xfs is "
- "running (pid %d); exiting\n", pidFile, oldpid);
+ "running (pid %ld); exiting\n", pidFile, oldpid);
exit(1);
}
+ if (atexit (RemovePid))
+ ErrorF ("could not register RemovePid() with atexit()\n");
}
}
-static int
+static long
+/*
+ * Create and populate file storing process ID.
+ */
StorePid (void)
{
- int oldpid;
+ long oldpid;
+ char pidstr[11]; /* enough space for a 32-bit pid plus \0 */
+ size_t pidstrlen;
- if (pidFile[0] != '\0') {
- pidFd = open (pidFile, O_RDWR);
- if (pidFd == -1 && errno == ENOENT)
- pidFd = open (pidFile, O_RDWR|O_CREAT, 0666);
- if (pidFd == -1 || !(pidFilePtr = fdopen (pidFd, "r+")))
+ if (pidFile[0] != '\0')
+ {
+ pidFd = open (pidFile, O_WRONLY|O_CREAT|O_EXCL, 0666);
+ if (pidFd == -1)
{
- ErrorF ("cannot open process-id file %s: %s\n", pidFile,
- strerror (errno));
- return -1;
+ if (errno == EEXIST)
+ {
+ /* pidFile already exists; see if we can open it */
+ pidFilePtr = fopen (pidFile, "r");
+ if (pidFilePtr == NULL)
+ {
+ ErrorF ("cannot open process ID file %s for reading: "
+ "%s\n", pidFile, strerror (errno));
+ return -1;
+ }
+ if (fscanf (pidFilePtr, "%ld\n", &oldpid) != 1)
+ {
+ ErrorF ("existing process ID file %s empty or contains "
+ "garbage\n", pidFile);
+ oldpid = -1;
+ }
+ fclose (pidFilePtr);
+ return oldpid;
+ }
+ else
+ {
+ ErrorF ("cannot fdopen process ID file %s for writing: "
+ "%s\n", pidFile, strerror (errno));
+ return -1;
+ }
}
- if (fscanf (pidFilePtr, "%d\n", &oldpid) != 1)
- oldpid = -1;
- if (fseek (pidFilePtr, 0L, SEEK_SET) == -1)
+ if ((pidFilePtr = fdopen (pidFd, "w")) == NULL)
{
- ErrorF ("cannot seek process-id file %s: %s\n", pidFile,
- strerror (errno));
- return -1;
+ ErrorF ("cannot open process ID file %s for writing: %s\n",
+ pidFile, strerror (errno));
+ return -1;
}
- if (fprintf (pidFilePtr, "%5ld\n", (long) getpid ()) != 6)
+ (void) snprintf (pidstr, 11, "%ld", (long) getpid());
+ pidstrlen = strlen (pidstr);
+ if (fprintf (pidFilePtr, "%s\n", pidstr) != ( pidstrlen + 1))
{
- ErrorF ("cannot write to process-id file %s: %s\n", pidFile,
+ ErrorF ("cannot write to process ID file %s: %s\n", pidFile,
strerror (errno));
return -1;
}
@@ -573,3 +608,19 @@
}
return 0;
}
+
+
+/*
+ * Remove process ID file. This function should be registered with atexit().
+ */
+static void
+RemovePid (void)
+{
+#ifdef DEBUG
+ fprintf (stderr, "unlinking process ID file %s\n", pidFile);
+#endif
+ if (unlink (pidFile))
+ if (errno != ENOENT)
+ ErrorF ("cannot remove process ID file %s: %s\n", pidFile,
+ strerror (errno));
+}
Index: xc/programs/xfs/xfs.man
===================================================================
--- xc.orig/programs/xfs/xfs.man 2005-03-01 00:35:18.000000000 +0700
+++ xc/programs/xfs/xfs.man 2005-07-03 13:48:12.000000000 +0800
@@ -37,206 +37,320 @@
.\" suitability of this software for any purpose. It is provided "as is"
.\" without express or implied warranty.
.\" $Xorg: xfs.man,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $
-.TH XFS 1 __xorgversion__
+.TH xfs __mansuffix__ __xorgversion__
.SH NAME
xfs \- X font server
.SH SYNOPSIS
-.B "xfs"
-[\-config \fIconfiguration_file\fP]
-[\-daemon]
-[\-droppriv]
-[\-ls \fIlisten_socket\fP]
-[\-nodaemon]
-[\-port \fItcp_port\fP]
-[\-user \fIusername\fP]
+.B xfs
+[
+.BI "\-config " configuration_file
+]
+[
+.B \-daemon
+]
+[
+.B \-droppriv
+]
+[
+.BI "\-ls " listen_socket
+]
+[
+.B \-nodaemon
+]
+[
+.BI "\-pid " pid_file
+]
+[
+.BI "\-port " tcp_port
+]
+[
+.BI "\-user " username
+]
.SH DESCRIPTION
+.B xfs
+is the X Window System font server.
+It supplies fonts to X Window System display servers.
+The server is usually run by a system administrator, and started via
+.BR init (__osadmmansuffix__).
+Users may also wish to start private font servers for specific sets of
+fonts.
.PP
-.I Xfs
-is the X Window System font server. It supplies fonts to X Window
-System display servers.
-.SH "STARTING THE SERVER"
-The server is usually run by a system administrator, and started via
-boot files like \fI/etc/rc.local\fR. Users may also wish to start
-private font servers for specific sets of fonts.
-.SH "OPTIONS"
-.TP 8
-.B \-config configuration_file
-Specifies the configuration file the font server will use. If this
-parameter is not specified, the default file, \fI/usr/X11R6/lib/X11/fs/config\fR
+To connect to a font server, see the documentation for your X server; it
+likely supports the syntax documented in the \(lqFONT SERVER NAMES\(rq
+section of
+.BR X (__miscmansuffix__).
+.SH OPTIONS
+.TP
+.BI "\-config " configuration_file
+specifies the configuration file
+.B xfs
+will use.
+If this parameter is not specified, the default file,
+.IR __projectroot__/lib/X11/fs/config ,
will be used.
-.TP 8
-.B \-ls listen_socket
-Specifies a file descriptor which is already set up to be used as the
-listen socket. This option is only intended to be used by the font server
-itself when automatically spawning another copy of itself to handle
-additional connections.
-.TP 8
-.B \-port tcp_port
-Specifies the TCP port number on which the server will listen for connections.
-The default port number is 7100.
-.TP 8
+.TP
.B \-daemon
-Instructs xfs to fork and go into the background automatically at
-startup If this option is not specified, xfs will run as a regular
-process (unless xfs was built to daemonize by default).
-.TP 8
+instructs
+.B xfs
+to fork and go into the background automatically at startup.
+If this option is not specified,
+.B xfs
+will run as a regular process (unless it was built to daemonize by
+default).
+When running as a daemon,
+.B xfs
+will attempt to create a file in which it stores its process ID, and will
+delete that file upon exit; see
+.BR \-pid .
+.TP
.B \-droppriv
-If specified, xfs will attempt to run as user and group \fIxfs\fR (unless
-the
+instructs
+.B xfs
+to attempt to run as user and group
+.I xfs
+(unless the
.B \-user
-option is used). This
-has been implemented for security reasons, as xfs may have undiscovered
-buffer overflows or other paths for possible exploit, both local and
-remote. With this option, you may also wish to specify
-"no-listen = tcp"
-in the config file, which ensures that xfs will not to use a TCP port at all.
-.TP 8
+option is used).
+This has been implemented for security reasons, as
+.B xfs
+may have undiscovered buffer overflows or other paths for possible exploit,
+both local and remote.
+When using this option, you may also wish to specify \(oqno\-listen =
+tcp\(cq in the config file, which ensures that
+.B xfs
+will not to use a TCP port at all.
+By default,
+.B xfs
+runs with the user and group IDs of the user who invoked it.
+.TP
+.BI "\-ls " listen_socket
+specifies a file descriptor which is already set up to be used as the
+listen socket.
+This option is only intended to be used by the font server itself when
+automatically spawning another copy of itself to handle additional
+connections.
+.TP
.B \-nodaemon
-When xfs is built to daemonize (run in the background) by default,
-this prevents that and starts xfs up as a regular process.
-.TP 8
-.B \-user username
-This is equivalent to
+instructs
+.B xfs
+not to daemonize (fork and detach from its controlling terminal).
+This option only has an effect if
+.B xfs
+is built to daemonize by default, which is not the stock configuration.
+.TP
+.BI "\-pid " pid_file
+instructs
+.B xfs
+to save its process ID into
+.IR pid_file ,
+instead of the default,
+.IR /var/run/xfs.pid .
+If
+.B xfs
+is not running as a daemon, this option has no effect.
+.TP
+.BI "\-port " tcp_port
+specifies the TCP port number on which the server will listen for
+connections.
+The default port number is 7100.
+This option is ignored if
+.B xfs
+is configured to not listen to TCP transports at all (see \(lqConfiguration
+File Format\(rq below).
+.TP
+.BI "\-user " username
+instructs
+.B xfs
+to run as the user
+.IR username.
+See
.B \-droppriv
-except that xfs will run as user \fIusername\fR.
-.SH "SIGNALS"
-.TP 8
-.I SIGTERM
-This causes the font server to exit cleanly.
-.TP 8
-.I SIGUSR1
-This signal is used to cause the server to re-read its configuration file.
-.TP 8
-.I SIGUSR2
-This signal is used to cause the server to flush any cached data it
-may have.
-.TP 8
-.I SIGHUP
-This signal is used to cause the server to reset, closing all active
-connections and re-reading the configuration file.
-.SH "CONFIGURATION"
+for why this may be desired.
+By default,
+.B xfs
+runs with the user and group IDs of the user who invoked it.
+.SH "INPUT FILES"
+.B xfs
+reads and serves any font file format recognized by the X server itself.
+It locates font files through the specification of a
+.IR catalogue ,
+which is delcared in
+.BR xfs 's
+configuration file.
+.SS "Configuration File Format"
+.B xfs
+reads its configuration from
+.I __projectroot__/lib/X11/fs/config
+by default (see the
+.B \-config
+option in the \(lqOPTIONS\(rq section above).
The configuration language is a list of keyword and value pairs.
-Each keyword is followed by an '=' and then the desired value.
+Each keyword is followed by an equals sign (\(oq=\(cq) and then the desired
+value.
.PP
Recognized keywords include:
-.sp
-.\" .IP "cache-size (cardinal)"
-.\" Size in bytes of the font server cache.
-.IP "catalogue (list of string)"
-Ordered list of font path element names.
-Use of the keyword "catalogue" is very misleading at present,
-the current implementation only supports a single catalogue ("all"),
+.TP
+.BR alternate\-servers " (list of \fIstring\fPs)"
+lists alternate servers for this font server.
+See the \(lqFONT SERVER NAMES\(rq section of
+.BR X (__miscmansuffix__)
+for the syntax of the string.
+.\" .TP
+.\" .BR cache\-size " (\fIcardinal\fP)"
+.\" determines the size (in bytes) of the font server cache.
+.TP
+.BR catalogue " (list of \fIstring\fPs)"
+declares as ordered list of font path element names from which fonts will
+be served.
+Use of the keyword \(oqcatalogue\(cq is very misleading at present: the
+current implementation only supports a single catalogue (\(oqall\(cq),
containing all of the specified fonts.
-.IP "alternate-servers (list of string)"
-List of alternate servers for this font server.
-.IP "client-limit (cardinal)"
-Number of clients this font server will support
-before refusing service. This is useful for tuning
-the load on each individual font server.
-.IP "clone-self (boolean)"
-Whether this font server should attempt to clone itself
-when it reachs the client-limit.
-.IP "default-point-size (cardinal)"
-The default pointsize (in decipoints) for fonts that
-don't specify. The default is 120.
-.IP "default-resolutions (list of resolutions)"
-Resolutions the server supports by default.
-This information may be used as a hint for
-pre-rendering, and substituted for scaled fonts
-which do not specify a resolution.
-A resolution is a comma-separated pair of x and y resolutions in
-pixels per inch.
+.TP
+.BR client\-limit " (\fIcardinal\fP)"
+determines the number of clients this font server will support before
+refusing service.
+This is useful for tuning the load on each individual font server.
+.TP
+.BR clone\-self " (\fIboolean\fP)"
+indicates whether this font server should attempt to clone itself when the
+number of connected clients reaches the
+.BR client\-limit .
+.TP
+.BR default\-point\-size " (\fIcardinal\fP)"
+The default pointsize (in decipoints) for font requests that don't specify
+a point size.
+The default is 120.
+.TP
+.BR default\-resolutions " (list of \fIresolution\fPs)"
+indicates the resolutions the server supports by default.
+This information may be used as a hint for pre-rendering, and substituted
+into requests for scaled fonts which do not specify a resolution.
+A
+.I resolution
+is a comma-separated pair of horizontal and vertical resolutions in pixels
+per inch.
Multiple resolutions are separated by commas.
-.IP "error-file (string)"
-Filename of the error file. All warnings and errors
-will be logged here.
-.IP "no-listen (trans-type)"
-Disable a transport type. For example, TCP/IP connections can
-be disabled with no-listen tcp
-.IP "port (cardinal)"
-TCP port on which the server will listen for connections.
-.IP "use-syslog (boolean)"
-Whether syslog(3) (on supported systems) is to be used
-for errors.
-.IP "deferglyphs (string)"
-Set the mode for delayed fetching and caching of glyphs. Value is
-"none", meaning deferred glyphs is disabled, "all", meaning it is
-enabled for all fonts, and "16", meaning it is enabled only for
-16-bits fonts.
-.\" .IP "trusted-clients (list of string)"
-.\" Those clients the fontserver will talk to. Others
-.\" will be refused for the initial connection. An empty
-.\" list means the server will talk to any client.
-.SH "EXAMPLE"
+.TP
+.BR deferglyphs " (\fIstring\fP)"
+sets the mode for delayed fetching and caching of glyphs.
+.I string
+should be one of \(oqnone\(cq, meaning glyphs deferment is disabled,
+\(oqall\(cq, meaning it is enabled for all fonts, and \(oq16\(cq, meaning
+it is enabled only for 16-bit fonts.
+.TP
+.BR error\-file " (\fIstring\fP)"
+indicates the filename of the error file.
+All warnings and errors will be logged here, unless
+.B use\-syslog
+is set to a true value (see below).
+.TP
+.BR no\-listen " (\fItrans-type\fP)"
+disables the specified transport type.
+For example, TCP/IP connections can be disabled with \(oqno\-listen =
+tcp\(cq.
+.TP
+.BR port " (\fIcardinal\fP)"
+indicates the TCP port on which the server will listen for connections.
+.\" .TP
+.\" .BR trusted-clients " (list of \fIstring\fPs)"
+.\" idefntifies the clients the font server will talk to.
+.\" Others will be refused for the initial connection.
+.\" An empty list means the server will talk to any client.
+.TP
+.BR use\-syslog " (\fIboolean\fP)"
+determines whether errors and diagnostics should be reported via
+.BR syslog (__oslibmansuffix__)
+(on supported systems) instead of being written to the
+.B error\-file
+(see above).
+.SS "Example Configuration File"
.nf
XCOMM
XCOMM sample font server configuration file
XCOMM
-XCOMM allow a max of 10 clients to connect to this font server
-client-limit = 10
+XCOMM allow a max of 10 clients to connect to this font server.
+client\-limit = 10
-XCOMM when a font server reaches its limit, start up a new one
-clone-self = on
+XCOMM When a font server reaches the above limit, start up a new one.
+clone\-self = on
-XCOMM alternate font servers for clients to use
-alternate-servers = hansen:7101,hansen:7102
+XCOMM Identify alternate font servers for clients to use.
+alternate\-servers = hansen:7101,hansen:7102
-XCOMM where to look for fonts
-XCOMM the first is a set of Speedo outlines, the second is a set of
-XCOMM misc bitmaps and the last is a set of 100dpi bitmaps
+XCOMM Look for fonts in the following directories. The first is a set of
+XCOMM Speedo outlines, the second is a set of misc bitmaps (such as terminal
+XCOMM and cursor fonts), and the last is a set of 100dpi bitmaps.
XCOMM
catalogue = /usr/X11R6/lib/X11/fonts/speedo,
- /usr/X11R6/lib/X11/fonts/misc,
- /usr/X11R6/lib/X11/fonts/100dpi/
+ /usr/X11R6/lib/X11/fonts/misc,
+ /usr/X11R6/lib/X11/fonts/100dpi/
XCOMM in 12 points, decipoints
-default-point-size = 120
+default\-point\-size = 120
XCOMM 100 x 100 and 75 x 75
-default-resolutions = 100,100,75,75
-use-syslog = off
-.fi
-.sp
-.SH "FONT SERVER NAMES"
-One of the following forms can be used to name a font server that
-accepts TCP connections:
-.sp
-.nf
- tcp/\fIhostname\fP:\fIport\fP
- tcp/\fIhostname\fP:\fIport\fP/\fIcataloguelist\fP
-.fi
-.PP
-The \fIhostname\fP specifies the name (or decimal numeric address)
-of the machine on which the font server is running. The \fIport\fP
-is the decimal TCP port on which the font server is listening for connections.
-The \fIcataloguelist\fP specifies a list of catalogue names,
-with '+' as a separator.
-.PP
-Examples: \fItcp/fs.x.org:7100\fP, \fItcp/18.30.0.212:7101/all\fP.
-.PP
-One of the following forms can be used to name a font server that
-accepts DECnet connections:
-.sp
-.nf
- decnet/\fInodename\fP::font$\fIobjname\fP
- decnet/\fInodename\fP::font$\fIobjname\fP/\fIcataloguelist\fP
+default\-resolutions = 100,100,75,75
+
+XCOMM Specify our log filename.
+error\-file = /var/log/xfs.log
+
+XCOMM Direct diagnostics to our own log file instead of using syslog.
+use\-syslog = off
.fi
-.PP
-The \fInodename\fP specifies the name (or decimal numeric address)
-of the machine on which the font server is running.
-The \fIobjname\fP is a normal, case-insensitive DECnet object name.
-The \fIcataloguelist\fP specifies a list of catalogue names,
-with '+' as a separator.
-.PP
-Examples: \fIDECnet/SRVNOD::FONT$DEFAULT\fP, \fIdecnet/44.70::font$special/symbols\fP.
-.SH "SEE ALSO"
-X(__miscmansuffix__), \fIThe X Font Service Protocol\fP,
-.br
-\fIFont server implementation overview\fP
+.SH "OUTPUT FILES"
+When operating in daemon mode,
+.B xfs
+sends diagnostic messages (errors and warnings) to the system log via the
+.B syslog
+C library function by default.
+However, these messages can be sent to an alternate location via the
+.B error\-file
+and
+.B use\-syslog
+configuration variables; see \(lqConfiguration File Format\(rq, above.
+.SH "ASYNCHRONOUS EVENTS"
+.B xfs
+handles the following signals specially:
+.TP
+.I SIGTERM
+causes the font server to exit cleanly.
+.TP
+.I SIGUSR1
+causes
+.B xfs
+to re-read its configuration file.
+.TP
+.I SIGUSR2
+causes
+.B xfs
+to flush any cached data it may have.
+.TP
+.I SIGHUP
+causes
+.B xfs
+to reset, closing all active connections and re-reading the configuration
+file.
.SH BUGS
Multiple catalogues should be supported.
+.SH "FUTURE DIRECTIONS"
+Significant further development of
+.B xfs
+is unlikely.
+One of the original motivations behind it was the single-threaded nature of
+the X server \(em a user's X session could seem to \(oqfreeze up\(cq while
+the X server took a moment to rasterize a font.
+This problem with the X server, which remains single-threaded in all
+popular implementations to this day, has been mitigated on two fronts:
+machines have gotten much faster, and client-side font rendering
+(particularly via the Xft library) is the norm in contemporary software.
.SH AUTHORS
Dave Lemke, Network Computing Devices, Inc
.br
Keith Packard, Massachusetts Institute of Technology
+.SH "SEE ALSO"
+.BR X (__miscmansuffix__),
+.BR init (__osadmmansuffix__),
+.BR syslog (__oslibmansuffix__),
+.IR "The X Font Service Protocol" ,
+.I Font Server Implementation Overview
Reply to: