summaryrefslogtreecommitdiff
path: root/usr/src/lib/print/libprint/common/job.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/print/libprint/common/job.c')
-rw-r--r--usr/src/lib/print/libprint/common/job.c591
1 files changed, 0 insertions, 591 deletions
diff --git a/usr/src/lib/print/libprint/common/job.c b/usr/src/lib/print/libprint/common/job.c
deleted file mode 100644
index b379648d26..0000000000
--- a/usr/src/lib/print/libprint/common/job.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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"
-
-/*LINTLIBRARY*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <string.h>
-#include <dirent.h>
-#include <sys/mman.h>
-#include <sys/systeminfo.h>
-#include <syslog.h>
-#include <errno.h>
-#include <libintl.h>
-#include <grp.h>
-
-#include <job.h>
-#include <misc.h>
-#include <list.h>
-
-
-#define MAX_RETRIES (5)
-
-static char *_control_file_prefix = CONTROL_FILE_PREFIX;
-static char *_xfer_file_prefix = XFER_FILE_PREFIX;
-
-
-/*
- * _job_unlink_data_file() will unlink the path for the jobfile passed in.
- * this is only to be used with job_destroy() so it can iterate through
- * the job_df_list.
- */
-static int
-_job_unlink_data_file(jobfile_t *file)
-{
- syslog(LOG_DEBUG, "_job_unlink_data_file(%s)",
- ((file != NULL) ? file->jf_spl_path : "NULL"));
- if (file && file->jf_spl_path)
- return (unlink(file->jf_spl_path));
- else
- return (-1);
-}
-
-/*
- *
- */
-static void
-_job_file_free(jobfile_t *file)
-{
- if (file == NULL)
- return;
- if (file->jf_spl_path != NULL) free(file->jf_spl_path);
- if (file->jf_src_path != NULL) free(file->jf_src_path);
- if (file->jf_name != NULL) free(file->jf_name);
- if (file->jf_data != NULL) {
- if (file->jf_mmapped)
- (void) munmap(file->jf_data, file->jf_size);
- else
- free(file->jf_data);
- }
- free(file);
-}
-
-
-/*
- *
- */
-static void
-_vjob_file_free(jobfile_t *file)
-{
- _job_file_free(file);
-}
-
-
-/*
- * job_free() frees up memory mmapped for malloced
- * being used by the structure.
- */
-void
-job_free(job_t *job)
-{
- if (job == NULL)
- return;
-
- syslog(LOG_DEBUG, "job_free(%d, %s, %s)", job->job_id,
- (job->job_printer ? job->job_printer : "NULL"),
- (job->job_server ? job->job_server : "NULL"));
-
- if (job->job_printer) free(job->job_printer);
- if (job->job_server) free(job->job_server);
- if (job->job_user) free(job->job_user);
- if (job->job_host) free(job->job_host);
- if (job->job_cf)
- _job_file_free(job->job_cf);
- (void) list_iterate((void *)job->job_df_list, (VFUNC_T)_vjob_file_free);
-
- if (job->job_df_list)
- free(job->job_df_list);
-
- if (job->job_spool_dir)
- free(job->job_spool_dir);
-
- free(job);
-}
-void
-job_destroy(job_t *job)
-{
- char *name = NULL;
- jobfile_t *cf;
-
- if (job == NULL)
- return;
-
- syslog(LOG_DEBUG, "job_destroy(%d, %s, %s)", job->job_id,
- job->job_printer, job->job_server);
- if (chdir(job->job_spool_dir) < 0)
- return;
- (void) list_iterate((void *)job->job_df_list,
- (VFUNC_T)_job_unlink_data_file);
-
- /* lose privilege temporarily */
- (void) seteuid(get_user_id(job->job_user));
-
- if ((cf = job->job_cf) != NULL) {
- for (name = cf->jf_data; name != NULL;
- name = strchr(name, '\n')) {
- if (name[0] == '\n')
- name++;
- if (name[0] == CF_UNLINK) {
- struct stat st;
- char *path = strcdup(&name[1], '\n'),
- *p;
-
- if (stat(path, &st) < 0) {
- free(path);
- continue;
- }
-
- if (st.st_uid == getuid()) {
- (void) unlink(path);
- free(path);
- continue;
- }
-
- p = strdup(path);
- if ((p = strrchr(p, '/')) != NULL)
- *++p = NULL;
-
- if (access(p, W_OK) == 0)
- (void) unlink(path);
- free(path);
- }
- }
- }
- (void) seteuid(0); /* get back privilege */
-
- (void) unlink(cf->jf_src_path);
- (void) _job_unlink_data_file(cf);
- job_free(job);
-}
-
-static int
-get_job_from_cfile(jobfile_t *file, char *cFile, char *xFile, job_t *tmp)
-{
- jobfile_t *file1;
- int n_cnt;
- char *p, *cfp;
-
- /* map in the control data */
- if ((file->jf_size = map_in_file(cFile, &file->jf_data, 0)) <= 0) {
- syslog(LOG_INFO, "could not read control file (%s): %m, "
- "canceling %d destined for %s:%s",
- (file->jf_spl_path ? file->jf_spl_path:"NULL"),
- tmp->job_id,
- (tmp->job_server ? tmp->job_server : "NULL"),
- (tmp->job_printer ? tmp->job_printer : "NULL"));
- return (0);
- }
- file->jf_mmapped = 1;
- tmp->job_cf = file;
-
- /* look for usr, host, & data files */
-
- /*
- * Bugid 4137904 - "File Name" can be
- * anywhere in control file.
- * Bugid 4179341 - "File Name" can be missing
- * in control file.
- * Keep a separate pointer to the control file.
- * When a CF_UNLINK entry is found use the second
- * pointer to search for a corresponding 'N' entry.
- * The behavior is to associate the first CF_UNLINK
- * entry with the first 'N' entry and so on.
- * Note: n_cnt is only used to determine if we
- * should test for 'N' at the beginning of
- * the file.
- */
- cfp = file->jf_data;
- n_cnt = 0;
- for (p = file->jf_data - 1; p != NULL; p = strchr(p, '\n')) {
- switch (*(++p)) {
- case CF_USER:
- tmp->job_user = strcdup(++p, '\n');
- break;
- case CF_HOST:
- tmp->job_host = strcdup(++p, '\n');
- break;
- case CF_UNLINK:
- if ((file1 = calloc(1, sizeof (*file))) == NULL) {
- syslog(LOG_DEBUG, "cf_unlink: calloc() failed");
- munmap(file->jf_data, file->jf_size);
- file->jf_mmapped = 0;
- return (0);
- }
- file1->jf_src_path = strdup(xFile);
- file1->jf_spl_path = strcdup(++p, '\n');
- file1->jf_size = file_size(file1->jf_spl_path);
-
- if (cfp != NULL) {
- /*
- * Beginning of file. Check for first
- * character == 'N'
- */
- if ((n_cnt == 0) && (*cfp == 'N')) {
- cfp++;
- n_cnt++;
- } else {
- cfp = strstr(cfp, "\nN");
- if (cfp != NULL) {
- cfp += 2;
- n_cnt++;
- }
- }
- if (cfp != NULL) {
- file1->jf_name = strcdup(cfp, '\n');
- /*
- * Move cfp to end of line or
- * set to NULL if end of file.
- */
- cfp = strchr(cfp, '\n');
- }
- }
- tmp->job_df_list = (jobfile_t **)list_append((void **)
- tmp->job_df_list, (void *)file1);
- break;
- }
- }
- if (tmp->job_df_list == NULL) {
- munmap(file->jf_data, file->jf_size);
- file->jf_mmapped = 0;
- return (0);
- }
-
- return (1);
-}
-
-/*
- * job_retrieve() will retrieve the disk copy of a job associated with the
- * transfer file name passed in. It returns a pointer to a job structure
- * or a NULL if the job was not on disk.
- */
-job_t *
-job_retrieve(char *xFile, char *spool)
-{
- int retry_cnt = 0;
- char *s;
- jobfile_t *file;
- char cFile[BUFSIZ];
- char buf[BUFSIZ];
- int fd;
- flock_t flk;
- job_t *tmp;
-
- syslog(LOG_DEBUG, "job_retrieve(%s)", xFile);
- if ((tmp = (job_t *)calloc(1, sizeof (*tmp))) == NULL) {
- return (NULL);
- }
-
- if ((file = calloc(1, sizeof (*file))) == NULL) {
- free(tmp);
- return (NULL);
- }
-
- flk.l_type = F_RDLCK;
- flk.l_whence = 1;
- flk.l_start = 0;
- flk.l_len = 0;
-
- (void) memset(buf, NULL, sizeof (buf));
- /* get job id, from binding file name */
- (void) strlcpy(buf, xFile + strlen(_xfer_file_prefix) + 1,
- sizeof (buf));
-
- buf[3] = NULL;
- tmp->job_id = atoi(buf);
-
- /* Construct data file and control file names */
- (void) strlcpy(cFile, _control_file_prefix, sizeof (cFile));
- (void) strlcat(cFile, xFile + strlen(_xfer_file_prefix),
- sizeof (cFile));
-
- /* remove data file and control file whenever xFile is removed */
- if ((fd = open(xFile, O_RDONLY)) < 0) {
- syslog(LOG_DEBUG, "job_retrieve(%s) open failed errno=%d",
- xFile, errno);
- if (get_job_from_cfile(file, cFile, xFile, tmp))
- job_destroy(tmp);
- free(file);
- free(tmp);
- (void) unlink(xFile);
- (void) unlink(cFile);
- return (NULL);
- }
-
- /*
- * If failed to get a lock on the file, just return NULL. It will
- * be retried later.
- */
- if ((fcntl(fd, F_SETLK, &flk)) < 0) {
- syslog(LOG_DEBUG, "job_retrieve(%s) lock failed errno=%d",
- xFile, errno);
- close(fd);
- free(file);
- free(tmp);
- return (NULL);
- }
-
- /*
- * Retry a few times if we failed to read or read returns 0, just
- * to make sure we tried hard before giving up. In practice,
- * there were cases of read() returning 0. To handle that
- * scenario just try a few times.
- */
- for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
- if ((read(fd, buf, sizeof (buf))) > 0) {
- close(fd);
- if ((s = strtok(buf, ":\n")) != NULL)
- tmp->job_server = strdup(s);
- if ((s = strtok(NULL, ":\n")) != NULL)
- tmp->job_printer = strdup(s);
- syslog(LOG_DEBUG, "job_retrieve(%s) success - %s:%s",
- xFile, tmp->job_server, tmp->job_printer);
- break;
- }
- }
- /*
- * If failed to read after MAX_RETRIES, return NULL and remove xFile,
- * and cFile.
- */
- if (retry_cnt == MAX_RETRIES) {
- syslog(LOG_DEBUG, "job_retrieve(%s) unsuccessful", xFile);
- if (get_job_from_cfile(file, cFile, xFile, tmp))
- job_destroy(tmp);
- free(file);
- free(tmp);
- (void) unlink(xFile);
- (void) unlink(cFile);
- return (NULL);
- }
-
- file->jf_src_path = strdup(xFile);
- file->jf_spl_path = strdup(cFile);
-
- if (!get_job_from_cfile(file, cFile, xFile, tmp)) {
- (void) unlink(file->jf_spl_path); /* control file */
- (void) unlink(file->jf_src_path); /* binding file */
- free(file->jf_src_path);
- free(file->jf_spl_path);
- free(file);
- free(tmp);
- return (NULL);
- }
-
- tmp->job_spool_dir = strdup(spool);
- return (tmp);
-}
-
-
-/*
- * job_compar() compare 2 jobs for creation time ordering
- */
-static int
-job_compar(job_t **j1, job_t **j2)
-{
- int server;
- int printer;
- struct stat s1,
- s2;
- jobfile_t *f1 = (*j1)->job_cf,
- *f2 = (*j2)->job_cf;
-
- /*
- * If there is a null value, assume the job submitted remotely.
- * Jobs submitted remotely take precedence over those submitted
- * from the server.
- */
- if (((*j1)->job_server) == NULL || ((*j1)->job_printer) == NULL ||
- ((*j1)->job_cf) == NULL)
- return (-1);
-
- else if ((*j2)->job_server == NULL || (*j2)->job_printer == NULL ||
- (*j2)->job_cf == NULL)
- return (1);
-
- server = strcmp((*j1)->job_server, (*j2)->job_server);
- printer = strcmp((*j1)->job_printer, (*j2)->job_printer);
-
- if (server != 0)
- return (server);
- if (printer != 0)
- return (printer);
-
- if ((stat(f1->jf_spl_path, &s1) == 0) &&
- (stat(f2->jf_spl_path, &s2) == 0))
- return (s1.st_ctime - s2.st_ctime);
-
- return (0);
-}
-
-
-/*
- * job_list_append() reads all of the jobs associated with the printer passed
- * in and appends them to the list of jobs passed in. The returned result
- * is a new list of jobs containing all jobs passed in and jobs for the
- * printer specified. If the printer is NULL, all jobs for all printers
- * are added to the list.
- */
-job_t **
-job_list_append(job_t **list, char *printer, char *server, char *spool)
-{
- struct dirent *d;
- DIR *dirp;
- job_t *job;
- int i, found = 0;
-
- syslog(LOG_DEBUG, "job_list_append(0x%x, %s, %s)", list,
- ((printer != NULL) ? printer : "NULL"),
- ((server != NULL) ? server : "NULL"));
-
- /*
- * 4239765 - in.lpd segfaults performing strcmp()
- * in job_list_append()
- */
- if (server == NULL) {
- server = "";
- }
-
- if ((dirp = opendir(spool)) == NULL)
- return (NULL);
-
- /* should use scandir */
- while ((d = readdir(dirp)) != NULL) {
- if (strncmp(d->d_name, _xfer_file_prefix,
- strlen(_xfer_file_prefix)) != 0)
- continue;
- if ((job = job_retrieve(d->d_name, spool)) == NULL)
- continue;
- syslog(LOG_DEBUG, "job_printer is (%s:%s)",
- job->job_printer, job->job_server);
-
- found = 0;
-
- if ((printer == NULL) ||
- ((strcmp(printer, job->job_printer) == 0) &&
- (strcmp(server, job->job_server) == 0))) {
- if (list) {
- for (i = 0; list[i] != NULL; i++) {
- if ((list[i]->job_cf != NULL) &&
- (job->job_cf != NULL) &&
- (strcmp(list[i]->job_cf->jf_spl_path,
- job->job_cf->jf_spl_path) == 0))
- found = 1;
- }
- } /* if (list) */
-
- if (!found)
- list = (job_t **)list_append((void **)list,
- (void *)job);
- }
- } /* while */
-
- /* count the length of the list for qsort() */
- if (list) {
- for (i = 0; list[i] != NULL; i++)
- ;
-
- qsort(list, i, sizeof (job_t *),
- (int(*)(const void *, const void *))job_compar);
- }
- (void) closedir(dirp);
- return (list);
-}
-
-
-
-/*
- *
- * Shared routines for Canceling jobs.
- *
- */
-
-
-/*
- * vjob_match_attribute() checks to see if the attribute passed in
- * matches the the user or id of the job passed in via stdargs. This is
- * intended for use with list_iterate().
- */
-int
-vjob_match_attribute(char *attribute, va_list ap)
-{
- job_t *job = va_arg(ap, job_t *);
-
- if ((strcmp(attribute, job->job_user) == 0) ||
- (job->job_id == atoi(attribute)))
- return (1);
- else
- return (0);
-}
-
-
-/*
- * vjob_job() determines if the job passed in is for the printer and server
- * of the cancel request, and if it is from the user requesting or the
- * user is root, it checsk the attributes. If the job matches all of this
- * it cancels the job and prints a message. It is intented to be called
- * by list_iterate().
- */
-int
-vjob_cancel(job_t *job, va_list ap)
-{
- int killed_process = 0;
- int lock;
- char *user = va_arg(ap, char *),
- *printer = va_arg(ap, char *),
- *server = va_arg(ap, char *),
- **list = va_arg(ap, char **);
-
- syslog(LOG_DEBUG, "vjob_cancel((%s, %s, %d), %s, %s, %s)",
- job->job_printer, job->job_server, job->job_id, user, printer,
- server);
- if (((strcmp(user, "root") == 0) ||
- (strcmp(user, job->job_user) == 0)) &&
- ((strcmp(printer, job->job_printer) == 0) &&
- (strcmp(server, job->job_server) == 0))) {
- if (list_iterate((void **)list,
- (VFUNC_T)vjob_match_attribute, job) != 0) {
- while ((lock = get_lock(job->job_cf->jf_src_path,
- 0)) < 0) {
- (void) kill_process(job->job_cf->jf_src_path);
- killed_process = 1;
- }
- job_destroy(job);
- syslog(LOG_DEBUG, "\t%s-%d: canceled\n", printer,
- job->job_id);
- (void) printf(
- (char *)gettext("\t%s-%d: canceled\n"), printer,
- (int)job->job_id);
- close(lock);
- }
- }
- return (killed_process);
-}