The most expedient method of gathering a list of printers is to execute the command "/usr/bin/lpstat -v". This command only performs a naming lookup and displays results. To use this programatically, an application can use the popen(3) function and parse the input stream.
/*
* Copyright (C) 1998, by Sun Microsystems, Inc.
* All Rights Reserved
*/
#pragma ident "@(#)popen_printer_list.c 1.2 98/05/11 SMI"
#include <stdio.h>
#include <strings.h>
main(int ac, char *av[])
{
FILE *fp;
if ((fp = popen("/usr/bin/lpstat -v", "r+")) != NULL) {
char buf[BUFSIZ];
while (fgets(buf, sizeof (buf), fp) != NULL) {
strtok(buf, ": "); /* eat system/device */
strtok(NULL, ": "); /* eat for */
printf("printer: %s\n", strtok(NULL, ": "));
}
fclose(fp);
}
}
When the lp command is invoked, the instance of the command parses the command line arguments and builds a print request. This request is actually derived from the command line options, configuration data, and the data to be print. Many of the lp(1) command line options set various request characteristics. These characteristics include datatype, filter options,. reporting actions, etc.
By default when an lp(1) request is made, the job data is printed by reference. What this means to an application submitting data to print is that it must tell lp(1) to copy the job data before printing if the data is kept in a temporary file. If the data is piped to lp(1), it will be placed in a temporary file automatically by lp(1).
Another atcion performed by the Solaristm; print server further down the line is a quick scan of the input data. It does this to attempt to auto-detect whether or the the print data is PostScript or not. If the data begins with "%!" or "^d%!" the print spooler lp(1) consideres the data to be PostScript. If the data is PostScript, but doesn't begin with "%!" or "^d%!" or the data is to print as simple text, but begins with either of these sequences, the application will need to add "-T postscript" or "-T simple" to get the desired result.
/*
* Copyright (C) 1998, by Sun Microsystems, Inc.
* All Rights Reserved
*/
#pragma ident "@(#)popen_submit.c 1.2 98/05/11 SMI"
#include <stdio.h>
#include <strings.h>
/*
* This file contains some relatively simple examples of how to submit print
* jobs to the LP system programatically in Solaris. The examples are
* complete enough to run, but should be tailored to your needs. Also,
* you will note that snprintf(3c) is used to avoid buffer overflow problems.
* This interface is not available until Solaris 2.6. Finally, it is important
* to note that popen(3) can fail because file descriptors 0-255 are in use.
* This is a file pointer limitation. If your application uses a large
* number of file descriptors, you may want to run lp via pipe(), fork()
* and exec() or simply via system() depending on your needs.
*/
/*
* Assuming that the command uses any user defined data, It is a good
* idea to replace some shell meta characters that may breakup the command
* and/or allow the user to run something of their own. Something like this
* is particularly important if the program is SUID.
*/
void remove_shell_meta_characters(char *command)
{
char *ptr = command;
while ((ptr = strpbrk(ptr, "`&;|>^$\\")) != NULL)
*ptr = '_';
}
/*
* This function returns a file pointer that can be used to send output
* to. Once the file pointer is closed, the job is submitted.
*/
FILE * fp_submit(char *printer)
{
char command[BUFSIZ];
snprintf(command, sizeof (command), "/usr/bin/lp -s -d %s", printer);
remove_shell_meta_characters(command);
return (popen(command, "w+"));
}
/*
* This function submits a file to print
*/
int filename_submit(char *printer, char *file)
{
char command[BUFSIZ];
snprintf(command, sizeof (command), "/usr/bin/lp -s -c -d %s %s",
printer, file);
remove_shell_meta_characters(command);
return (system(command));
}
/*
* sample job submission from an application
*/
main(int ac, char *av[])
{
char *printer = av[1];
char *file = av[2];
FILE *fp;
filename_submit(printer, file);
if ((fp = fp_submit(printer)) != NULL) {
fprintf(fp, "this is printing via a file pointer\n");
fclose(fp);
}
}
The examples found in this document can also be found in the PRINTtoys
package available for download via the web.