submit_job.c revision 0a44ef6d9afbfe052a7e975f55ea0d2954b62a82
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <libintl.h>
#include <syslog.h>
#include <stdarg.h>
#include "misc.h"
/* lpsched include files */
#if defined PS_FAULTED
#endif /* PS_FAULTED */
#include "lp.h"
#include "msgs.h"
#include "printers.h"
#include "class.h"
#include "requests.h"
#include "secure.h"
#define PROTOCOL_MAX 1000
#define LP_UID 71
/*
* This function replaces characters in a string that might be used
* to exploit a security hole. Replace command seperators (`, &, ;, |, ^),
* output redirection (>, |), variable expansion ($), and character
* a real library for LP, this should go in it.
*
* Bugid 4141687
* Add ( ) < * ? [
* Remove \
*/
static void clean_string(char *ptr)
{
char *cp;
cp++;
continue;
}
if (len == 1 &&
(wc == L'[')))
*cp = '_';
}
}
/*
* mail() will send a mail message to the requesting user in the event of an
* error during job submission.
*/
static void
{
char *uname;
char *mail_zonename = NULL;
/*
* to enter reader mode
*/
uname++;
if (*uname == '\0')
return; /* No username found */
/*
* If in the global zone and the system is labeled, mail is
* handled via a local labeled zone that is the same label as the
* request.
*/
(char *)-1) {
/* error during get_labeled_zonename, just return */
return;
}
}
/*
* in the labeled zone 'mail_zonename'.
*/
if (mail_zonename != NULL) {
} else {
uname);
}
return;
gettext("(unknown)")));
}
/*
* is_postscript() will detect if the file passed in contains postscript
* data. A one is returned if the file contains postscript, zero is returned
* if the file is not postscript, and -1 is returned if an error occurs
*/
#define PS_MAGIC "%!"
#define PC_PS_MAGIC "%!"
static int
is_postscript(const char *file)
{
char buf[3];
int fd;
return (-1);
return (-1);
}
return (1);
else
return (0);
}
/*
* name_to_id_no() will pull the id number out of a file name and attempt to
* assign that ID to a print job. If the ID collides with an existing one, it
* will increment and try again. This continues until an open ID is found, or
* the ID space is exausted.
*/
static int
name_to_id_no(const char *name)
{
int done = 1;
int start;
int id;
int fd;
return (-1);
start = 0;
do {
id %= PROTOCOL_MAX;
if (--id < 0)
"No Request IDs available");
return (-1);
}
}
} else
done = 0;
} while (done != 0);
return (id);
}
static void
unlink_files(char **files)
{
}
/*
* parse_cf() will pass through the BSD Control file data and fill in a
* request structure will all the information it can. The actual job data
* files will not be placed in the request by this function.
*/
static REQUEST *
{
*entry,
*s,
int copies_set = 0,
count = 0,
pr_specified = 0,
banner = 0;
copies_set++;
} else if ((copies_set == 0) &&
switch (entry[0]) {
/* RFC-1179 options */
case 'J': /* RFC-1179 Banner Job Name */
break;
case 'C': /* RFC-1179 Banner Class Name */
break;
case 'L': /* RFC-1179 Banner toggle */
banner = 1;
break;
case 'T': /* RFC-1179 Title (pr) */
break;
case 'H': /* RFC-1179 Host */
/* use the host as known by us, not by them */
break;
case 'P': /* RFC-1179 User */
++entry;
*s = '_';
break;
case 'M': /* RFC-1179 Mail to User */
break;
case 'W': /* RFC-1179 Width (pr) */
break;
case 'I': /* RFC-1179 Indent (pr) */
break;
case 'N': /* RFC-1179 Filename */
/* could have HP extension embedded */
break;
case 'U': /* RFC-1179 Unlink */
break; /* ignored */
case '1': /* RFC-1179 TROFF Font R */
case '2': /* RFC-1179 TROFF Font I */
case '3': /* RFC-1179 TROFF Font B */
case '4': /* RFC-1179 TROFF Font S */
break;
case 'f': /* RFC-1179 ASCII file (print) */
case 'l': /* RFC-1179 CATV file (print) */
else
}
break;
case 'o': /* RFC-1179 Postscript file (print) */
break;
case 'p': /* RFC-1179 PR file (print) */
pr_specified = 1;
break;
case 't': /* RFC-1179 TROFF file (print) */
break;
case 'n': /* RFC-1179 DITROFF file (print) */
break;
case 'd': /* RFC-1179 DVI file (print) */
break;
case 'g': /* RFC-1179 GRAPH file (print) */
break;
case 'c': /* RFC-1179 CIF file (print) */
break;
case 'v': /* RFC-1179 RASTER file (print) */
break;
case 'r': /* RFC-1179 FORTRAN file (print) */
break;
/* Sun Solaris Extensions */
case 'O':
++entry;
do {
if (*entry != '"')
} while (*entry++);
break;
case '5':
switch (entry[1]) {
case 'f': /* Solaris form */
break;
case 'H': /* Solaris handling */
else
"handling (%s): unknown",
entry[2]);
break;
case 'p': /* Solaris notification */
/* request.alert = strdup(&entry[2]); */
break;
case 'P': /* Solaris page list */
break;
case 'q': /* Solaris priority */
break;
case 'S': /* Solaris character set */
break;
case 'T': /* Solaris type */
break;
case 'y': /* Solaris mode */
break;
default:
"Warning: cf message (%s) ignored",
entry);
break;
}
break;
/* HP Extensions */
/* Undefined Extensions */
default:
"Warning: cf message (%s) ignored", entry);
break;
}
}
/* The -p option must be specified with the -T, -w, and -i options */
if (pr_specified == 1) {
prtitle);
} else
"as the pr filter option was not specified");
if (width != -1)
if (pr_specified == 1) {
width);
} else
"as the pr filter option was not specified");
if (indent != -1)
if (pr_specified == 1) {
indent);
} else
"as the pr filter option was not specified");
if (banner != 0) {
} else
}
}
}
return (&request);
}
/*
* submit_job() takes in a printer, host, control file, and list of data files.
* it attempts to submit the print job to the local spooler using the lpsched
* local named pipe. The routine will auto-detect if the first data file
* is postscript, and set the job to "postscript". If an error occurs, a
* message is mailed back to the requestor.
*/
int
char **df_list)
{
char buf[MAXPATHLEN];
int file_no = 0;
int rc = -1;
char *tmp_dir;
char *tmp;
short status;
long bits;
int request_id = 0;
int job_size = 0;
return (-1);
return (-1);
"Error parsing control file, Contents:\n%s\n", cf);
return (-1);
}
++file_no);
}
"Job %d doesn't contain any data files", request_id);
return (-1);
}
/* submit the request */
/* save the request file */
gettext("Can't save print request"));
return (-1);
}
/* save the secure file */
gettext("Can't save print secure file"));
return (-1);
}
/* kick lpsched */
/* how did we do ? */
rc = -1;
switch (status) {
case MNOMEM:
gettext("lpsched: out of memory"));
break;
case MNOFILTER:
gettext("No filter available to convert job"));
break;
case MNOOPEN:
gettext("lpsched: could not open request"));
break;
case MERRDEST:
gettext("An error occured in submission"));
break;
case MDENYDEST:
gettext("Destination: %s, denied request"),
printer);
break;
case MNOMEDIA:
gettext("unknown form specified in job"));
break;
case MDENYMEDIA:
gettext("access denied to form specified in job"));
break;
case MNOPERM:
gettext("no permission for printer or job data empty"));
break;
case MTRANSMITERR:
gettext("failure to communicate with lpsched"));
break;
default:
gettext("Unknown error: %d"),
status);
break;
}
/* clean it up */
} else { /* It was OK */
rc = 0;
}
return (rc);
}