Graphics and Media • 56:20
The Common Unix Printing System (CUPS) forms the basis of the Mac OS X printing architecture. Hear how Mac OS X integrates the latest version of CUPS to extend the capabilities and performance of the printing system. Developers of advanced printing applications, printer drivers, and printer management software will not want to miss this information-packed session.
Speaker: Mike Sweet
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Well, welcome everybody. This is the last session of the day and we're going to talk about CUPS today. My name is Michael Sweet. I'm actually the guy behind just about everything in CUPS. I have my own company, it's Easy Software Products, and Apple uses me and licenses our technology to make Mac OS printing work as well as it does. I want to start off by saying thank you. Everybody that's ever worked on printing in Mac OS X has given us plenty of feedback. The things that you're doing in printing on Mac OS X are incredible, and the envy of everybody else in the open source world. So, thank you.
To give some background on CUPS before we get into the new stuff that's in the leopard seed, we developed CUPS back in 1997. Basically, we were doing Linux printing and UNIX printing for a long time and found that what was there was pretty lacking. We were trying to find a way to print a document and it was pretty hard to do that.
You could spool a file and you might be able to do some filtering of that data, but you really didn't have any notion of a document or printer options and each of the operating systems did their own thing. There was no commonality there. As a solution vendor, there was just no way for us to support all of those different operating systems. In 1997, we just started doing CUPS. IPP, the Internet Printing Protocol, was something that was just coming out.
We decided to go with IPP and design a really state-of-the-art printing system for UNIX. We provide CUPS under the GPL and LGPL and Apple also licenses it so you guys can do pretty much anything you want with CUPS. If you go on the CUPS website, there's a lot of free stuff that you can add to the CUPS that comes with Mac OS X to do things like printer accounting and various other interesting stuff.
Now, if you look at the history of CUPS on Mac OS X, we joined the scene on 10.2 in Jaguar, and there's been a steady progression of new versions as new releases of Mac OS X came out. The Leopard C that you have has the equivalent of CUPS 1.2.1 on it, and I'm sure as we go forward there'll be newer versions. You can get the latest Mac OS X version of CUPS on the CUPS website. That's something that we produce that Apple doesn't support, but it's available if you want to do some testing, even on Tiger.
CUPS is, it's worth mentioning, CUPS is the standard printing system on Linux, and it's available on all the commercial Unixes. It's available on the BSDs through the ports system. And just pretty much everybody that really needs to do any kind of printing uses CUPS now. And my company does sell a lot of the products that we have. We have all CUPS support, CUPS consulting, driver writing services, and so forth. So if you need something beyond what you get from Apple, we're available to fill the gap.
Now CUPS itself is organized around a scheduler program. If you look in the process list, you'll see User Espen CUPS-D. We chose this kind of architecture because it's simple and fast and very portable. On Mac OS X, it started on demand by the launch D service, unless you're sharing printers, in which case it actually has to run to share those printers.
And the program itself is very lightweight because it doesn't do a whole lot. It keeps track of the printers that are on the system and the jobs that have been queued up, but when it actually goes to do any work, it runs other programs to do that for it.
Because of various security needs for authentication and so forth, it has to run as a root user, but whenever it can, it runs the other programs, the helper programs, as an unprovenced user. And on Mac OS X, that's the LP user account. Your applications, whether you know it or not, are talking IPP to the scheduler.
So when you go to print a file, it's an IPP request, print job, and it actually spools up the file for printing. Similarly, when you go to show the printer dialogue and get the print settings, it uses HTTP to get the PPD file that's associated with that printer.
And, you know, as an aside, the printers in Mac OS X and in CUPS use PostScript printer description files, whether it's a PostScript printer or not. It's a de facto standard description format for printing. So, you know, if you're using PostScript printers in the industry, you know, you use it for PostScript printers, why not use it for non-PostScript printers too? And, you know, we just display all the printer features from that.
From the architecture, you'll see an application can talk through Cocoa, through the Print Manager API, or to CUPS, and all of that layers through to get through to the scheduler using IPP and HTTP. Both the scheduler and the application use the CUPS API, and if you were to look at the scheduler code, you'll notice that most of the calls it's making are the same calls that your application would be making.
Now, once you submit a job for printing from the print dialog, it gets stored in a spool file on disk in the spool directory for the scheduler, and then it goes out to look what it needs to do to actually print the job. There are several programs that will get run for a print job.
They're kind of classified as filters, drivers, port monitors, which are something new in CUPS 1.2, and backends that actually communicate with the printer. It runs the programs it needs to to get the document file into a format the printer will accept, and once it does that, your file gets actually printed. Once the job's been printed, it removes the spool job file and moves on to the next one.
For security reasons, we run all the filters, drivers, and port monitors as the LP user, so they can't actually do something to the system. But the backends sometimes do run as root, because they may need some sort of backup. So you can use some sort of privileged resource, and we'll get into that a little bit later, is how you can control whether it's run as LP or as root.
Now if we show it graphically, an application submits a document and then CUPS runs a series of filters. So for a PDF document you might see CGPDF to raster or CGPDF to PS that's run to convert that into an intermediate format that the print driver can handle. The print driver is run for printers that need more processing than say a PostScript printer where it could take the PostScript data directly.
And then the port monitor does any additional encoding for the interface that you're using. So for example with a PostScript printer you might use BCP or TBCP to encode the print data so you can print raw binary data. It could also be used for doing 1284 packet framing and so forth.
All that gets piped into the back end which then communicates with the printer and the printer starts printing something out. Now in CUPS 1.2 we also have back channel support. So if the printer goes back and says hey something's gone wrong or I'm low on ink or the paper tray is empty, the back end can feed that data back to the port monitor and the driver. So either one of those can actually handle the back channel data and actually inform the user what's gone wrong.
Now beyond the local printing scenario, printer sharing is very common. You have a laptop, you have a desktop machine, a wireless network, all that stuff at home. Or in the office environment, you have a centralized print server, and you have all the client machines you want to print to it.
CUPS was designed from the ground up to make that simple. Previously, you'd have to manually add remote printers on a client machine, and if you have 1,000 client machines, you've got to do that 1,000 times. We didn't want that to be the user experience with CUPS. So from the very beginning, we've had this idea that a CUPS server, the scheduler, can simply share out its printers, and the clients will automatically see those printers. In CUPS, a server is just any system that's sharing one or more printers. So if you aren't sharing printers, it's not visible to the network.
What happens is the clients will forward the jobs that are printed on the local application to the remote system, wait for it to complete on the remote system, and then remove its local copy. So if something goes wrong on the server, your job isn't lost. It'll just get reprinted when that printer comes back up.
And something that's really unique to CUPS is this notion of automatic load balancing and fail-safe printing. If you have more than one server providing access to the same printer or even different printers with the same capabilities, CUPS can automatically merge those, or you can do it manually, so that you have a round-robin printing approach, printer pooling, that when you print to a particular queue, it goes to the next available printer in that class. And if one of the servers goes down, it automatically switches to another server to get that job printed. So it's very popular among our enterprise customers. obviously you don't see it too much in the home.
And to show it graphically, the scheduler on the client will run the IPP backend to communicate with the scheduler on the server and get the print job done. And then the scheduler on the server sends back a message to the client saying, "This job is printed." And the IPP backend then informs the scheduler on the client, "This job is completed.
You can remove it." Now, in order to find these printers, we actually have two different sharing protocols that are supported on Mac OS X. The first one is Bonjour. It's a lot newer and it's available in Tiger. And basically, it allows you to do it on the cheap. You can advertise that you have a resource available, but until somebody asks for that resource, it doesn't actually clutter up the network with any packets. The other real advantage with the Bonjour sharing is it doesn't depend on any infrastructure, such as a domain name server.
So if you have a home system set up and you're calling it Mac Pro and you have your MacBook, you can look at MacPro.local and it doesn't matter what IP address has been assigned to it, it'll find it. Whereas with a traditional managed network, you've got to know the IP address or the fully qualified domain name or that sort of stuff. So Bonjour is really good. It's really great for the unmanaged network situation, and it's really great when you don't want to have a lot of network traffic. It's a default in Leopard, and please test it out. On the other side of things is our original CUPS protocol.
It's what the Bonjour folks would call chatty, in that it broadcasts periodically to say, "I have these printers available," and then expects the client systems on that network to pick up on that information and then make it available to the user. It's a default in Tiger. It's still available in Leopard if you need it. It's the only protocol that's supported on non-Mac OS X clients at this time. And we find it most useful when you have managed networks and large numbers of printers because the current Bonjour implementation doesn't scale beyond about 300 printers on a server.
And I'll show this a little graphically. The Bonjour printer sharing, the client systems will send out a query, "I'm looking for a printer," and then the server system's going to respond, "I have these printers," and then you'd see it in the printer browser and select the printers that you want to use. The CUPS printer sharing architecture is a little bit different, where the server system just announces, "Hey, everybody, I've got all these printers," and then expects anybody that's on that network to listen and to keep track of that information.
Now, when you're supporting non-CUPS printers, you're still back to that old, okay, now I have to point it at the server and set up the remote queue. We do support that, though, because we have a lot of customers that work with legacy clients. On the Windows side, you can print via IPP or Samba, the SMB protocol. Both methods require a Windows printer driver, and we do have a CUPS specific driver for Windows available on the CUPS website.
And you use several different programs to access that. On the Samba side, you use CUPS@SMB as a command line utility or the new web interface to export your printers to the Windows clients. And for the Windows side, if you're going to use IPP, we actually have a free Windows client that you can download that will use IPP and that same CUPS driver to print.
For the Samba method, you'll see the Windows Print Service communicate with Samba via SMB, and then Samba via the CUPS API will talk IPP to the scheduler to actually get the job printed. It also does print status, printer lists, and all that sort of stuff via that same API.
For a Unix client, you're going to use the LPD protocol. We have what we call a mini-daemon program. It's CUPS LPD. It's normally run from XINETD in the open source world, and that's what you get with Tiger. But in Leopard, we're now using LaunchD, just the nice common server starter for Mac OS X.
And basically, it handles all of the LPD protocol stuff and converts it into IPP for the scheduler. Unix clients will typically use an interface script or some other application-defined print driver and send text or postscript, and then the Mac system can interpret that and get it into something the print driver can print.
Worth noting here is that the options, because LPD doesn't support passing of options, you have to specify them with the LP options command or in 1.2, the LP admin command, so that the defaults are there for whatever you want those users to do. And again, a little graphic. The UNIX Print Spooler will talk via LPD to the CUPS daemon there for LPD. It will use the CUPS API to talk to the scheduler, get the job printed, show the printer status, all those sorts of things.
[Transcript missing]
Now, as a user, there's two main things that you're going to see as improvements in 1.2. The first one is that printer sharing works a whole lot better. Before, every time you rebooted your system, you'd kind of start from scratch. Your shared printers would appear and disappear, and it just wasn't a great user experience.
So you've added a cache to that that keeps those printers available, so you don't have that disappearing printer problem. But if you do change networks, you go to an internet cafe or something, then any of those shared printers from the previous network are going to disappear. On the printer setting side of things, we now support PPD files with multiple languages.
So for you driver developers, this means you can ship one PPD to support 20 languages, and you can have the same PPD support users with reading different languages. So you can have a printer that's going to be able to read the same language as you do in your office.
Somebody reads French, somebody reads English, somebody does German. You don't have to decide on a common one, English, just because that's the only one that you can all agree on. You can actually all have the language of your choice. The generic PostScript printer PPD that's included with the Leopard seed does include languages for all the supported locales, and whenever you install a printer, you plug it in, it's now going to use the correct language. And support all of them rather than just the default language. When you do the options in your driver, you can now provide custom options without writing a custom PDE.
The crux of this is basically we have certain developers where you need a passcode or a type in option for a watermark. And I'll show examples of those in a little bit that you don't just want to have a bunch of standard choices. You want to actually have the user type those in. So you can now do that, and the user will now have the ability to select that without having to go to a separate PDE panel.
Now, if you're an administrator, we've added a whole bunch of stuff for you. The biggest one, the number one that we kept getting requests for was IP version 6 support. It's flung through the whole system, and the only thing that doesn't use IP version 6 right now is the CUPS protocol for browsing, but if you use the Bonjour, you get IP version 6 there.
We also added support for automatic SSL detection, so instead of having a separate port number for your encrypted versus non-encrypted traffic, you can now do it over the same port number, so you get the advantages of the automatic upgrade to encrypted status, whether you're on a web browser or in a CUPS client.
For printer sharing, we now support server-side defaults and timeouts. So when you're configuring your printers on the server, you can actually say the default for the page label or for the job hold until is now this specific value. That gets out to all the clients, so they immediately will use that as well.
Mike Sweet Previously, you would have to run LP options on every system and hope that those options would be honored in all applications. The timeout allows you to specify a different browse timeout with the CUPS browsing protocol. And basically, before, you'd have to change the timeout on every client. Now you can just change it on the server to what's appropriate for that server, and the clients will use that timeout when they're figuring out when to get rid of a printer.
The last thing here on the slide is SNMP based network printer detection. What's in 1.2 is the first attempt. We have a lot of feedback and I encourage you to provide more feedback if you don't see your point being made in the bug database. Mike Sweet But basically now it will find any printer that uses the host MIB and automatically show it in the web interface, in the GUIs, and on the command line when you want to find a printer. We're going to be updating it some more to deal with some edge cases and also to not advertise a printer via both Bonjour and SNMP.
Because of that, we're looking at this as a supplement to Bonjour. All the printers don't support it, so we still want to give the user a chance to use it. We want to give the user the ability to find their printers easily rather than going to the printer and hitting the test page on the printer to get that. The local device detection all works in with this as well. So basically any new printer that gets added on the network or on the local machine is detected by CUPS now.
So, you saw the printer browser on the previous presentation if you were here. Basically, you can now see all the printers for individual protocols or for all protocols. You can filter and search and everything. This is all made possible by all of the infrastructure in CUPS to find devices.
Now, if you're a power user or an administrator that has to manage a lot of different systems, you may have looked at the web interface. It's pretty much the one that everybody depends on in the open source world, but it's something that's available if you're going to want to use it. I'm going to show you some of the new features in the web interface.
Big things we have new online help systems searchable and you can extend it if you like. All of the pages are searchable, pageable, and you can change the order of things. Because of the new network printer discovery support, we can now support things like add this printer and it will add the printer. And over the years we've gotten the same question from many different people.
How do I turn on debugging? How do I allow people to print to my system? How do I enable sharing? Those are now just check boxes that you can do and will automatically set those things up. And finally, we're now integrated better with Samba. So instead of having to use the command line, you can do it all from the web interface and you get all the same benefits.
Now, the help system is pretty basic. You have a search bar at the top. You have a topic section on the side. And every time you go into a document, that expands and shows you the current documents table of contents, the current section, what documents are in it, and all the sections that are available.
Now, the help system is pretty basic. You have a search bar at the top. You have a topic section on the side. And every time you go into a document, that expands and shows you the current documents, table of contents, the current section, what documents are in it, and all the sections that are available. Printers is a button that says export printer to Samba. And basically, that's the equivalent of the CUPS add SMB command, but through the web interface. Gives you a nice little list of printers, and you can export all of them if you'd like.
There's direct access now via HTTP to the CUPSd.conf file and all the log files. They are also access controlled, so if you want only people that have certain privileges, they will get a challenge for the password and all that stuff. And you can limit it to only your network or particular IPs if you would like to do it that way. Right underneath that is the simple settings, and right now there's five items there. Just to run through them quick, show the printers that are available on other servers, that's a default. Share the printers that I've got.
Allow other users to cancel your jobs. Allow remote administration, so if you want to set up a bunch of servers and have them allow remote administration, you just check that and then, you know, that's the only change you need to do. And then the last one, enable debug logging, allows you to track down problems more easily.
And if you're doing tech support for your team, and you have a lot of users and they don't know why things aren't working, you can just say, "Click on this and then we'll look at the log file." Now, underneath the printers there, you have the standard operations, but then it also shows you when it finds new devices. And the way it does this is it goes out, sees what devices are available, and sees what devices have been added, and then gives you the list of stuff that hasn't been added that actually has a make and model associated with it.
Each one will have a little button that says, "Add this printer." When you click on that, it takes you right to the make and model selection page, and it'll preselect the driver if you have it available. It chooses the best match for the printer. You click "Add Printer," and you get your printer page. So it's very quick to add network printers now. Similar experience in Mac OS X, and we're trying to have feature parity between the GUI, the command line, and the web interface. So I think we're getting a lot closer with that.
As you notice in here, the job information for a particular printer is now searchable and pageable as well. There aren't any jobs in this particular screenshot. And we've also added the ability to show the completed jobs, the active jobs, and all jobs in the system. So as soon as you click on Show Completed Jobs, it'll show you from the most recent to the least recent. You click on Active Jobs, it shows you the next job that's going to be printed and all jobs, it does so as well.
Now, we've had a lot of requests from people saying, "I want to not stop the printer when something goes wrong talking to it." So we've added per-printer error policies. This feature is probably going to be expanded again in CUPS 1.3. We have three basic policies right now. You can stop the printer, the default, and that's what we did before.
You can tell it to retry the job, and the way that works is just like with a fax queue. It'll keep retrying for a certain number of times at a certain interval, and when it finally can't get to the printer, it'll give up on it and cancel the job. Or you can just say, "Cancel the job right away. I don't want the queue to fill up." So that's available through the web interface. It's available through the command line, and you can set it to any one of those three right now. There'll be more later.
Another common complaint has been that you can't configure what individual users can do. Over the years, people have gotten in the habit of putting in location lines in their Cupsd.conf and saying, OK, for this web interface task to start a printer, I want to have this particular set of permissions. And the problem with that is only applied to the web interface. It didn't affect the command line or the GUI.
So what we've done is we've come up with a replacement for that mechanism called policies. And what you basically do is you create a policy with a name, and then you use all the same sort of location-based access control lines-- allow, deny, require, and so forth-- for individual IPP operations.
So you can say, I want all users to be able to print and start and stop printers, but I don't want them to be able to add a printer. Now, each printer can have its own policy. And then there's a default policy that's used for the server-level operations, such as adding and deleting printers.
Now, we have a little sample policy, really simple. Only thing we want to do is limit send document to the person that actually created the job. So we don't want somebody piggybacking on somebody else's jobs, but other than that, they can do just about anything they want. So you put this in the CUPSd.com file, which you could do through the web interface, and then select that policy for that particular printer, which you can also do from the web interface.
We get a lot of questions on the CUPS forums about the log messages that they're seeing in the access log in particular. Why do I see a post every five seconds? Any number of things. And you just don't know what's going on there. Well, we extended the access log format a little bit to add the IPP operation and status code from that operation to any posts that are IPP operations. So now, if you look in your access log, you'll see get default and get printers and so forth and whatever status they return. So you know kind of what's going on in the system without having to delve into the error log file.
If you're supporting LPD clients, we now support banner pages and multi-file LPD jobs are now created as a single CUPS or IPP job rather than a series of individual ones. That should make things work a whole lot more consistently within your environment and that way too you don't have people's jobs getting mixed in with others.
And if you're trying to track jobs on multiple servers, we've added two new attributes to handle that. One is the job UUID attribute. It's UUID as defined by the RFC. Basically, it gives you a unique ID to track that job throughout the network, over the Internet, anywhere the job goes, it's included in any transactions. The other attribute is the job actual printer URI, and the difference between that and the job printer URI is that it actually corresponds to the printer that printed the job versus printing to a class and then it gets sent off to some other printer or server.
For you CUPS developers, general improvements in all of the APIs, they're all now thread-safe. We added thread safety fairly late in the 1.2 development process, but it's been in various states in Tiger as well and 1.1. And basically, now whenever you're doing a threaded application, you can feel pretty safe that you're not going to have any issues. The only thing you have to be careful about is if you're sharing data structures between threads, that we don't guarantee that thread safety just for function calls and using your own connections and so forth.
For URIs, we found that, you know, every release we would come out with a new rev of the URI APIs, and we finally came up with a generic enough API that will work for all special cases that we could come up with. So you want to look at the HTTP Assemble URI, and separate URI APIs if you're going to be dealing with printer URIs in particular. They handle all of the internationalization issues with doing percent encoding for international characters in the URIs, any specific issues with encoding for you. And when you pull them apart, you can also specify that you want certain parts of the URI encoded or decoded as needed.
They also support some error checking, so if you have a URI, you're not sure about, you can use the separate URI API to validate that URI, and we use that within CUPS pretty extensively. There's new address APIs to handle all the different address formats. Previously, we just did IP version 4 throughout, and it was pretty limiting, so we came up with a generic address structure that encapsulated all the formats that we support and in the future that we could add.
So if you're doing any kind of address manipulation with CUPS, use these APIs. They'll save you a lot of time. They handle IP version 4, version 6, and domain sockets right now. And if in the future we come up with some other network protocol that we need to support, that'll get rolled into that without any changes to your code.
We're also in the process of making the HTTP type structure private. In the 1.2, it is still available, but it's historically been marked as a private structure, but just in the public header. Because of the changes we had to make for large-scale, large file support, while we've been able to keep the structure binary compatible, for application developers, as we go forward, we want to make sure that you can just keep coding to the interface and not to the structure.
So there's new accessor APIs for all of the data that's in the connection structure. Use those instead of accessing it directly. We've had some problems on the open source side with that, but I think it should be pretty well resolved. On the IPP side, there's new convenience APIs for creating attributes and requests. If you're doing a lot of attribute creation or request creation, you'll probably find that using those new functions will save you a lot of code.
The IPP new request function is part of that, and when we switched to using that within the CUPS source tree, we cut down about 1,200 lines of code. So a pretty significant savings. One of the nice things in CUPS 1.2 is now you get an actual error message along with the status code.
That's exposed with the CUPS last error string API. So anytime you do an IPP request, it will set the CUPS last error and CUPS last error string value, and you can use that rather than trying to fish through the attributes to find the status message attribute and display an actual error message to the user. Now instead of just client error not found, you're going to see printer foo doesn't exist.
IPP notifications are something that the printer working group has been developing for quite some time. They finally got standardized last year and basically it was one of the big features that we wanted to get into CUPS 1.2 because it gets away from polling for status to notify me when something has changed.
Excuse me. The way it's implemented in CUPS is that we have a series of notifier helper programs that are run to deliver any event messages to the recipient. We include an email notifier with CUPS 1.2. But because in the Mac OS world, you're typically using some sort of a POP or IMAP account, it's not all that useful unless you have your own mail server.
There's a mailto.conf file that you can look at that defines all of the configuration options for that. Once it's configured, it works really well. Because there's no way to use that standard email notification mechanism, there's no user interface exposed in Mac OS X. But a PDE can add the notify events and notify recipient URI attributes in your print settings to actually get a notification created with the print job. This might be used for communicating with your own desktop application that is providing some additional feedback to the user to do manual duplexing or something of that nature.
In order to support notifiers, we have two APIs, notify subject and notify text. They give you a standard message that you can feed to the user based on an event message. And that, combined with writing a little notifier program that goes in the directory called notifier, you can actually have your own notifiers communicate with the user in various ways, instant messaging, paging, whatever the case may be.
For the PPD API, and that's now more exposed in the top levels, there's a new function to handle the multi-language PPD files. You run PPD localize, and it localizes the PPD file to your current language preference. Mike Sweet And we decided on using UTF-8 throughout because it's nice and compatible with the ISO Latin one and so forth that's normally used in the PPD world. And it's compact enough for what we need it for. Mike Sweet For the custom PPD options, there's some new functions to access those.
We modeled it off of the custom page size mechanism that's already present in the PPD spec. Mike Sweet And you can do integers, read, and paste. Mike Sweet So we have fields, curves, dimensions, strings, passcodes, and passwords. Some of those are new. The passcodes, passwords, and curves are non-standard extensions to the Adobe spec, but basically allow you to have different kinds of input. Mike Sweet The curve is just a standard power curve that you could drag and have the user select that way. And then the passcodes and passwords are non-visible text fields. Passcodes for numeric stuff, passwords for alphanumeric.
Mike Sweet What we're recommending to developers is use these in conjunction with standard options. So for example, a watermark option, you might have draft, confidential, and so forth standard options, and then provide a custom option where they can enter their own text. Mike Sweet There's new APIs to access the options and the parameters, and each of the options can have one or more parameters associated with it. You'll see that in a sec.
Now, here's an example of a custom option that uses PGL to implement a passcode feature on a printer. Now, as you can see, we have the normal option code in the PPD file for that passcode option. And there's four standard options: none for no code, and then 1111, 2222, and 3333.
Obviously, users don't necessarily want to use those passcodes because they're not particularly secure, and if everybody's using the same one, then what's the point? So you add the custom JCL passcode option in there to specify the command to run. And if you notice in there, there is a backslash 1 in that code. That's used to substitute the value in for the PGL option. The param custom JCL passcode line just gives you the parameter for this particular option. Since this one, we just need one option, we just have one line.
In code, you just pass it through. It's the option name equals custom.value. So if you have 8675 for the passcode, you'd use JCL passcode equals custom.8675. And in your CUPS API, you'd add the option or use parse options to grab out a string, say, from the command line, and put that into an option string, which then gets passed into a print job. Similar things happen on the print manager side.
For PostScript custom option, it works a little bit different because with PostScript options, the values actually get pushed on the stack and then the code gets executed to pull those options off the stack. It's the same way that the custom page size works and we just decided to stick with that to be consistent.
Here we have a watermark option. You have none and draft of the two standard options. You have the custom code which will pull the string off of the stack and put it into a CUPS string one page attribute. And then the parameter for that is a text string from zero to 32 characters.
Again, we use the option name equals custom.value. If you have a value that contains a space, like top space secret, you'd put the value in quotes. So watermark text equals, quote, custom.top space secret, quote. And again, in the application code, it works exactly the same, including the single quotes around the value, and just pass that through in the print job.
Now, a more complex example, and this is kind of contrived, but say you have a control to control the overall gamma and density of the output to make it lighter, darker, and so forth. Have three standard options here, and then the custom page size-- custom code here actually pulls two values off of the stack. We define two parameters. One's called gamma, and one's called density.
And the value of the index 1 and index 2 defines the order that they're pushed on the stack. For multi-valued options, you actually use curly braces around it and then you use the named parameters. So you'd use gamma density equals gamma equals 1.0, density equals 0.5 in curly braces to specify that compound value. Again, same thing on the CUPS code.
If you're developing a printer driver or a back end that talks to a printer, you can now do back channel data. And the way we've implemented it is as a non-blocking pipe between the back channel and the filters upstream. There's two functions to actually access this information. Back channel read reads the data from the back end into the driver or filter, and back channel write writes it from the back end to the driver or filter.
There's a timeout in there so you can say, "If I don't get a response back within one second, then this printer doesn't support back channel data, so I'll use the unidirectional mode of my driver." If you're doing anything with PostScript or JCL options in your own drivers, there's a PPD emit JCL end which handles any cleanup PGL that needs to be put out for a particular printer.
And then the emit string which is a more general purpose function for actually collecting all of the options for a particular section and putting them into a string that then you can put in memory or send out to a file or send out to the printer. And we use this with a new PostScript filter in CUPS to better support different page layout options and get things out to the printer correctly.
If you're doing a raster driver, we've expanded the amount of information that's put in the page header, largely in response to the Gutenprint folks, but this will be useful for everybody, I think. There's a borderless scaling factor attribute that's in there that corresponds to the scaling factor that was used for a borderless print.
That comes from Tiger and has been forwarded into the raster format, so now you don't have to guess at what value was used. It's in there. Similarly, we've added floating point page sizes and imageable areas so that if you have a page size that is not an integral number of points, you can actually get the actual dimensions at a much better resolution. And if you have letter and letter full bleed and the sizes are the same, well, you can get the size name now. It tells you it's letter or letter.fullbleed.
There's marker type and rendering intent string options that you can control that in your driver. You're going to be using a particular set of inks or you're using a particular rendering model. That information can be passed through and would be passed through from a client as well, so you don't have to depend on a PDE for that. And then there's general purpose integer, real, and string attributes that you can use for anything.
In order to support this, we have three new APIs. The first one is most useful if you're doing a RIP. It's CUPS Raster Interpret PPD. It takes the commands and stuff that are in the PPD and the options that the user specified and generates a page header from that that you can use. It also has a callback interface so that if the user is asking for something that the RIP doesn't support, you can say hey, wait a minute, I need to fix this. And the Interpret PPD function then handles that situation for you.
The Raster Read Header 2 and Raster Write Header 2 functions do the new CUPS Raster format header so that you get all of the extended page attributes. If you don't use these, the old APIs, Read Header and Write Header, automatically handle expanding and dropping the data that you don't need.
Something new in CUPS 1.2 is the port monitor interface. Previously, you'd have generic filters, then a print driver filter, and then talk directly to the back end. And if you wanted anything special to happen between that driver and the back end, you had to write a new back end. Now we have a port monitor interface that sticks between the driver and the back end so that if you need to do any special protocol conversions such as TBCP or BCP or 1284 packet encoding or anything of that nature, you can put it there.
I also recommend if any of your users do any kind of raw printing that you use this to do printer accounting, ink monitoring, that sort of thing, there rather than in the driver because it will give you a better user experience. In order to support different port monitors for different interfaces, we have a new attribute you can specify in the PPD, CUPS Port Monitor, and basically in this example here, you can say when I'm talking via socket connection, I need to use TBCP because it isn't an 8-bit clean channel, but when I'm going via USB, I don't need anything. And we have TBCP and BCP port monitors in CUPS.
When you're running as a back-end, previously you always ran as the root user. We've changed that in 1.2. It's probably the only incompatible change from a program standpoint. Basically, if the back-end has world execute privileges, it gets run as LP. If it doesn't, it gets run as root. So if you're shipping a driver right now or back-end that needs to run as root, just change the driver to have mode 700 in your package, and that will work for both tiger and leopard.
[Transcript missing]
The backends, when you're advertising your device, you can now include the 1284 device ID in your advertisement. This allows for better automatic driver selection. We know that if a printer has a certain device ID, it corresponds to this exact driver on the system. So I encourage you, if you're doing your own backends, add support for that if you can. All of the standard CUPS backends do that now.
And instead of getting a static snapshot of what the devices were when you booted the system or when you first requested the list, we now run the backends every time somebody asks for a list of devices. So in the web interface, you go to the admin page, ask for the devices. You go to add a printer in your printer browser, it asks for devices.
So keep in mind that your backend might be run more frequently in the discovery mode than originally. Because we don't keep track of the devices that are available on the system beyond when somebody asks for it, we now only validate that the URI is compliant with the corresponding RFCs and the scheme is registered as a backend.
So keep in mind that your back end might be run more frequently in the discovery mode than originally. Because we don't keep track of the devices that are available on the system beyond when somebody asks for it, we now only validate that the URI is compliant with the corresponding RFCs. And the scheme is registered as a back end. So you can't use this to dynamically control what options are available all the time. But it can give you a snapshot when you first add the device.
If you're going to update your PPD, you can do that from your port monitor, your back end, or your driver, and enable certain options. It's got the duplexer now, or it doesn't have the duplexer, and that sort of thing. What we're going to use it for in the Gutenprint drivers is to provide virtual drivers.
And basically, the Gutenprint drivers are capable of generating their own PPD files already. We've been doing that for many years now. But generating static files that can then be distributed, now we'll be able to do a driver interface that lists all the drivers in there, and then just provide the one that you're actually going to use.
So it'll save 50,000 files and many megabytes of disk space that way. You can also use it for grabbing PPD files over the network, doing all sorts of dynamic stuff. It's a very general purpose interface. And we look forward to seeing what people do with it. There's a helper program called CUPS Driver D. You'll see whenever somebody's asking for the list of PPDs on the system. And it's now responsible for handling the PPD database that used to be managed by the scheduler. So you'll notice that things moved around a little bit that way.
So for CUPS 1.3, which is the next major release, that's where we're going to get Kerberos support in there. It's scheduled for release in October. So I know I say sometimes we're going to have a release out in a few weeks or a few months. We've actually changed our whole development process from the lessons we learned in 1.2 to say we're not going to try to lump in 90 new features into a minor release. We're going to do one or two, and maybe a few of the little ones there.
But we get them out more frequently, and there's less code churn between them. So as you're upgrading, you're not going to notice sudden huge changes that are going to completely disrupt your lives. So we're going to get the 1.3 out in October, and we'll have the Kerberos support. There's actually one of the Samba developers that's doing it as a Google Summer of Code project for us, and he did Kerberos support in Samba. So we're very confident that's going to come off very well, and that you can actually look at his progress.
So we're going to have the 1.3 version of Kerberos support in the CUPS Subversion Repository. So we want to get your involvement. We have a web page that handles the bug reports and feature requests for CUPS, and there's a roadmap page there. So if you're at all interested in shaping the future of CUPS, please go to our site. Please provide your feedback.
If you're running into problems, feel free to file bug reports with us. If it's something that's really Apple-specific, definitely file it with them. But we're interested in knowing about problems as well. And we can just keep working like we have been for the last four years and make CUPS even better.
If you're familiar with the CUPS book that's currently out, it's got a big squid on the front and there were some various allusions in that to printing. We're coming out with a new CUPS book, something that we're publishing, and no more squids. Just nice clean cover with the CUPS mascot. It's going to cover all of the new stuff in 1.2 and beyond.
It's also going to cover the CUPSDDK, ESP Go script, Gutenprint and so forth. And we've organized it differently so that it's more about I want to get this done, so here's the steps to get that done and then here's why these steps work. So it's a much more effective, I think, manual for learning how to use CUPS than the previous book.
That's also available in October. CUPS resources, you have the website, the forms and mailing lists are available there. The CUPS books are available there. The feature request page is there and the source code is there. So you can go and download the source code, download the universal package for Mac OS X Tiger and just have fun.
If you're doing something for Mac OS X specifically, there's the Apple bug reporting page. Make use of it when you find a bug. We can't fix bugs we don't know about. And the printing list, if you have questions, especially if you're developing software, this list is great. I'm there and a lot of the Apple developers are there helping out, answering questions about the printing system and how to do things.
And finally, the open source printing page, that's where you get the actual copy of this CUPS source code that's included with a particular Mac OS X release. And if you want to rebuild it yourself and play around with it, start there because there are differences between the standard CUPS software and CUPS.org and what Apple provides. Mainly, as we're syncing things up, they're a little bit further ahead than we are.
As a developer, there's online documentation now. All the APIs are documented with online help on the web interface, so bookmark that. And we have a driver developer kit. If you're writing a printer driver for CUPS, this is what you should be using, whether you're using it for your actual printer driver or just generating the PPD files. We have utilities now to actually merge multiple single-language PPD files into a single multi-language PPD file.
So if you're even not going to use the PPD compiler in the DDK, but you want to do stuff and support Mac OS X more quickly, use this utility. It'll save you a whole bunch of time, and you can move on to more exciting things. There's standard drivers for PCL and Epson printers in the DDK. If you have a multifunction device that just uses one of those standard languages, you can use those drivers freely. They're GPLed.