MIT Information Systems

Macintosh Development

[Home] [About Us] [People] [Information Systems]
[Kerberos for Macintosh] [Applications] [Miscellaneous Documentation]


This summer while working on allowing Macintoshes to print authenticated over Athena printers, I experimented with writing extensions, print drivers and user authentication methods. In this document I will explain basic concepts and list good sources so that the next person who has to write or modify one of these will not have to spend the time I spent looking for sources and can jump straight to writing code. For quick reference, I have listed all the sources I recomend at the end. Happy coding!
--Alexandra Ellwood, August 18, 1993

Stand-alone Code Resources

Stand-alone code resources are similar to the 'CODE' resources of applications, only instead of requiring the other resources (BNDLs, FREFs, etc), they can be executed without application status. Here is a list of the most common stand-alone code resources:
DRVR
Driver resource. Neccessary for drivers and desk accessories. Called at system startup.
CDEF
Control definition function: defines a non-standard control. Exectuted by an application; portable between applications.
cdev
Resource for control panels: called at system startup.
INIT
Initialization resource: called at system startup.
MDEF
Menu definition code.
WDEF
Window definition resource: defines a window.
XCMD, XFNC
Easily portable units of code for use with Hypercard.
FKEY
Executed when a control key combination is pressed.
A complete listing can be found in the Macintosh Technical Notes (TN #256).

Without Application Status: the A5 World

There is a critical difference between an application and stand-alone code: the A5 world. There is a detailed description of the A5 world in the Technical Notes (#256), but in short, the A5 world is the mechanism by which an application's memory management and access to system globals is handled. Without an A5 world, as is the case with most stand-alone code, the program cannot access any system globals or call any toolbox calls which use globals (a lot of QuickDraw functions are like this). The solution to this is to have the code save the present A5 world (since an application or the finder will probably be running simultaneuosly), create its own A5 world, make calls to globals, and then dispose of its A5 world and restore the old one. In this way, the stand-alone code creates its own temporary A5 world. Technical Note #256 gives a good explanation and sample code for how to do this. The important thing to remember is that compilers will not check to see if an A5 world is neccessary. Therefore, the error that will occur if you need one and don't have one will happen during run time. The program must also have an A5 world if its memory consumption is to exceed 32k. This is because the A5 world is the mechanism by which the segment loader (which divides an application into 32k blocks of memory to accomodate the 68000 processor) controls memory management. Without it the microprocessor will be overloaded. However, a stand-alone code resource should never really have to exceed this limit. If it is, then the job it is trying to do is too large. Stand-alone code should perform small, specific tasks.

Trapping Commands

The most common thing for INITs and other stand-alone code resources to do is to add a feature to some existing toolbox call. They do this by trapping into the memory locations of the toolbox calls and making their own calls before the toolbox call executes. The easiest toolbox calls to trap are those in ROM. A listing of which calls are in ROM and which are not is in the TrapWords section in Think Reference. Using NGetTrapAddress and NSetTrapAddress, you can get the location of a system call in ROM, make a modified version of it, and replace the call with your modified one. Trapping commands not in ROM is more difficult, but in some cases not impossible. For the managers whose routines are not in ROM, there is usually one routine that is. In the case of the Print Manager, this command is _PrGlue or _Printing, depending on what Macintosh you are using (you can use the Gestalt manager to determine this) -- _Printing is more common and recent than _PrGlue. To trap any command, such as PrOpen, you just trap _Printing and check the routine selector on the stack to see which Print Manager call is going to be executed. The routines and selectors are described in Inside Macintosh Volume 5, p. 409. After this, the process is the same. However, before you do this, make sure that the trap exists on the system you are running. If you want your program to run on systems like the new PowerPC or really old systems, then you must check to see if the trap exists there. Think Reference describes a way of determining which trap to use in the "Determining Whether a Trap is Available" section of About Compatibility.

Print Drivers

Print Drivers are also stand-alone code resources, however, in general, they are much more complicated than the average extension or control panel. A print driver must allow the Print Manager to take the data from the application and translate it into something that the printer can use. The print driver must supply dialogs for printing, page setup, and any other related dialogs it wishes to support. It must also respond to calls from the Chooser asking what kind of printer it supports and what it is (laserwriter, inkjet, dotmatrix, etc). If the print driver translates to postscript (laserwriters do this), then it must also implement Printer Access Protocol (PAP). This is a series of calls (described in the PAP chapter of Inside AppleTalk) which send postscript to the printer. The PAP code is contained within PDEF 10 of postscript print drivers.

The easiest way to learn how a print driver works, is to read Learning to Drive. This document is the best source for information about print drivers, the chooser, and the print manager. If you are writing your own print driver, some useful code to look at is the STD File Saver. STD File Saver is a print driver which prints to a PICT file. It is a good example of all the calls that a print driver is required to support and is a good starting place for writing from scratch. (It can also be a useful utility if the program you are running doesn't support printing to PICTs.)

A Couple Things You Can't Do With Print Drivers

You can't use more than one print driver at once. The reason is that all the Print Manager calls are not driver specific. The Chooser tells the Print Manager which driver to use. The Print Manager then opens this driver and uses it to print. If the driver tries to open another driver and call it, it must use Print Manager calls. Unfortunately the Print Manager calls, aside from DrvrOpen and DrvrClose, do not specify which driver to use. The Print Manager will use the driver first opened (not the most recently opened one) to make the calls from. In order to actually use a second driver you would have to imitate the Print Manager and interpret the print driver yourself. This is not impossible (see below) but as writing the print driver itself is time consuming, the extra coding to load another isn't worth it (look for an easier way to do it).

You cannot depend on every application call a print driver (or even the Print Manager) to print. Certain older applictions and some of the more complex ones (eg: PageMaker) *do not call* the Print Manager at all. Instead they come with their own drivers and call those themselves in order to print. Any extension trapping Print Manager calls or modified print driver (this includes PAP) will not be called by these applications. So if you are trying to modify the printing process for all applications, be careful.

User Authentication Methods

User Authentication Methods (or UAMs) are another kind of code that does not have application status. UAMs are used to authenticate users of services over AppleTalk networks. They are presently implemented for file servers and a method exists for print servers.

When a user tries to connect to a file server, the server requests a UAM, at which point AppleShare looks in the AppleShare folder (if there is one) for the correct type of UAM. If the UAM is not present, it will refuse the connection. Otherwise, AppleShare will call the UAM. The UAM will bring up a dialog asking for a username and password. When both have been entered, the UAM will do any scrambling of the password and then AppleShare will send the username and password to the server, which then must interpret both and either let the user use the service or deny them access. (Note that if the "Randnum Exchange" UAM is used, the password does not actually go across the network -- see Inside AppleTalk 2ed. for the protocol)

The print server UAM works similarly, however, instead of the UAM being a separate piece of code, it is incorporated into the PAP code (see print drivers above) within PDEF 10. While it may be presently incorporated into some versions of the LaserWriter driver, this UAM cannot be guaranteed to be on any driver. If it is not already on, you can modify the PDEF 10 resource (specifically the JMP to the call "PAPOpen") to add the features described the UAM. Note, however, that any program which uses its own drivers will never call this code, and therefore cannot be supported by this method. (See trapping above).

The best way to learn how UAMs work is to read Inside AppleTalk. A good example of UAM code is the University of Michigan's AFS Kerberos. this is available via FTP from terminator.cc.umich.edu. This UAM authenticates AFS servers, using the University of Michigan's version of Kerberos (not the same as MIT's, but close). At some point, Apple will also be releasing a document which is more specific on how file server UAMs, like AFS Kerberos, should work. UAMs for print servers are basically undocumented outside of Inside AppleTalk.

Sources


Questions or comments? Send mail to macdev@mit.edu
Last updated on $Date: 2003/11/18 21:58:21 $
Last modified by $Author: smcguire $