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.
Using the X System
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.
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:
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.)
These applications can run on the same machine as your server, or elsewhere on the network.
Just like your other client programs, the window manager can run on the same machine as the server, or remotely.
In the next module we describe the contents of the MIT Release of X, which is representative of many commercial X systems.
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.
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: 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.
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:
In the next module we describe how to run remote applications.
(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 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'.
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.
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.
Running character-based applications via an X terminal emulator gives you many advantages even though you are still using a character-based program:
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.
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.
(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.
(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:
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.
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.
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 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).
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.
System Administration
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.
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.
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.
(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:
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.)
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:
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.
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.
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:
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.)-*-*-bold-*-*-*-*-240-*-*-*-*-*-*
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.
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:
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.
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.
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:
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.
(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.
(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.
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.
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.
Installing the server
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.)
Installing the client software
Application configuration
Session management
Enabling and restricting access - UID administration
In the next chapter we move on to the related topic of how individual applications can be customized.
Customizing Applications
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.
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.
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.
The attribute of the resource is appended to the object name; thus the full resource name for the foreground colour of this window is:xtexm.vt100
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
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.xterm.vt100.foreground: green
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.
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.)
(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:
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.xterm.vt100.foreground
xterm.vt100.background
xterm.vt100.cursorColor
xterm.vt100.pointerColor
xterm.vt100.pointerColorBackground
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:
This is turn has children, one of which is buttonS, itself a manager, with full name:xedit.paned
This manages three button widgets and one text widget. The full name of the Save button is:xedit.paned.buttons
and to specify red for the background attribute of this button we say:xedit.paned.buttons.save
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.xedit.paned.buttons.save.background: red
(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:
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*background: black
xedit*foreground: red
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.)xedit.foreground:
xedit.paned.foreground:
xedit.paned.buttons.foreground
xedit.paned.buttons.save.foreground
(This is an Athena application: Command is the class name for Athena pushbuttons.)xedit*Command.foreground: yellow
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
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:
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.)xedit*Command.foreground: orange
xedit*search*foreground: blue
xedit*foreground: pink
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
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.
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:xterm -fg yellow -fn '*-courier-bold-*-18-*' -bg gray
xterm -bg black -fg white -ic
are transformed by xterm into:-fg white
-ic
(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.)xterm*foreground: white
xterm.iconic : On
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"
(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:
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:Event sequence Action(s)
Left button pressed Set()
Left button released notify() unset()
Thus translation tables let you tailor keyboard and mouse-button bindings (and even use other events, such asSpace-bar pressed set() notify() unset()
Return key pressed set() notify() unset()
In the next module we look at how translation tables and actions relate to callbacks.
(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:
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.)Event sequence Action(s)
Space-bar pressed set() notify() unset()
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.
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:
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.
In the next chapter we move on from customization, and consider the performance of X systems.
Performance Factors
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.
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:
Another example of local-execution optimization is the MIT-SHM shared memory extension described in Module 3.8.
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.
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.
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 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.
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.
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.
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.
Surprisingly, running a client remotely over the network can often be faster than running it locally. There are several factors involved:
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.
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.
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.)
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:
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.
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.
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.
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.)
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.
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 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.
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.
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.
Writing X Programs
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.
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.
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.
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.
We strongly recommend that you use imake for X development.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
Epilogue
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:
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:
in the existing implementation.
In the next module we look at how the Consortium and other bodies define X standards
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.
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.
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
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:xpert-request@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.)xstuff@expo.lcs.mit.edu
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).
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.
. 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!