# Part 3 -

Using the System, System Administration, Performance, and Programming

Up to now we have concentrated on the architecture of the system and its internal mechanisms. In this Part of the book we move on and look at how you use the system in practice - what you need to get started, what tools are available, programming issues, administering and tailoring your system, and evaluating its performance.

# Chapter 10-

Using the X System

#### Introduction

Ttus chapter outlines how you use the X system, especially in a network environment. We also look at how you can use programs for character-based terminals and for other window systems in conjunction with X.

## 10.1 What you need to get started

The realistic minimum system is a server, a window manager, the basic X client applications, and ideally some X administration tools. The easiest way to start is to use a multitasking workstation, and initially avoid the complexities of running over a network.

The easiest way to get started using X is with a workstation running a multitasking operating system such as UNIX or VMS. Your system is self-contained, with all the components on a single machine (Figure A). If you start with a networked configuration (Figure B) not only do you have to work out which components go where, but you also have to ensure the network is properly set up, and you need to use network commands to run applications remotely. While most of this is relatively straightforward, it is a complication the newcomer can do without.

To use X you need:

- The X server for your particular hardware and operating system. The server is supplied with the fonts it needs, and the colour database (typically just a single file) which it uses to translate colour names into internal colour values.

  As shown in Figure B, all these components reside on the machine where the server is running. (Later, if you need to, you can store fonts elsewhere on your network using the font server we mentioned in Module 3.5.1.)

- Basic applications programs and tools to let you perform the work you use your computer for. If you have been able to obtain X software for your particular applications, you can start using it immediately. More often, however, you will have existing, non-X, applications, so you need a terminal emulator program such as the MIT program xterm, to let you use your character-based applications (see Module 10.3). A terminal emulator is almost essential for system administration work too. Other convenient but non-essential tools are small applications such as a clock, a desk calculator, etc.

  These applications can run on the same machine as your server, or elsewhere on the network.

- A window manager to manage your application windows.

  Just like your other client programs, the window manager can run on the same machine as the server, or remotely.

- Standard defaults files which are supplied as part of your applications, to specify the default layout, fonts and colours used, etc. by the applications. These files usually reside on the same machine as the application they relate to, or at least are accessible from that machine using a networked file system such as NFS. (We cover these files in detail in Module 12.2.)
- Shared libraries. If your system supports shared libraries and your application uses them, you will need the libraries on each machine the applications run on. (See Module 14.1 for details.)

In the next module we describe the contents of the MIT Release of X, which is representative of many commercial X systems.

#### Using X in a networked environment

If you are going to run applications remotely over a network, then as well at the network itself you will need for both the server machine and the machine(s) on which the applications are to run:

- Network hardware to connect the machine onto the network, for example an Ethernet interface card.
- Network software to drive the network interface and transfer data to and from it, to provide the basic transport which X requires: for example, TCP/IP software. On the server end you will also need software to allow you to start applications running on remote machines: for example, the rsh or telnet programs which work over TCP/IP.

Of course, if you are using an X-terminal and not a workstation, these components will already be incorporated, and most of your work will relate to configuring the host machine elsewhere on the network, which the X clients are to run on.

###### Figure A. A standalone workstation containing all the components of the X system.

###### Figure B. Networked X is more complex, as system components are distributed.

### 10.1.1 What the MIT system comprises

The MIT release of X contains source code for servers and clients for several different Unix platforms, with installation scripts and complete documentation. The range of applications provided is typical of many commercial X systems.

The MIT release of X provides source code for a complete working system, plus everything needed to build it. We include details here to give you an indication of what a typical system contains.

The release includes many basic clients, such as the xterm terminal emulator, the xedit text editor, bitmap editors, desk accessories such as clocks, tools to read and send e-mail, and of course a window manager. There is also a comprehensive set of administration tools for configuring your system and checking its status, covering aspects such as fonts, preferred settings and defaults both for your display and individual applications, keyboard mapping, etc.

The following is an extract from the release notes for Release 5:

- clients This directory contains most of the sample applications. See the program man pages for details.
- config This directory contains configuration files and the imake program used to build the release. Details are covered in other sections below
- demos This directory contains a small collection ofgraphics demonstration programs, a few utility/test programs, and some performance demonstration programs. These are by no means the `best' demo programs around, they just happen to be ones we try to maintain.
- doc This directory contains troffsources to X Consortium standards, server internals documentation, documentation for various utility libraries, some useful tutorial material.
- extensions This directory contain,s implementations of X server extensions, both the server internals and the application programming libraries, and some test programs. Ofparticular note here, new in Release 5, is PEX, the PHIGS Extension to X usedfor 3D graphics, and the PHIGS programming library which interfaces to the PEX protocol.
- fonts This directory contains bitmap fonts in source form, some outline fonts, a sample font server a utility font library used by the X server and font.server a client font library for interacting with the font server and programs for building fonts and querying the font server
- hardcopy This directory contains pre-generated PostScriptfilesfor the client man pages and for most of the documentation found in the doc directory. The files are compressed with compress to save disk space. If you do not have compress on your system, you will find a version in the mit/util/compress directory.
- include This directory contains various library-independent C headerfiles and a collection of bitmap files.
- lib This directory contains programming libraries and support files. Of note are Xlib (the lowest-level C programming interface to X), Xt (the X Toolkit Intrinsics), Xmu (an eclectic set ofutilityfunctions), Xaw (the Athena Widget Set), and CLX (a Common Lisp inlerface to X).
- man This directory contains a few top-level man pages about the release (general information, server access control mechanisms, the X Consortium, and X Consortium standards), and man pages for some of the programming libraries.
- rgb This directory contains a program to generate the color database used by the X server and sample databases.
- server This directory contains the X server sources, both device-independent (dix) and device-dependent (ddx). In this release, there is support for building the following servers:
  - DECstation 2100/3100 monochrome and color displays
  - DECstation 5000 CX and MX displays
  - IBM RS/6000 skyway adapter
  - Apple Macintosh monochrome and color displays
  - MIPS monochrome and color displays
  - OMRON LUNA monochrome displays
  - Tektronix 4319 color display
  - VAXstation QVSS and QDSS displays
  - Sun monochrome and 8-bit color displays (with GX support)
  - Various VGA displays under System V/386

  If your favorite hardware is not listed above, please do not blame us at MIT, we ship what Consortium members provide. Only in a few cases do we try to maintain device-specific software for our own development needs.

- util This directory contains miscellaneous utility programs and shell scripts used to build, maintain, and install the release.

## 10.2 How you use the network facilities

Running applications on remote hosts but displaying to your X station lets you create a very flexible and rich user environment. Using remote applications is easy.

When using an X-terminal, which cannot run any of its own applications, you have to run your X clients remotely over the network. Even when running with the X server on a multitasking workstation which can run applications locally, many users frequently use X's remote execution facilities. This is because on most real-life networks, there are facilities - special hardware, or a partieular software package - which are available only on specific machines; having a window open onto that machine or running that package is very convenient. Using X like this, to share expensive or limited resources among many users across the network, can be very cost-effective. (Even for inexpensive resources, it is often cheaper to provide them centrally to save on administration costs.)

Figure A shows a typical scenario, of an X-terminal (mars) and two workstations (venus and pluto) on a network. There are several points to note, which are typical of real-life use:

- The two workstations and the X-terminal are using applications from several different remote hosts at the same time.
- A workstation often runs local applications for its own server as well as applications for other remote servers.
- The window manager, mwm, is always run from venus (presumably because Motif has been licensed only for venus). It is run locally for the display on venus itself, and remotely for mars and other displays.
- pluto is running a different window manager, olwm, locally.
- Whereas the X-terminal has to run all clients remotely, the workstation will normally run locally any `standard' widely available clients such as the xterm terminal emulator and `small' applications such as the clock and calculator.
- pluto is running xterm remotely on venus as well as locally, giving pluto's user a terminal session on venus. This type of setup is particularly useful to system administrators who need simultaneous access to many machines on the network when configuring, troubleshooting, or just monitoring the performance of the systems.
- Applications that are using files intensively are best run remotely on the machine where the files are resident, rather than on the user's own machine with the files shared using a networked file system like NFS. (For example, the database is shown running on neptune rather than on venus.) In this way the network load is minimized (see Module 13.2 for more details).

In the next module we describe how to run remote applications.

###### Figure A. Running programs remotely over the network to an xterminal

### 10.2.1 How applications are started remotely

Networking software systems provide commands that make it easy to start single programs running on machines elsewhere on the network, or to run a whole session on a remote machine. You use these commands to run your applications remotely, displaying back to your own X server.

(If technical details aren't so relevant to you, you can skip over this module.)

With suitable networking software it is very easy to start a program on a remote machine displaying back to your own. For example, with a TCP/IP system the usual commands you use are:

- rsh. To start a program running on a remote machine you enter a command of the form :

         rsh remote-machine-name program-to-run...

  Figure A illustrates how, from the workstation venus, you would start a clock locally, and then a window manager, calculator, and xedit text editor running remotely. You can see that each rsh line starts a single command, and the line must specify the command completely; no information or status persists from any previous command, which is why you have to repeat the display-name specification `-display venus'.
- rexec is imilar to rsh, and is usually provided on System V implementations of UNIX, whereas r5h is part of the Berkeley UNIX implementations.
- telnet lets you login to a remote host and run an entire session on that machine, terminating only when you explicitly log out. Figure B shows a telnet session from venus onto saturn, starting the same commands as in the previous example. (The setenv line stores the name of the display to use, venus, into the standard environment variable DISPLAY, to avoid having to type -display name for each command.) When you have a lot of work to do on one particular machine telnet is probably the easiest option, because you can customize aspects of your environment in this way. The alternative is to use rsh to start an xterm running on the remote machine, and then within that xterm window do the rest of your work.

Being able to connect applications on remote machines to your display has its disadvantages too: it allows other people on those hosts to use your display and possibly interfere with your work or steal your password. X does provide security mechanisms to control access to your server, which we cover in Module 11.4.

###### Figure A. Starting remote applications using rsh

###### Figure B. Starting remote applications using telnet.

## 10.3 Using character-based applications - terminal emulators

Terminal emulators let you use non-X character-based applications on any X display, without any change to the application.

Most programs and applications have not been written specifically for X. So how can you use them on an X display? As we said in Module 2.2.3, the answer is: via a special program called a terminal emulator.

Simply, a terminal emulator is a program that `pretends to be' a real terminal: it gives you a window which in almost every respect behaves like a physical terminal. Starting the emulator is analogous to switching on a real terminal and logging in. After that, you have a normal terminal session with your normal system prompt, and you run programs and receive their output as normal (Figure A, top left window). In UNIX terms, a shell or command-line interpreter is running in the window; it receives the input you type in the window just as though it had been typed on a normal terminal keyboard, and it runs the programs you command it to. Output from the shell and the programs you run appears in the window just as though on a terminal's screen.

Thus, a terminal emulator lets you run all your old programs written for charaeterbased terminals. This of course includes all the standard operating system commands such as ls, cat, pwd, vi (or DIR, TYPE, SHOW DEF, and TPU), as well as all the compiler, linker and debugger programs for your system. (So in a way, you can consider that your terminal emulator is a virtual terminal, something which is `giving you back the old world' or providing you with a `gateway to history', that is to old, non-windowed, programs.)

As an example, let's look at the DEC VT102 emulation provided by the MIT xterm program. The real VT102 terminal supports many features, including cursor addressing, character underlining, inverse video, etc. xterm gives you exactly the same facilities. In addition it provides extras, such as the ability to change the font size on the fly by means of pop-up menus. xterm also provides emulation of the Tektronix 4014 graphics terminal (Figure A, bottom right window). Many other emulators are available commercially, especially of the Tektronix graphics and DEC terminals. There are also programmable or customizable emulators available, described in Module 14.3.

#### Advantages of terminal emulators

Running character-based applications via an X terminal emulator gives you many advantages even though you are still using a character-based program:

- You can cut-and-paste between your emulator and other X windows, giving some degree of communication between your old application and other clients.
- You can have multiple `terminals' on screen at once in different windows, allowing you to perform various parti of an overall task easily, and cut-andpaste between them, instead of having to stop one program, start another, and then go back to the first. And of course you can run several copies of one program if you want to.
- You can customize your keyboard, and map function keys on a per-window basis.
- You can scroll your output, to look back at output that has gone by. You can also log your session to a file.
- You can dynamically change fonts, for example to select a very small font to display the maximum amount of information in your window. You can make the emulator window very large to show even more information, or very small if that's all you require.
- Multiple terminal emulators can be connected to different hosts, allowing you to use old applications on many different machines together.

In the next module we describe how emulators can handle applications running on other hosts, and in the module after that we look at the internal operation of a terminal emulator.

###### Figure A. A terminal emulator behaves just like a character-based terminal.

### 10.3.1 Terminal emulators and applications on different machines

Using facilities such as telnet allows the X terminal emulator to run on one host while the character-based application it is handling runs on another host elsewhere on the network. Thus, with terminal emulators you can even use applications running on machines which have no X support.

While non-windowed applications are often run on the same machine as your emulator, especially standard utilities such as mail programs, editors, directory listings, etc., the non-X application doesn't have to run on the same machine. Instead it can run elsewhere, and be connected to the emulator via telnet or something similar (Figure A). This is often necessary where the old application is on a platform which doesn't support X, but as long as that platform has some network remote execution facilities like telnet or SET HOST, you can still use the application from your X station.

We shall see in Module 14.3 how this same principle is used by programmable terminal emulators to provide an X front-end to character-based applications on systems which don't support X.

In the next module we look at the internals of the terminal emulator's operation.

###### Figure A. Application running remotely from a terminal emulator.

### 10.3.2 How a terminal emulator works

The non-X application runs on its normal machine and operating system, but is connected to a `pseudo-terminal' instead of a real terminal. The terminal emulator captures the character output and draws it in an X window, and transforms X keyboard input into characters which it sends to the application as though it were connected directly to a normal terminal keyboard.

(If technical details aren't so relevant to you, you can skip over this module.)

The non-X application, which for simplicity we are assuming uses ASCII characters, is run as normal but, instead of being connected to a real terminal (Figure A), it is connected to a pseudo-terminal (Figure B).

A pseudo-terminal is a facility provided by the machine's operating system. It is just a terminal communications channel, but instead of being attached to a physical terminal with a human at the the other end, it is controlled by some other application. All normal input and output handling which occurs on a physical terminal also occurs on a pseudo-terminal. For example, sending a Delete character will remove from the input buffer the last character typed; and most terminal characteristics can be set as usual, for example whether input is to be echoed, whether characters are 7-bit or 8- bit, etc. So the application takes its input from the input side of the pseudo-terminal instead of taking it direct from a terminal keyboard; what it receives will be whatever the application controlling the pseudo-terminal sent. And instead of writing its output direct to a terminal screen, the original application writes it to the output side of the pseudo-terminal, where the controlling application reads it and can do with it whatever it decides is necessary.

Here the application controlling the pseudo-terminal is an X terminal emulator program. Internally, the terminal emulator is taking in X events from the server, and translating them into characters (ASCII for simplicity) which it sends to the `old' program. The terminal emulator is also receiving ASCII characters output by the program over the pseudo-terminal, and translates these into the appropriate X requests to make the output appear in the terminal emulator window in the same place as it would on a real terminal. The fiow of events, characters and requests in the system is shown schematically in Figure C.

The next module deals with how the emulator handles output to the `terminal' screen.

###### Figure A. Application connected to a physical terminal

###### Figure B. Application connected to a pseudoterminal.

###### Figure C. The flow of information when a terminal emulator is used.

### 10.3.3 How the terminal emulator handles output

The terminal emulator program must duplicate the functionality of the physical terminal it is emulating, to handle functions such as cursor addressing, characterunderlining, inverse video, etc.

(If technical details aren't so relevant to you, you can skip over this module.)

The output stage of the emulator is crucial, as it determines what physical terminal is emulated. The functions normally performed by a physical terminal's hardware or firmware must now be mimicked by the emulator to produce the same result. So the emulator must watch the stream of input characters and handle all the escape sequences and mode changes that the target terminal-type supports. As an example, let's look at some of the features of the DEC VT102 emulation provided by xterm:

- Elementary character printing. Handling of output to the `terminal screen' is straightforward. The first string of printing characters is printed in the first `row' and first `column' of the screen with an XDrawString() request. As further characters arrive, the emulator prints them on the same row (same Y-coordinate in the X-window) as the previous character string, but the print position is moved successively to the right (increased X-coordinate in the X-window) each time. If an incoming string contains a newline character, it has to be split in two; the parts before and after the newline are drawn by separate XDrawString() requests on separate `rows'.
- Cursor addressing. When the character sequence:

         ESC  [  num  A

  is received by the terminal emulator, the cursor is to be moved num lines up the screen (in fact, up the window). To do this xterm must keep a representation of the screen in its memory; when it next draws a character in its window, the coordinates specified to the XDrawString() function should be num lines above the previous position.

- Character underlining. The VT102 can be switched via an escape sequence into a mode where all characters printed are underlined. X does not have special fonts with underlines included. Therefore xterm, as well as having to recognize the escape sequence requesting underlining, has to underline the characters explicitly. Thus, when the emulator is in underline mode, whenever it draws a character string in its window, it immediately afterwards performs an XDrawLine() function in the row of pixels immediately below the characters just written (Figure A).
- Inverse video is handled by reversing the foreground and background colour settings for the XDrawString() function used to draw the characters on the screen.

###### Figure A. How the terminal emulator prints underlined characters

## 10.4 Integrating X with other systems

You can use X on machines already running other window systems by means of special servers. These let you mix applications for X and for the system's native window system on the same screen. Other facilities let you run Macintosh and Microsoft Windows applications remotely, but display their output and interact with them on your X screen just as if they were remote X applications.

As mentioned in Module 2.2.4, for computers running some other window system, special servers enable you to work with both X and the native window system. There are special servers available for SunView, Microsoft Windows, NeXT and Macintosh systems.

Figure A shows a Microsoft Windows screen, with both X and DOS applications simultaneously on screen. This system is typical of what these special servers provide. You can run your X applications as shown, with each as a separate window in the native window system, and with the window management being done by the native system and not by X. If the X programs use the Motif toolkit the integration achieved is particularly good, as the Motif and Microsoft Windows user interfaces are very similar. Alternatively, you can have a single native window which acts as a virtual X screen (shown as the shaded window in Figure B) with all the X applications running within it and under the eontrol of an X window manager. However, this does not provide such seamless integration - the user has to operate in two different `worlds', and it's obvious whieh programs are native and which are X.

The advantages to the user are illustrated by Figure C. The X server is effectively bridging the DOS and UNIX operating systems, giving the user access to the best application for the tasks to be done. This setup is also bridging the Novell and TCP/IP networked file systems, again making use of the facilities best suited to the particular task.

The systems we have described so far allow you to add X to the system already on your desktop machine. There are other systems that work almost in reverse, by giving you access from any X screen to applications written for other systems. Figure D shows this facility linking a Macintosh (running on its own AppleTalk network) into a TCP/IP-based X network. The hardware bridge is necessary to convert the two network protocols, and it also contains special software which gives the remote user access to the application running on the Macintosh. What the user gets is the ability to use Macintosh applications without having a Macintosh on their desk. (In a sense, the Macintosh is acting as a `Macintosh-application server' to the rest of the network.)

Similar facilities are available for DOS applications. There are also complete DOS emulators that are entirely software-based, to run on many different types of workstation and minicomputer, which use X to display the virtual PC screen and to receive the keyboard input to be sent to the DOS application.

###### Figure A. Microsoft windows and X applications running simultaneously on a DOS screen.

###### Figure B. All X applications running in a single Microsoft window.

###### Figure C. The special X server bridges Novell and TCP/IP, DOS and UNIX or VMS.

###### Figure D. Using a Macintosh application from an X station, via a TCP/IP AppleTalk bridge

## 10.5 Where to get the software

The MIT Release of X is available free, or at very little cost. It contains much useful documentation and code, but is unsupported. While it can be used to build a complete working system, organizations starting with X are better off buying a supported implementation elsewhere. A lot of other useful software is available free, too.

#### The MIT Release

The MIT X Consortium makes the full source release of X available on a variety of tape formats for a small distribution cost. (Figure A gives the contact details for the Consortium.) The same software is available completely free via ftp file transfer from MIT (but you need suitable networking facilities). There are also a number of archive sites which can provide the software via electronic mail over various public networks.

The MIT software is the starting point for most commercial implementations, and it includes a lot of documentation and some example programs. The user-contributed software included in the release contains many useful tools for system administration and programming, as well as applications for image processing and other tasks.

The MIT Release also provides a very cheap system - it includes everything required to build a fully functional working system. Because it is provided at no cost, it is of course unsupported and provided without any warranty. It is only suitable (without modification) for systems running UNIX. Moreover, installing the MTT Release involves a lot of work and needs a lot of disk space; while many (primarily academic or research) sites do use the MIT software directly, organizations new to X should, at least initially, either use the X system provided by their hardware vendor, or purchase a supported X system from a third-party supplier. (However, should you requing it, some consultancy houses do offer support for the MIT software.)

#### Other X implementations

Most hardware vendors now also supply X for their systems, and often their versions are specially tailored and optimized for the particular platform. There are also many thirdparty suppliers that supply versions of X for common workstations; such companies are particularly useful for providing the latest software very soon after release, and for providing and supporting additional software such as toolkits.

Other sources of X software include user groups (see Module 15.3) and the various interest groups on the public networks which make available a huge amount of free software (of varying quality).

###### Figure A. Contact details for the MIT X Consortium

## Summary

This chapter has described how the X system is seen by a user and how its various features are used in practice, from getting started, through using the network to integrating applications for character-based terminals and for other window systems into your X environment. For fuller details about using the system, see this book's companion volume, The X Window System: A User's Guide, or any of the other user handbooks now available.

In the next chapter we look at the system from a different perspective, and see how it is set up and administered.

# Chapter 11-

System Administration

#### Introduction

In this chapter we concentrate on those aspects of the system that most concecn the system manager. We first look at how you start up the system, and how a workstation, X-terminal, or PC can be configured to bring the user automatically into X at switch-on time. We then look at how you can customize your overall environment. We see how fonts are administered to overcome pcoblems caused by dependence on the resolution of users' displays, and by limited font availability. We consider the security aspects of X systems, and some of the emerging security mechanisms. Finally, we summarize the elements of system administration required for X, and the administration tools available.

## 11.1 Starting up the system

Well-engineered X servers give you an easy way to start an initial client at the same time as the server, so you can `bootstrap' the complete environment you require. More sophisticated startup systems are continually being developed, which greatly simplify the system administration of X networks.

What the X Protocol covers is specific and relatively limited - how the server should respond to requests from clients, and how it should handle input from the hardware, and other events. This doesn't address a lot of things that are vital to someone using the system - in particular, how do you start the first client?

This is a problem (especially on an X-terminal) because once the server starts without a client, no application is connected to the display. Therefore, while all input from the keyboard and mouse is handled by the server, it is immediately thrown away because no client has registered an interest in these events. Figure A shows a screen with only the X server running - there is nothing for the user to interact with !

The primitive and cumbersome solution is to walk over to another terminal or workstation and from there run a client displaying to your X server. You start an xterm or some other program that enables you to issue further commands to your operating system. Then you can walk back to your X display and from within the xterm start any other programs you want (now, or later on as you need them).

A simple and better solution, but suitable only for a multitasking system, is provided by the program xinit. This starts the server as a sub-process, and once the server is running xinit starts a (specified) client connected to that server. By default the client started is xterm, so that you can then run any other programs you wish.

For X-terminals and PC X servers a similar approach is used. However, because an X-terminal can't run any clients locally, the initial client to be started must be on a remote machine, and so the command used to start the client must be a network command connecting to that remote machine. As we described in Module 10.2.1, you can use a non-interactive command like rsh to start a single remote program and go on from there. Or you can use an interactive program like telnet giving you a full interactive session, allowing you to start as many clients as you want. ln practice, most people use rsh to run a shell script or command file, which in turn starts all the clients required, in the desired configuration. Figure B shows a configuration file for a PC X server: it specifies that the initial program my_startx is to be run on the remote machine Saturn by executing the rsh command as user niall. (The other lines are configuration opaons specific to this particular server.) With a suitable script file, a setup like this can start up your X environment exactly as you want, automatically. PC users can even include the server start up commands in their AUTOEXEC.BAT file, so that their X session comes up as soon as they switch on. Figure C shows a simple script to start up X with our usual applications.

However, the most recently developed, and best, way to start up your X system is with xdm, described in the next module.

###### Figure A. An X screen with only the server running.

###### Figure B. A typical startup configuration file for a PC X server

###### Figure C. Shell script to start our usual applications.

### 11.1.1 xdm, the X Display Manager

xdm manages your display by starting your server, and giving you a window in which you log on to the system. It then starts a specified application or script and, when you have finished your work session, xdm resets the server and presents the login window again, ready for the next user.

xdm gives you a clean way to start up your X system. It allows you to start your server, and just like xinit starts a client also. However, the client it starts initially gives you a login window (Figure A). Once you have logged in, xdm runs either an xterm (the default), or a program specified by you. Often the program you specify is a shell script or command file which starts up your usual applications and configures your X environment, as we described for rsh in the previous module. Alternatively, the script can be a standard one set up for your whole site by your system manager. The sample script provided with xdm lets the system manager define standard facilities for all users, but allows individual users to customize their own environment if they want (see next module).

xdm is the best way to start X on a workstation because it gives the cleanest and most obvious interface. If the workstation is to be used as a dedicated X station, xdm can be run from the operating system's startup script, so that as soon as the machine is fully booted the X server is up and running, with xdm waiting for a user to log in (just as a character-based terminal gives a login prompt when it is switched on). You as user don't have to know what programs are necessary to run X - you just log in! xdm makes starting an X session similar to and just as easy as starting a session on a character-based terminal.

xdm can also be used with X-terminals and PC X servers to provide the same loginwindow facility. As the xdm program itself cannot be run on the terminal or PC, it is run remotely from elsewhere, and one running copy of it can handle multiple terminals or PCs.

Prior to Release 4, in this basic configuration xdm periodically polled the Xterminals it knew about (their names or network addresses were listed in a configuration file), and when it found a terminal that had an X server which it was not already managing, it started up a login window and continued as normal. On the X-terminal side, the server was started with no initial client, and it waited for xdm to notice that the server was now running. With Release 4, the facility XDMCP (X Display Manager Control Protocol) was introduced which lets xdm handle X-terminals in a much more sophisticated way. We cover that in the module after next, but in the next module we look at what an X `session' is.

###### Figure A. xdm's login window.

### 11.1.2 Sessions and session management

A `session' is everything between when a user logs on and logs off the system - typically a continuous period of work by one user. You can tailor your startup configuration to set up your complete environment automatically, instead of having to start manually the applications you want, each time you begin an X session. If the terminal or workstation is public, a session by one user will often be followed by a session by another user. Only rudimentary session managers are currently available.

xdm's login window facility effectively defines the start of your X session, but what is the end of the session - how do you log off? In fact your session ends when your initial client terminates, that is, when the application that runs just after you have successfully logged in to xdm ends. Then all other applications are killed off, the server resets, and you get the xdm login window again to start the next session, either for you, or for some other user if the X station you are using is a `public' resource within your orgamzation.

If your initial client was an xterm, it means that when you close down that window (by typing logout or exit or ctl-D, or by using an option from an xterm menu) your session is ended. 1f it was a script, your session ends when the script program terminates (which is when the last program in the script exits). People usually configure their script so the last program is either an xterm as above, or else is the window manager: then, when they exit the window manager, the session ends. As most window managers provide a convenient way to end - usually a menu option - this gives you a neat way to finish off your session. The Motif window manager, mwm, asks for confirmation before exiting. (You really need this if exiting the window manager is going to end your session too, because then all running applications will be killed off forcefully and you won't get a chance to close them down gracefully.)

As we mentioned in Module 11.1, by specifying a script or command file as your initial client, you can have your standard environment set up for you automatically at the beginning of each session. A script typically sets any specific server features the user wants (Module 11.2), starts the usual applications the user wants (for example, our own script starts four xterms, a text editor, our own screen configuration program, and a clock), plus a window manager.

If written properly, a script lets the system manager provide a standard default environment for the site as a whole, but which individual users can refine for themselves if they want to and know how. Thus end users do not have to concern themselves with technicalities, but at the same time programmers have the freedom to set up the facilities they need without affecting anyone else. Figure A shows a very simple xdm script: if the user has a file .xsession in their home directory, it is taken to be the script to be executed. Otherwise, the default setups for the site are performed - load the user's defaults settings if the file .Xresources exists, run an xterm, and finally start the MIT window manager twm. Our own .xsession file (Figure B) illustrates how the starting position and size of applications can be specified with the -geometry flag.

#### Session managers

There are no session managers publicly available, but the ICCCM defines standards for what they should do - be able to start a collection of clients as a group, remember the current state of running clients so they can later be restarted in the same state, and be able to close down clients in a controlled way. In Module 8.4.1 we saw how window managers used WM_SAVE_YOURSELF message and WM_COMMAND property for some of these functions, and some of the more complex window managers and desktop managers provide part of the functionality we expect from a session manager. More capable session managers will be commonly available soon.

###### Figure A. xdm lets you customize your startup environment via a simple command script.

###### Figure B. Our own startup script for use with xdm.

### 11.1.3 XDMCP - the X Display Manager Control Protocol

XDMCP lets you connect X-terminals into a network and have them automatically managed by an xdm program running on a remote host. You don't need to maintain any special tables or configuration files for xdm or XDMCP, so managing large networks of X-terminals is made easier.

(If technical details aren't so relevant to you, you can skip over this module.)

The simple way that xdm handles displays on X-terminals and PC X servers, described in the pnevious module, has a big problem - xdm has to be configured so that it knows which terminals it is to manage. While that may not seem very important, for large networks especially it would be very much better if you could just connect your Xterminal into the network and let the terminal itself request an xdm service from some other machine without any pre-configuration. This is what XDMCP, the X Display Manager Protocol, does.

As before, you have to have one or more machines running xdm and prepared to provide service for terminals, but now these xdms listen on the network for XDMCP requests for server. Now when a terminal starts up and wants xdm service it goes through the process shown in detail in Figure A. Briefiy, what happens is:

1. The terminal broadcasts a request on its network, saying that it wants an xdm session. This request is in the format specified by XDMCP.
2. Any machine running xdm which is prepared to handle the terminal replies, saying it is willing.
3. The terminal decides which xdm-provider it wants, and replies to that provider (and only that one) saying it has been chosen.
4. The chosen provider replies saying that it accepts this. (The other providers do nothing.)
5. The terminal says that, yes, it really does want to be handled by this provider. (The seeming redundancy in these steps is necessary for reliable handshaking.)
6. The provider starts an xdm sub-process to manage the terminal, and display the login window. The main xdm just goes back to where it started, and waits for requests from other terminals.

The beauty of this is that the terminal and the xdm provider don't need any configuration to tell one about the other. You can just plug in an X-terminal onto your network, and with XDMCP you can be running an X session almost immediately. (You do of course have to set up the network configuration for the provider and the terminalensure that they have valid network addresses, etc.) Now connecting a new X-terminal into a network is easier than connecting a character terminal to a minicomputer. (Another benefit of having the terminal initiate the xdm session is that it removes the need for xdm to poll the terminals constantly, thus eliminating some wasteful network traffic and CPU activity.)

If more than one machine is prepared to provide xdm for the terminal, at step 3 above the terminal can use any mechanism it wishes, to decide which offer to accept. For terminals that don't have any special mechanism of their own, xdm can run the program choo5er to display a menu of hosts from which the user (rather than the terminal) picks which one to use.

While xdm and XDMCP are part of the standard MIT release, they are not part of the base X system - they are not part of the X Protocol. Rather, they are extras which make systems easier to use and administer. Changes like these - new facilities which improve real-life implementations of the system but don't involve any change to the Protocol - are typical of the differences between one release and another. (XDMCP was perhaps the most significant functional enhancement in Release 4.)

###### Figure A. How an xterminal requests xdm to start a session.

## 11.2 Customizing server settings

You can customize many aspects of the server - for example, the keyboard mapping, whether the keyboard keys auto-repeat, where fonts are to searched for, etc. The server is reset to its default settings at the end of each session, so you must re-invoke your customizations each time you start a session.

You can configure or customize many server parameters, to match your personal preferences, or to take account of any special configuration required by you or your site. The most significant settings are:

- Keyboard mappings. As we described in Module 4.2.2, each key on the keyboard has a unique keycode which identifies it, and the server has an internal table which maps these keycodes onto keysyms - symbols representing what is painted on the key top. The client uses the keysyms to interpret the key event as a character in whatever character-set it is using (ASCII, EBCDIC, or whatever).

  You can change the keysyms associated with a particular keycode and so remap your keyboard. (The MIT program xmodmap is an easy way to do this.) As you are changing this mapping within the server, the changes will affect all clients on your display. You can use this facility to customize function keys, or to redefine which keys are to be used as the modifiers (Ctrl, Alt, etc.) This is convenient when you use different machines with different keyboards: you can remap the keyboards so that they are all consistent, for example, changing the relative positions of the Shift, CapsLock and Ctrl keys on a PC to match those on a workstation. Another common requirement in Europe is to change the layout of the alphabetic keys on the left side of the keyboard to match the national convention.

- Keyboard parameters. The MIT program xSet lets you customize such characteristics as key click, and auto-repeat, as well as determining their current settings.
- Directories for storing fonts. Also with xset you can add to or change the list of directories in which fonts are stored for your server. You often use this to specify a directory of your own which contains fonts specific to you or your workgroup.
- Bug compatibility mode. Most implementations of X up to Release 3 ignored incorrect values in the unused bytes in some server requests. This was eorrected in Release 4, with the result that some earlier programs now fail. These can be made to work again by enabling this compatibility mode (which requires the extension MIT-SUNDRY-NONSTANDARD).
- Screen saver. To prevent your screen burning out when the same image is displayed for long periods, you ean enable the screen saver which either blanks out the screen or displays a moving pattern, after your server has been idle for a specified time (10 minutes by default).
- Root window settings. Using the program xsetroot you can change the background and foreground colours of your root window, and the shape of the cursor and its colour. You can also specify a bitmap to be used to pattern the window (Figure A) rather than having just a plain coloured ground.

Any changes of settings you make to your server persist only for the length of this session, that is, until the server is reset or restarted. So if you want these settings every time you use the display, you should incorporate in your startup script for xdm (or whatever startup system you use) the xset, xmodmap, etc. commands to make the changes. Examples of such settings were shown in Figure 11.1.2B.

Chapter 12 describes how you customize individual applications.

###### Figure A. Customized colours and pattern in the root window.

## 11.3 Administering fonts

X fonts are often supplied in a portable form which you then compile into the specific form required by your server. Font converters and editors may be useful when you are migrating from other systems. Correct definition of font search paths can give you display-resolution independence even with bitmap fonts.

Server vendors usually provide a large set of fonts for use with their server. Many of these are part of the MIT release of X and may be used freely, but some fonts are proprietary and you may have to license them for use on other machines. (For example, `Times' is a trademark of Linotype, and the Times-Roman font in the MIT distribution is copyrighted by Adobe.) You can also obtain fonts from many public-domain sources, or buy them from font developers (or `foundries', as they call themselves).

Fonts are normally provided neady for use with your server. They may also be distributed in a portable, plain-text, format called BDF (Bitmap Distribution Format) which you then have to convert into the format your server needs, using a font-compiler provided with your server. (All the fonts in the MIT Release are supplied in BDF.) In Release 5, the server's internal format is PCF (Portable Compiled Format): this stores the font information in an efficient internal form, but it is portable across all servers from Release 5 onwards. In Release 4 and earlier, the internal format was SNF (Server Natural Format); while the specification did allow this to be platform-specific, in practice it was often portable across platforms which had the same byte-ordering; however BDF was the only guaranteed portable form.

Many conversion utilities are available (especially in the MIT user-contributed software release) to convert vendor-specific font formats to BDF, so you can continue to use fonts that you have on another window system. There are also font editors if you need to create or modify fonts.

As we described in Module 3.5, X uses XLFD (X Logical Font Description) for naming fonts, and this includes a lot of information about the font in the name. A full XLFD name for a Times Bold font is shown in Figure A. X applications can get a `directory listing' of fonts (of all fonts, or those matching a specified name which may contain wildcard characters), and so obtain a list of fonts matching a desired set of eriteria. For example, instead of specifying one explicit font in an application, the programmer can give a wildcard specification:

       -*-*-bold-*-*-*-*-240-*-*-*-*-*-*

to select a bold font, at 24 point size. (The size is expressed in tenths of points, 240 here, to make it easy to specify decimals of point-sizes.)

Using wildcard specifications like this makes the application independent of specific fonts to some extent. (The alternative would be for the application to check that the font requested is available, and if it isn't, use some fallback or default font). Programmers and system administrators need to be careful when specifying fonts because there is no standard set of X fonts - you cannot assume that a particular font will be available, or even if it is, that it will be available at the point-size you want. However, the introduction in Release 5 of scalable fonts will make this less of a problem in the future.

Because fonts are stored as bitmaps, they are not resolution independent: a specific ` 10-point' font will show up three times bigger on a 40 d.p.i. scneen than on a 120 d.p.i. (the characters are drawn with the same number of pixels on each screen, but on the 40 d.p.i. screen the pixels are three times bigger). To overcome this problem, X stores its fonts on the server in different `directories', with fonts intended for use at a particular resolution stored in a directory of their own. So, we might have two directories, called dpi40 and 120dots, say, each containing fonts that are very similar, but designed for use at the particular resolution. The fonts' names will be very similar too: the only components of the names that will differ are those indicating the resolution the font was designed for. We can tell the server to search the directories in a particular order when it is looking for a font. If we specify the search order correctly, and use suitably wildcarded names to specify fonts, being careful to omit the resolution-related parts of the XLFD-name, we can get resolution independence. Using the example above, and assuming we told the server to look in dpi40 first, if there is a bold font there with a point-size of 24 (that is, 24 point when printed on a 40dpi screen) then the server will use that font. Only if there is no suitable font there will the server continue by looking in the other directories.

###### Figure A. The full XLFD name for a Times Bold font.

## 11.4 Security

Typical X systems provide rudimentary facilities for securing displays against unauthorized connections, and for securing connections against tampering. More sophisticated and secure systems are now becoming available.

X doesn't provide any protection on a per-window basis: if an application is connected to a display it can access any window (or other server resource) on that display. As we described in Module 8.4, the window manager depends on this to be able to manage the windows of all your applications. The disadvantage is that anyone connected to your display can (without your knowledge) capture images of any of your windows, or change their contents, and if your application accepts send-events, someone else can effectively type directly into your application (Module 9.3.1).

To provide some protection, X does let you control whether or not a request to open a connection onto your server is to be allowed, that is, if an application run by a particular user from some machine is allowed to use your display. The X Protocol doesn't specify which authorization scheme should be used, but it lets you use anything suitable that is supported by your server and applications.

Currently, most systems only provide a basic protection system - you specify which remote hosts you `trust', and connections are allowed only from those hosts. It doesn't matter who the user is - access is decided exclusively on the host name (or network address). By default, your own host is included in the trusted list. Using the MIT program xhoSt you can modify the list of trusted hosts interactively. But even allowing `my host only' isn't secure unless my host is properly secured in other ways. For example, prohibiting X applications on other machines connecting to my display won't help much if people can telnet or rlogin or rsh to my machine and run X applications from there.

The Protocol does have hooks (provision in the code for adding extra facilities) for including more sophisticated authorization mechanisms. The MIT sample server implements three other access control systems that allow connections to be controlled on the basis of the user who is connecting, not just the machine the application is running on:

1. MIT-MAGIC-COOKIE-1: MIT's own system. As this is a representative facility, we discuss it in more detail later.
2. XDM-AUTHORIZATION-1: a DES-based authorization system, similar to MIT-MAGIC-COOKIE-1. However, it uses DES to encrypt the authorization keys (passwords) so that they are never sent `in clear' over the network. This gives extra security where network snoopers could be monitoring the network traffic looking for passwords, etc.
3. SUN-DES-1: this is based on a public-key secure remote procedure call system available with Sun's operating system.

Another increasingly common security system is Kerberos authentication, which we describe in Module 11.4.2.

What we are discussing here is how to prevent other unauthorized people connecting to your server. If you succeed in doing this, then the threat of intruders capturing images of your windows or changing their contents, or of using send-events to interfere with the input to your application (Module 9.3.1) is removed, because these actions can only be performed by a client connected to your server.

As an aside, commercial vendors are now providing X servers that meet military security requirements.

In the next module we describe the Magic Cookie scheme in a little more detail.

### 11.4.1 The Magic Cookie authorization scheme

The MIT Magic Cookie system restricts connections to your server by insisting that applications requesting a connection present a secret password-like token to the server. This token is stored in a file that only you - and therefore the applications you are running - are allowed access. Thus the scheme is using the file-system security mechanisms to secure your X server.

The Magic Cookie scheme (Figure A) is simple. The user who starts up the server is trusted, because it is `their' server. xdm puts a randomly-generated key (the magic cookie) into a file (.Xauthority) which xdm makes accessible only to this trusted user, by setting the file's access permissions appropriately. Later, when this user starts a program connecting to this server, the XOpenDisplay function provided by Xlib reads the key from the file, and includes it in its request to the server to be allowed connect. If the key sent by the client matches the one the server started off with, the connection is allowed, as it will be in the case we've just described. Otherwise, the server reverts to the host-based system described in the previous module, and uses that to decide whether to allow the connection or not. If another user's application tries to read the key from your file, it will not succeed because xdm has set the file permissions so as not to allow access.

If an application on another machine needs to connect to this server, then either the user on that machine must have access to your .Xauthority file via NFS or similar network file system, or else the user (which we hope really is you) has to explicitly copy the authorization information to that machine. (The MIT program xauth lets you edit and manage authorization files for this purpose.)

Essentially Magic Cookie is based on the security of your file system: if someone else can read your .Xauthority file, then they can steal your cookie and gain access to your server. However, this scheme provides a simple and usable security system, especially where snoopers can't get at the network easily. It is widely available because it is included in the MIT Release, and unlike DES, there are no export restrictions placed on it by the US Government. Even though MIT provide it, it is not an X Consortium standard.

###### Figure A. Schematic of the MIT-MAGIC-COOKIE authorization scheme.

### 11.4.2 The Kerberos authentication system

Kerberos securely identifies a user who is requesting the use of some service, that is, it `authenticates' the user's identity. Kerberos can be used merely to control initial connection to a server, or if necessary to authenticate each request and message passed between client and server. It issues `tickets' to the client, to allow use of a particular server. Kerberos authentication is secure even on a non-secure network.

The Kerberos security system was developed at MIT as part of Project Athena. It is becoming popular for managing the security of large networks with large numbers of machines. It is not included in the MIT release, but commereial vendors are now starting to supply it as part of their systems. It is a general authentication system, and isn't limited just to X systems. (It gets its name from Kerberos or Cerberus, a three-headed dog who guarded the entrance to Underworld in Greek mythology.)

The function of Kerberos is to identify a user who is asking to use some service, that is, to authenticate the user's identity. In `the old days', knowing which workstation a program was running on was a fairly reliable way of identifying its user, because workstations were a limited resource and available only to a restricted (supposedly responsible) group of people. As networks get larger and more difficult to control, and as access to workstations gets easier, you can't rely on a workstation's identity as proving its user's identity any more. (For example, in a UNIX environment, if the user on a remote workstation is called rOOt, who is really out there?)

As shown in Figure A, Kerberos is a `third party' authentication system: there is a Kerberos authentication server which is used both by the provider of a service (in this case the X server), and the user of that service (an X application). The details of how Kerberos authenticates a connection are long-winded: we describe them fully in the next module, but here you just need to appreciate the main features.

Like many operating system security systems, Kerberos relies completely on secret passwords as being the only way for someone to prove they are who they say they are. If the person at the other end claims to be `Mary' and uses Mary's secret password, Kerberos believes the person really is Mary. (So as usual, users must ensure nobody else learns their password.) Kerberos also relies on the security of the Kerberos server and other authentication servers that may be required. However, it does not rely on the security of the client or requesting machine. Kerberos doesn't rely on the network being secure either, because it takes appropriate precautions:

- Passwords are never sent over the network in an unencrypted form, so network snoopers can't steal passwords easily.
- The messages Kerberos uses include time-stamps so that snoopers can't just capture all the Kerberos messages, and `replay' them later: the time-stamps will show that these are old messages, and Kerberos will not accept them.
- When you ask to use a particular service, such as an X server, a file-server or whatever, Kerberos gives you a ticket. A Kerberos ticket is just like a real-life ticket for a train or an aeroplane - it is only valid for the service for which it was issued (you can't travel on an aeroplane using a train ticket), you have to send it to the right place to get the service you want, and it has your name on it and can't be used by anyone else. But unlike a travel ticket, a Kerberos ticket doesn't give you permission to use the service: it merely proves you are who you say you are. When you want to connect to the service you need, you send your ticket to the service with your request to connect, and now that it knows who you really are, the service decides whether to allow you or not.

Our discussion of Kerberos here and in the next modules deals with authenticating only the initial connection to the service. Kerberos can be extended so that each message between client and service is authenticated, and in turn this can be enhanced so that the message is not only authenticated (that is, that the server knows the message came from the particular client or user) but encrypted also (so that nobody else can see the contents of the message).

In the next module we look at the basic ideas behind Kerberos, and in the module after that we describe its operation in detail.

###### Figure A. Kerberos is separate from both the user and the server used

### 11.4.3 Basic principles of Kerberos

Kerberos uses double encryption to preserve security. Messages between the Kerberos server and the client are encrypted with a key or password known only to Kerberos and the user; messages between client and the requested service are protected by encrypting with a key known only to that server and to Kerberos. `Tickets' are issued to prove the identity of the client.

(If technical details aren 't so relevant to you, you can skip over this module.)

This module introduces the basic ideas used in Kerberos; the full procedure is described in the next module.

The basic principle of Kerberos is that you and Kerberos both know a secret key (password) which identifies you; if you can give the correct password for your username when you are asked, Kerberos believes you are that user. In addition, Kerberos and the service you want to use both know (share) a different password, so the service also can prove its identity to Kerberos.

Let's say your name is `Mary'. When someone signs onto the system and enters their user-name as Mary, the login program sends a message to Kerberos containing the name `Mary' and the name of a service this program wants to use. So far, no password has been entered.

When Kerberos receives the message from the user, it builds but doesn't yet send a reply authenticating you (that is, proving that you are who you say you are - Mary). Kerberos then doubly-encrypts this reply, first using the service's key, and secondly using your password, and sends it back to the login program.

The login program asks the user for their password. If the user really is you, you enter your (Mary's) password, and you can decrypt the reply from Kerberos. If the user is somebody else pretending to be Mary, they don't know Mary's password, thus they cannot decrypt the reply or get at the authenticating information, so they cannot proceed any further.

At this point, you (or in fact your login program) has a piece of information that proves you are Mary; we'll call this information your initial ticket. Later on, you, or rather the applications you ane using, will present your initial ticket to the service you want to use, to prove you are who you say you are. You can present it many times, as you may want to use the service more than once. From the ticket, the service knows that you are who you say you are, and can decide whether to allow you access to the service or not. The whole process is outlined in Figure A; however, the picture isn't complete, because there are complications, which we describe in the next module.

###### Figure A. Simplistic view of obtaining and using a Kerberos ticket.

### 11.4.4 Kerberos in detail

Kerberos uses 'authenticators' to prove that the ticket was presented to the service by the person it was issued to, and wasn't stolen by someone else. So you don't have to enter your password each time you request a service, Kerberos uses a `Ticket Granting Service'.

(If technical details aren 't so relevant to you, you can skip over this module.)

There is a problem in what we have done so far: as you send your ticket over the network, someone else may snoop and take a copy of the ticket, and then present it themselves to the service, pretending to be you. To avoid this problem, Kerberos is slightly more complicated than we outlined earlier; as well as possessing the ticket, you must also have some way of proving that you are the person it was given to in the first place. Kerberos uses authenticators for this.

When building the reply to the login program, Kerberos generates a random session key which will later allow you to communicate securely with the service you want. Kerberos includes this session key in the initial ticket itself, and also in the overall message, which is encrypted with your password and sent to you (Figure A). So when you decrypt the reply from Kerberos you have a copy of this session key as well as the initial ticket. Now when you request a service, you build an authenticator consisting of your user-name (Mary) and your machine's network address. (Other information is included too.[Footnote:Timestamps are used so that if a network suooper copies your messages and tries to replay them later this can be detected. However, for simplicity we'll forget about these details.] the initial ticket to the service you are requesting.

When the service receives your request (Figure B) it decrypts the initial ticket using its own password, because that is what Kerberos encrypted it with originally. Now the service has the information proving who you are, but it also has a copy of the session key that was included in the iniaal ticket. It now uses the session key to decrypt the authenticator your program sent, and checks the information in the authenticator: is the user-name the same as in the ticket? Is the network address actually the one we received the request from? If so, the service is happy that the sender of the ticket is the person to whom it was given in the first place, because only that person ever had access to the randomly generated session key, which was never transmitted `in clear' (unencrypted) over the network.

#### Using Kerberos to access an X server

If Kerberos used only the mechanism outlined above, the user would have to enter the password each time a service was requested, because the ticket obtained is valid only for a single service. This would be very tedious, so Kerberos uses another phase in the whole process. Your initial ticket gives you access not to an X server, or file-server or whatever, but to a Kerberos Ticket Granting Service or TGS. As before, you have had to enter your password.

Now, you ask the TGS and not Kerberos itself to give you further tickets to use specific facilities such as X servers, etc. These tickets are just the same in form as the initial ticket, but the key used for the internal encryption is one shared only by the TGS and the requested service. This full sequence is illustrated in Figure C.

###### Figure A. A Kerberos ticket contains the sessionkey, both singly- and doubly-encrypted.

###### Figure B. How a service processes a ticket and authenticator.

###### Figure C. The full sequence of accessing an X server.

## 11.5 A summary of X system administration

This module outlines all the aspects of system administration required for X systems.

Depending on your system (for example, if you have only workstations and no Xterminals) some of the tasks listed below will not be necessary, and many others will be performed automatically when you install a complete X `package' supplied by a vendor. Even so, this list should give you a clearer picture of what is happening at a detailed level.

#### Resource/capacity planning

1. Provide adequate CPU power on your hosts to run applications for Xterminal users.
2. Ensure there is enough disk space for fonts and for the applications you will be using.
3. Make sure hosts running applications have adequate swap or paging space, because X applications are relatively large.
4. Ensure that your hosts have enough memory to run all the applications expected of them, without having to swap excessively. (See the next chapter.)

####

Installing the server

1. Install the X-terminal hardware.

2. Configure the X-terminal for your network. Allocate its network address, and if necessary tell it from which machines it will download any files (such as fonts) or programs (for example, the X server), and how it will access them (for example, via explicit file transfer, or using NFS).

   Ensure that any necessary network services software is available to service remote terminals and hosts, and is configured. (For example, rarpd and others are necessary for booting many X-terminals, and will require configuration information in the /etc/ethers file; file transfer requires a tftpd or an ftpd daemon.)

3. Install the server software on workstations running X. If you are upgrading to a later release, keep your earlier version accessible for some time, in case you run into problems with applications and need to check whether they are due to the change of server.

4. Ensure the keyboard mappings are correct for your hardware.

5. Install your fonts. Make sure they are accessible to any other machines that need them, probably using NFS. Compile any special fonts you require. Remember, fonts are used by the server, not the client, and each different type of X-terminal you use will probably need its own specific fonts. Configure your font server(s) if you are using them.

####

Installing the client software

1. Install the standard clients on a machine accessible to any other workstations or X-terminals that will need to run the applications remotely.

2. Build any clients you require from the MIT contrib user-donated software release. Install them.

3. Install third-party and in-house developed applications.

4. Ensure all the window managers required by your users are available somewhere on your network and are accessible.

####

Application configuration

1. Install all the application-defaults files in the standard directories.

2. Modify any resources files necessary, for site-wide or per user customization.

####

Session management

1. Make sure one or more machines provides xdm (with XDMCP facilities for X-terminals) and starts xdm automatically at boot time.

2. Set up default scripts for xdm

####

Enabling and restricting access - UID administration

1. Configure system hosts.equiv files, or users'.rhoSts files, so that they can easily run applications on those remote machines they are allowed to use.
2. Configure your access control system (xhost, Kerberos, etc.).
3. Make sure that unauthorized users cannot get root or system privileges on any system, so that they cannot bypass any X access controls.
4. Set any environment variables necessary in users' .profile or .login file, in particular those specifying the location of resource files, and the PATH variable so they can access the X programs.
5. Ensure you have enough licences to let everyone have access to the applications they require. Ensure any networked licence management software is started automatically.

## Summary

In this chapter we have described the most important aspects of setting up an X system. We covered how a user starts up the system, and how by using xdm and XDMCP the system manager can easily control the startup to provide the environment necessary for the users. We saw how you can alter various server settings according to preference. We then looked at how fonts can be administered to provide some resolution independence, and we dealt with aspects of security in an X environment. Finally we summarized the steps necessary to manage a complete system.

In the next chapter we move on to the related topic of how individual applications can be customized.

# Chapter 12-

Customizing Applications

## Introduction

In the previous chapter we saw how you or your system manager can tailor your user environment to mateh your own requirements and preferences. In this chapter we look at the 'resources' mechanism provided by the basic X system, which allows initial and default values to be specified for parameters in an application. Afier that we describe how the X Toolkit builds on this foundation, and allows you to customize almost any aspect of a Toolkit program by using resources.

## 12.1 Customizing applications

X makes it easy to write applications that the user can customize by specifying the initial values for many aspects of the program. You can set colour preferences, positions of applications and items within applications, fonts, key mappings, etc. You can customize third-party applications as well as those developed in-house.

It is very easy to make X programs customizable by the user, using standard functions provided by the standard X library Xlib, and the X Toolkit. A great deal of the program's behaviour can be altered: changing simple visual characteristics such as the colours and fonts used is straightforward, and offered by almost every window system. However, X goes much further, and lets you specify different keyboard mappings for each window in the application, whether functions can be invoked from the keyboard or using the mouse, the placement of items in the user interface, the text on labels and buttons, which bitmaps are to be used for images, etc. You can (if the program is written appropriately) even customize non-X aspects - for example, the names of files, numeric values of any kind, chemical formulae, stock names and prices, and so on; the possibilities are literally endless. First, let us look at why it is useful to be able to customize an application (and some of the problems it creates, too), and then in the rest of the chapter we will look at the mechanisms X provides for doing this.

#### Why do we need to customize applications?

At the simplest level, people like to tailor applications to match their own preferences, especially regarding the visual characteristics such as colour, fonts used, and so on. [Footnote: An extreme example of this is one programmer we know who aways uses the most garish colours on his screen: the reason is that he wears sunglasses when programming, and his colours show up nicely though the glasses !] Beyond this simple matter of taste, there are many other reasons why we want applications to be customizable:

- Keyboard differences. Keyboards vary a lot from system to system and country to country. Users may need to customize an application to make it easier to use on their computer.
- Internationalization. Not everyone in the world lives in the USA or Europe. As we discussed in Module 5.3, the language used, and therefore the text displayed in messages and in the user interface components such as labels and buttons, must be modifiable, which in turn may require changes in the size and layout of the components.
- Customizable programs are easier to integrate with other applications. Visual characteristics and keyboard and mouse usage can be made consistent across all the applications used in an organization. This reduces the load on the application vendor's development and support staff: they don't have to anticipate everything anybody could possibly want - instead the users (or their system managers) have the flexibility to change the application as they require.
- Multiple copies of the same application need different settings. For example, if you need several xterm windows, you want different names for each window so you can distinguish between them when they are iconified. You also want them to start up automatically in particular positions with particular sizes (which is perhaps the most common customization required for any program). Occasionally it is helpful to colour code your windows, too, for quick identification.
- Physical disabilities of the user. People with a visual handicap may need to use very large fonts, which in turn may require layout changes. For colour-blind users, letting them choose their own colours is a good idea. Users with motor control disabilities may find it very difficult to use the mouse and prefer to invoke functions using the keyboard instead.
- Applications are used in different circumstances. In a demonstration environment, people will need to use (very) large fonts. In a proeess control environment, certain colours may be reserved (such as red for danger, orange for warning) and if you have used these colours for aesthetic purposes, the program must be changed. If your application is being used in an astronomy observatory at night, the users will probably want to change the colours used to dark ones and especially reds, so the dark-adaptation of their eyes isn't much affected. You just don't know who will want to use your software, or where.

However, making programs very customizable can cause its own problems. First is the question of documentation: how do you document a program if the user has changed it? And even more difficult, how do you provide on-line context-sensitive help? (There's no easy answer to this, though we may eventually see programs which are self-documenting by means of adaptive help systems, which provide information based on the current configuration, examined dynamically, rather than just printing fixed help messages stored in a file.) The second difficulty is that the user may customize the program incorrectly, but then blame the developer for incorrect operation. Examples are changing colours so that the application is writing white characters on a white background (not noted for its readability), specifying keys for use within the application which have already been reserved by the toolkit or the window manager being used, or changing the position of items so they are off-screen or hidden behind others. A partial solution is to structure the way customization is done within the program so that items are grouped and are automatically altered together: for example, preventing ill-considered positioning of single items in a menu.

In the next module we look at the basic mechanisms Xlib provides for customizing programs, and later we'll see how the Toolkit develops that into a very flexible and powerful customization facility.

## 12.2 The Resources mechanism for customizing applications

Xlib provides the `resources' for specifying parameter values in an application. Resource values are specified in text files or in properties, are read in by the application when it starts running, and are stored in a table within the program. The program can retrieve values from this table when it requires them.

X uses the concept of a resource for customizing applications. (Resources in this sense are default values or parameter settings, and have nothing to do with server resources; unfortunately, X uses the same word for both.) At its simplest, a resource is just an item which has a name and a value, and you can retrieve the value associated with a given name. When the program starts up, values are loaded in from various resources files (or defaults files as they are also known) and are stored in a table held in memory within the application. This table of names and values is often called the application's Resource Database. When the program requires a value, it queries the database for a resource of a particular name, and the value is returned if found. The returned value is just a text string at this level of operation, and the application must then process this text and convert it to the appropriate internal form.

Resources are implemented by Xlib. The set of functions within Xlib which handle resources and manage the Resource Database are often called the Resource Manager. In Module 12.3 we'll see how the Toolkit adds extra functionality to this.

#### Resource names

A resource name can be viewed as consisting of two main parts, the first specifying an `object' and the second specifying some attribute of that object, such as its foreground colour, its width, or the text string displayed within it. In practice, the object to which a resource specification refers is typically a user interface component or widget. For example, in xterm, the terminal emulator window is called:

       xtexm.vt100

The attribute of the resource is appended to the object name; thus the full resource name for the foreground colour of this window is:

       xterm.vt100.foreground

which is the name you use in a resources or defaults file. To make a full resource specification you append a colon and the value required. So to specify green as the foreground colour, use:

       xterm.vt100.foreground: green

When xterm starts, this line is read by the Resource Manager, and stored in the Resource Database. If the application queries for the foreground attribute of the drawing window (by specifying the full resource name exactly as above), the value green will be returned as a text string containing five characters; the application can then manipulate this as required - for example, converting it to an internal representation of the colour.

The resource database mechanisms are part of Xlib, but to use them the Xlib programmer must explicitly call the Resource Manager functions and write the code to make use of the returned values. If this isn't done, the program will not be customizable via

resources.

Here we have described the simple use of resources. In fact the resources mechanism is very sophisticated, and in the next module we look at resource naming in more detail, and see how resources are applied to widgets in a Toolkit application.

#### Where and when resources are specified

When each application starts, the Resource Manager within that application loads its Resource Database by reading in resource specifications from several places. These include files specific to the application, files specific to the host the application is running on, and to the user running it, and from the RESOURCE_MANAGER property on the root window of the display the application is using. The user can also specify particular files to be used, and specific directories to be searched for resources files with the environment variables XAPPLRESDIR, XFILESEARCHPATH and XUSERFILESEARCHPATH. In this way very precise tailoring of resources is possible, taking account of which operating system the application is running on, and the capabilities of the server - whether it supports colour, what its resolution is, etc. The MIT program xrdb is very useful for conditionalizing settings like this. Again because resource settings are loaded from many places, it is easy to set up site-wide default settings for the system as a whole and/or for particular applications, and then let individual users selectively override them according to their own personal preferences.

Figure A shows a defaults file with several resource specifications. (The meaning of these should be fairly clear, but the next module explains the precise format used.)

###### Figure A. A defaults tile containing several simple resource specifications

### 12.2.1 How resources are named

Resource names are hierarchical, consisting of one or more sub-names. The X Toolkit also uses a hierarchical naming scheme for widgets, and so it is easy to link resource names to widget names. In turn this allows values for attributes to be specified on a per-widget basis, so it is possible to customize almost anything in a Toolkit program.

(If technical details aren't so relevant to you, you can skip over this module.)

The naming scheme for resources has evolved to meet the requirements of toolkits, by allowing a single object to have many different attributes. For example, the vt100 widget in xterm has several attributes specifying the various colours it is to use, and their full resource names are:

       xterm.vt100.foreground
       xterm.vt100.background
       xterm.vt100.cursorColor
       xterm.vt100.pointerColor
       xterm.vt100.pointerColorBackground

This fits in well with the idea of widgets: a widget is an object, and it has many characteristics or attributes governing its appearance and behaviour.

The full name of an `object' from the point of view of the Resource Manager actually consists of one or more sub-names concatenated together and separated by a dot. Xlib attaches no meaning to the sub-names, [Footnote: Even the attribute is itself just another sub-name; as far as the Resource Manager is concerned it is not special. However, we have given it a special name, not only to make the explanation simpler, but also to follow the X Toolkit's terminology.] the requirements of the Toolkit, because concatenated names easily lend themselves to hierarchical, tree-structured, naming. The Toolkit defines the full name of a widget to be the widget's own specific or sub-name, preceded by the full name of its parent. (So widget names reflect the tree structure of the application's widget hierarchy, which we described in Module 7.2.) Using the Toolkit's widget full names gives us a simple way of providing unique object names to the Resource Manager for resources. Let's use the MIT text editor, xedit, as an example.

Figure A shows a typical xedit window, which you can see is made up of many components that are in fact widgets. Figure B shows the widget tree. The xedit is the application's top-level window; its full name is xedit. Its only child is the widget called paned, which is a composite widget managing the overall layout; its full name is:

        xedit.paned

This is turn has children, one of which is buttonS, itself a manager, with full name:

        xedit.paned.buttons

This manages three button widgets and one text widget. The full name of the Save button is:

        xedit.paned.buttons.save

and to specify red for the background attribute of this button we say:

        xedit.paned.buttons.save.background: red

Thus, the basic Xlib hierarchical resource naming scheme allows us to use concatenated sub-names to specify a Toolkit widget precisely and, by appending an attribute name, to specify one out of the many possible attributes for that particular widget.

###### Figure A. The xedit text editor's window.

###### Figure B. xedit's widget tree.

### 12.2.2 Wildcards and class names in resources

Resource specifications can contain `wildcards' and widget and attribute class names, so many values can be set at once. If many different resource specifications apply to one attribute of an object, precedence rules determine which single specification is actually used.

(If technical details aren't so relevant to you, you can skip over this module. )

When you specify values in resources files the name of the resource does not have to be specified exactly - the Resource Manager lets you use wildcards. To specify that red is to be the foreground colour and black the background throughout the application, you can use the specifications:

       xedit*background: black
       xedit*foreground: red

where the `*' is the wildcard, taking the place of zero or more sub-names. Thus the effect of the second line in the example above is to specify red as the value for each of:

       xedit.foreground:
       xedit.paned.foreground:
       xedit.paned.buttons.foreground
       xedit.paned.buttons.save.foreground

as well as all the foreground for all other widgets in the application. (Below we see how such broad specifications are kept manageable, through resource precedence rules.)

#### Using class-names in resource specifications

You can also specify objects andlor attributes by their class names instead of their own specific names, which is effectively a more specific form of wildcarding. Thus, to specify that all menu buttons are to have a yellow foreground, without affeeting the foreground settings of any other objects, use:

       xedit*Command.foreground: yellow

(This is an Athena application: Command is the class name for Athena pushbuttons.)

Even the application or program can be specified by class name rather than its own specific name. There are no rules on how application class names should be formed --- they are merely hard-coded into the application, although often the class name consists of the application name with the first one or two letters capitalized. For example, xedit's class name is Xedit, xclock's is XClock, and xfontsel's is XFontsel. (You can see what the name actually is by running xprop on the application's window and looking at the WM_CLASS property.) Application class names are useful because you may run several copies of a particular application, each with a different application name, set with the command-line flag -name. You can set resources for all these applications as a group using the application class name, and set resources specific to an instance using its particular application name:

       XTerm*cursorColor: DeepSkyBlue
       console*cursorColor: red

#### How conflicting resource specifications are resolved

What we are doing is giving the Resource Manager more or less imprecise keys on which to retrieve a single value from the Resource Database each time it performs a query. Often, more than one of the specifications you have entered can apply to a single object; for example, each of the last two or three examples above specify a foreground colour for the Save button in our application. When the application queries the Resource Database for the value for this resource, what will be returned, red or yellow? The Resource Manager returns only a single value ever --- the specification that is the most specific match to the object queried for. Above, red applies to everything in the application, but yellow is specific to buttons, so the value returned in this case will be yellow. (There are many other rules for deciding which one value of many is to apply, but we omit the details here.)

Combining hierarchical naming with wildcarding, and using class-names in resource specifications, gives you great flexibility and power in specifying resource values. For example, the three specifications:

       xedit*Command.foreground: orange
       xedit*search*foreground: blue
       xedit*foreground: pink

set the default foreground colour for everything in the xedit program to pink; however, all pushbuttons will be orange, except those that are descended from the search widget (which is a pop-up dialog) - this widget and all its descendants including pushbuttons will have a blue foreground. (For reasons we won't go into, the second resource specification above takes precedence over the first and third; but the order in which the specifications are listed in the file doesn't matter.)

A resource specification is really a pattern, and the Resource Manager will use it and the value it specifies only if it matches the full name of the object and attribute for which a value is being queried. If a sub-name or attribute in the specification is misspelled, it will be ignored, because when the Resource Manager looks at it, it won't match what is being looked for. And, because the Resource Manager attaches no meaning to names or sub-names, it can never detect such misspellings, so errors like this can be very difficult to find. Of course, if you misspell a value for a resource, the Toolkit may not recognize it when it tries to convert it, and will give you an error message:

       venus% xclock -fg geern
       Warning: Color name "geern" is not defined

## 12.3 How the Toolkit uses resources

The Toolkit uses resources for all values relating to widgets, giving you the ability to customize without having to write any code yourself. The Toolkit adds a lot of extra functionality to resources, and defines the semantics of many resource types, including common data-types such as strings and numerics, but also many X-specific types such as colours, geometry specifications, colormaps, etc.

The resource mechanisms we have considered so far are those provided by Xlib. Xlib doesn't have a pre-defined set of resource types, or any view of what they relate to: values are retumed as text strings and the programmer can do what she wants with them. However, the Intrinsics uses resources for all values relating to widgets in the Toolkit, and it adds a lot of extra meaning to resources. It defines how values represented as text strings (ASCII characters in a defaults file) are to be converted to the internal type needed, as well as providing functions called resource converters for performing these conversions. Each widget class defines the types of values each of its resources needs (or can accept).

Let's take an example. If the foreground colour is specified as red, then the value retumed by the Resource Manager to the Toolkit will consist of a three-character ASCII string containing r, e, and d. The Toolkit must then look up this string in the colour database, to find what RGB value it represents, and then convert this to the intemal pixel value used by the server. A simpler example is how Boolean (on/off or true/false) values are handled: the two-character string On and the three-character string Off have to be recognized (and others rejected) and then converted to their internal values (probably one and zero respectively).

The Toolkit contains converter functions for almost every type of X-related data needed in an applications program, so you can specify a value in a resources file for almost anything you require. Resource types defined include numeric values (for sizes, positions, etc.), string values (for labels and buttons), font names, and of course colours and Boolean values which we have already mentioned. There are other more complex types that are used intemally, such as pixmaps, geometry specifications, callback functions, and colormaps. And in the next module we look in detail at another type of resource, the translation table.

Because the X Toolkit uses resources intemally for all widget values, Toolkit programs are automatically customizable: the programmer doesn't have to write any code for the customizability to be included. As a result, you can customize third-party Toolkit applications and those you develop in-house, in exactly the same way. The only limitation is that values which are hard-coded into the program cannot be overridden; developers should bear this in mind, and wherever possible place even basic values required by the program in a resources file. To make this easier, the Toolkit uses the concept of the application-defaults file. This file is stored in a system-wide standard directory, derives its name from the application it relates to, and is read by the Resource Manager only when that application is run. Thus it can contain settings exclusive to that application. When taken to its full extent, the `app-defaults' file can contain all the application's parameters, so that it really is an integral part of the application, and should be shipped with the binary (executable) program. The advantage of separating parameters out into a separate text file is that the application is now highly customizable, and major changes such as localization for use in another country are possible, without the involvement of the developer and without having to ship source code.

Another good reason for keeping values in a file rather than hard-coding them into the program, is that you reduce your coding work very considerably. Data checking and conversions are being done by the Toolkit converters instead of by code which you would otherwise have had to write yourself. For instance, in the `red foreground' example above, you would not have had to include any colour-handling code for it to work correctly. Moreover, as new facilities are added to later releases of the Toolkit as device-independent colour specifications were in Release 5, your application will be able to make use of them without requiring any programming changes.

#### Customizing applications from the command-line

The X Toolkit provides command-line options or flags for setting commonly altered resource values, which is another form of customization. For example, the flags -fg, -bg, -fn and -ic specify the foreground and background colours, the font to be used, and that the application should be iconified immediately it starts up. This makes it easy to start several instances of the same program with distinctive visual characteristics, in the configuration you want, as in:

       xterm -fg yellow -fn '*-courier-bold-*-18-*' -bg gray
       xterm -bg black -fg white -ic

Internally, the operation of these flags is simple. Using conversion tables provided by the programmer, the Toolkit merely textually converts the strings on the command-line into full resource specifications which are then processed as normal. For example, the flags:

       -fg white
       -ic

are transformed by xterm into:

       xterm*foreground: white
       xterm.iconic : On

(Notice that the application name is included in the expansion, and the delimiter for iconic is a dot, not a star, so there is no wildcarding --- the iconic resource is being set only for the main xterm application window, not for each widget within it.)

The Toolkit provides specific flags only for setting resources which the user will often want to change from one instance of the program to the next. However, you can include any resource specification on the command-line by quoting it and prefixing with the -xrm flag (for `X Resource Manager'), as in:

xcalc -xrm "*ti.button5.pointer Colour Background: RGB:00/aa/aa"

## 12.4 Translation tables resources and keyboard mapping

One of the most useful resource types is the `translation table' which lets you customize the bindings of your keyboard and mouse buttons on a per-window or per-application basis.

(If technical details aren't so relevant to you, you can skip over this module. )

A complex resource type that is used frequently is the translation table (or just translations) which provides application-specific or even window-specific keyboard mappings. In Module 7.4 we explained that callbacks are `high-level' or `logical' events, and that procedures written by the applications programmer can be invoked when these callbacks occur - for instance, on the `activation' of a pushbutton. Here we describe how real X events are mapped onto these logical occurrences.

What happens is that each widget has a translation table, which specifies that certain actions are to occur (more precisely that certain action procedures are to be executed) when particular sequences of X events occur in this widget. Using the Athena pushbutton as an example, the default operation is that the widget is set when the left mouse button is pressed, and it is activated when the mouse button is released again. (The button activates on release rather than press to make it easier to use. First, the 5et action inverts the button colours, so you get visual confirmation of which button you have pressed. Second, if you have pressed the button by mistake, you can avoid activating it, by moving the pointer out of the button before releasing; the button then just unsets and reverts to its normal colours, without ever activating.) The button's partial translation table is:

          Event sequence          Action(s)
          Left button pressed     Set()
          Left button released    notify() unset()

The notify action just calls the callbacks registered for activation (and some other minor functions which we diseuss in the next module). Using a table like this gives a level of indirection between X events and the actions executed by the widget as a result: by changing the table, we can invoke the same actions with different events, or invoke different actions with the same events. For example, we could use the keyboard to operate the pushbutton by changing the table to:

          Space-bar pressed      set() notify() unset()
          Return key pressed     set() notify() unset()

Thus translation tables let you tailor keyboard and mouse-button bindings (and even use other events, such as , , , etc.) to invoke functions within the application. By including the default bindings for the application in an application-defaults file, not only is the default clearly documented, but it is easily accessible to the system manager who might need to change it. Figure A shows a resource specification for a translation table for the manualPage widget in the MIT program xman.

In the next module we look at how translation tables and actions relate to callbacks.

###### Figure A. Specifying a translations table for the manualpage widget in the xman program.

### 12.4.1 Translation tables, actions, and callbacks

Translation tables specify that certain action procedures are to be called when a particular sequence of events occurs in a widget. Most action procedures are defined by the widget in which they are used, to implement the callbacks for that widget. Applications programmers can also write their own action procedures.

(If technical details aren 't so relevant to you, you can skip over this module.)

What is the relationship between actions (or action procedures) and callbacks? In the example from the previous module:

         Event sequence    Action(s)
         Space-bar pressed set() notify() unset()

when are the activation callbacks called, if ever? The answer is that the notify action procedure includes code to call any callbacks registered for activation. By contrast, the set action [Footnote: We are talking about the Athena pushbutton here. The equivalent action for the Motif pushbutton is arm, which does have callbacks associated with it, though they are rarely used in practice. Another difference is that a Motif button can be activated even if there hasn't been a prior arm action.] has no callbacks associated with it: the action merely changes internal state variables, to allow a subsequent notify to go ahead, and changes the appearance of the button so that it's clear that is has been set. (We referred to this briefly in Module 7.4.1.)

Figure A shows the relationship of X events, translation tables, actions, and callback functions. This shows that our schematic diagram in Module 7.4 was in fact a simplification and omitted the translations mechanism. The figure here also illustrates the point we made above, that some actions defined by the widgets themselves have related callbacks, whereas others have no relation to callbacks at all.

#### Where action procedures are defined

Action procedures are provided by the widget (precisely, the widget class) and can be used only within that type of widget. For example, you can't use an unset action in a translation table for a scrollbar widget, because unset is meaningful only for pushbuttons.

The applications programmer can also write action procedures of her own, and these can be used in translation tables just like a widget's own action procedures. Programmerdefined actions are crucial in allowing the user of the application to customize how certain tasks within the application are to be invoked, for two reasons:

1. These actions typically perform application-oriented tasks. For example, in an e-mail program, actions defined might include send-this-message, move-to-next-message, etc. By contrast, widget actions tend to be rather low-level, and concerned with the internal operation of the widget or the user interface. Figure B shows just some of the programmer-defined actions provided by xterm.
2. Programmer-defined actions can be included in the translation table for any widget, and therefore they can be invoked from any place in the user interface. For example in our e-mail program, forwarding a mail message to another person might normally be invoked from a menu; but by using translations, the user (or system manager) could specify that it could also be invoked by pressing key F7 in the main edit window, or by clicking the middle mouse button in the `read message' window.

###### Figure A. Relationship of translation tables, actions, and callbacks

###### Figure B. Some of the actions defined in xterm

## 12.5 Tools for customizing resources

Recent MIT releases of X include tools that simplify customizing an application. Some tools list which resources apply to the application, and their values. Another tool lets you interactively edit the resource settings for a running program: the tool's `point and click' interface makes resource editing fairly simple, and it lets you see immediately the effect your changes have had.

The MIT release contains several tools to help you customize programs. viewres shows graphically the tree of widget classes it knows about, and lets you display which resources (attributes) each class provides, as shown in Figure A. (By default viewres supports only the MIT Athena set, but it can be re-compiled to include others.) listres performs a similar function but prints out resource names rather than showing them graphically.

Two other MIT programs let you work with resources for a specific application. appres (`application resources') prints out the resource value settings that the Resource Manager would return for the components or widgets in the application you specify. The program editres (`edit resources') lets you interact with a running X Toolkit application, and dynamically edit resource settings on the application's widgets, so you can see exactly the effect they have (Figure B). You can save the modified resource settings for future use, too. editres is particularly useful when you need to set resources for a program where the widget hierarchy isn't listed clearly in the documentation, because the widget tree is shown so clearly. As with viewres, editres by default knows only about the Athena widget set, but can be re-compiled to support others.

###### Figure A. viewres window showing resources for subclasses of Command.

###### Figure B. The editres resource editor.

## Summary

In this chapter we introduced the basic resources mechanism provided by Xlib, and described how an application can use resources to retrieve values to use within that program. We saw how resources are named, and that objects and attributes in the program can be specified not just by name but also by class, and by using `wildcard' specifications as well. Then we looked at how the X Toolkit uses resources for all values relating to widget, thus letting you customize a large portion of a Toolkit program's interface. You get this customizability `for free' - it is a fundamental part of the Toolkit - so you can customize third-party applications as well as your own. We looked at a specific type of resource specification, the translation table, and how it relates to callbacks and widget actions, and we finished off with a brief description of some tools you can use to manage resource customization.

In the next chapter we move on from customization, and consider the performance of X systems.

# Chapter 13-

Performance Factors

## Introduction

In this chapter we examine the three main components of the X system - the server, the network and the client - to see what factors affect the performance perceived by the user. We also describe some of the measurement tools available, which can help you choose a server suited to your application mix, or perhaps tune your existing X system.

## 13.1 Server performance

The speed of X servers varies widely, and is very dependent on the hardware used. Memory usage in the server can be critical for satisfactory operation. Most servers offer standard facilities that can improve the performance of graphicsintensive applications.

The speed for a given X operation can vary by up to a factor of 100 between different servers. Some of the many aspects of the performance of a server are:

- The speed of the server's CPU. The faster the CPU the better, especially for operations that involve manipulating a lot of data in memory. (Operations mostly use integer arithmetic, so the floating point performance of the CPU isn't so important.)
- Server graphics hardware. Clearly, performance can be affected by any special graphics hardware used by the server. However, what is crucial is how much of its graphical manipulation and computation the server can delegate to the graphical hardware, instead of having to perform it explicitly itself in the main server CPU. For example, there is a wide range of graphics boards available for DOS PC X servers, but what appears to be a wonderfully fast board from its specifications will do you no good unless your server software can make use of the board's fast facilities, and has in fact been written to do so. X lays down strict standards for the results of graphics operations, and if the special graphics hardware doesn't match these specifications, the facilities it provides won't be much use to you. You should really try out any special hardware with the applications and servers you will actually be running before you invest heavily.
- Special optimizations for local operation. Applications running locally on the same machine as the server can improve performance by bypassing some or all of the standard Xlib code and going direct to the hardware. For example, Sun take this approach with the XGL software (Figure A). Simply, the system can bypass both the code needed to package requests in the standard format, and the code in the server which interprets and executes these requests. Instead, when the application is aware of the local hardware and its capabilities, it can take a short eut and communicate directly with the hardware to perform the operation. (This functionality is of course transparent to the applications programmer, and is hidden in the standard development libraries provided with the particular system.)

  Another example of local-execution optimization is the MIT-SHM shared memory extension described in Module 3.8.

- Platform-specific optimization. Many vendors start off using the MIT Release code as a base. (This is not surprising, considering that new releases come out relatively frequently.) However, to get the best performance from a particular machine, the developers should not just port the server but should optimize it and change it to take advantage of any special features that are available in the hardware or operating system. (Alas, not every server developer does this in practice.)

You should also note that servers are not uniformly fast over the whole range of X functions: a server may be fast in one area and slow in another. To find the best server for your purposes, you should consider benchmark tests (see Module 13.4). And in the next module we look at standard facilities that can greatly improve a server's effeetive performance.

#### Memory usage

X servers need memory for fonts, for pixmaps, bitmaps, windows, backing store (see next module), etc., and in Module 13.3 we'll see how a client can, at the expense of a good deal of server memory, improve its own performance.

The server's memory requirement is dynamic, and it is quite possible that at some point your server will run out of memory. (This is a major difference between Xterminals and normal ones - you can't imagine your VT220 terminal failing because of lack of memory!) What happens depends on your server. Some servers will just crash, others will give an error message and let you kill off clients to free memory or abandon the client that had requested the memory, so that at least your whole session isn't lost.

Many servers now use virtual memory, which more or less eliminates this problem in practice. Virtual memory is of course available on most multitasking workstations, but X-terminals are increasingly making use of it too.

X doesn't provide any way for an application to ask the server about memory availability or usage, but some servers do let the user get this information manually, for instance by pressing some special key sequence. You can use this information to get a profile of the memory requirements for the different applications you run, and so configure your X stations accordingly, to avoid memory problems.

###### Figure A. Some special applications can bypass the local server and access the hardware directly.

### 13.1.1 Standard server facilities: backing store and save-unders

`Backing store' and `save-unders' are two facilities that cause the server instead of the application to maintain the contents of windows which have been obscured. Backing store is typically used for large or complex graphics windows, whereas save-unders are used for transient windows such as pop-up menus and dialogs.

With Release 3, two new facilities were introduced to minimize the load of handling exposure events - backing store and save-unders. They both cause the server instead of the application to maintain the contents of windows which have been obscured, so the server can redraw the window when it is exposed, without imposing any load at all on the client. However, the two serve quite different purposes.

#### Backing store

When backing store is enabled on a window the server will maintain the contents of this window even when it is covered up (Figure A). When the window is exposed again, the server can redraw the window immediately and doesn't have to send an expose event to the client. Not having to redraw can save some clients a lot of computation and other resources.

Backing store can be quite consumptive. The server can easily require a megabyte or more to store an obscured full-screen window on a colour system. Moreover, the window may remain covered for a long time, so the memory is required for a long time. If there are many windows with backing store enabled, the server could run out of memory, so X allows the server either to refuse to enable backing store on a window when requested, or if it is enabled, to disable it dynamically at any time, forcing exposure events to occur as normal again. In fact a server does not have to implement backing store at all to comply with the X standard, but in practice virtually every server now provides it.

Backing store is enabled on a per-window basis. Typically in an application the programmer would enable backing store on the main working windows which involve a lot of graphics and take a long time to redraw. Other windows, sueh as the menus, labels, text widgets, etc., would not have backing store enabled: they don't take long to redraw, and enabling backing store would use up memory in the server.

#### Save-unders

When save-unders are enabled on a window, the server maintains the contents of any window which this window obscures - not the contents of this window itself. Saveunders are normally enabled on menus, pop-ups, and other short-lived items, to avoid causing potentially very expensive expose events on other windows. Save-unders generally require less memory than backing store, as the menus, etc., they are typically used for are fairly small. And because save-unders are usually used for transient windows, their requirement for memory is usually short-term.

When a window enables backing store, it is effectively saying `I am an important window and the server should maintain my contents'. By contrast, when a window enables save-unders, it is saying `I am unimportant, but I want to cause as little disruption as possible to other windows'. So save-unders are social-minded citizens, whereas backing storers are hogs.

###### Figure A. With backing-store, the server remembers the contents of covered sections of the window.

## 13.2 Network performance

Network bandwidth is not normally a performance bottleneck.

As we discussed in Module 4.5, there are two measures of the speed of a network - its bandwidth and its latency - and these affect performance in different ways. Latency relates to how long a round-trip on the network will take, and primarily affects response time, as we discuss in the next module.

The bandwidth of a network is a measure of capacity - how many bits per second you can transmit and receive. For example, the bandwidth of many serial lines is 9.6 kbits/s, and that of an Ethernet is 10 Megabits/s.

Because X is asynchronous, most of its traffic is one-way and not `round-trip'. As a result, X can make good use of the available bandwidth: for example, once a client has sent one request it can immediately send another without any delay, because it doesn't have to wait for a response. In turn, X's good utilization of bandwidth means that the network capacity needed is less than you might expect.

Studies show that on average an X-terminal uses about 1 % of an Ethernet when the terminal is active. As terminals are idle quite a lot of the time, it means the effective average requirement per terminal is a good deal less than 1%, so a typical network can handle many many X stations without overloading. (X-terminal vendors claim an Ethernet can support hundreds of X-terminals.)

These data tie in well with investigations of X over X.25 networks: it was found that for a typical application mix, an average bandwidth of about 20 kbit/s was adequate. There are of course transient requirements for much higher bandwidth, so this figure doesn't mean that a single user with a 19.2 kbit/s line would have perfect response. But it does suggest that ten users sharing a network with 200 kbit/s capacity would be OK, because of the statistical spread of their usage. Nonetheless X has been run over 9.6 kbit/s serial lines (usually by people at home connecting to their office) and performance is just about tolerable. Vendors and the X Consortium are working on developing a standard for using X over slow lines, using compression or other techniques (see Module 15.1 ).

Traffic patterns have been measured for different types of operation (Figure A), and show surprisingly low network loading, usually with a large number of small packets. Even window management, which for many users of office-automation type systems is the most demanding interactive activity they cany out, isn't very heavy. Resizing a window, which involves dragging with the mouse, gives lots of very small packets, and even rapid mouse motion still uses only 1 % of the Ethernet; however, resize can be jerky if the CPU or network is heavily loaded. (As we mentioned in Module 3.2.2, using a local window manager can get over this problem.) Some applications can impose high intermittent network loads. A typesening previewer, which is drawing whole pages at a time, generates big packets, and the utilization increases, up to about 10% of an Ethernet.

When applications start manipulating images, loading can increase a lot. The network packets are often of maximum size, and as we mentioned in Module 4.4, X becomes more network-efficient with larger packets. For example, when transferring the image of a window with the MIT program xwud, there are spikes of around 25% Ethernet utilization, as a lot of data is being transmitted. If an application is transferring a lot of images all the time, it can result in very bad performance and heavy loading of the network; applications like this are better run locally on a multitasking workstation, as described below. Higher bandwidth networks, such as FDDI with a bandwidth of around 100 Megabits/s, can improve the performance of data-intensive applications. However, for most X applications, where the traffic consists of many and small packets, these networks don't give as much a benefit as the numbers would suggest, as the networks are less efficient with small packet sizes.

#### Fast wide area networks

The bandwidth of wide area networks (WANs) is increasing dramatically, as bandwidthon-demand systems, ATM (Asynchronous Transfer Mode), frame relay, and SONET (Synchronous Optical Network) technologies are being widely developed and deployed. These networks are making bandwidths of 10, 100, or even 1000 Megabits/s fairly common. Moreover, ATM allows you to control, and if necessary minimize, the variability of transmission time of separate network packets; this is important to avoid a deterioration in interactive response. Experiments are being conducted on the use of ATM even for links to the desktop.

Availability of such networks will surely affect which applications can viably be run over long-haul WANs, or even on your LAN; systems will become very much more distributed.

In the next module we consider the performance implications of running applications remotely.

###### Figure A. Representative performance figures for intensive phases of typical X activities.

### 13.2.1 Performance of local versus remote clients

Running a client remotely may not degrade its performance, and sometimes may even improve it. However, some intensive applications benefit considerably from running locally. High network latency (as in a satellite link) can cause problems by increasing response times.

Surprisingly, running a client remotely over the network can often be faster than running it locally. There are several factors involved:

- Running remotely, there are two CPUs working in parallel, one generating the graphics, and the other drawing them on the screen, rather than a single CPU doing everything.
- On many servers the graphics hardware's performance is a bottleneck; by running the client elsewhere the server CPU can be dedicated to keeping the graphics hardware fully utilized. And if graphics hardware is limiting the throughput, any delay caused by using the network isn't likely to be very significant.
- With local execution on a workstation, not only are the server and client competing for the CPU, but also they may cause swapping or paging (as X servers and clients are often quite large in memory), and other non-X applications may also be contending for machine resources.

However, to avoid network congestion and slow performance, certain data-intensive applications need to be run locally on the same CPU as the server, that is, in a workstation environment. This is especially the case for applications dealing with images, as they are transfemng each individual pixel between client and server. As an example, an image on an 8-bit colour system requires one byte per pixel, and therefore approximately a million bytes for a full-screen image. Thus to transfer the image, we must transfer a million bytes or 8 Megabits; now the nominal bandwidth of an Ethernet is 10 Megabits/s, so we can see that the minimum transfer time is almost a second, theoretically, and will be a good deal more in practice. (By contrast, when we are dealing with graphics specified as objects such as lines, arcs, polygons, etc., X uses high-level requests which require relatively few bytes to be transmitted.) Running the application locally we avoid the network completely. Moreover, the use of shared memory can result in very high effective bandwidth between client and server (see Module 3.8) and in addition local clients may be able to make use of optimizations for local running, for example bypassing the server and addressing the hardware directly, as we described in Module 13.1.

#### The response-time of remote clients

In Module 4.5 we defined the latency of a network as a measure of how long it takes for a bit you transmit to arrive at the other end. The latency affects operations which require a round-trip- transmission from client to server and back again. Many window management tasks, such as manipulating a rubber-band outline of a window when resizing or positioning a window, generate a lot of round-trip traffic. Low latency is important for interactive working like this, and on high latency connections it is beneficial to run at least the window manager locally.

#### Special communications methods for slow network links

For low bandwidth networks special X systems are available which compress the data sent between the clients and the server. Current implementations require special, non-Xstandard software on the host that is communicating with the server. In some cases the host-based software is providing little more than data compression and decompression, whereas in other cases it is almost as though part of the server has been moved to the host.

Systems such as these let you use distant X stations over modem connections (Figure A) or even connect stations on-site over serial lines such as RS-232 links instead of over a LAN.

An MIT X Consortium working group has been set up to address this requirement for better X performance over slow links, and provide a standard solution. (This is often referred to as LBX or Low Bandwidth X.)

###### Figure A. Using an X-terminal connected via modems or serial line

## 13.3 Client performance

Many factors affect client performance, including use of particular programming techniques and whether the application has been built with the standard X Toolkit. Complex graphics applications may benefit from drawing indirectly to an offscreen image in memory and then to the screen, rather than directly, to simplify redrawing after expose-events.

Like all applications, X programs benefit from good coding and optimization, but there are several factors specific to X.

Because an application should always be ready to respond to incoming events, it should contain no very long non-interruptible tasks, as we describe in Module 14.1.2. If a program breaks this rule it will give a bad interactive response - you will have to wait a long time before the application notices what you have just done (pressed a button, or typed some text) and actions it. The least the programmer should do is give some visual feedback that the program is busy, so the user can see what's happening: for example, by changing the cursor to a clock or the `hour-glass' shape.

Exposure event handling can be very costly for applications that have very complex graphics. It can be improved in two ways:

1. Enabling backing store on the windows containing the complex graphics results in fewer expose events, although there is no guarantee that the server will always be able to provide backing store. (But if an application is sufficiently important to you and it really needs backing store, make sure you have a server which provides what you need.)
2. As well as writing the graphics directly to the window on the screen, you can also write exactly the same thing to an off-screen image, to a pixmap in fact, thus maintaining an exact copy in memory of your window. When the application receives an expose event on the window, instead of having to regenerate the graphics, it only has to copy the image from the pixmap to the window (Figure A).

Enabling save-unders on your application's pop-up windows won't directly improve its performance, but it reduces the load on other programs, which may benefit your application, especially if it is running on the same host as the other programs.

Minimizing round trips makes your application more responsive, especially when run remotely over a network where the round-trip time can be very considerable. The section below discusses how the Toolkit helps you in this. Query-requests (asking for information about fonts, pointer position, colours, etc.) require round trips; where possible, they should be cached in the client once they have received. Module 7.2.3 discussed how using gadgets can increase the number of pointer motion events generated for an application; while these don't directly involve round trips, any requirement on a client to wait for a particular event before issuing the next request effectively requires a round-trip time, so having to process a stream of such events will degrade performance.

#### Using the X Toolkit

One of the goals in the design of the X Toolkit was to reduce the amount of traffic to the server, and the number of round trips in particular. The Toolkit meets this aim well. Two versions of the `Hello, world' client program (Modules 5.2.2 and 5.2.4) were studied, one built with Xlib, the other using the X Toolkit. The communications traffic between server and client was monitored: for initial setup the traffic generated is roughly the same for both, but for resizing the window under control of a window manager, the Toolkit version transfers less data and involves very few round-trip messages.

However, you need to be careful about widget creation. Widgets do consume resources, so you shouldn't use too many; tens and even a few hundreds of widgets in a program perform acceptably, but when you have thousands, you are likely to suffer performance problems. If your program really does need a large number of widgets, you are in a dilemma. Either you create them all at once when the program starts, giving you a long startup time, or else you create them as needed, which may give you bad interactive response time. You can overcome this to some extent by caching things like dialogs for reuse where possible. Another approach is to use gadgets instead of widgets. As we discussed in Module 7.2.3, opinion is divided on this, but it is worth experimenting with your particular application and server to see if you get an appreciable benefit.

Memory allocation is one of the most time-consuming activities in the Toolkit internals, so if your standard libraries don't provide fast and efficient versions of the memory allocation functions, you should consider replacing them with better ones.

We look at memory usage in a little more detail in the next module.

###### Figure A. Using a pixmap as an off-screen image, to improve expose event handling.

### 13.3.1 Effect of memory usage and CPU on client performance

Providing adequate memory on the hosts running the X applications is one of the best ways to avoid performance degradation. Providing more CPU power may overcome some problems, too.

Just like any other programs, X applications consume memory and their performance degrades if there isn't enough. However, with X the problem is more common. First, because both X clients and server are quite large; second, because with a window system you run many applications simultaneously; and finally, because with X-terminals and PC X servers you often end up running all the applications for many users on a central machine.

In fact, lack of memory on the hosts running the applications is probably the single most common cause of performance problems with X systems. The effect you see is a great deal of swapping and paging, resulting in poor response and inefficient utilization of the CPU.

There are two answers. The first is to buy more physical memory. Often this is cheaper than any other change you can make to your system. (As an example of how effective this can be, when we upgraded one of our workstations from 4 Mb to 8 Mb of memory, elapsed time to run one sequence of X programs reduced from 250 seconds to 45 seconds.)

Another answer is to use shared libraries if your operating system allows. As we describe in Module 14.1, this can reduce memory requirements dramatically, especially for small applications, as well as reducing the amount of space required to store the

programs on disk.

#### CPU considerations

If, in spite of all the improvements you make, your application still runs too slowly, you can consider running the application on a more powerful CPU. This solution may not be popular, with you or your customers, but it is an option that many other systems won't give you. Depending on your configuration, only one central machine may need to be upgraded, with users accessing it remotely from their own workstations or Xterminals. If you compare the cost of the extra hardware with the total cost of the system including software, management time, and training, this may be a better option than it first appears. (It at least has the advantage that it's very quick to implement!)

## 13.4 Benchmarks and tests

As X matures, benchmarks are being continually developed for evaluating servers. These are best used in conjunction with tools which profile how your application mix loads the server. The MIT X Consortium has also developed a suite of tools for testing servers.

The basic purpose of benchmarks is to provide a comparison on paper of servers, to save you having to run real-life evaluations of many different machines to which you probably don't have easy access. To be of most value, these comparisons ought to be representative of real-life performance of the applicauons and environment you will actually be using. In particular, you want to identify what will be the slowest part of the system, to see if it will sull give acceptable response time and adequate speed.

Several benchmark tools have been developed; here we'll mention only those which are widely available and are free. (There are some commercial benchmark systems available too.)

#### xbench

The user-contributed program xbenCh runs about 40 individual tests consisting of different X operaaons; typical output is shown in Figure A. It combines the results of these tests into a single measure using a set of arbitrary weightings; the final number is the rating of your server in Xstones (by analogy with Whetstones and Dhrystones). The higher the number of Xstones, the faster the server.

There are some problems interpreting xbench results. First, the weightings of the various aspects of the server may be inappropriate for your task or application mix; you can quite easily get a variation of a factor of two between xbench results and actual elapsed-time measurements of the same task on the different servers. Secondly, xbench doesn't measure everything, and some of the featunes it omits may be important for your work, or may even be those parts of the server under test which have the worst performance. Finally, your actual performance and response times may be heavily influenced by other factors that will swamp the server, no matter how good it isfor example, problems on your host (maybe not enough memory), or the effect of the network.

#### x11perf

The MIT program x11perf tests over 150 different aspects of the server, covering virtually every feature in X. It gives a separate time for each feature tested (see Figure B) and does not combine all the figures into a single `representative' benchmark figure, because, according to xbench's authors: "We consider such numbers to be uninformative at best and misleading at worst. Some servers which are very fast for certain applications can be very slow for others. No single number or small set of numbers are sufficient to characterize how an X implementation will perform on all applications. However by knowledge of your favorite application, you may be able to use the numbers x11perf reports to predict its performance on a given X implementation."

In other words, you have to decide which aspects of the server matter to you for your work; then you can measure them directly with x11perf. (The companion program x11perfcomp merges output into a convenient tabular form for comparisons.) How do you decide which server features are most important for your applications? Use xscope, described in the next module.

#### The MIT test suite

The X Consortium has commissioned a suite of programs to test how faithfully an X implementation conforms to the X Protocol. It is based on Test Environment Toollut from X/Open, the OSF and UNIX International. It has been designed to allow automated and extensible testing, without having to have a real person clicking mouse buttons, typing at the keyboard and so on, and it uses a special server extension, XTEST, to allow synthetic or simulated events to be used instead.

The suite was released publicly in September 1992. The tests uncovered many detailed bugs in a wide range of servers, typically relating to exactly which pixels should be affected by a given drawing operation. Now that the suite is widely available we can expect improved servers, and vendors will probably publish the results of tests on future releases of their servers.

###### Figure A. Typical output from a run of the xbench benchmark.

###### Figure B. Typical output from a run of the x11 perf benchmark.

### 13.4.1 Profiling applications, and replaying sessions

You can profile any application to see what mix of requests it generates, by using a special program which appears to the application as a server, but in fact is just a client that captures details of the requests and passes them on to a real server. This lets you find out what features of the server are most important for performance of that application. Modified servers let you capture and record all the requests in a session, so that you can replay it later, for demonstration or testing purposes.

#### xscope and xrecorder

The user-contributed program xscope monitors all traffic between a client and the server. It does this using the technique we outlined in Module 4.3 - by pretending to be a server as far as the client is concerned: when you start the client you connect to xscope, not to the real server. xscope receives all requests from the client, prints out the request contents in more or less detail, and then passes on the requests, completely unaltered, to the real server, which actions them. Similarly, all events and replies from the server are passed via xscope, which prints them out and sends them on to the client. This is shown schematically in Figure A.

Note that you can use xSCOpe with any X station, as it just another client as far as the real server is concerned - it can even run remotely from the real server (Figure B). (You can think of xscope as a protocol analyser for X.)

xscope lets you specify the level of detail you want printed, from just the names of the requests, to every byte involved. Figure C shows the least detailed output, of an xclock starting up. From this you can see how it is possible to analyse what X operations are dominant in the application, by post-processing the text printed out.

xrecorder is another user-contributed program. It is effectively an enhanced version of xscope which lets you filter out any particular types of event you are interested for printing or recording in a file.

#### xghost

The user-contributed xghost software is a set of modifications to the standard MIT server, so that all requests sent to the server are captured, and recorded in a file. Later, you can replay these events to the server, with their time-separation maintained, so that your whole session is re-run almost exactly as before - you can see the mouse pointer moving, pushbuttons being depressed, scrollbars moving, etc. This is obviously useful for demonstrations of software, but also for regression testing - to check that the current version of some software still works correctly after changes have been made, and that no new bugs have been introduced.

Even if you are not using MIT software for production work on your machines, if you need this type of facility you could make it available on a single workstation with the MIT server, and dedicate that to testing and profiling. The alterations are only to the server, so you can run your own or third-party applications unaltered.

###### Figure A. xscope sits between client and server, intercepting all traffic.

###### Figure B. xscope, the application being protiled, and the real server, all running remote from one another.

###### Figure C. Output from xscope.

## Summary

In this chapter we looked at the factors affecting each of the major components of an X system - server, network, and client. We have outlined some practical steps you can take to examine your system, and if necessary to re-configure or change it to improve performance. Finally, we looked at the benchmarking tools available to characterize server performance, and for analysing applications to see which aspects of the server performance are the most important for your particular application mix.

# Chapter 14-

Writing X Programs

## Introduction

In this chapter we look at how you write X programs. This is not a programming tutorial, and we don't look at any coding details. Instead, we outline the factors that are specific to X programming, and some aspects requiring special consideration. First we look at some techniques that are typical of many X applications. Then we look at some specialist tools for developing new applications, and foc porting existing applications to X. Finally, we briefly consider how the user interface should be developed.

## 14.1 Programming the system, and development tools

To write X programs you need at minimum the basic Xlib library (or equivalent) for the host on which the application is to run. Ideally you should also have a toolkit. Specialist tools such as User Interface Management Systems and migration and porting tools are becoming increasingly common.

#### What you need for programming with X

If you are going to write programs using X (or build any user-contributed software, from the MIT contrib release or elsewhere), you will need, as well as the basic components we listed in Module 10.1, some extra software:

- Libraries of X functions. The Xlib function- or subroutine-library is essential (except on some systems using exotic languages which provide their own equivalent of Xlib). In addition you need the function libraries for

  whatever toolkit you are using.

  Note that these libraries are collections of object files compiled for the particular hardware and operating system that the application is to run on, so you need a version of the libraries for each target platform. When writing your program, you are not concerned at all with what type of server you expect to be using the application with, other than ensuring the correct network transport protocol is supported.

- Header files, the *.h files to include system definitions, etc. in your source program. (These files often include definitions specific to the target platform for the application.)

This is the absolute minimum you need. However, when writing applications it is almost essential that you use either a toolkit as we described in Chapter 6, or an even higher-level programming system such as the user interface management systems and porting tools that we describe in Module 14.2.

#### Shared libraries

Shared libraries are a way of reducing the run-time memory requirements of a system. Instead of linking a copy of a library into each application which uses it, only a pointer is linked in, so that the size of the executable file is very much smaller. At run time the library is loaded into memory if it is not already resident, and the running program accesses the functions it requires. If the library had already been loaded, then the application can immediately access it. The overall effect is that only one copy of the library is ever resident, no matter how many programs are using it (Figure A) whereas with normal `static' libraries there is one copy resident per program (Figure B). The X libraries are large (on our machine Xlib is about 450 kbytes, and the Toolkit library is about 300 kbytes), so reducing the number of copies can save a lot of memory when you are running several X applications. Because a copy of the libraries are not linked into the application, the size of the executable file stored on disk is very much smaller too.

However, shared libraries can cause problems, too. If the libraries are updated, for example with a later release of software, but the applications remain the same, you may get some incompatibility between the two. This is sometimes called version skew --- the version of the libraries in use doesn't match the version the application was built with. If you get this problem, you must either relink the application to use the new libraries, or make sure the older versions remain available as well. Some people refuse to use shared libraries because of this problem, and always use static linking, especially for applications that are shipped to customers. The compromise is to provide two versions to customers, one statically linked which you know will always work, the second linked with shared libraries that customers can use if they wish, to save on memory and disk space.

###### Figure A. Only one copy of a shared library is in memory at run-time.

###### Figure B. Each running program has its own copy of a static library

### 14.1.1 Compiling and managing X source programs

Xlib and Toolkit libraries are incorporated into the program when it is compiled and linked. The MIT program imake helps manage building and maintaining large software developments.

Modules 5.2 and 5.2.4 described what a typical X application consists of, with layers of software providing basic X functions, toollcit and widget functionality, and at the highest level the application code. Here we look at how these vacious components are brought together.

The compilation process is shown schematically in Figure A. The UNIX commands to build the simple `hello world' X program mentioned in Module 5.2.2 are shown in Figure B, illustrating that the locations of the include files and libraries mentioned above are specified if they are non-standard. For more complex programs, there would of course be many source files, and probably libraries specific to the problem-domain addressed by the application (for example, a graphics program might have a GKS library) as well as in-house and operating system standard libraries.

#### Configuration management - imake

Large-scale development with X can be administratively complex, because of the many parameters and development-administration tools which may be site- or machine-specific. To overcome this problem, and to make its own nelease as portable as possible, MIT uses the imake program, which is included in the MIT Release. This is an enhanced version of the UNIX make program which automates the building of software components. imake uses a site-wide set of configuration and template files to isolate the vendor- and site-dependent parameters, so that the files specifying how to build a particular program are brief, portable, and site-independent. Figure C shows a sample imake file.

We strongly recommend that you use imake for X development.

###### Figure A. Block diagram for the compile and link process.

###### Figure B. The commands used to compile and link a typical X program.

###### Figure C. The imake file to build the MIT server

### 14.1.2 X programming techniques

The event-driven programming style required by X demands that no task should take very long, in order that events are handled promptly and the time to respond to an action of the user is short. However, `modal' dialogs and other techniques let the programmer inhibit user-input, forcing the user to give a reply to an important question, or confirm a particular action is required, before the program can proceed.

The event-driven nature of X has several important consequences. X programs are usually written in an `event loop' style (Module 7.4). The main routine of the program consists of a loop which waits for an event, and when one arnves despatches it to a separate event-specific routine for processing. While this routine is executing, any further events which amve are kept in a queue. When this routine completes, it returns to the main routine, where any queued events are despatched in turn, and the cycle repeats forever. The Toolkit simplifies writing programs in this form, by providing the event loop functions, and easy mechanisms to cause callback functions to be executed when particular events occur in specified widgets. Thus, almost all event processing and despatching can be handled automatically by the Toolkit.

This program architecture imposes constraints: the program must always be ready to handle events. However, while the program is in an event-processing function, other events which arnve for the program are being queued and not processed immediately. Now as long as the program returns to the main loop quickly, events will be handled promptly. But if a long period elapses, events remain in the queue for a long time, unprocessed (Figure A). This causes problems when you are using the program: it appears that the program is doing nothing, or hasn't noticed your mouse or keyboard input, and you may repeat your last actions. But then, when the time-consuming function completes and event processing is resumed, your original actions (events) are still in the queue, and both those and the repeats are processed, usually causing results that you didn't want or expect. So ideally, callback and other functions that process events should be quick and shouldn't involve any long computations or very time-consuming I/O. If a lot of processing really is necessary, either structure your program so that the large tasks are broken into small subtasks which are executed in workprocs (Module 7.4.2) and other events can be handled between subtasks, or else delegate the large task to a sub-process, so that the main program can continue to handle events. Alternatively, at least set the program into a mode where further events can't be generated, and give a visual indication that the program is busy: for example, change the cursor to a clock or an hour-glass shape.

Fortunately, the callback structure of the Toolkit encourages a style of programming where each event (in fact each callback) is processed by its own specific function, and it is easy to write your program using a lot of small (and hopefully quick) functions. Also, the MIT X Consortium is working on multi-threading for clients and servers (Module 15.1) which may overcome some of the problems of long callbacks.

#### Dialogs, blocking input and inhibiting events

Some dialogs also require special handling, and they block input so the user can't do anything else while the dialog is on-screen. The program is no longer fully event-driven; instead of letting the user drive the application as normal, invoking whatever menu or action they want, the application is demanding some specific information from the user. The Toolkit addresses this requirement by providing modal dialogs, which stop you using the rest of the application until the dialog is finished. For example, when you try to exit a word processor without first saving your file, you are often given a modal dialog asking whether you want to save your change, and you have to reply. (The Toolkit also provides modeless dialogs, which don't affect the operation of other parts of the application. A typical example of a modeless dialog is the printer-setup within an application --- it is taking in information specific to one area of the program's function, and has no need to inhibit the operation of other parts of the application.)

Motif further distinguishes between the types of modal dialogs it provides. The type described above is application modal --- it suspends the operation of the rest of this application, but you can use all other applications as normal. System modal dialogs prevent you using this and any other application while the dialog is on-screen. For example, when you want to exit or reset the Motif window manager, it gives you a system-modal dialog asking if you really want to perform this action.

###### Figure A. The toolkit event-loop, showing how events may be queued when a callback function executes for a long time.

### 14.1.3 Other programming techniques

Your application needs to address major differences in hardware capabilities, colour versus monochrome screens, for example, although the code handling these differences can be isolated to one part of the program. It also needs to take account of interactions with the window manager, and that it must share resources (colours, memory, etc.) with other clients. Applications should be user-customizable so they can be used in different countries and in different environments.

#### Taking account of different hardware capabilities

While X is almost completely hardware independent,there are some fundamental hardware characteristics that the application or the toolkit it uses must take account of. For example, different screens have different sizes,you can't display colour on a monochrome screen,and the user can't press a middle button on a two-button mouse.

Even so,the design of the X system simplifies your work. All X servers have a large core of common functionality,and differ only in the few areas relating to hardware capability. As a result,programs don't need multiple control paths (Figure A) with frequent checks to see if some particular facility is available on this implementation. Such branching program structures are common with systems like GKS, for example, which allow many aspects of the implementation to be optional.But with X,you can normally isolate the specific programming required for the few areas of difference to the setup or initialization part of the application,and thereafter use a single control- path (Figure B).[Footnote:In many cases, what is happening internally is that Xlib is finding out about the server's capabilities, and is setting up internal parameters accordingly; later, when other Xlib functions come to be called, they will operate within these constraints determined during initialization. So within Xlib different control-paths may be used, but this is transparent to the applications programmer.] And as we mentioned in Module 7.1, by using the Toolkit, applications programmers can avoid having to learn much about the low-level Xlib programming, and leave the handling of different server capabilities (such as colour versus monochrome) to the Toolkit internals.

#### Interactions with window manager and other applications

As we saw in Module 9.5, when writing an X application you have to consider its interaction with the window manager. You can't assume that you will have a particular window manager, nor that your application's window is a particular size. You must be prepared to operate in the environment that the window manager gives your application. You must also be aware that there are likely to be other clients running on the same display, and that to some extent these will be competing for server resources, such as colours in the colormap, server memory for fonts, etc. It is good practice to free resources after use when you don't need them any more.

#### Making your application customizable

Module 12.1 showed how applications employing Xlib's resources mechanism are easier to use and to integrate into an overall system, because they can be customized. You too should follow the conventional wisdom, and ensure that your applications are usercustomizable. When you are writing an application, remember that you can't really be sure where that application may eventually be used, and the users may speak a different language and be working in a very different environment.

In almost any application area, programming for portability and machine independence is good discipline even if, to the best of your current knowledge, the software will will only ever be run on the one platform. Similarly when you are writing programs, if you keep in mind that your software may need to be heavily customized later on in ways that you can't easily foresee, you can anticipate problems and avoid pitfalls and bad design which would limit the usefulness of your software.

###### Figure A. Optional functionality in a system can lead to complex, branching, control paths in applications.

###### Figure B. X applications have predominantly a straight, unbranched, control path.

## 14.2 User interface management systems and other

development tools

`User interface management systems' and `interface design tools' let you develop the user interface of your program interactively by manipulating objects on screen rather than specifying them by writing lines of code. They let you build prototype applications quickly and easily. Other development systems use interpreted languages to facilitate rapid development.

Even though toolkits simplify X programming a lot and reduce the amount of code required, writing X applications in the conventional way is still complex, lengthy, and error-prone. This is partly because there is a lot of detail to be handled, partly because some aspects of X programming are genuinely tricky, but mostly because it is so longwinded: as we saw in Module 5.2.2, even a tiny X program can take hundreds of lines of code. Another factor is that you are designing something which is essentially visual - the graphical user interface - using the verbal and procedural methods of a programming language.

Interface design tools (IDTs) or layout editors are a way of simplifying X programming. They allow you to build the layout part of the application graphically and interactively. You no longer write some code to create an `XYZ' widget, and define its colour and text characteristics, and position. Instead, you drag into a work area an icon representing the type of widget you want, position it where you want it, type directly into the label the text that it is to contain, etc. (Figure A). You can set other more complex characteristics with interactive dialogs --- still without programming. Module 7.2 illustrated an idealized view of what building an interface ought to be like! An interesting development would be to combine the interactive layout approach with a virtual seality system so that, with a data glove and a video headset, you could open a toolbox of widgets with your hand, pick up in your fingers the widgets you want, and place them directly on your workplace. You could write the text labels in with your virtual pen, and paint the widgets with spray-cans!

Some systems let you develop the interface graphically, but when you are finished they generate lines of C or some other language from the graphical definition, which you then incorporate in the program. The problem with this is that once you've finished the program, if you want to alter the interface you have to go back, change the graphical representation, and regenerate the C code: any manual changes you have made to the original generated code are lost and have to be-reincorporated.

User interface management systems (UIMSs) are a further extension of layout editors, allowing you to specify notjust the static layout and appearance ofthe interface, but also its dynamics or behaviour as well. For example, you can create and destroy components, change the contents of labels and buttons, manage menus and pop them up and down as appropriate, resize windows, and similar functions which are beyond the capabilities of a layout editor. Typically you do this using an in-built interpreted language specially designed for X programming, making specification of callbacks and other aspects of user interface coding very easy. These systems are usually well integrated, and you make changes to a program in just the same way as you developed it: the graphical representation you work with and the specification language is the sourcecode of the program, so there is no separate, previously generated code, which can get out of step with the graphical representation. Some UIMSs even include C-language interpreters, so you can interactively run your (half built) application and check that what you've done so far is correct.

UIMSs are an area of X where major developments are occumng; there are already dozens of different systems available from commercial and academic sources, and more and more sophisticated systems are becoming available.

The Motif user interface language, UIL (Module 7.5.1), addresses some of the same problems as UIMSs, but it is still a procedural method, and only specifies the static layouts of the widgets and their characteristics. It doesn't let you change things graphically or interactively, nor does it have any programming facilities for specifying the dynamics of the user interface - how windows change in response to user actions, and how the different parts of the application relate to and invoke others.

#### Other development systems

New types of development system are also starting to emerge from the research community. Some systems of note are Xtent from AT&T, WINTERP (a widget interpreter) from Hewlett-Packard Labs, and Tcl from Berkeley. While they differ a lot in their style of use, all of these systems generally offer very rapid prototype development via an interpreted language. Some are based on Lisp, others on an extension the standard X notation used in defaults files. These tools are a good indicator of what to expect from commercial systems in the near future: a very productive environment, with very high-level and expressive programming facilities.

Another example of this type of system is WKSH from UNIX System Laboratories. This is a windowing version of the Korn shell; it is a shell (command-line interpreter) with enhancements that allow the programmer to create and handle Motif or OPEN LOOK widgets. Thus it is possible to develop windowed applications by writing shell scripts (command procedures) instead of C or other compiled code.

###### Figure A. With a UIMS you build the user interface interactively.

## 14.3 Migrating old applications to X - enhanced terminal emulators

Extended and programmable terminal emulators can be customized and configured for particular character-based applications, allowing a full graphical X user interface to be added as a front end, without changing the application at all.

Most existing programs have not been written to use X, because it is only a relatively new system. We already saw in Module 10.3 that terminal emulators allow you to use character-based applications within X. There are now enhanced systems available which, though they are still essentially terminal emulators, go far beyond straightforward mimicking of a character terminal, and allow you to add an X front-end to a characterbased application without changing it at all. (These systems have sometimes been called `frontware'.)

The simplest systems provide a terminal emulator window, but with an attached control panel containing pushbuttons. You can configure (with a script file) what each button does - typically enter text into the window as though it were typed from the keyboard, to run commands or to select some function in an application.

The more advanced systems are fully programmable, and can be used to provide much more sophisticated front-ends. The programmer can specify that when the terminal emulator receives a particular stream of characters from the application, instead of just displaying them at the appropriate position on the X window, the emulator is to perform other more complex actions, which are programmed in the script language. The programmer can use all X's facilities to improve the user interface. For example, the front-end can make use of components such as scrollbars, pushbuttons, dialogs, etc. With sufficient programming, the old character-based interface can be completely hidden, and what the user gets is a full-function graphical interface.

As a simple example, consider a character-based application which always prints its cryptic, computer-oriented, error messages on line 24 of the screen - messages like ERR-72 or ERR-53, as shown in Figure A. We program the emulator to recognize when the characters output by the application would cause the string ERR- to be printed at the beginning of line 24. However, instead of printing them, we now extract the characters following the ERR- prefix, giving us the error number. Then in our emulator script we translate this number into the corresponding English-language message, and display it as an X dialog (Figure B). Of course, the application could be improved furt.her by providing much more in the front-end than just error handling, as we describe in the next module.

The example above transforms characters coming from the application into an enhanced action on the user interface (X) side. We can also do the reverse: add extra components into the user interface on the X side, and transform their activity into characters to be sent to the application. For example, to provide a button to exit the application, we create a pushbutton in the script, and program it to input the characters QUIT when it is pressed. Or consider incorporating a scrollbar into an enhanced version of a text editor: this is programmed so that when the scrollbar is moved, its callback inputs to the editor, as text, the commands necessary to scroll forward or back the appropriate number of lines.

A big advantage of these systems is that the original application hasn't been changed at all; it doesn't matter what language it was written in, and you don't even need the source code. You can enhance applications for which you have lost the source code (your 20-year-old invoicing program in Cobol, perhaps) or never had it (a commercial database system, or a standard utility program provided with your operating system). And because you're not changing the application, you are certain it will continue to work correctly, so you can use this technique on applications which are so old that nobody knows how to maintain them, but which are still crucial to your organization. The commercial X versions of a well-known integrated office-automation system and of a leading spreadsheet package use Alex, which is a system of this type.

In the next module we look in more detail at how these systems work, and how you can use them to add improved X user interfaces even to applications running on machines that don't support X.

###### Figure A. Cryptic textual error message from a character-based application.

###### Figure B. The same error message transformed by an enhanced terminal emulator.

### 14.3.1 How enhanced terminal emulators work

Enhanced terminal emulators don't contain hard-coded rules specifying rigidly how characters from the application it is running are to be displayed on the emulator's window. Instead, they allow the programmer to write a customization program or script which creates a user interface in the emulator's X window, and specifies how this interface and the application interact.

With a physical terminal there is a fixed eorrespondence between eharacters the application sends to the terminal and what appears on the screen; this is determined by the firmware in the terminal. With a normal terminal emulator there is a similar relationship between characters sent and what appears in the emulator's X window, determined by the type of emulation - for example, VT100 or Tek 4014 --- which is hard-coded into the emulator program (Figure A). However, with the new tools this mapping is no longer fixed; it is programmable in a high-level language so you can tailor the emulator for a particular application by writing a customization script. So the user gets an enhanced X interface (provided within the emulator) while leaving the original application unaltered (Figure B).

In the simplest case the interface in the emulator's window will look very like the screen of the character-based terminal. More sophisticated customizations will provide a highly graphical interface which hides most of the complexity, and perhaps awkwardness, of the original application. For example, the character-based application may require the user to type in a particular code in some field, obliging the user to remember the type of code and which particular one to use. The X front-end could easily alter this, so that a menu or dialog listing the valid codes is presented instead, and the user just has to select one with the mouse-pointer.

A different customization script is required for each application customized, although the main terminal emulator program remains the same in each case. For commercial applications built using systems like these, such as the spreadsheet mentioned in the previous module, the total product shipped consists of the emulator itself, the standard application, and the customization script. For major applications, the customization process is quite lengthy and involves a lot of programming in the customization language.

#### Migrating applications on platforms that do not support X

Module 10.3.1 showed how an emulator need not run on the same machine as the application: they can be connected via a network, and the same is true here. Figure C shows an elderly Cobol application running on an elderly IBM mainframe, customized using an emulator executing on a UNIX workstation, with the X server running elsewhere.

In this way an X front-end can even be added to an application continuing to run on a platform which does not itself support X. The only requirement is that the emulator and the application be able to communicate over the network; in practice this means that the `old' machine must at least support networking software and some form of remote execution, such as telnet for a TCP/IP network.

###### Figure A. Output on the X screen in a standard terminal emulator is determined by the type of physical terminal emulated.

###### Figure B. In a programmable terminal emulator, the application's input and output can be manipulated by a customization script.

###### Figure C. The `old application', the terminal emulator, and the X server can all be executing on different computers.

## 14.4 Porting from other window systems, and multiple-platform applications

Specially developed toolkits simplify porting applications written for other window systems to run under X. Development systems are available which let you write a single source program that you can then compile and link on different target platforms, such as Microsoft Windows and the Macintosh, to give you the same application on several platforms, each with the native look and feel of its particular platform.

Terminal emulators let you use character-based applications under X, but they don't let you use applications that were written for other window systems. If the particular window system is the native one for your workstation or PC, there may be an X server that runs on that window system, and that will let you run both X and native window applications together on your screen. Otherwise, you must get the source code of the application, and port it to X.

Converting an application manually can be very difficult: the functions provided by the other window system, and the style of programming it requires, may be very different from X's. To reduce the amount of work required, some vendors have provided special migration toolkits.

- Sun produced the Xview toolkit to simplify converting SunView applications to X. This has been designed so that with the minimum of modification an Xview source program can be recompiled and relinked with the Xview and X libraries instead of the old SunView ones. The structure of the source program is the same as before, and converting a program takes a fraction oi the time that would be necessary for a re-write. Xview is not a standard toolkit (that is, not Intrinsics-based) because it has to follow the program structure imposed by SunView and cannot use the event loop and despatch architecture of the standard X Toolkit.
- A toolkit has recently been announced which allows you to port Microsoft Windows programs to Motif and UNIX. On your UNIX system you compile your Microsoft Windows source using this special toolkit, and the result is a UNIX Motif application. (There are also courses available on how to port Microsoft Windows applications to Motif without special toolkits.)

#### GUI-independent toolkits

Special toolkits for converting from another window system to X are not common. However as we mentioned in Module 7.6, there are several GUI-independent toolkits available, which allow you to write a single application suitable for multiple platforms. They support not just different machine-types, but also different combinations of GUI and operating system. Rather than using a portable window system such as X, these systems aim to let you write an application that is portable across window systems.

Typically these systems allow the same source program to be used for X (usually Motif under several variants of UNIX and perhaps VMS, and occasionally OPEN LOOK under UNIX), Microsoft Windows, the Macintosh, and maybe Presentation Manager. Instead of writing your program to use the specific components, characteristics and features of one GUI, you program in terms of generic objects and functions. For example, you don't use a Motif scrollbar and Motif-specific features for controlling scrolling. Instead, you work with a more abstract scrollbar and scrollbar functions, which at a lower level inside the toolkit map onto the particular functionality provided by each GUI's scrollbar. In each case the resulting application is true to the style of its target system. (So the version of the application generated for the Macintosh has the standard Macintosh look and feel, and is quite different from the version of the same program generated for a VMS Motif system, although overall they offer similar functionality.)

These systems achieve pottability by providing a `virtual interface' to the graphics and user interface facilities, that is, by abstracting the basic functions and objects required, and providing them at a high level in a platform-independent way. Underneath, a lower-level library on the particular platform maps these high-level abstractions onto the specific mechanisms provided by this system, as shown in Figure A. (Note that for the X versions of the application produced this way, it is the look and feel we are most interested in, not the implementation. So, the blocks labelled `Motif' on the VMS and UNIX systems in the diagram are not necessaaly standard, Intrinsics-based, Motif toolkits; how the look and feel is implemented internally is the decision of the developer of the GUI-independent toolkit.)

These systems are useful where the same application has to be made available on many platforms, and where you can't assume that X is available, or where users may want not to use X - for example, if the application you are writing is targeted for standalone PCs and Macintoshes.

###### Figure A. The architecture of a GUI-independent programming system

## 14.5 User interface design, and programming

User interface design is a specialist discipline that has very little to do with programming. It should be carried out by specialist user interface designers and not by programmers.

User interface design is a discipline in its own right. It demands its own particular set of skills and experience, and involves a very different approach to that required for programming. For example, one of the most useful approaches in developing a user interface is to produce an initial version quickly, test it on users to find out what is wrong, and iterate like this more or less by trial and error until a representative group of users find the interface satisfactory. If you handled software system design in the same way (as we did in the good old days!) you would end up with a flawed and unmaintainable system (as we did in the good old days!)

Good user interface design requires specialists, usually with graphic design or psychology training, and the interface has to be tested on real end-users. Often, some of the most serious flaws in a program's usability are in completely unexpected areas, and once identified may require very little programming effort to rectify. It is amost impossible to find these problems without end-user testing.

Increasingly, major software project teams now include a `human factors' or `humancomputer interface' (HCI) member. Unfortunately, many software engineers don't accept the rationale for this, believing that if it involves programming they can do it as well as or better than anyone else. This may explain why many software products are almost unusable.

## Summary

This chapter has outlined the factors you have to bear in mind when developing X programs. First we looked at the basic components that are required on a development system, and the mechanics of compiling an X application. We saw that writing an event-driven application requires its own style of programming, and constraining the user so that data is entered for a particular field requires special handling: for example, using modal dialogs. We moved on to development tools, and looked at user interface management systems for developing new programs, special toolkits and programmable terminal emulators for migrating existing programs to X, and systems to let you write a single program which can be built for many different platforms. Finally, we looked at the development of the human aspect of the user interface, and suggested that this should not be left to programmers at all.

# Chapter 15-

Epilogue

## Introduction

In this epilogue we finish by looking at factors that affect the future viability of X - how you can be confident that X will continue to be developed and enhanced, without allowing incompatible and divergent versions to proliferate, how you can get more information to help you use X to your best advantage, and how the future of X might develop.

## 15.1 The MIT X Consortium

The MIT X Consortium is a self-financing `vendor-neutral' body, which promotes the development of X. It administers the current X standards, and plays a large part in enhancing and developing the core system.

Initially X was developed at MIT, jointly by the Laboratory for Computer Science and Project Athena for their own purposes. Other organizations started to adopt it and when it became clear, at the beginning of 1988, that X was going to have a significant role in the commercial computer industry, the X Consortium was founded. Its aims are:

- to promote the further development of X,
- to promote cooperation in creating standard interfaces for all layers of X,
- to provide coordinated technical and administrative leadership in these efforts, in a way that is vendor-neutral.

Another way of looking at it is that the Consortium is the keeper of the standards, but unlike most formal standards bodies, it is also a driving force pushing X forward. It needed to be formed to reassure commercial vendors in the early days that X would have a continuing and standardized future. MIT was the natural choice for leading such a body, because that is where X began, it is a neutral third party as far as vendors are concerned, and a single system architect was necessary to avoid design by committee.

The Consortium is financially self-supporting. Any organization can join. Large organizations become `members', small organizations can become `affiliates' (which is much cheaper but carnes the same benefits).

The Consortium cames out its work mostly by electronic mail, with occasional meetings, followed by public reviews (and revision if necessary) of the resulting work.

The Consortium defines standards for X, and also produces sample releases of X software. (By `sample' we mean `not reference': if the software doesn't behave according to the standards or protocol specifications, then you assume it is the software that is wrong, not the specification.) The best known software is of course the set of full releases of X, the most recent being Release 5. The Consortium also funds specific developments, such as the sample implementation of PEX (the OPhigs extension), and the X testing suite.

The Consortium is also involved in the following activities, some of which have their own working groups of Consortium members:

- Low Bandwidth X (LBX) - mechanisms to allow X to be be used over low bandwidth connections such as serial lines.

- Multi-threaded server and Xlib, so that X Protocol requests which take a long time to execute (such as some PEX 3-D graphics) don't lock up the server completely and stop the user interacting with other applications.

- Multi-threading will also let servers take advantage of the multi-processor hardware that is coming into more widespread use.

- The X Test Suite (see Module 13.4).

- Revising the PEX protocol, both to accommodate changes necessary to match the final ISO standard of OPhigs Plus, and to overcome some problems

  in the existing implementation.

- Extensions for multi-buffering, and to allow very large requests, which are necessary for PEX and for handling large images.

- Synchronization extension, to allow several streams of X activity to be synchronized with each other, and to allow X streams to be synchronized with non-X activities, such as audio or video.

- Image extension, to support fax group-3, fax group-4, and JPEG compressed images, and to provide image enhancement, geometric transformations and image-drawing operations such as dithering.

- Improved typographic support, to allow kerning, scaling and rotation of characters, and other features such as vertical writing (required by Chinese text, for example).

- Standards and protocols for internationalization, so that new input methods can be added more easily in a way that is not specific to the vendors' implementation of Xlib, and to support bi-directional writing (required by text containing both Arabic and English, for example).

- Designing a toolkit for C++

- Extensions to the ICCCM, covering among other topics improvements in session management, the Selections Service and handling colormaps. Drag and drop is also being worked on, so that it will operate consistently across different vendors' GUIs - for example, allowing you to drag a Motif item and drop it into an OPEN LOOK application.

In the next module we look at how the Consortium and other bodies define X standards

## 15.2 The X standards

The current X standards are administered by the X Consortium. Other organizations such as ANSI and IEEE are actively drawing up standards for various components of the X system. Major bodies such as the USA's NIST and the Commission of the European Community have included X in their development standards.

#### X Consortium standards

The major standards defined by the X Consortium are:

- The X Protocol itself.
- The programming interfaces and `rules': the basic X library Xlib, the Toolkit Intrinsics, and the Inter-Client Communicaaon Conventions Manual (ICCCM).
- The Display Manager protocol, XDMCP.
- Font-related standards: the XLFD naming system, the BDF portable distribution format, and the font server protocol.
- Extensions: the Input Extension and its programming interface, and the Shape Extension for non-rectangular windows. Forthcoming standards will include the following extensions too:
  - PEX
  - Double-buffering, multi-buffering and stereo.

#### Other standards bodies

The formal standards bodies are developing X standards. The ANSI task group X3H3 is working on a standard, The X Window Data Stream Definition, that is, the X Protocol, including how it should operate over OSI networks. The IEEE P1201.1 group is working on standards for the user interface (which are not specific to X, although the group did start out aiming to standardize on an X toolkit).

Other large influential bodies have adopted X and nelated technologies. Examples are the European Commission which has specified X and Motif as standards for its own use, and the USA's NIST/FIPS which has specified X as a standard for US Government systems.

The standards for the look and feels remain with their developers - the Open Software Foundation for Motif, and UNIX System Laboratories (USL) for OPEN LOOK.

## 15.3 Sources of further information and assistance

Hundreds of articles and many books have been written about X. Product catalogues, user groups, consultancy houses and training companies are proliferating. Much advice and free software is available on the public networks.

As X has become increasingly important commercially, we have seen a corresponding increase in the amount of information and literature relating to it. All the major market research companies have produced reports on it, and there is even one research company specializing exclusively in X.

#### User Groups

On the non-commercial side, there are now many user groups addressing the needs of the X community throughout the world. Many of these serve a local area, while other cover a whole country or an even wider area. Unfortunately, the contacts for the groups change frequently, and published lists tend to get out of date very quickly. So, if you want to find a group near you, the best thing to do is get in touch with the European group, who may be able to give you up-to-date details of other groups:
- European X Users' Group (EXUG). The Group holds a major technical conference annually, as well as smaller local meetings. It publishes quarterly newsletters, and distributes a hard-copy version of the list of `Frequently Answered Questions' about X (FAQ) which is widely circulated on the electronic mail networks, and is compiling a catalogue of publicly available X software. The Group's contact address is:

          The Secretary

          European X Users Group

          PO Box 458

          Cambridge CB4 4AA

          England

          phone: +44 223 426 534

          fax: +44 223 420 251

          email address: P.Whitehead @ Imperial.ac.uk

  #### Conferences

  Conferences covering both commercial and technical issues, and vendor exhibitions of products and services, are now held regularly throughout the world. The X Consortium itself hosts the X Technical Conference every January in Boston, USA. The printed proceedings of these conferences provide timely information on current trends in X.

  #### Other information

  The MIT X Consortium maintains a register of consultants and trainers in X. It also provides two electronic mail services. The first is a bulletin board or electronic mailing list for discussion of X topics, which anyone can participate in (and which is also available on the Usenet `network news' group comp.windows.x). To join, send an e-mail message to:

          xpert-request@expo.lcs.mit.edu

  The second service is an information repository of programs, documentation, etc., which you can request directly using e-mail. To find out more, send an e-mail message, with the single word `help' as the subject, or as the only word of the first and only line of the message, to:

          xstuff@expo.lcs.mit.edu

  There are many other publicly accessible archives of software and information and discussion groups on the public networks. These often include new user-contributed software, and are a source of very useful tools. Unfortunately there are so many and they change so frequently that we can't give detailed information here; try asking your organization's network or system manager, or your local user group, or a network provider in your country. (Most of these facilities are supported by research, academic, or computer science organizations, and so are most easily accessed on TCP/IP `Intemet' networks and UUCP e-mail networks. So providers of this type of network are the most likely to be able to help you.)

  Software and hardware vendors have a lot of material of more or less usefulness regarding X. One of the more interesting is a catalogue of X software available from NCD, the X-terminal manufacturer.

  Many books and articles have been written about X. There are also two regular (monthly/quarterly) publications dedicated to X (The X Resource, and The X Journal) as well as good coverage in many specialist computing publications, especially those dealing with UNIX and open systems (and Unix World in particular).

  #### How to obtain X and its documentation

  Most workstation vendors already provide X for their systems, although sometimes as a chargeable extra option. The many software and consulting companies concentrating on X also provide competitive X systems which may address any special needs you have, as well as providing X as an add-on for systems such as PCs.

  Many of these third-party companies can also provide copies of the source code of the MIT Release, as well as the MIT documentation (which provides a complete, if very technical, description of the system). They also offer toolkits such as Motif and OPEN LOOK for systems that don't include them as standard.

  ## Summary

  In the three Parts of this book you have seen all the important aspects of the X system:

  . In the first Part (X in a Nutshell) you saw briefly how X worked, and how it could help you build more flexible and integrated systems, to make your organization more effective.

  . The second Part (How X Works, in Detail) covered the details of X's operation, including some of the more complex internal aspects necessary for an understanding of the system and how it can be applied. It described the functions and operation of the server itself, the network link together with the events and requests transmitted over it. You saw the role of the client programs, how they get the look and feel from toolkits, and how the window manager contributes it own look and feel.

  . This final Part (Using the System) of the book has concentrated on practical matters - how to get started with the system, what's involved in making it available to your users and customizing it for them, how you write X programs, and how to go about getting the best performance out of your system. We finished off with a very brief outline of where you can go for further information and assistance.

  X is developing on many different fronts: new applications, new development tools, and new user interface systems are constantly emerging. In parallel, existing aspects of the system are being officially standardized so they can form a solid basis for future developments. X's usefulness and power is being enhanced still further by advances in hardware and networking technology, and soon we'll be seeing X systems integrated with sound and multimedia facilities, taking advantage of video and synchronization extensions. X is continually being applied to new application areas, from medical imaging to hypertext to financial dealing, and even to mission-critical tasks with realtime requirements such as air-traffic control. On the development side, a vast amount of effort is being devoted to making X programs easier to produce, we hope to the extent that people who are not computer specialists will be able to build and control useful tools for themselves.

  X is a dynamic and rapidly expanding area - we hope you find it as productive and exciting as we have!