smbd_spool.c revision 23a9c295bad892ce51d86fda89698563b5810495
/*
* 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 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
* CUPS support for the SMB and SPOOLSS print services.
*/
#include <strings.h>
#include <syslog.h>
#include <signal.h>
#include <pthread.h>
#include <synch.h>
#include <dlfcn.h>
#include <errno.h>
#include <smbsrv/smb_share.h>
#include "smbd.h"
#define SMB_SPOOL_WAIT 2
#define SMBD_PJOBLEN 256
#define SMBD_PRINTER "Postscript"
#define SMBD_FN_PREFIX "cifsprintjob-"
#define SMBD_CUPS_SPOOL_DIR "//var//spool//cups"
#define SMBD_CUPS_DOCNAME "generic_doc"
typedef struct smbd_printjob {
int pj_sysjob;
int pj_fd;
int pj_status;
int pj_page_count;
char pj_filename[SMBD_PJOBLEN];
char pj_jobname[SMBD_PJOBLEN];
char pj_username[SMBD_PJOBLEN];
char pj_queuename[SMBD_PJOBLEN];
typedef struct smb_cups_ops {
void *cups_hdl;
cups_lang_t *(*cupsLangDefault)();
const char *(*cupsLangEncoding)(cups_lang_t *);
void (*cupsLangFree)(cups_lang_t *);
ipp_status_t (*cupsLastError)();
int (*cupsGetDests)(cups_dest_t **);
void (*cupsFreeDests)(int, cups_dest_t *);
const char *, const char *);
void (*ippDelete)();
char *(*ippErrorString)();
ipp_attribute_t *(*ippAddString)();
http_t *(*httpConnect)(const char *, int);
static smb_cups_ops_t smb_cups;
static mutex_t smbd_cups_mutex;
static void *smbd_spool_monitor(void *);
static smb_cups_ops_t *smbd_cups_ops(void);
static void *smbd_share_printers(void *);
static void smbd_spool_copyfile(smb_inaddr_t *, char *, char *, char *);
/*
* Initialize the spool thread.
* Returns 0 on success, an error number if thread creation fails.
*/
void
smbd_spool_init(void)
{
int rc;
(void) pthread_attr_init(&attr);
(void) pthread_attr_destroy(&attr);
if (rc != 0)
}
/*
* A single pthread_kill should be sufficient but we include
* a couple of retries to avoid implementation idiosyncrasies
* around signal delivery.
*/
void
smbd_spool_fini(void)
{
int i;
return;
break;
(void) sleep(1);
}
}
/*
* This thread blocks waiting for close print file in the kernel.
* It then uses the data returned from the ioctl to copy the spool file
* into the cups spooler.
*
* This mechanism is really only used by Windows Vista and Windows 7.
* Other versions of Windows create a zero size file, which is removed
* by smbd_spool_copyfile.
*/
/*ARGSUSED*/
static void *
smbd_spool_monitor(void *arg)
{
char username[MAXNAMELEN];
char path[MAXPATHLEN];
int error_retry_cnt = 5;
smbd_online_wait("smbd_spool_monitor");
errno = 0;
error_retry_cnt = 5;
} else {
break;
(void) sleep(SMB_SPOOL_WAIT);
}
}
smbd.s_spool_tid = 0;
return (NULL);
}
/*
* All versions of windows use this function to spool files to a printer
* via the cups interface
*/
static void
char *doc_name)
{
char new_jobname[SMBD_PJOBLEN];
char clientname[INET6_ADDRSTRLEN];
int rc = 1;
return;
}
/*
* Remove zero size files and return; these were inadvertantly
* created by XP or 2000.
*/
"smbd_spool_copyfile: cannot remove %s: %s",
return;
}
return;
"smbd_spool_copyfile: cupsd not running");
return;
}
"smbd_spool_copyfile: ipp not running");
return;
}
"smbd_spool_copyfile: %s: unknown client", clientname);
goto out;
}
"smbd_spool_copyfile: printer %s: %s",
} else {
rc = 0;
}
} else {
"smbd_spool_copyfile: unable to print to %s",
}
if (rc == 0)
out:
if (response)
if (language)
if (http)
}
int
smbd_cups_init(void)
{
(void) mutex_lock(&smbd_cups_mutex);
(void) mutex_unlock(&smbd_cups_mutex);
return (0);
}
(void) mutex_unlock(&smbd_cups_mutex);
"smbd_cups_init: cannot open libcups");
return (ENOENT);
}
smb_cups.ippErrorString = (char *(*)())
(void) mutex_unlock(&smbd_cups_mutex);
"smbd_cups_init: cannot load libcups");
return (ENOENT);
}
(void) mutex_unlock(&smbd_cups_mutex);
return (0);
}
void
smbd_cups_fini(void)
{
(void) mutex_lock(&smbd_cups_mutex);
}
(void) mutex_unlock(&smbd_cups_mutex);
}
static smb_cups_ops_t *
smbd_cups_ops(void)
{
return (NULL);
return (&smb_cups);
}
void
smbd_load_printers(void)
{
int rc;
return;
(void) pthread_attr_init(&attr);
(void) pthread_attr_destroy(&attr);
if (rc != 0)
}
/*
* All print shares use the path from print$.
*/
/*ARGSUSED*/
static void *
smbd_share_printers(void *arg)
{
int num_dests;
int i;
return (NULL);
return (NULL);
"smbd_share_printers unable to load %s", SMB_SHARE_PRINT);
return (NULL);
}
continue;
else
"smbd_share_printers: unable to add share %s: %u",
}
return (NULL);
}
static void
{
char *comment;
char *name;
char *value;
int i;
comment = "Print Share";
return;
}
for (i = 0; i < dest->num_options; ++i) {
continue;
break;
}
}
}