summaryrefslogtreecommitdiff
path: root/scheduler
diff options
context:
space:
mode:
authorjlovell <jlovell@a1ca3aef-8c08-0410-bb20-df032aa958be>2007-03-14 16:55:44 +0000
committerjlovell <jlovell@a1ca3aef-8c08-0410-bb20-df032aa958be>2007-03-14 16:55:44 +0000
commitf7deaa1a21758ec90bf23314af018481ea8aea7f (patch)
tree28c1e9c935060b27e10b2e9daa788f69508f3726 /scheduler
parentb86bc4cf571c35972a94a634ea884baff9799fa9 (diff)
downloadcups-f7deaa1a21758ec90bf23314af018481ea8aea7f.tar.gz
Load cups into easysw/current.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@279 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'scheduler')
-rw-r--r--scheduler/Dependencies30
-rw-r--r--scheduler/Makefile20
-rw-r--r--scheduler/auth.c378
-rw-r--r--scheduler/auth.h5
-rw-r--r--scheduler/banners.c4
-rw-r--r--scheduler/classes.c72
-rw-r--r--scheduler/client.c756
-rw-r--r--scheduler/client.h23
-rw-r--r--scheduler/conf.c69
-rw-r--r--scheduler/conf.h53
-rw-r--r--scheduler/cups-driverd.c4
-rw-r--r--scheduler/cups-lpd.c14
-rw-r--r--scheduler/cups-polld.c4
-rw-r--r--scheduler/cupsd.h27
-rw-r--r--scheduler/dirsvc.c698
-rw-r--r--scheduler/dirsvc.h14
-rw-r--r--scheduler/filter.c61
-rw-r--r--scheduler/ipp.c789
-rw-r--r--scheduler/job.c156
-rw-r--r--scheduler/job.h8
-rw-r--r--scheduler/listen.c21
-rw-r--r--scheduler/log.c88
-rw-r--r--scheduler/main.c640
-rw-r--r--scheduler/mime.c4
-rw-r--r--scheduler/mime.h8
-rw-r--r--scheduler/network.c4
-rw-r--r--scheduler/network.h4
-rw-r--r--scheduler/policy.c4
-rw-r--r--scheduler/printers.c401
-rw-r--r--scheduler/printers.h55
-rw-r--r--scheduler/process.c15
-rw-r--r--scheduler/quotas.c4
-rw-r--r--scheduler/select.c946
-rw-r--r--scheduler/server.c15
-rw-r--r--scheduler/statbuf.c4
-rw-r--r--scheduler/subscriptions.c30
-rw-r--r--scheduler/subscriptions.h4
-rw-r--r--scheduler/sysman.c26
-rw-r--r--scheduler/testlpd.c17
-rw-r--r--scheduler/testmime.c4
-rw-r--r--scheduler/testsub.c4
41 files changed, 4047 insertions, 1436 deletions
diff --git a/scheduler/Dependencies b/scheduler/Dependencies
index e90107a76..46199952f 100644
--- a/scheduler/Dependencies
+++ b/scheduler/Dependencies
@@ -178,11 +178,11 @@ mime.o: ../cups/array.h ../cups/ipp.h ../cups/file.h
type.o: ../cups/string.h ../config.h mime.h ../cups/array.h ../cups/ipp.h
type.o: ../cups/file.h ../cups/debug.h
cups-deviced.o: util.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-cups-deviced.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h
+cups-deviced.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
cups-deviced.o: ../cups/language.h ../cups/file.h ../cups/string.h
cups-deviced.o: ../config.h ../cups/array.h ../cups/dir.h
cups-driverd.o: util.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
-cups-driverd.o: ../cups/md5.h ../cups/ppd.h ../cups/array.h ../cups/file.h
+cups-driverd.o: ../cups/ppd.h ../cups/array.h ../cups/file.h
cups-driverd.o: ../cups/language.h ../cups/file.h ../cups/string.h
cups-driverd.o: ../config.h ../cups/dir.h ../cups/transcode.h
cups-lpd.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/md5.h
@@ -193,20 +193,20 @@ cups-polld.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/md5.h
cups-polld.o: ../cups/ipp-private.h ../cups/ipp.h ../cups/cups.h
cups-polld.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
cups-polld.o: ../cups/language.h ../cups/string.h
-testdirsvc.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
-testdirsvc.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+testdirsvc.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h
+testdirsvc.o: ../cups/array.h ../cups/file.h ../cups/language.h
testdirsvc.o: ../cups/string.h ../config.h
-testlpd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
-testlpd.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
-testlpd.o: ../cups/string.h ../config.h
+testlpd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h
+testlpd.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/string.h
+testlpd.o: ../config.h
testmime.o: ../cups/string.h ../config.h mime.h ../cups/array.h ../cups/ipp.h
testmime.o: ../cups/file.h ../cups/dir.h
-testspeed.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
-testspeed.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
+testspeed.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h
+testspeed.o: ../cups/array.h ../cups/file.h ../cups/language.h
testspeed.o: ../cups/language.h ../cups/debug.h
-testsub.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
-testsub.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
-testsub.o: ../cups/debug.h ../cups/string.h ../config.h
-util.o: util.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
-util.o: ../cups/ppd.h ../cups/array.h ../cups/file.h ../cups/language.h
-util.o: ../cups/file.h ../cups/string.h ../config.h
+testsub.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h
+testsub.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/debug.h
+testsub.o: ../cups/string.h ../config.h
+util.o: util.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/ppd.h
+util.o: ../cups/array.h ../cups/file.h ../cups/language.h ../cups/file.h
+util.o: ../cups/string.h ../config.h
diff --git a/scheduler/Makefile b/scheduler/Makefile
index 2eb297051..c76690e06 100644
--- a/scheduler/Makefile
+++ b/scheduler/Makefile
@@ -1,9 +1,9 @@
#
-# "$Id: Makefile 5940 2006-09-11 18:30:09Z mike $"
+# "$Id: Makefile 6291 2007-02-19 21:54:27Z mike $"
#
# Scheduler Makefile for the Common UNIX Printing System (CUPS).
#
-# Copyright 1997-2006 by Easy Software Products, all rights reserved.
+# Copyright 1997-2007 by Easy Software Products, all rights reserved.
#
# These coded instructions, statements, and computer programs are the
# property of Easy Software Products and are protected by Federal
@@ -43,6 +43,7 @@ CUPSDOBJS = \
printers.o \
process.o \
quotas.o \
+ select.o \
server.o \
statbuf.o \
subscriptions.o \
@@ -188,14 +189,15 @@ cupsd: $(CUPSDOBJS) libmime.a ../cups/$(LIBCUPS)
echo Linking $@...
$(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) libmime.a \
$(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
- $(LIBPAPER) $(LIBMALLOC) $(CUPSDLIBS) $(LIBS)
+ $(LIBPAPER) $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBS) \
+ $(LIBGSSAPI)
cupsd-static: $(CUPSDOBJS) libmime.a ../cups/libcups.a
echo Linking $@...
$(CC) $(LDFLAGS) -o cupsd-static $(CUPSDOBJS) libmime.a \
$(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \
../cups/libcups.a $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \
- $(LIBMALLOC) $(CUPSDLIBS)
+ $(LIBMALLOC) $(CUPSDLIBS) $(DNSSDLIBS) $(LIBGSSAPI)
#
@@ -261,7 +263,7 @@ testdirsvc: testdirsvc.o
testlpd: testlpd.o ../cups/libcups.a cups-lpd
echo Linking $@...
$(CC) $(LDFLAGS) -o testlpd testlpd.o ../cups/libcups.a \
- $(COMMONLIBS) $(LIBZ) $(SSLLIBS)
+ $(COMMONLIBS) $(LIBZ) $(SSLLIBS) $(LIBGSSAPI)
#
@@ -271,7 +273,7 @@ testlpd: testlpd.o ../cups/libcups.a cups-lpd
testmime: testmime.o libmime.a ../cups/libcups.a
echo Linking $@...
$(CC) $(LDFLAGS) -o $@ testmime.o libmime.a ../cups/libcups.a \
- $(COMMONLIBS) $(LIBZ) $(SSLLIBS)
+ $(COMMONLIBS) $(LIBZ) $(SSLLIBS) $(LIBGSSAPI)
#
@@ -281,7 +283,7 @@ testmime: testmime.o libmime.a ../cups/libcups.a
testspeed: testspeed.o ../cups/libcups.a
echo Linking $@...
$(CC) $(LDFLAGS) -o testspeed testspeed.o ../cups/libcups.a \
- $(COMMONLIBS) $(LIBZ) $(SSLLIBS)
+ $(SSLLIBS) $(COMMONLIBS) $(LIBZ) $(LIBGSSAPI)
#
@@ -291,7 +293,7 @@ testspeed: testspeed.o ../cups/libcups.a
testsub: testsub.o ../cups/libcups.a
echo Linking $@...
$(CC) $(LDFLAGS) -o testsub testsub.o ../cups/libcups.a \
- $(LIBGSSAPI) $(SSLLIBS) $(COMMONLIBS) $(LIBZ)
+ $(SSLLIBS) $(COMMONLIBS) $(LIBZ) $(LIBGSSAPI)
#
@@ -302,5 +304,5 @@ include Dependencies
#
-# End of "$Id: Makefile 5940 2006-09-11 18:30:09Z mike $".
+# End of "$Id: Makefile 6291 2007-02-19 21:54:27Z mike $".
#
diff --git a/scheduler/auth.c b/scheduler/auth.c
index 41fd65f87..8baf94511 100644
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -1,9 +1,12 @@
/*
- * "$Id: auth.c 5948 2006-09-12 13:58:39Z mike $"
+ * "$Id: auth.c 6314 2007-03-01 19:11:54Z mike $"
*
* Authorization routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ *
+ * This file contains Kerberos support code, copyright 2006 by
+ * Jelmer Vernooij.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -49,9 +52,11 @@
* compare_locations() - Compare two locations.
* cups_crypt() - Encrypt the password using the DES or MD5
* algorithms, as needed.
+ * get_gss_creds() - Obtain GSS credentials.
* get_md5_password() - Get an MD5 password.
* pam_func() - PAM conversation function.
* to64() - Base64-encode an integer value...
+ * check_authref() - Check an authorization services reference.
*/
/*
@@ -79,6 +84,14 @@
#ifdef HAVE_MEMBERSHIP_H
# include <membership.h>
#endif /* HAVE_MEMBERSHIP_H */
+#ifdef HAVE_AUTHORIZATION_H
+# include <Security/AuthorizationTags.h>
+# ifdef HAVE_SECBASEPRIV_H
+# include <Security/SecBasePriv.h>
+# else
+extern const char *cssmErrorString(int error);
+# endif /* HAVE_SECBASEPRIV_H */
+#endif /* HAVE_AUTHORIZATION_H */
/*
@@ -87,17 +100,23 @@
static cupsd_authmask_t *add_allow(cupsd_location_t *loc);
static cupsd_authmask_t *add_deny(cupsd_location_t *loc);
+#ifdef HAVE_AUTHORIZATION_H
+static int check_authref(cupsd_client_t *con, const char *right);
+#endif /* HAVE_AUTHORIZATION_H */
static int compare_locations(cupsd_location_t *a,
cupsd_location_t *b);
#if !HAVE_LIBPAM && !defined(HAVE_USERSEC_H)
static char *cups_crypt(const char *pw, const char *salt);
#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */
+#ifdef HAVE_GSSAPI
+static gss_cred_id_t get_gss_creds(const char *service_name);
+#endif /* HAVE_GSSAPI */
static char *get_md5_password(const char *username,
const char *group, char passwd[33]);
#if HAVE_LIBPAM
static int pam_func(int, const struct pam_message **,
struct pam_response **, void *);
-#else
+#elif !defined(HAVE_USERSEC_H)
static void to64(char *s, unsigned long v, int n);
#endif /* HAVE_LIBPAM */
@@ -309,8 +328,8 @@ void
cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
{
int type; /* Authentication type */
- char *authorization, /* Pointer into Authorization string */
- *ptr, /* Pointer into string */
+ const char *authorization; /* Pointer into Authorization string */
+ char *ptr, /* Pointer into string */
username[65], /* Username string */
password[33]; /* Password string */
const char *localuser; /* Certificate username */
@@ -356,7 +375,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
* Decode the Authorization string...
*/
- authorization = con->http.fields[HTTP_FIELD_AUTHORIZATION];
+ authorization = httpGetField(&con->http, HTTP_FIELD_AUTHORIZATION);
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAuthorize: Authorization=\"%s\"",
authorization);
@@ -364,6 +383,14 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
username[0] = '\0';
password[0] = '\0';
+#ifdef HAVE_AUTHORIZATION_H
+ if (con->authref)
+ {
+ AuthorizationFree(con->authref, kAuthorizationFlagDefaults);
+ con->authref = NULL;
+ }
+#endif /* HAVE_AUTHORIZATION_H */
+
if (type == AUTH_NONE)
{
/*
@@ -384,6 +411,59 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
"cupsdAuthorize: No authentication data provided.");
return;
}
+#ifdef HAVE_AUTHORIZATION_H
+ else if (!strncmp(authorization, "AuthRef", 6) &&
+ !strcasecmp(con->http.hostname, "localhost"))
+ {
+ OSStatus status; /* Status */
+ int authlen; /* Auth string length */
+ AuthorizationItemSet *authinfo; /* Authorization item set */
+
+ /*
+ * Get the Authorization Services data...
+ */
+
+ authorization += 7;
+ while (isspace(*authorization & 255))
+ authorization ++;
+
+ authlen = sizeof(nonce);
+ httpDecode64_2(nonce, &authlen, authorization);
+
+ if (authlen != kAuthorizationExternalFormLength)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdAuthorize: External Authorization reference size"
+ "is incorrect!");
+ return;
+ }
+
+ if ((status = AuthorizationCreateFromExternalForm(
+ (AuthorizationExternalForm *)nonce, &con->authref)) != 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdAuthorize: AuthorizationCreateFromExternalForm "
+ "returned %d (%s)",
+ (int)status, cssmErrorString(status));
+ return;
+ }
+
+ if ((status = AuthorizationCopyInfo(con->authref,
+ kAuthorizationEnvironmentUsername,
+ &authinfo)) != 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdAuthorize: AuthorizationCopyInfo returned %d (%s)",
+ (int)status, cssmErrorString(status));
+ return;
+ }
+
+ if (authinfo->count == 1)
+ strlcpy(username, authinfo->items[0].value, sizeof(username));
+
+ AuthorizationFreeItemSet(authinfo);
+ }
+#endif /* HAVE_AUTHORIZATION_H */
else if (!strncmp(authorization, "Local", 5) &&
!strcasecmp(con->http.hostname, "localhost"))
{
@@ -754,6 +834,118 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
return;
}
}
+#ifdef HAVE_GSSAPI
+ else if (!strncmp(authorization, "Negotiate", 9) && type == AUTH_KERBEROS)
+ {
+ int len; /* Length of authorization string */
+ gss_cred_id_t server_creds; /* Server credentials */
+ gss_ctx_id_t context; /* Authorization context */
+ OM_uint32 major_status, /* Major status code */
+ minor_status; /* Minor status code */
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER,
+ /* Input token from string */
+ output_token = GSS_C_EMPTY_BUFFER;
+ /* Output token for username */
+ gss_name_t client_name; /* Client name */
+
+
+ con->gss_output_token.length = 0;
+
+ /*
+ * Find the start of the Kerberos input token...
+ */
+
+ authorization += 9;
+ while (isspace(*authorization & 255))
+ authorization ++;
+
+ if (!*authorization)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAuthorize: No authentication data specified.");
+ return;
+ }
+
+ /*
+ * Get the server credentials...
+ */
+
+ if ((server_creds = get_gss_creds(GSSServiceName)) == NULL)
+ {
+ con->no_negotiate = 1;
+ return;
+ }
+
+ /*
+ * Decode the authorization string to get the input token...
+ */
+
+ len = strlen(authorization);
+ input_token.value = malloc(len);
+ input_token.value = httpDecode64_2(input_token.value, &len,
+ authorization);
+ input_token.length = len;
+
+ /*
+ * Accept the input token to get the authorization info...
+ */
+
+ context = GSS_C_NO_CONTEXT;
+ client_name = GSS_C_NO_NAME;
+ major_status = gss_accept_sec_context(&minor_status,
+ &context,
+ server_creds,
+ &input_token,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &client_name,
+ NULL,
+ &con->gss_output_token,
+ NULL,
+ NULL,
+ &con->gss_delegated_cred);
+
+ if (GSS_ERROR(major_status))
+ {
+ cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
+ "cupsdAuthorize: Error accepting GSSAPI security "
+ "context");
+
+ if (context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER);
+
+ con->no_negotiate = 1;
+ return;
+ }
+
+ /*
+ * Get the username associated with the credentials...
+ */
+
+ if (major_status == GSS_S_COMPLETE)
+ {
+ major_status = gss_display_name(&minor_status, client_name,
+ &output_token, NULL);
+
+ if (GSS_ERROR(major_status))
+ {
+ cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status,
+ "cupsdAuthorize: Error getting username");
+ gss_release_name(&minor_status, &client_name);
+ gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER);
+ con->no_negotiate = 1;
+ return;
+ }
+
+ gss_release_name(&minor_status, &client_name);
+ strlcpy(username, output_token.value, sizeof(username));
+
+ gss_release_buffer(&minor_status, &output_token);
+ gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER);
+ }
+ else
+ gss_release_name(&minor_status, &client_name);
+ }
+#endif /* HAVE_GSSAPI */
else
{
cupsdLogMessage(CUPSD_LOG_DEBUG,
@@ -1493,7 +1685,8 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
"NONE",
"BASIC",
"DIGEST",
- "BASICDIGEST"
+ "BASICDIGEST",
+ "KERBEROS"
};
@@ -1623,9 +1816,11 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
* See if encryption is required...
*/
- if (best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls &&
+ if ((best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls &&
strcasecmp(con->http.hostname, "localhost") &&
- best->satisfy == AUTH_SATISFY_ALL)
+ best->satisfy == AUTH_SATISFY_ALL) &&
+ !(best->type == AUTH_KERBEROS ||
+ (best->type == AUTH_NONE && DefaultAuthType == AUTH_KERBEROS)))
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdIsAuthorized: Need upgrade to TLS...");
@@ -1669,7 +1864,11 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: username=\"%s\"",
con->username);
+#ifdef HAVE_AUTHORIZATION_H
+ if (!con->username[0] && !con->authref)
+#else
if (!con->username[0])
+#endif /* HAVE_AUTHORIZATION_H */
{
if (best->satisfy == AUTH_SATISFY_ALL || auth == AUTH_DENY)
return (HTTP_UNAUTHORIZED); /* Non-anonymous needs user/pass */
@@ -1692,8 +1891,13 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
* Get the user info...
*/
- pw = getpwnam(username);
- endpwent();
+ if (username[0])
+ {
+ pw = getpwnam(username);
+ endpwent();
+ }
+ else
+ pw = NULL;
if (best->level == AUTH_USER)
{
@@ -1713,6 +1917,28 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdIsAuthorized: Checking user membership...");
+#ifdef HAVE_AUTHORIZATION_H
+ /*
+ * If an authorization reference was supplied it must match a right name...
+ */
+
+ if (con->authref)
+ {
+ for (i = 0; i < best->num_names; i ++)
+ {
+ if (!strncasecmp(best->names[i], "@AUTHKEY(", 9) &&
+ check_authref(con, best->names[i] + 9))
+ return (HTTP_OK);
+ else if (!strcasecmp(best->names[i], "@SYSTEM") &&
+ SystemGroupAuthKey &&
+ check_authref(con, SystemGroupAuthKey))
+ return (HTTP_OK);
+ }
+
+ return (HTTP_UNAUTHORIZED);
+ }
+#endif /* HAVE_AUTHORIZATION_H */
+
for (i = 0; i < best->num_names; i ++)
{
if (!strcasecmp(best->names[i], "@OWNER") && owner &&
@@ -1858,6 +2084,59 @@ add_deny(cupsd_location_t *loc) /* I - Location to add to */
}
+#ifdef HAVE_AUTHORIZATION_H
+/*
+ * 'check_authref()' - Check if an authorization services reference has the
+ * supplied right.
+ */
+
+static int /* O - 1 if right is valid, 0 otherwise */
+check_authref(cupsd_client_t *con, /* I - Connection */
+ const char *right) /* I - Right name */
+{
+ OSStatus status; /* OS Status */
+ AuthorizationItem authright; /* Authorization right */
+ AuthorizationRights authrights; /* Authorization rights */
+ AuthorizationFlags authflags; /* Authorization flags */
+
+
+ /*
+ * Check to see if the user is allowed to perform the task...
+ */
+
+ if (!con->authref)
+ return (0);
+
+ authright.name = right;
+ authright.valueLength = 0;
+ authright.value = NULL;
+ authright.flags = 0;
+
+ authrights.count = 1;
+ authrights.items = &authright;
+
+ authflags = kAuthorizationFlagDefaults |
+ kAuthorizationFlagExtendRights;
+
+ if ((status = AuthorizationCopyRights(con->authref, &authrights,
+ kAuthorizationEmptyEnvironment,
+ authflags, NULL)) != 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "AuthorizationCopyRights(\"%s\") returned %d (%s)",
+ authright.name, (int)status, cssmErrorString(status));
+ return (0);
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "AuthorizationCopyRights(\"%s\") succeeded!",
+ authright.name);
+
+ return (1);
+}
+#endif /* HAVE_AUTHORIZATION_H */
+
+
/*
* 'compare_locations()' - Compare two locations.
*/
@@ -1993,6 +2272,79 @@ cups_crypt(const char *pw, /* I - Password string */
#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */
+#ifdef HAVE_GSSAPI
+/*
+ * 'get_gss_creds()' - Obtain GSS credentials.
+ */
+
+static gss_cred_id_t /* O - Server credentials */
+get_gss_creds(const char *service_name) /* I - Service name */
+{
+ OM_uint32 major_status, /* Major status code */
+ minor_status; /* Minor status code */
+ gss_name_t server_name; /* Server name */
+ gss_cred_id_t server_creds; /* Server credentials */
+ gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+ /* Service name token */
+ char buf[1024], /* Service name buffer */
+ fqdn[HTTP_MAX_URI]; /* Hostname of server */
+
+
+ snprintf(buf, sizeof(buf), "%s@%s", service_name,
+ httpGetHostname(NULL, fqdn, sizeof(fqdn)));
+
+ token.value = buf;
+ token.length = strlen(buf);
+ server_name = GSS_C_NO_NAME;
+ major_status = gss_import_name(&minor_status, &token,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &server_name);
+
+ memset(&token, 0, sizeof(token));
+
+ if (GSS_ERROR(major_status))
+ {
+ cupsdLogGSSMessage(CUPSD_LOG_WARN, major_status, minor_status,
+ "gss_import_name() failed");
+ return (NULL);
+ }
+
+ major_status = gss_display_name(&minor_status, server_name, &token, NULL);
+
+ if (GSS_ERROR(major_status))
+ {
+ cupsdLogGSSMessage(CUPSD_LOG_WARN, major_status, minor_status,
+ "gss_display_name() failed");
+ return (NULL);
+ }
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "Attempting to acquire credentials for %s...",
+ (char *)token.value);
+
+ server_creds = GSS_C_NO_CREDENTIAL;
+ major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
+ GSS_C_NO_OID_SET, GSS_C_ACCEPT,
+ &server_creds, NULL, NULL);
+ if (GSS_ERROR(major_status))
+ {
+ cupsdLogGSSMessage(CUPSD_LOG_WARN, major_status, minor_status,
+ "gss_acquire_cred() failed");
+ gss_release_name(&minor_status, &server_name);
+ gss_release_buffer(&minor_status, &token);
+ return (NULL);
+ }
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "Credentials acquired successfully for %s.",
+ (char *)token.value);
+
+ gss_release_name(&minor_status, &server_name);
+ gss_release_buffer(&minor_status, &token);
+
+ return (server_creds);
+}
+#endif /* HAVE_GSSAPI */
+
+
/*
* 'get_md5_password()' - Get an MD5 password.
*/
@@ -2146,7 +2498,7 @@ pam_func(
return (PAM_SUCCESS);
}
-#else
+#elif !defined(HAVE_USERSEC_H)
/*
@@ -2170,5 +2522,5 @@ to64(char *s, /* O - Output string */
/*
- * End of "$Id: auth.c 5948 2006-09-12 13:58:39Z mike $".
+ * End of "$Id: auth.c 6314 2007-03-01 19:11:54Z mike $".
*/
diff --git a/scheduler/auth.h b/scheduler/auth.h
index 87bd72cd9..61c7ae993 100644
--- a/scheduler/auth.h
+++ b/scheduler/auth.h
@@ -1,5 +1,5 @@
/*
- * "$Id: auth.h 5305 2006-03-18 03:05:12Z mike $"
+ * "$Id: auth.h 5919 2006-08-31 04:20:45Z mike $"
*
* Authorization definitions for the Common UNIX Printing System (CUPS)
* scheduler.
@@ -38,6 +38,7 @@
#define AUTH_BASIC 1 /* Basic authentication */
#define AUTH_DIGEST 2 /* Digest authentication */
#define AUTH_BASICDIGEST 3 /* Basic authentication w/passwd.md5 */
+#define AUTH_KERBEROS 4 /* Kerberos authentication */
#define AUTH_ANON 0 /* Anonymous access */
#define AUTH_USER 1 /* Must have a valid username/password */
@@ -158,5 +159,5 @@ extern http_status_t cupsdIsAuthorized(cupsd_client_t *con, const char *owner);
/*
- * End of "$Id: auth.h 5305 2006-03-18 03:05:12Z mike $".
+ * End of "$Id: auth.h 5919 2006-08-31 04:20:45Z mike $".
*/
diff --git a/scheduler/banners.c b/scheduler/banners.c
index f78a1077d..31847ad2f 100644
--- a/scheduler/banners.c
+++ b/scheduler/banners.c
@@ -1,5 +1,5 @@
/*
- * "$Id: banners.c 5948 2006-09-12 13:58:39Z mike $"
+ * "$Id: banners.c 5947 2006-09-12 13:58:22Z mike $"
*
* Banner routines for the Common UNIX Printing System (CUPS).
*
@@ -215,5 +215,5 @@ free_banners(void)
/*
- * End of "$Id: banners.c 5948 2006-09-12 13:58:39Z mike $".
+ * End of "$Id: banners.c 5947 2006-09-12 13:58:22Z mike $".
*/
diff --git a/scheduler/classes.c b/scheduler/classes.c
index 749a1bda0..63a818bfd 100644
--- a/scheduler/classes.c
+++ b/scheduler/classes.c
@@ -1,9 +1,9 @@
/*
- * "$Id: classes.c 5151 2006-02-22 22:43:17Z mike $"
+ * "$Id: classes.c 6318 2007-03-06 04:36:55Z mike $"
*
* Printer class routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -366,7 +366,21 @@ cupsdLoadAllClasses(void)
{
cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading class %s...", value);
- p = cupsdAddClass(value);
+ /*
+ * Since prior classes may have implicitly defined this class,
+ * see if it already exists...
+ */
+
+ if ((p = cupsdFindDest(value)) != NULL)
+ {
+ p->type = CUPS_PRINTER_CLASS;
+ cupsdSetStringf(&p->uri, "ipp://%s:%d/classes/%s", ServerName,
+ LocalPort, value);
+ cupsdSetString(&p->error_policy, "retry-job");
+ }
+ else
+ p = cupsdAddClass(value);
+
p->accepting = 1;
p->state = IPP_PRINTER_IDLE;
@@ -400,6 +414,13 @@ cupsdLoadAllClasses(void)
"Syntax error on line %d of classes.conf.", linenum);
return;
}
+ else if (!strcasecmp(line, "AuthInfoRequired"))
+ {
+ if (!cupsdSetAuthInfoRequired(p, value, NULL))
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad AuthInfoRequired on line %d of classes.conf.",
+ linenum);
+ }
else if (!strcasecmp(line, "Info"))
{
if (value)
@@ -703,6 +724,7 @@ cupsdSaveAllClasses(void)
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
cups_option_t *option; /* Current option */
+ const char *ptr; /* Pointer into info/location */
/*
@@ -776,11 +798,49 @@ cupsdSaveAllClasses(void)
else
cupsFilePrintf(fp, "<Class %s>\n", pclass->name);
+ if (pclass->num_auth_info_required > 0)
+ {
+ cupsFilePrintf(fp, "AuthInfoRequired %s", pclass->auth_info_required[0]);
+ for (i = 1; i < pclass->num_auth_info_required; i ++)
+ cupsFilePrintf(fp, ",%s", pclass->auth_info_required[i]);
+ cupsFilePutChar(fp, '\n');
+ }
+
if (pclass->info)
- cupsFilePrintf(fp, "Info %s\n", pclass->info);
+ {
+ if ((ptr = strchr(pclass->info, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the info string...
+ */
+
+ cupsFilePuts(fp, "Info ");
+ cupsFileWrite(fp, pclass->info, ptr - pclass->info);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Info %s\n", pclass->info);
+ }
if (pclass->location)
- cupsFilePrintf(fp, "Location %s\n", pclass->location);
+ {
+ if ((ptr = strchr(pclass->info, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the location string...
+ */
+
+ cupsFilePuts(fp, "Location ");
+ cupsFileWrite(fp, pclass->location, ptr - pclass->location);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Location %s\n", pclass->location);
+ }
if (pclass->state == IPP_PRINTER_STOPPED)
{
@@ -864,5 +924,5 @@ cupsdUpdateImplicitClasses(void)
/*
- * End of "$Id: classes.c 5151 2006-02-22 22:43:17Z mike $".
+ * End of "$Id: classes.c 6318 2007-03-06 04:36:55Z mike $".
*/
diff --git a/scheduler/client.c b/scheduler/client.c
index 44a76f49e..9c0a17dc6 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -1,9 +1,12 @@
/*
- * "$Id: client.c 6247 2007-02-07 20:54:37Z mike $"
+ * "$Id: client.c 6329 2007-03-12 14:48:28Z mike $"
*
* Client routines for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ *
+ * This file contains Kerberos support code, copyright 2006 by
+ * Jelmer Vernooij.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -33,6 +36,7 @@
* cupsdSendHeader() - Send an HTTP request.
* cupsdUpdateCGI() - Read status messages from CGI scripts and programs.
* cupsdWriteClient() - Write data to a client as needed.
+ * cupsdWritePipe() - Flag that data is available on the CGI pipe.
* check_if_modified() - Decode an "If-Modified-Since" line.
* encrypt_client() - Enable encryption for the client...
* get_cdsa_certificate() - Convert a keychain name into the CFArrayRef
@@ -94,7 +98,7 @@ static int encrypt_client(cupsd_client_t *con);
#ifdef HAVE_CDSASSL
static CFArrayRef get_cdsa_certificate(cupsd_client_t *con);
#endif /* HAVE_CDSASSL */
-static char *get_file(cupsd_client_t *con, struct stat *filestats,
+static char *get_file(cupsd_client_t *con, struct stat *filestats,
char *filename, int len);
static http_status_t install_conf_file(cupsd_client_t *con);
static int is_cgi(cupsd_client_t *con, const char *filename,
@@ -405,7 +409,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
*/
val = 1;
- setsockopt(con->http.fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+ setsockopt(con->http.fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
/*
* Close this file on all execs...
@@ -417,10 +421,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
* Add the socket to the select() input mask.
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdAcceptClient: Adding fd %d to InputSet...",
- con->http.fd);
- FD_SET(con->http.fd, InputSet);
+ cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, NULL, con);
/*
* Temporarily suspend accept()'s until we lose a client...
@@ -587,13 +588,7 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */
if (con->file >= 0)
{
- if (FD_ISSET(con->file, InputSet))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdCloseClient: %d Removing fd %d from InputSet...",
- con->http.fd, con->file);
- FD_CLR(con->file, InputSet);
- }
+ cupsdRemoveSelect(con->file);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdCloseClient: %d Closing data file %d.",
@@ -615,11 +610,8 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */
* Only do a partial close so that the encrypted client gets everything.
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdCloseClient: Removing fd %d from OutputSet...",
- con->http.fd);
shutdown(con->http.fd, 0);
- FD_CLR(con->http.fd, OutputSet);
+ cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, NULL, con);
}
else
{
@@ -627,12 +619,8 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */
* Shut the socket down fully...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdCloseClient: Removing fd %d from InputSet and OutputSet...",
- con->http.fd);
+ cupsdRemoveSelect(con->http.fd);
close(con->http.fd);
- FD_CLR(con->http.fd, InputSet);
- FD_CLR(con->http.fd, OutputSet);
con->http.fd = -1;
}
}
@@ -671,6 +659,14 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */
con->language = NULL;
}
+#ifdef HAVE_AUTHORIZATION_H
+ if (con->authref)
+ {
+ AuthorizationFree(con->authref, kAuthorizationFlagDefaults);
+ con->authref = NULL;
+ }
+#endif /* HAVE_AUTHORIZATION_H */
+
/*
* Re-enable new client connections if we are going back under the
* limit...
@@ -711,7 +707,7 @@ cupsdFlushHeader(cupsd_client_t *con) /* I - Client to flush to */
* 'cupsdReadClient()' - Read data from a client.
*/
-int /* O - 1 on success, 0 on error */
+void
cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
{
char line[32768], /* Line from client... */
@@ -740,7 +736,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (con->http.error)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadClient: http error seen...");
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
#ifdef HAVE_SSL
@@ -764,9 +761,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
buf[0] & 255);
if (!encrypt_client(con))
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
- return (1);
+ return;
}
}
#endif /* HAVE_SSL */
@@ -782,7 +779,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdReadClient: httpGets returned EOF...");
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
/*
@@ -846,7 +844,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
"Bad request line \"%s\" from %s!", line,
con->http.hostname);
cupsdSendError(con, HTTP_BAD_REQUEST);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
case 2 :
con->http.version = HTTP_0_9;
break;
@@ -857,7 +856,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
"Bad request line \"%s\" from %s!", line,
con->http.hostname);
cupsdSendError(con, HTTP_BAD_REQUEST);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
if (major < 2)
@@ -871,7 +871,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
else
{
cupsdSendError(con, HTTP_NOT_SUPPORTED);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
break;
}
@@ -916,7 +917,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad URI \"%s\" in request!",
con->uri);
cupsdSendError(con, HTTP_METHOD_NOT_ALLOWED);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
/*
@@ -949,7 +951,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad operation \"%s\"!", operation);
cupsdSendError(con, HTTP_BAD_REQUEST);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
con->start = time(NULL);
@@ -972,12 +975,16 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
* Parse incoming parameters until the status changes...
*/
- status = httpUpdate(HTTP(con));
+ while ((status = httpUpdate(HTTP(con))) == HTTP_CONTINUE)
+ if (con->http.used == 0 ||
+ !memchr(con->http.buffer, '\n', con->http.used))
+ break;
if (status != HTTP_OK && status != HTTP_CONTINUE)
{
cupsdSendError(con, HTTP_BAD_REQUEST);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
break;
@@ -1044,7 +1051,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_BAD_REQUEST))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else if (con->operation == HTTP_OPTIONS)
{
@@ -1055,7 +1065,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (con->best && con->best->type != AUTH_NONE)
{
if (!cupsdSendHeader(con, HTTP_UNAUTHORIZED, NULL))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
if (!strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") &&
@@ -1067,7 +1080,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
@@ -1075,25 +1091,40 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
httpPrintf(HTTP(con), "\r\n");
if (cupsdFlushHeader(con) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (!encrypt_client(con))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
#else
if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
#endif /* HAVE_SSL */
}
if (!cupsdSendHeader(con, HTTP_OK, NULL))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST, PUT\r\n");
httpPrintf(HTTP(con), "Content-Length: 0\r\n");
httpPrintf(HTTP(con), "\r\n");
if (cupsdFlushHeader(con) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else if (!is_path_absolute(con->uri))
{
@@ -1102,7 +1133,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_FORBIDDEN))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else
{
@@ -1115,7 +1149,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
@@ -1123,13 +1160,22 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
httpPrintf(HTTP(con), "\r\n");
if (cupsdFlushHeader(con) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (!encrypt_client(con))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
#else
if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
#endif /* HAVE_SSL */
}
@@ -1139,7 +1185,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
"cupsdReadClient: Unauthorized request for %s...\n",
con->uri);
cupsdSendError(con, status);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
if (con->http.expect &&
@@ -1152,7 +1199,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendHeader(con, HTTP_CONTINUE, NULL))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else
{
@@ -1161,13 +1211,19 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendHeader(con, HTTP_EXPECTATION_FAILED, NULL))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
httpPrintf(HTTP(con), "Content-Length: 0\r\n");
httpPrintf(HTTP(con), "\r\n");
if (cupsdFlushHeader(con) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
}
@@ -1189,7 +1245,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
else
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1258,7 +1317,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (!cupsdSendCommand(con, con->command, con->options, 0))
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else
cupsdLogRequest(con, HTTP_OK);
@@ -1279,7 +1341,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_FORBIDDEN))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1293,7 +1358,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
sizeof(buf))) == NULL)
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1310,7 +1378,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (!cupsdSendCommand(con, con->command, con->options, 0))
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else
cupsdLogRequest(con, HTTP_OK);
@@ -1323,7 +1394,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (!check_if_modified(con, &filestats))
{
if (!cupsdSendError(con, HTTP_NOT_MODIFIED))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else
{
@@ -1333,7 +1407,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
if (!write_file(con, HTTP_OK, filename, line, &filestats))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
}
break;
@@ -1357,7 +1434,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1368,7 +1448,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_BAD_REQUEST))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1460,7 +1543,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
sizeof(buf))) == NULL)
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1474,7 +1560,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_UNAUTHORIZED))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
}
break;
@@ -1494,7 +1583,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_FORBIDDEN))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1517,7 +1609,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1528,7 +1623,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_BAD_REQUEST))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1548,7 +1646,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (con->file < 0)
{
if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
fchmod(con->file, 0640);
@@ -1559,7 +1660,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
case HTTP_DELETE :
case HTTP_TRACE :
cupsdSendError(con, HTTP_NOT_IMPLEMENTED);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
case HTTP_HEAD :
if (!strncmp(con->uri, "/printers/", 10) &&
@@ -1577,7 +1679,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
else
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1596,13 +1701,22 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendHeader(con, HTTP_OK, "text/html"))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (httpPrintf(HTTP(con), "\r\n") < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (cupsdFlushHeader(con) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
cupsdLogRequest(con, HTTP_OK);
}
@@ -1619,7 +1733,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, HTTP_FORBIDDEN))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
break;
}
@@ -1627,14 +1744,20 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
sizeof(buf))) == NULL)
{
if (!cupsdSendHeader(con, HTTP_NOT_FOUND, "text/html"))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
cupsdLogRequest(con, HTTP_NOT_FOUND);
}
else if (!check_if_modified(con, &filestats))
{
if (!cupsdSendError(con, HTTP_NOT_MODIFIED))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
cupsdLogRequest(con, HTTP_NOT_MODIFIED);
}
@@ -1651,24 +1774,39 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
if (!cupsdSendHeader(con, HTTP_OK, line))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n",
httpGetDateString(filestats.st_mtime)) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n",
(unsigned long)filestats.st_size) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
cupsdLogRequest(con, HTTP_OK);
}
if (httpPrintf(HTTP(con), "\r\n") < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
if (cupsdFlushHeader(con) < 0)
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
con->http.state = HTTP_WAITING;
break;
@@ -1694,35 +1832,45 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
"CHUNKED" : "LENGTH",
CUPS_LLCAST con->http.data_remaining, con->file);
- if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0)
- return (cupsdCloseClient(con));
- else if (bytes > 0)
+ do
{
- con->bytes += bytes;
+ if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0)
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+ else if (bytes > 0)
+ {
+ con->bytes += bytes;
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdReadClient: %d writing %d bytes to %d",
- con->http.fd, bytes, con->file);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdReadClient: %d writing %d bytes to %d",
+ con->http.fd, bytes, con->file);
- if (write(con->file, line, bytes) < bytes)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdReadClient: Unable to write %d bytes to %s: %s",
- bytes, con->filename, strerror(errno));
+ if (write(con->file, line, bytes) < bytes)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdReadClient: Unable to write %d bytes to %s: %s",
+ bytes, con->filename, strerror(errno));
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdReadClient: Closing data file %d...",
- con->file);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdReadClient: Closing data file %d...",
+ con->file);
- close(con->file);
- con->file = -1;
- unlink(con->filename);
- cupsdClearString(&con->filename);
+ close(con->file);
+ con->file = -1;
+ unlink(con->filename);
+ cupsdClearString(&con->filename);
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+ }
}
- }
+ }
+ while (con->http.state == HTTP_PUT_RECV && con->http.used > 0);
if (con->http.state == HTTP_WAITING)
{
@@ -1755,7 +1903,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
cupsdClearString(&con->filename);
if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
/*
@@ -1769,7 +1920,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
*/
if (!cupsdSendError(con, status))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
break;
@@ -1782,94 +1936,112 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
"CHUNKED" : "LENGTH",
CUPS_LLCAST con->http.data_remaining, con->file);
- if (con->request)
+ do
{
- /*
- * Grab any request data from the connection...
- */
-
- if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR)
+ if (con->request)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdReadClient: %d IPP Read Error!",
- con->http.fd);
+ /*
+ * Grab any request data from the connection...
+ */
- cupsdSendError(con, HTTP_BAD_REQUEST);
- return (cupsdCloseClient(con));
- }
- else if (ipp_state != IPP_DATA)
- {
- if (con->http.state == HTTP_POST_SEND)
+ if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR)
{
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdReadClient: %d IPP Read Error!",
+ con->http.fd);
+
cupsdSendError(con, HTTP_BAD_REQUEST);
- return (cupsdCloseClient(con));
+ cupsdCloseClient(con);
+ return;
}
+ else if (ipp_state != IPP_DATA)
+ {
+ if (con->http.state == HTTP_POST_SEND)
+ {
+ cupsdSendError(con, HTTP_BAD_REQUEST);
+ cupsdCloseClient(con);
+ return;
+ }
- break;
- }
- else
- con->bytes += ippLength(con->request);
- }
+ break;
+ }
+ else
+ con->bytes += ippLength(con->request);
+ }
- if (con->file < 0 && con->http.state != HTTP_POST_SEND)
- {
- /*
- * Create a file as needed for the request data...
- */
+ if (con->file < 0 && con->http.state != HTTP_POST_SEND)
+ {
+ /*
+ * Create a file as needed for the request data...
+ */
- cupsdSetStringf(&con->filename, "%s/%08x", RequestRoot, request_id ++);
- con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
+ cupsdSetStringf(&con->filename, "%s/%08x", RequestRoot, request_id ++);
+ con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadClient: %d REQUEST %s=%d", con->http.fd,
- con->filename, con->file);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadClient: %d REQUEST %s=%d", con->http.fd,
+ con->filename, con->file);
- if (con->file < 0)
- {
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
- }
+ if (con->file < 0)
+ {
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+ }
- fchmod(con->file, 0640);
- fchown(con->file, RunUser, Group);
- fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
- }
+ fchmod(con->file, 0640);
+ fchown(con->file, RunUser, Group);
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+ }
- if (con->http.state != HTTP_POST_SEND)
- {
- if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0)
- return (cupsdCloseClient(con));
- else if (bytes > 0)
+ if (con->http.state != HTTP_POST_SEND)
{
- con->bytes += bytes;
+ if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0)
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+ else if (bytes > 0)
+ {
+ con->bytes += bytes;
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdReadClient: %d writing %d bytes to %d",
- con->http.fd, bytes, con->file);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdReadClient: %d writing %d bytes to %d",
+ con->http.fd, bytes, con->file);
- if (write(con->file, line, bytes) < bytes)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdReadClient: Unable to write %d bytes to %s: %s",
- bytes, con->filename, strerror(errno));
+ if (write(con->file, line, bytes) < bytes)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdReadClient: Unable to write %d bytes to %s: %s",
+ bytes, con->filename, strerror(errno));
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdReadClient: Closing file %d...",
- con->file);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdReadClient: Closing file %d...",
+ con->file);
- close(con->file);
- con->file = -1;
- unlink(con->filename);
- cupsdClearString(&con->filename);
+ close(con->file);
+ con->file = -1;
+ unlink(con->filename);
+ cupsdClearString(&con->filename);
- if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+ }
+ }
+ else if (con->http.state == HTTP_POST_RECV)
+ return;
+ else if (con->http.state != HTTP_POST_SEND)
+ {
+ cupsdCloseClient(con);
+ return;
}
}
- else if (con->http.state == HTTP_POST_RECV)
- return (1); /* ??? */
- else if (con->http.state != HTTP_POST_SEND)
- return (cupsdCloseClient(con));
- }
+ }
+ while (con->http.state == HTTP_POST_RECV && con->http.used > 0);
if (con->http.state == HTTP_POST_SEND)
{
@@ -1910,7 +2082,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
}
if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
if (con->command)
@@ -1918,7 +2093,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
if (!cupsdSendCommand(con, con->command, con->options, 0))
{
if (!cupsdSendError(con, HTTP_NOT_FOUND))
- return (cupsdCloseClient(con));
+ {
+ cupsdCloseClient(con);
+ return;
+ }
}
else
cupsdLogRequest(con, HTTP_OK);
@@ -1926,7 +2104,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
}
if (con->request)
- return (cupsdProcessIPPRequest(con));
+ {
+ cupsdProcessIPPRequest(con);
+ return;
+ }
}
break;
@@ -1935,9 +2116,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
}
if (!con->http.keep_alive && con->http.state == HTTP_WAITING)
- return (cupsdCloseClient(con));
- else
- return (1);
+ cupsdCloseClient(con);
}
@@ -1989,14 +2168,7 @@ cupsdSendCommand(
fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSendCommand: Adding fd %d to InputSet...", con->file);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdSendCommand: Adding fd %d to OutputSet...",
- con->http.fd);
-
- FD_SET(con->file, InputSet);
- FD_SET(con->http.fd, OutputSet);
+ cupsdAddSelect(con->file, (cupsd_selfunc_t)cupsdWritePipe, NULL, con);
con->sent_header = 0;
con->file_ready = 0;
@@ -2044,9 +2216,12 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */
/*
* To work around bugs in some proxies, don't use Keep-Alive for some
* error messages...
+ *
+ * Kerberos authentication doesn't work without Keep-Alive, so
+ * never disable it in that case.
*/
- if (code >= HTTP_BAD_REQUEST)
+ if (code >= HTTP_BAD_REQUEST && con->http.auth_type != AUTH_KERBEROS)
con->http.keep_alive = HTTP_KEEPALIVE_OFF;
/*
@@ -2066,8 +2241,8 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */
return (0);
#endif /* HAVE_SSL */
- if ((con->http.version >= HTTP_1_1 && !con->http.keep_alive) ||
- (code >= HTTP_BAD_REQUEST && code != HTTP_UPGRADE_REQUIRED))
+ if (con->http.version >= HTTP_1_1 &&
+ con->http.keep_alive == HTTP_KEEPALIVE_OFF)
{
if (httpPrintf(HTTP(con), "Connection: close\r\n") < 0)
return (0);
@@ -2091,7 +2266,8 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */
text = _cupsLangString(con->language,
_("Enter your username and password or the "
"root username and password to access this "
- "page."));
+ "page. If you are using Kerberos authentication, "
+ "make sure you have a valid Kerberos ticket."));
else if (code == HTTP_UPGRADE_REQUIRED)
{
text = urltext;
@@ -2162,6 +2338,9 @@ cupsdSendHeader(cupsd_client_t *con, /* I - Client to send to */
http_status_t code, /* I - HTTP status code */
char *type) /* I - MIME type of document */
{
+ char auth_str[1024]; /* Authorization string */
+
+
/*
* Send the HTTP status header...
*/
@@ -2209,22 +2388,77 @@ cupsdSendHeader(cupsd_client_t *con, /* I - Client to send to */
auth_type = DefaultAuthType;
else
auth_type = con->best->type;
-
- if (auth_type != AUTH_DIGEST)
- {
- if (httpPrintf(HTTP(con),
- "WWW-Authenticate: Basic realm=\"CUPS\"\r\n") < 0)
- return (0);
- }
- else
+
+ auth_str[0] = '\0';
+
+ if (auth_type == AUTH_BASIC || auth_type == AUTH_BASICDIGEST)
+ strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str));
+ else if (auth_type == AUTH_DIGEST)
+ snprintf(auth_str, sizeof(auth_str), "Digest realm=\"CUPS\", nonce=\"%s\"",
+ con->http.hostname);
+#ifdef HAVE_GSSAPI
+ else if (auth_type == AUTH_KERBEROS && !con->no_negotiate &&
+ con->gss_output_token.length == 0)
+ strlcpy(auth_str, "Negotiate", sizeof(auth_str));
+#endif /* HAVE_GSSAPI */
+
+#ifdef HAVE_AUTHORIZATION_H
+ if (con->best)
{
- if (httpPrintf(HTTP(con),
- "WWW-Authenticate: Digest realm=\"CUPS\", nonce=\"%s\"\r\n",
- con->http.hostname) < 0)
- return (0);
+ int i; /* Looping var */
+ char *auth_key; /* Auth key buffer */
+ size_t auth_size; /* Size of remaining buffer */
+
+
+ auth_key = auth_str + strlen(auth_str);
+ auth_size = sizeof(auth_str) - (auth_key - auth_str);
+
+ for (i = 0; i < con->best->num_names; i ++)
+ {
+ if (!strncasecmp(con->best->names[i], "@AUTHKEY(", 9))
+ {
+ snprintf(auth_key, auth_size, ", authkey=\"%s\"",
+ con->best->names[i] + 9);
+ /* end parenthesis is stripped in conf.c */
+ break;
+ }
+ else if (!strcasecmp(con->best->names[i], "@SYSTEM") &&
+ SystemGroupAuthKey)
+ {
+ snprintf(auth_key, auth_size, ", authkey=\"%s\"", SystemGroupAuthKey);
+ break;
+ }
+ }
}
+#endif /* HAVE_AUTHORIZATION_H */
+
+ if (auth_str[0] &&
+ httpPrintf(HTTP(con), "WWW-Authenticate: %s\r\n", auth_str) < 0)
+ return (0);
}
+#ifdef HAVE_GSSAPI
+ /*
+ * WWW-Authenticate: Negotiate can be included even for
+ * non-401 replies...
+ */
+
+ if (con->gss_output_token.length > 0)
+ {
+ char buf[2048]; /* Output token buffer */
+ OM_uint32 minor_status; /* Minor status code */
+
+
+ httpEncode64_2(buf, sizeof(buf),
+ con->gss_output_token.value,
+ con->gss_output_token.length);
+ gss_release_buffer(&minor_status, &con->gss_output_token);
+
+ if (httpPrintf(HTTP(con), "WWW-Authenticate: Negotiate %s\r\n", buf) < 0)
+ return (0);
+ }
+#endif /* HAVE_GSSAPI */
+
if (con->language && strcmp(con->language->language, "C"))
{
if (httpPrintf(HTTP(con), "Content-Language: %s\r\n",
@@ -2282,7 +2516,7 @@ cupsdUpdateCGI(void)
* 'cupsdWriteClient()' - Write data to a client as needed.
*/
-int /* O - 1 if success, 0 if fail */
+void
cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
{
int bytes; /* Number of bytes written */
@@ -2301,7 +2535,28 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
if (con->http.state != HTTP_GET_SEND &&
con->http.state != HTTP_POST_SEND)
- return (1);
+ return;
+
+ if (con->pipe_pid)
+ {
+ /*
+ * Make sure we select on the CGI output...
+ */
+
+ cupsdAddSelect(con->file, (cupsd_selfunc_t)cupsdWritePipe, NULL, con);
+
+ if (!con->file_ready)
+ {
+ /*
+ * Try again later when there is CGI output available...
+ */
+
+ cupsdRemoveSelect(con->http.fd);
+ return;
+ }
+
+ con->file_ready = 0;
+ }
if (con->response)
{
@@ -2347,7 +2602,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
con->sent_header = 2;
if (httpPrintf(HTTP(con), "Content-Length: 0\r\n") < 0)
- return (0);
+ return;
}
else if (!strncasecmp(buf, "Status:", 7))
{
@@ -2362,7 +2617,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
if (con->http.version == HTTP_1_1)
{
if (httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n") < 0)
- return (0);
+ return;
}
}
}
@@ -2392,7 +2647,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
if (cupsdFlushHeader(con) < 0)
{
cupsdCloseClient(con);
- return (0);
+ return;
}
if (con->http.version == HTTP_1_1)
@@ -2417,7 +2672,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
httpPrintf(HTTP(con), "%s", buf);
con->http.activity = time(NULL);
- return (1);
+ return;
}
else if (bytes == 0)
con->http.activity = time(NULL);
@@ -2432,7 +2687,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
con->http.fd, bytes);
cupsdCloseClient(con);
- return (0);
+ return;
}
con->bytes += bytes;
@@ -2456,27 +2711,17 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
if (httpWrite2(HTTP(con), "", 0) < 0)
{
cupsdCloseClient(con);
- return (0);
+ return;
}
}
con->http.state = HTTP_WAITING;
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdWriteClient: Removing fd %d from OutputSet...",
- con->http.fd);
-
- FD_CLR(con->http.fd, OutputSet);
+ cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, NULL, con);
if (con->file >= 0)
{
- if (FD_ISSET(con->file, InputSet))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdWriteClient: Removing fd %d from InputSet...",
- con->file);
- FD_CLR(con->file, InputSet);
- }
+ cupsdRemoveSelect(con->file);
if (con->pipe_pid)
cupsdEndProcess(con->pipe_pid, 0);
@@ -2518,25 +2763,28 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */
if (!con->http.keep_alive)
{
cupsdCloseClient(con);
- return (0);
- }
- }
- else
- {
- con->file_ready = 0;
-
- if (con->pipe_pid && !FD_ISSET(con->file, InputSet))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdWriteClient: Adding fd %d to InputSet...",
- con->file);
- FD_SET(con->file, InputSet);
+ return;
}
}
con->http.activity = time(NULL);
+}
- return (1);
+
+/*
+ * 'cupsdWritePipe()' - Flag that data is available on the CGI pipe.
+ */
+
+void
+cupsdWritePipe(cupsd_client_t *con) /* I - Client connection */
+{
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdWritePipe: CGI output on fd %d...",
+ con->file);
+
+ con->file_ready = 1;
+
+ cupsdRemoveSelect(con->file);
+ cupsdAddSelect(con->http.fd, NULL, (cupsd_selfunc_t)cupsdWriteClient, con);
}
@@ -2667,7 +2915,7 @@ encrypt_client(cupsd_client_t *con) /* I - Client to encrypt */
con->http.tls = conn;
return (1);
-
+
# elif defined(HAVE_GNUTLS)
http_tls_t *conn; /* TLS session object */
int error; /* Error code */
@@ -2712,7 +2960,7 @@ encrypt_client(cupsd_client_t *con) /* I - Client to encrypt */
}
gnutls_certificate_allocate_credentials(credentials);
- gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
+ gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
ServerKey, GNUTLS_X509_FMT_PEM);
gnutls_init(&(conn->session), GNUTLS_SERVER);
@@ -2979,11 +3227,13 @@ get_file(cupsd_client_t *con, /* I - Client connection */
/*
- * Need to add DocumentRoot global...
+ * Figure out the real filename...
*/
if (!strncmp(con->uri, "/ppd/", 5))
snprintf(filename, len, "%s%s", ServerRoot, con->uri);
+ else if (!strncmp(con->uri, "/rss/", 5) && !strchr(con->uri + 5, '/'))
+ snprintf(filename, len, "%s/rss/%s", CacheDir, con->uri + 5);
else if (!strncmp(con->uri, "/admin/conf/", 12))
snprintf(filename, len, "%s%s", ServerRoot, con->uri + 11);
else if (!strncmp(con->uri, "/admin/log/", 11))
@@ -3472,7 +3722,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
int pid, /* Process ID of command */
status; /* Status of command */
char command[1024], /* Command */
- *argv[11], /* Command-line arguments */
+ *argv[12], /* Command-line arguments */
*envp[MAX_ENV + 1], /* Environment variables */
home[1024], /* HOME environment variable */
infofile[1024], /* Type-in information for cert */
@@ -3548,7 +3798,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
envp[envc++] = home;
envp[envc] = NULL;
- if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, 1, &pid))
+ if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, &pid))
{
unlink(seedfile);
return (0);
@@ -3625,7 +3875,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
infofd = open(infofile, O_RDONLY);
- if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, 1, &pid))
+ if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, &pid))
{
close(infofd);
unlink(infofile);
@@ -3858,7 +4108,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
infofd = open(infofile, O_RDONLY);
- if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, 1, &pid))
+ if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, &pid))
{
close(infofd);
unlink(infofile);
@@ -3928,10 +4178,11 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
int envc; /* Number of environment variables */
char argbuf[10240], /* Argument buffer */
*argv[100], /* Argument strings */
- *envp[MAX_ENV + 17]; /* Environment variables */
+ *envp[MAX_ENV + 18]; /* Environment variables */
char content_length[1024], /* CONTENT_LENGTH environment variable */
content_type[1024], /* CONTENT_TYPE environment variable */
http_cookie[32768], /* HTTP_COOKIE environment variable */
+ http_referer[1024], /* HTTP_REFERER environment variable */
http_user_agent[1024], /* HTTP_USER_AGENT environment variable */
lang[1024], /* LANG environment variable */
path_info[1024], /* PATH_INFO environment variable */
@@ -4126,6 +4377,13 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
envp[envc ++] = http_user_agent;
}
+ if (con->http.fields[HTTP_FIELD_REFERER][0])
+ {
+ snprintf(http_referer, sizeof(http_referer), "HTTP_REFERER=%s",
+ con->http.fields[HTTP_FIELD_REFERER]);
+ envp[envc ++] = http_referer;
+ }
+
if (con->operation == HTTP_GET)
{
envp[envc ++] = "REQUEST_METHOD=GET";
@@ -4190,7 +4448,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
*/
if (cupsdStartProcess(command, argv, envp, infile, fds[1], CGIPipes[1],
- -1, root, &pid) < 0)
+ -1, -1, root, &pid) < 0)
{
/*
* Error - can't fork!
@@ -4267,15 +4525,13 @@ write_file(cupsd_client_t *con, /* I - Client connection */
else
con->http._data_remaining = INT_MAX;
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "write_file: Adding fd %d to OutputSet...", con->http.fd);
-
- FD_SET(con->http.fd, OutputSet);
+ cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient,
+ (cupsd_selfunc_t)cupsdWriteClient, con);
return (1);
}
/*
- * End of "$Id: client.c 6247 2007-02-07 20:54:37Z mike $".
+ * End of "$Id: client.c 6329 2007-03-12 14:48:28Z mike $".
*/
diff --git a/scheduler/client.h b/scheduler/client.h
index d11feb836..50f095abf 100644
--- a/scheduler/client.h
+++ b/scheduler/client.h
@@ -1,5 +1,5 @@
/*
- * "$Id: client.h 6205 2007-01-22 22:04:43Z mike $"
+ * "$Id: client.h 6253 2007-02-10 18:48:40Z mike $"
*
* Client definitions for the Common UNIX Printing System (CUPS) scheduler.
*
@@ -22,6 +22,10 @@
* WWW: http://www.cups.org
*/
+#ifdef HAVE_AUTHORIZATION_H
+# include <Security/Authorization.h>
+#endif /* HAVE_AUTHORIZATION_H */
+
/*
* HTTP client structure...
*/
@@ -56,6 +60,16 @@ struct cupsd_client_s
http_addr_t clientaddr; /* Client address */
char servername[256];/* Server name for connection */
int serverport; /* Server port for connection */
+#ifdef HAVE_GSSAPI
+ int no_negotiate; /* Don't offer WWW-Authenticate: Negotiate */
+ gss_buffer_desc gss_output_token;
+ /* Output token for Negotiate header */
+ gss_cred_id_t gss_delegated_cred;
+ /* Credentials from client header */
+#endif /* HAVE_GSSAPI */
+#ifdef HAVE_AUTHORIZATION_H
+ AuthorizationRef authref; /* Authorization ref */
+#endif /* HAVE_AUTHORIZATION_H */
};
#define HTTP(con) &((con)->http)
@@ -108,7 +122,7 @@ extern void cupsdDeleteAllListeners(void);
extern int cupsdFlushHeader(cupsd_client_t *con);
extern void cupsdPauseListening(void);
extern int cupsdProcessIPPRequest(cupsd_client_t *con);
-extern int cupsdReadClient(cupsd_client_t *con);
+extern void cupsdReadClient(cupsd_client_t *con);
extern void cupsdResumeListening(void);
extern int cupsdSendCommand(cupsd_client_t *con, char *command,
char *options, int root);
@@ -119,9 +133,10 @@ extern void cupsdShutdownClient(cupsd_client_t *con);
extern void cupsdStartListening(void);
extern void cupsdStopListening(void);
extern void cupsdUpdateCGI(void);
-extern int cupsdWriteClient(cupsd_client_t *con);
+extern void cupsdWriteClient(cupsd_client_t *con);
+extern void cupsdWritePipe(cupsd_client_t *con);
/*
- * End of "$Id: client.h 6205 2007-01-22 22:04:43Z mike $".
+ * End of "$Id: client.h 6253 2007-02-10 18:48:40Z mike $".
*/
diff --git a/scheduler/conf.c b/scheduler/conf.c
index c8a3afa43..d033627ad 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -1,5 +1,5 @@
/*
- * "$Id: conf.c 6205 2007-01-22 22:04:43Z mike $"
+ * "$Id: conf.c 6253 2007-02-10 18:48:40Z mike $"
*
* Configuration routines for the Common UNIX Printing System (CUPS).
*
@@ -117,13 +117,19 @@ static cupsd_var_t variables[] =
{ "FilterLimit", &FilterLimit, CUPSD_VARTYPE_INTEGER },
{ "FilterNice", &FilterNice, CUPSD_VARTYPE_INTEGER },
{ "FontPath", &FontPath, CUPSD_VARTYPE_STRING },
- { "HideImplicitMembers", &HideImplicitMembers, CUPSD_VARTYPE_BOOLEAN },
+#ifdef HAVE_GSSAPI
+ { "GSSServiceName", &GSSServiceName, CUPSD_VARTYPE_STRING },
+#endif /* HAVE_GSSAPI */
{ "ImplicitClasses", &ImplicitClasses, CUPSD_VARTYPE_BOOLEAN },
{ "ImplicitAnyClasses", &ImplicitAnyClasses, CUPSD_VARTYPE_BOOLEAN },
{ "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER },
{ "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_INTEGER },
{ "KeepAliveTimeout", &KeepAliveTimeout, CUPSD_VARTYPE_INTEGER },
{ "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN },
+#ifdef HAVE_LAUNCHD
+ { "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_INTEGER },
+ { "LaunchdConf", &LaunchdConf, CUPSD_VARTYPE_STRING },
+#endif /* HAVE_LAUNCHD */
{ "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER },
{ "ListenBackLog", &ListenBackLog, CUPSD_VARTYPE_INTEGER },
{ "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_INTEGER },
@@ -161,13 +167,12 @@ static cupsd_var_t variables[] =
{ "ServerKey", &ServerKey, CUPSD_VARTYPE_STRING },
# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
#endif /* HAVE_SSL */
-#ifdef HAVE_LAUNCHD
- { "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_INTEGER },
- { "LaunchdConf", &LaunchdConf, CUPSD_VARTYPE_STRING },
-#endif /* HAVE_LAUNCHD */
{ "ServerName", &ServerName, CUPSD_VARTYPE_STRING },
{ "ServerRoot", &ServerRoot, CUPSD_VARTYPE_STRING },
{ "StateDir", &StateDir, CUPSD_VARTYPE_STRING },
+#ifdef HAVE_AUTHORIZATION_H
+ { "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING },
+#endif /* HAVE_AUTHORIZATION_H */
{ "TempDir", &TempDir, CUPSD_VARTYPE_STRING },
{ "Timeout", &Timeout, CUPSD_VARTYPE_INTEGER },
{ "UseNetworkDefault", &UseNetworkDefault, CUPSD_VARTYPE_BOOLEAN }
@@ -288,6 +293,9 @@ cupsdReadConfiguration(void)
cupsdSetString(&RemoteRoot, "remroot");
cupsdSetString(&ServerHeader, "CUPS/1.2");
cupsdSetString(&StateDir, CUPS_STATEDIR);
+#ifdef HAVE_GSSAPI
+ cupsdSetString(&GSSServiceName, CUPS_DEFAULT_GSSSERVICENAME);
+#endif /* HAVE_GSSAPI */
if (!strcmp(CUPS_DEFAULT_PRINTCAP, "/etc/printers.conf"))
PrintcapFormat = PRINTCAP_SOLARIS;
@@ -434,11 +442,15 @@ cupsdReadConfiguration(void)
MaxActiveJobs = 0;
MaxJobsPerUser = 0;
MaxJobsPerPrinter = 0;
- MaxCopies = 100;
+ MaxCopies = CUPS_DEFAULT_MAX_COPIES;
cupsdDeleteAllPolicies();
cupsdClearString(&DefaultPolicy);
+#ifdef HAVE_AUTHORIZATION_H
+ cupsdClearString(&SystemGroupAuthKey);
+#endif /* HAVE_AUTHORIZATION_H */
+
MaxSubscriptions = 100;
MaxSubscriptionsPerJob = 0;
MaxSubscriptionsPerPrinter = 0;
@@ -1705,6 +1717,16 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
if (loc->level == AUTH_ANON)
loc->level = AUTH_USER;
}
+#ifdef HAVE_GSSAPI
+ else if (!strcasecmp(value, "kerberos") ||
+ !strcasecmp(value, "gssapi"))
+ {
+ loc->type = AUTH_KERBEROS;
+
+ if (loc->level == AUTH_ANON)
+ loc->level = AUTH_USER;
+ }
+#endif /* HAVE_GSSAPI */
else
{
cupsdLogMessage(CUPSD_LOG_WARN,
@@ -1813,6 +1835,20 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
while (isspace(*value & 255))
value ++;
+#ifdef HAVE_AUTHORIZATION_H
+ if (!strncmp(value, "@AUTHKEY(", 9))
+ {
+ /*
+ * Grab "@AUTHKEY(name)" value...
+ */
+
+ for (valptr = value + 9; *valptr != ')' && *valptr; valptr ++);
+
+ if (*valptr)
+ *valptr++ = '\0';
+ }
+ else
+#endif /* HAVE_AUTHORIZATION_H */
if (*value == '\"' || *value == '\'')
{
/*
@@ -2700,6 +2736,10 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
DefaultAuthType = AUTH_DIGEST;
else if (!strcasecmp(value, "basicdigest"))
DefaultAuthType = AUTH_BASICDIGEST;
+#ifdef HAVE_GSSAPI
+ else if (!strcasecmp(value, "kerberos"))
+ DefaultAuthType = AUTH_KERBEROS;
+#endif /* HAVE_GSSAPI */
else
{
cupsdLogMessage(CUPSD_LOG_WARN,
@@ -2730,6 +2770,19 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
}
}
#endif /* HAVE_SSL */
+#ifdef HAVE_GSSAPI
+ else if (!strcasecmp(line, "Krb5Keytab"))
+ {
+ cupsdSetStringf(&Krb5Keytab, "KRB5_KTNAME=%s", value);
+ putenv(Krb5Keytab);
+
+# ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
+ gsskrb5_register_acceptor_identity(value);
+# else
+ cupsdSetEnv("KRB5_KTNAME", value);
+# endif /* HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY */
+ }
+#endif /* HAVE_GSSAPI */
else if (!strcasecmp(line, "User"))
{
/*
@@ -3289,5 +3342,5 @@ read_policy(cups_file_t *fp, /* I - Configuration file */
/*
- * End of "$Id: conf.c 6205 2007-01-22 22:04:43Z mike $".
+ * End of "$Id: conf.c 6253 2007-02-10 18:48:40Z mike $".
*/
diff --git a/scheduler/conf.h b/scheduler/conf.h
index 6320f9d19..cfb71fc4e 100644
--- a/scheduler/conf.h
+++ b/scheduler/conf.h
@@ -1,5 +1,5 @@
/*
- * "$Id: conf.h 5696 2006-06-26 18:34:20Z mike $"
+ * "$Id: conf.h 6291 2007-02-19 21:54:27Z mike $"
*
* Configuration file definitions for the Common UNIX Printing System (CUPS)
* scheduler.
@@ -30,19 +30,19 @@
typedef enum
{
- CUPSD_LOG_ATTR = -3, /* Used internally for attributes */
- CUPSD_LOG_STATE, /* Used internally for state-reasons */
- CUPSD_LOG_PAGE, /* Used internally for page logging */
+ CUPSD_LOG_ATTR = -3, /* Used internally for attributes */
+ CUPSD_LOG_STATE, /* Used internally for state-reasons */
+ CUPSD_LOG_PAGE, /* Used internally for page logging */
CUPSD_LOG_NONE,
- CUPSD_LOG_EMERG, /* Emergency issues */
- CUPSD_LOG_ALERT, /* Something bad happened that needs attention */
- CUPSD_LOG_CRIT, /* Critical error but server continues */
- CUPSD_LOG_ERROR, /* Error condition */
- CUPSD_LOG_WARN, /* Warning */
- CUPSD_LOG_NOTICE, /* Normal condition that needs logging */
- CUPSD_LOG_INFO, /* General information */
- CUPSD_LOG_DEBUG, /* General debugging */
- CUPSD_LOG_DEBUG2 /* Detailed debugging */
+ CUPSD_LOG_EMERG, /* Emergency issues */
+ CUPSD_LOG_ALERT, /* Something bad happened that needs attention */
+ CUPSD_LOG_CRIT, /* Critical error but server continues */
+ CUPSD_LOG_ERROR, /* Error condition */
+ CUPSD_LOG_WARN, /* Warning */
+ CUPSD_LOG_NOTICE, /* Normal condition that needs logging */
+ CUPSD_LOG_INFO, /* General information */
+ CUPSD_LOG_DEBUG, /* General debugging */
+ CUPSD_LOG_DEBUG2 /* Detailed debugging */
} cupsd_loglevel_t;
@@ -50,8 +50,8 @@ typedef enum
* Printcap formats...
*/
-#define PRINTCAP_BSD 0 /* Berkeley LPD format */
-#define PRINTCAP_SOLARIS 1 /* Solaris lpsched format */
+#define PRINTCAP_BSD 0 /* Berkeley LPD format */
+#define PRINTCAP_SOLARIS 1 /* Solaris lpsched format */
/*
@@ -111,6 +111,12 @@ VAR char *AccessLog VALUE(NULL),
/* Remote root user */
*Classification VALUE(NULL);
/* Classification of system */
+#ifdef HAVE_GSSAPI
+VAR char *GSSServiceName VALUE(NULL);
+ /* GSS service name */
+VAR char *Krb5Keytab VALUE(NULL);
+ /* Kerberos Keytab */
+#endif /* HAVE_GSSAPI */
VAR uid_t User VALUE(1);
/* User ID for server */
VAR gid_t Group VALUE(0);
@@ -127,7 +133,7 @@ VAR int ClassifyOverride VALUE(0),
/* Maximum number of clients */
MaxClientsPerHost VALUE(0),
/* Maximum number of clients per host */
- MaxCopies VALUE(100),
+ MaxCopies VALUE(CUPS_DEFAULT_MAX_COPIES),
/* Maximum number of copies per job */
MaxLogSize VALUE(1024 * 1024),
/* Maximum size of log files */
@@ -195,21 +201,32 @@ VAR char *LaunchdConf VALUE(NULL);
/* launchd(8) configuration file */
#endif /* HAVE_LAUNCHD */
+#ifdef HAVE_AUTHORIZATION_H
+VAR char *SystemGroupAuthKey VALUE(NULL);
+ /* System group auth key */
+#endif /* HAVE_AUTHORIZATION_H */
+
+
/*
* Prototypes...
*/
extern char *cupsdGetDateTime(time_t t);
extern int cupsdReadConfiguration(void);
-extern int cupsdLogRequest(cupsd_client_t *con, http_status_t code);
+#ifdef HAVE_GSSAPI
+extern int cupsdLogGSSMessage(int level, int major_status,
+ int minor_status,
+ const char *message, ...);
+#endif /* HAVE_GSSAPI */
extern int cupsdLogMessage(int level, const char *message, ...)
#ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 2, 3)))
#endif /* __GNUC__ */
;
extern int cupsdLogPage(cupsd_job_t *job, const char *page);
+extern int cupsdLogRequest(cupsd_client_t *con, http_status_t code);
/*
- * End of "$Id: conf.h 5696 2006-06-26 18:34:20Z mike $".
+ * End of "$Id: conf.h 6291 2007-02-19 21:54:27Z mike $".
*/
diff --git a/scheduler/cups-driverd.c b/scheduler/cups-driverd.c
index a51e4a934..39892bc71 100644
--- a/scheduler/cups-driverd.c
+++ b/scheduler/cups-driverd.c
@@ -1,5 +1,5 @@
/*
- * "$Id: cups-driverd.c 6214 2007-01-23 17:01:48Z mike $"
+ * "$Id: cups-driverd.c 6211 2007-01-23 15:44:34Z mike $"
*
* PPD/driver support for the Common UNIX Printing System (CUPS).
*
@@ -1122,5 +1122,5 @@ load_drivers(void)
/*
- * End of "$Id: cups-driverd.c 6214 2007-01-23 17:01:48Z mike $".
+ * End of "$Id: cups-driverd.c 6211 2007-01-23 15:44:34Z mike $".
*/
diff --git a/scheduler/cups-lpd.c b/scheduler/cups-lpd.c
index e771c9eff..a2b0f9003 100644
--- a/scheduler/cups-lpd.c
+++ b/scheduler/cups-lpd.c
@@ -1,5 +1,5 @@
/*
- * "$Id: cups-lpd.c 6022 2006-10-10 19:47:03Z mike $"
+ * "$Id: cups-lpd.c 6327 2007-03-12 14:32:10Z mike $"
*
* Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
*
@@ -96,7 +96,8 @@ static int get_printer(http_t *http, const char *name, char *dest,
int destsize, cups_option_t **options,
int *accepting, int *shared, ipp_pstate_t *state);
static int print_file(http_t *http, int id, const char *filename,
- const char *docname, const char *user, int last);
+ const char *docname, const char *user,
+ const char *format, int last);
static int recv_print_job(const char *name, int num_defaults,
cups_option_t *defaults);
static int remove_jobs(const char *name, const char *agent,
@@ -824,6 +825,7 @@ print_file(http_t *http, /* I - HTTP connection */
const char *filename, /* I - File to print */
const char *docname, /* I - document-name */
const char *user, /* I - requesting-user-name */
+ const char *format, /* I - document-format */
int last) /* I - 1 = last file in job */
{
ipp_t *request; /* IPP request */
@@ -846,6 +848,10 @@ print_file(http_t *http, /* I - HTTP connection */
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"document-name", NULL, docname);
+ if (format)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format);
+
if (last)
ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
@@ -1278,6 +1284,8 @@ recv_print_job(
docnumber ++;
if (print_file(http, id, temp[i], docname, user,
+ cupsGetOption("document-format", num_options,
+ options),
docnumber == doccount))
status = 1;
else
@@ -1717,5 +1725,5 @@ smart_gets(char *s, /* I - Pointer to line buffer */
/*
- * End of "$Id: cups-lpd.c 6022 2006-10-10 19:47:03Z mike $".
+ * End of "$Id: cups-lpd.c 6327 2007-03-12 14:32:10Z mike $".
*/
diff --git a/scheduler/cups-polld.c b/scheduler/cups-polld.c
index be6bbb5e6..2d21f1a0c 100644
--- a/scheduler/cups-polld.c
+++ b/scheduler/cups-polld.c
@@ -1,5 +1,5 @@
/*
- * "$Id: cups-polld.c 5871 2006-08-23 20:55:33Z mike $"
+ * "$Id: cups-polld.c 5870 2006-08-23 20:30:51Z mike $"
*
* Polling daemon for the Common UNIX Printing System (CUPS).
*
@@ -478,5 +478,5 @@ sighup_handler(int sig) /* I - Signal number */
/*
- * End of "$Id: cups-polld.c 5871 2006-08-23 20:55:33Z mike $".
+ * End of "$Id: cups-polld.c 5870 2006-08-23 20:30:51Z mike $".
*/
diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h
index dbdca8bef..81b5b3588 100644
--- a/scheduler/cupsd.h
+++ b/scheduler/cupsd.h
@@ -1,5 +1,5 @@
/*
- * "$Id: cupsd.h 5305 2006-03-18 03:05:12Z mike $"
+ * "$Id: cupsd.h 6170 2007-01-02 17:26:41Z mike $"
*
* Main header file for the Common UNIX Printing System (CUPS) scheduler.
*
@@ -151,13 +151,17 @@ extern const char *cups_hstrerror(int);
/*
+ * Select callback function type...
+ */
+
+typedef void (*cupsd_selfunc_t)(void *data);
+
+
+/*
* Globals...
*/
-VAR int MaxFDs, /* Maximum number of files */
- SetSize; /* The size of the input/output sets */
-VAR fd_set *InputSet, /* Input files for select() */
- *OutputSet; /* Output files for select() */
+VAR int MaxFDs; /* Maximum number of files */
VAR time_t ReloadTime VALUE(0);
/* Time of reload request... */
@@ -200,9 +204,18 @@ extern int cupsdEndProcess(int pid, int force);
extern const char *cupsdFinishProcess(int pid, char *name, int namelen);
extern int cupsdStartProcess(const char *command, char *argv[],
char *envp[], int infd, int outfd,
- int errfd, int backfd, int root, int *pid);
+ int errfd, int backfd, int sidefd,
+ int root, int *pid);
+
+extern int cupsdAddSelect(int fd, cupsd_selfunc_t read_cb,
+ cupsd_selfunc_t write_cb, void *data);
+extern int cupsdDoSelect(long timeout);
+extern int cupsdIsSelecting(int fd);
+extern void cupsdRemoveSelect(int fd);
+extern void cupsdStartSelect(void);
+extern void cupsdStopSelect(void);
/*
- * End of "$Id: cupsd.h 5305 2006-03-18 03:05:12Z mike $".
+ * End of "$Id: cupsd.h 6170 2007-01-02 17:26:41Z mike $".
*/
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
index bc5b3a466..73abd7bfc 100644
--- a/scheduler/dirsvc.c
+++ b/scheduler/dirsvc.c
@@ -1,5 +1,5 @@
/*
- * "$Id: dirsvc.c 6205 2007-01-22 22:04:43Z mike $"
+ * "$Id: dirsvc.c 6309 2007-02-24 03:11:56Z mike $"
*
* Directory services routines for the Common UNIX Printing System (CUPS).
*
@@ -23,10 +23,13 @@
*
* Contents:
*
+ * cupsdDeregisterPrinter() - Stop sending broadcast information for a
+ * local printer and remove any pending
+ * references to remote printers.
* cupsdLoadRemoteCache() - Load the remote printer cache.
+ * cupsdRegisterPrinter() - Start sending broadcast information for a
+ * printer update the broadcast contents.
* cupsdSaveRemoteCache() - Save the remote printer cache.
- * cupsdSendBrowseDelete() - Send a "browse delete" message for a
- * printer.
* cupsdSendBrowseList() - Send new browsing information as necessary.
* cupsdStartBrowsing() - Start sending and receiving broadcast
* information.
@@ -36,9 +39,18 @@
* cupsdStopPolling() - Stop polling servers as needed.
* cupsdUpdateCUPSBrowse() - Update the browse lists using the CUPS
* protocol.
+ * cupsdUpdateDNSSDBrowse() - Handle DNS-SD queries.
* cupsdUpdateLDAPBrowse() - Scan for new printers via LDAP...
* cupsdUpdatePolling() - Read status messages from the poll daemons.
* cupsdUpdateSLPBrowse() - Get browsing information via SLP.
+ * dnssdBuildTxtRecord() - Build a TXT record from printer info.
+ * dnssdDeregisterPrinter() - Stop sending broadcast information for a
+ * printer.
+ * dnssdPackTxtRecord() - Pack an array of key/value pairs into the
+ * TXT record format.
+ * dnssdRegisterCallback() - DNSServiceRegister callback.
+ * dnssdRegisterPrinter() - Start sending broadcast information for a
+ * printer or update the broadcast contents.
* dequote() - Remote quotes from a string.
* process_browse_data() - Process new browse data.
* process_implicit_classes() - Create/update implicit classes as needed.
@@ -60,6 +72,18 @@
#include "cupsd.h"
#include <grp.h>
+#ifdef HAVE_DNSSD
+# include <dns_sd.h>
+# include <nameser.h>
+# include <nameser.h>
+# ifdef HAVE_COREFOUNDATION
+# include <CoreFoundation/CoreFoundation.h>
+# endif /* HAVE_COREFOUNDATION */
+# ifdef HAVE_SYSTEMCONFIGURATION
+# include <SystemConfiguration/SystemConfiguration.h>
+# endif /* HAVE_SYSTEMCONFIGURATION */
+#endif /* HAVE_DNSSD */
+
/*
* Local functions...
@@ -135,6 +159,72 @@ static SLPBoolean slp_url_callback(SLPHandle hslp, const char *srvurl,
SLPError errcode, void *cookie);
#endif /* HAVE_LIBSLP */
+#ifdef HAVE_DNSSD
+/*
+ * For IPP register using a subtype of 'cups' so that shared printer browsing
+ * only finds other CUPS servers (not all IPP based printers).
+ */
+static char dnssdIPPRegType[] = "_ipp._tcp,_cups";
+static char dnssdIPPFaxRegType[] = "_fax-ipp._tcp";
+
+static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p);
+static void dnssdDeregisterPrinter(cupsd_printer_t *p);
+static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
+ int count);
+static void dnssdRegisterCallback(DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorCode,
+ const char *name, const char *regtype,
+ const char *domain, void *context);
+static void dnssdRegisterPrinter(cupsd_printer_t *p);
+#endif /* HAVE_DNSSD */
+
+
+/*
+ * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
+ * local printer and remove any pending
+ * references to remote printers.
+ */
+
+void
+cupsdDeregisterPrinter(
+ cupsd_printer_t *p, /* I - Printer to register */
+ int removeit) /* I - Printer being permanently removed */
+{
+ /*
+ * Only deregister if browsing is enabled and it's a local printers...
+ */
+
+ if (!Browsing || !p->shared ||
+ (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ return;
+
+ /*
+ * Announce the deletion...
+ */
+
+ if ((BrowseLocalProtocols & BROWSE_CUPS))
+ {
+ cups_ptype_t savedtype = p->type; /* Saved printer type */
+
+ p->type |= CUPS_PRINTER_DELETE;
+
+ send_cups_browse(p);
+
+ p->type = savedtype;
+ }
+
+#ifdef HAVE_LIBSLP
+ if (BrowseLocalProtocols & BROWSE_SLP)
+ slp_dereg_printer(p);
+#endif /* HAVE_LIBSLP */
+
+#ifdef HAVE_DNSSD
+ if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD))
+ dnssdDeregisterPrinter(p);
+#endif /* HAVE_DNSSD */
+}
+
/*
* 'cupsdLoadRemoteCache()' - Load the remote printer cache.
@@ -525,6 +615,30 @@ cupsdLoadRemoteCache(void)
/*
+ * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
+ * printer or update the broadcast contents.
+ */
+
+void
+cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
+{
+ if (!Browsing || !BrowseLocalProtocols || !BrowseInterval || !NumBrowsers ||
+ (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ return;
+
+#ifdef HAVE_LIBSLP
+/* if (BrowseLocalProtocols & BROWSE_SLP)
+ slpRegisterPrinter(p); */
+#endif /* HAVE_LIBSLP */
+
+#ifdef HAVE_DNSSD
+ if (BrowseLocalProtocols & BROWSE_DNSSD)
+ dnssdRegisterPrinter(p);
+#endif /* HAVE_DNSSD */
+}
+
+
+/*
* 'cupsdRestartPolling()' - Restart polling servers as needed.
*/
@@ -570,7 +684,7 @@ cupsdSaveRemoteCache(void)
return;
}
else
- cupsdLogMessage(CUPSD_LOG_INFO, "Saving remote.cache...");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Saving remote.cache...");
/*
* Restrict access to the file...
@@ -671,41 +785,6 @@ cupsdSaveRemoteCache(void)
/*
- * 'cupsdSendBrowseDelete()' - Send a "browse delete" message for a printer.
- */
-
-void
-cupsdSendBrowseDelete(
- cupsd_printer_t *p) /* I - Printer to delete */
-{
- /*
- * Only announce if browsing is enabled and this is a local queue...
- */
-
- if (!Browsing || !p->shared ||
- (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
- return;
-
- /*
- * First mark the printer for deletion...
- */
-
- p->type |= CUPS_PRINTER_DELETE;
-
- /*
- * Announce the deletion...
- */
-
- if ((BrowseLocalProtocols & BROWSE_CUPS) && BrowseSocket >= 0)
- send_cups_browse(p);
-#ifdef HAVE_LIBSLP
- if ((BrowseLocalProtocols & BROWSE_SLP) && BrowseSLPHandle)
- slp_dereg_printer(p);
-#endif /* HAVE_LIBSLP */
-}
-
-
-/*
* 'cupsdSendBrowseList()' - Send new browsing information as necessary.
*/
@@ -853,6 +932,7 @@ cupsdStartBrowsing(void)
{
int val; /* Socket option value */
struct sockaddr_in addr; /* Broadcast address */
+ cupsd_printer_t *p; /* Current printer */
BrowseNext = NULL;
@@ -945,11 +1025,8 @@ cupsdStartBrowsing(void)
* We only listen if we want remote printers...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStartBrowsing: Adding fd %d to InputSet...",
- BrowseSocket);
-
- FD_SET(BrowseSocket, InputSet);
+ cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)cupsdUpdateCUPSBrowse,
+ NULL, NULL);
}
}
else
@@ -1048,6 +1125,16 @@ cupsdStartBrowsing(void)
BrowseLDAPRefresh = 0;
}
#endif /* HAVE_OPENLDAP */
+
+ /*
+ * Register the individual printers
+ */
+
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ cupsdRegisterPrinter(p);
}
@@ -1129,7 +1216,7 @@ cupsdStartPolling(void)
argv[1] = pollp->hostname;
- if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1,
+ if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, -1,
0, &(pollp->pid)) < 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -1150,10 +1237,7 @@ cupsdStartPolling(void)
* Finally, add the pipe to the input selection set...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStartPolling: Adding fd %d to InputSet...", PollPipe);
-
- FD_SET(PollPipe, InputSet);
+ cupsdAddSelect(PollPipe, (cupsd_selfunc_t)cupsdUpdatePolling, NULL, NULL);
}
@@ -1164,9 +1248,26 @@ cupsdStartPolling(void)
void
cupsdStopBrowsing(void)
{
+ cupsd_printer_t *p; /* Current printer */
+
+
if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols))
return;
+ /*
+ * De-register the individual printers
+ */
+
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ cupsdDeregisterPrinter(p, 1);
+
+ /*
+ * Shut down browsing sockets...
+ */
+
if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) &&
BrowseSocket >= 0)
{
@@ -1180,11 +1281,7 @@ cupsdStopBrowsing(void)
close(BrowseSocket);
#endif /* WIN32 */
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopBrowsing: Removing fd %d from InputSet...",
- BrowseSocket);
-
- FD_CLR(BrowseSocket, InputSet);
+ cupsdRemoveSelect(BrowseSocket);
BrowseSocket = -1;
}
@@ -1228,9 +1325,7 @@ cupsdStopPolling(void)
cupsdStatBufDelete(PollStatusBuffer);
close(PollPipe);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopPolling: removing fd %d from InputSet.", PollPipe);
- FD_CLR(PollPipe, InputSet);
+ cupsdRemoveSelect(PollPipe);
PollPipe = -1;
PollStatusBuffer = NULL;
@@ -1515,6 +1610,34 @@ cupsdUpdateCUPSBrowse(void)
}
+#ifdef HAVE_DNSSD
+/*
+ * 'cupsdUpdateDNSSDBrowse()' - Handle DNS-SD queries.
+ */
+
+void
+cupsdUpdateDNSSDBrowse(
+ cupsd_printer_t *p) /* I - Printer being queried */
+{
+ DNSServiceErrorType sdErr; /* Service discovery error */
+
+
+ if ((sdErr = DNSServiceProcessResult(p->dnssd_ipp_ref))
+ != kDNSServiceErr_NoError)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "DNS Service Discovery registration error %d for \"%s\"!",
+ sdErr, p->name);
+ cupsdRemoveSelect(p->dnssd_ipp_fd);
+ DNSServiceRefDeallocate(p->dnssd_ipp_ref);
+
+ p->dnssd_ipp_ref = NULL;
+ p->dnssd_ipp_fd = -1;
+ }
+}
+#endif /* HAVE_DNSSD */
+
+
#ifdef HAVE_OPENLDAP
/*
* 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
@@ -2315,6 +2438,465 @@ process_browse_data(
}
+#ifdef HAVE_DNSSD
+/*
+ * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
+ */
+
+static char * /* O - TXT record */
+dnssdBuildTxtRecord(
+ int *txt_len, /* O - TXT record length */
+ cupsd_printer_t *p) /* I - Printer information */
+{
+ int i; /* Looping var */
+ char type_str[32], /* Type to string buffer */
+ state_str[32], /* State to string buffer */
+ rp_str[1024], /* Queue name string buffer */
+ *keyvalue[32][2]; /* Table of key/value pairs */
+
+
+ /*
+ * Load up the key value pairs...
+ */
+
+ i = 0;
+
+ keyvalue[i ][0] = "txtvers";
+ keyvalue[i++][1] = "1";
+
+ keyvalue[i ][0] = "qtotal";
+ keyvalue[i++][1] = "1";
+
+ keyvalue[i ][0] = "rp";
+ keyvalue[i++][1] = rp_str;
+ snprintf(rp_str, sizeof(rp_str), "%s/%s",
+ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name);
+
+ keyvalue[i ][0] = "ty";
+ keyvalue[i++][1] = p->make_model;
+
+ if (p->location && *p->location != '\0')
+ {
+ keyvalue[i ][0] = "note";
+ keyvalue[i++][1] = p->location;
+ }
+
+ keyvalue[i ][0] = "product";
+ keyvalue[i++][1] = p->product ? p->product : "Unknown";
+
+ snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
+ snprintf(state_str, sizeof(state_str), "%d", p->state);
+
+ keyvalue[i ][0] = "printer-state";
+ keyvalue[i++][1] = state_str;
+
+ keyvalue[i ][0] = "printer-type";
+ keyvalue[i++][1] = type_str;
+
+ keyvalue[i ][0] = "Transparent";
+ keyvalue[i++][1] = "T";
+
+ keyvalue[i ][0] = "Binary";
+ keyvalue[i++][1] = "T";
+
+ if ((p->type & CUPS_PRINTER_FAX))
+ {
+ keyvalue[i ][0] = "Fax";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_COLOR))
+ {
+ keyvalue[i ][0] = "Color";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_DUPLEX))
+ {
+ keyvalue[i ][0] = "Duplex";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_STAPLE))
+ {
+ keyvalue[i ][0] = "Staple";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_COPIES))
+ {
+ keyvalue[i ][0] = "Copies";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_COLLATE))
+ {
+ keyvalue[i ][0] = "Collate";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_PUNCH))
+ {
+ keyvalue[i ][0] = "Punch";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_BIND))
+ {
+ keyvalue[i ][0] = "Bind";
+ keyvalue[i++][1] = "T";
+ }
+
+ if ((p->type & CUPS_PRINTER_SORT))
+ {
+ keyvalue[i ][0] = "Sort";
+ keyvalue[i++][1] = "T";
+ }
+
+ keyvalue[i ][0] = "pdl";
+ keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript";
+
+ /*
+ * Then pack them into a proper txt record...
+ */
+
+ return (dnssdPackTxtRecord(txt_len, keyvalue, i));
+}
+
+
+/*
+ * 'dnssdDeregisterPrinter()' - Stop sending broadcast information for a
+ * printer.
+ */
+
+static void
+dnssdDeregisterPrinter(
+ cupsd_printer_t *p) /* I - Printer */
+{
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
+
+ /*
+ * Closing the socket deregisters the service
+ */
+
+ if (p->dnssd_ipp_ref)
+ {
+ cupsdRemoveSelect(p->dnssd_ipp_fd);
+ DNSServiceRefDeallocate(p->dnssd_ipp_ref);
+ p->dnssd_ipp_ref = NULL;
+ p->dnssd_ipp_fd = -1;
+ }
+
+ cupsdClearString(&p->reg_name);
+
+ if (p->txt_record)
+ {
+ /*
+ * p->txt_record is malloc'd, not _cupsStrAlloc'd...
+ */
+
+ free(p->txt_record);
+ p->txt_record = NULL;
+ }
+}
+
+
+/*
+ * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
+ * TXT record format.
+ */
+
+static char * /* O - TXT record */
+dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */
+ char *keyvalue[][2], /* I - Table of key value pairs */
+ int count) /* I - Items in table */
+{
+ int i; /* Looping var */
+ int length; /* Length of TXT record */
+ int length2; /* Length of value */
+ char *txtRecord; /* TXT record buffer */
+ char *cursor; /* Looping pointer */
+
+
+ /*
+ * Calculate the buffer size
+ */
+
+ for (length = i = 0; i < count; i++)
+ length += 1 + strlen(keyvalue[i][0]) +
+ (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0);
+
+ /*
+ * Allocate and fill it
+ */
+
+ txtRecord = malloc(length);
+ if (txtRecord)
+ {
+ *txt_len = length;
+
+ for (cursor = txtRecord, i = 0; i < count; i++)
+ {
+ /*
+ * Drop in the p-string style length byte followed by the data
+ */
+
+ length = strlen(keyvalue[i][0]);
+ length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0;
+
+ *cursor++ = (unsigned char)(length + length2);
+
+ memcpy(cursor, keyvalue[i][0], length);
+ cursor += length;
+
+ if (length2)
+ {
+ length2 --;
+ *cursor++ = '=';
+ memcpy(cursor, keyvalue[i][1], length2);
+ cursor += length2;
+ }
+ }
+ }
+
+ return (txtRecord);
+}
+
+
+/*
+ * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
+ */
+
+static void
+dnssdRegisterCallback(
+ DNSServiceRef sdRef, /* I - DNS Service reference */
+ DNSServiceFlags flags, /* I - Reserved for future use */
+ DNSServiceErrorType errorCode, /* I - Error code */
+ const char *name, /* I - Service name */
+ const char *regtype, /* I - Service type */
+ const char *domain, /* I - Domain. ".local" for now */
+ void *context) /* I - User-defined context */
+{
+ (void)context;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "dnssdRegisterCallback(%s, %s)", name, regtype);
+
+ if (errorCode)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "DNSServiceRegister failed with error %d", (int)errorCode);
+ return;
+ }
+}
+
+
+/*
+ * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
+ * or update the broadcast contents.
+ */
+
+static void
+dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
+{
+ DNSServiceErrorType se; /* dnssd errors */
+ cupsd_listener_t *lis; /* Current listening socket */
+ char *txt_record, /* TXT record buffer */
+ *name; /* Service name */
+ int txt_len, /* TXT record length */
+ port; /* IPP port number */
+ char str_buffer[1024];
+ /* C-string buffer */
+ const char *computerName; /* Computer name c-string ptr */
+ const char *regtype; /* Registration type */
+#ifdef HAVE_COREFOUNDATION_H
+ CFStringRef computerNameRef;/* Computer name CFString */
+ CFStringEncoding nameEncoding; /* Computer name encoding */
+ CFMutableStringRef shortNameRef; /* Mutable name string */
+ CFIndex nameLength; /* Name string length */
+#else
+ int nameLength; /* Name string length */
+#endif /* HAVE_COREFOUNDATION_H */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
+ !p->dnssd_ipp_ref ? "new" : "update");
+
+ /*
+ * If per-printer sharing was just disabled make sure we're not
+ * registered before returning.
+ */
+
+ if (!p->shared)
+ {
+ dnssdDeregisterPrinter(p);
+ return;
+ }
+
+ /*
+ * Get the computer name as a c-string...
+ */
+
+#ifdef HAVE_COREFOUNDATION_H
+ computerName = NULL;
+ if ((computerNameRef = SCDynamicStoreCopyComputerName(NULL, &nameEncoding)))
+ if ((computerName = CFStringGetCStringPtr(computerNameRef,
+ kCFStringEncodingUTF8)) == NULL)
+ if (CFStringGetCString(computerNameRef, str_buffer, sizeof(str_buffer),
+ kCFStringEncodingUTF8))
+ computerName = str_buffer;
+#else
+ computerName = ServerName;
+#endif /* HAVE_COREFOUNDATION_H */
+
+ /*
+ * The registered name takes the form of "<printer-info> @ <computer name>"...
+ */
+
+ name = NULL;
+ if (computerName)
+ cupsdSetStringf(&name, "%s @ %s",
+ (p->info && strlen(p->info)) ? p->info : p->name,
+ computerName);
+ else
+ cupsdSetString(&name, (p->info && strlen(p->info)) ? p->info : p->name);
+
+#ifdef HAVE_COREFOUNDATION_H
+ if (computerNameRef)
+ CFRelease(computerNameRef);
+#endif /* HAVE_COREFOUNDATION_H */
+
+ /*
+ * If an existing printer was renamed, unregister it and start over...
+ */
+
+ if (p->reg_name && strcmp(p->reg_name, name))
+ dnssdDeregisterPrinter(p);
+
+ txt_len = 0; /* anti-compiler-warning-code */
+ txt_record = dnssdBuildTxtRecord(&txt_len, p);
+
+ if (!p->dnssd_ipp_ref)
+ {
+ /*
+ * Initial registration...
+ */
+
+ cupsdSetString(&p->reg_name, name);
+
+ port = ippPort();
+
+ for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+ lis;
+ lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+ {
+ if (lis->address.addr.sa_family == AF_INET)
+ {
+ port = ntohs(lis->address.ipv4.sin_port);
+ break;
+ }
+ else if (lis->address.addr.sa_family == AF_INET6)
+ {
+ port = ntohs(lis->address.ipv6.sin6_port);
+ break;
+ }
+ }
+
+ /*
+ * Use the _fax subtype for fax queues...
+ */
+
+ regtype = (p->type & CUPS_PRINTER_FAX) ? dnssdIPPFaxRegType :
+ dnssdIPPRegType;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) type is \"%s\"",
+ p->name, regtype);
+
+ se = DNSServiceRegister(&p->dnssd_ipp_ref, 0, 0, name, regtype,
+ NULL, NULL, htons(port), txt_len, txt_record,
+ dnssdRegisterCallback, p);
+
+ /*
+ * In case the name is too long, try shortening the string one character
+ * at a time...
+ */
+
+ if (se == kDNSServiceErr_BadParam)
+ {
+#ifdef HAVE_COREFOUNDATION_H
+ if ((shortNameRef = CFStringCreateMutable(NULL, 0)) != NULL)
+ {
+ CFStringAppendCString(shortNameRef, name, kCFStringEncodingUTF8);
+ nameLength = CFStringGetLength(shortNameRef);
+
+ while (se == kDNSServiceErr_BadParam && nameLength > 1)
+ {
+ CFStringDelete(shortNameRef, CFRangeMake(--nameLength, 1));
+ if (CFStringGetCString(shortNameRef, str_buffer, sizeof(str_buffer),
+ kCFStringEncodingUTF8))
+ {
+ se = DNSServiceRegister(&p->dnssd_ipp_ref, 0, 0, str_buffer,
+ regtype, NULL, NULL, htons(port),
+ txt_len, txt_record,
+ dnssdRegisterCallback, p);
+ }
+ }
+
+ CFRelease(shortNameRef);
+ }
+#else
+ nameLength = strlen(name);
+ while (se == kDNSServiceErr_BadParam && nameLength > 1)
+ {
+ name[--nameLength] = '\0';
+ se = DNSServiceRegister(&p->dnssd_ipp_ref, 0, 0, str_buffer, regtype,
+ NULL, NULL, htons(port), txt_len, txt_record,
+ dnssdRegisterCallback, p);
+ }
+#endif /* HAVE_COREFOUNDATION_H */
+ }
+
+ if (se == kDNSServiceErr_NoError)
+ {
+ p->dnssd_ipp_fd = DNSServiceRefSockFD(p->dnssd_ipp_ref);
+ p->txt_record = txt_record;
+ p->txt_len = txt_len;
+ txt_record = NULL;
+
+ cupsdAddSelect(p->dnssd_ipp_fd, (cupsd_selfunc_t)cupsdUpdateDNSSDBrowse,
+ NULL, (void *)p);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "DNS-SD registration of \"%s\" failed with %d",
+ p->name, se);
+ }
+ else if (txt_len != p->txt_len || memcmp(txt_record, p->txt_record, txt_len))
+ {
+ /*
+ * Update the existing registration...
+ */
+
+ /* A TTL of 0 means use record's original value (Radar 3176248) */
+ se = DNSServiceUpdateRecord(p->dnssd_ipp_ref, NULL, 0,
+ txt_len, txt_record, 0);
+
+ if (p->txt_record)
+ free(p->txt_record);
+
+ p->txt_record = txt_record;
+ p->txt_len = txt_len;
+ txt_record = NULL;
+ }
+
+ if (txt_record)
+ free(txt_record);
+
+ cupsdClearString(&name);
+}
+#endif /* HAVE_DNSSD */
+
+
/*
* 'process_implicit_classes()' - Create/update implicit classes as needed.
*/
@@ -3192,5 +3774,5 @@ slp_url_callback(
/*
- * End of "$Id: dirsvc.c 6205 2007-01-22 22:04:43Z mike $".
+ * End of "$Id: dirsvc.c 6309 2007-02-24 03:11:56Z mike $".
*/
diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
index 2e3a05988..f9d0c025c 100644
--- a/scheduler/dirsvc.h
+++ b/scheduler/dirsvc.h
@@ -1,10 +1,10 @@
/*
- * "$Id: dirsvc.h 5833 2006-08-16 20:05:58Z mike $"
+ * "$Id: dirsvc.h 6291 2007-02-19 21:54:27Z mike $"
*
* Directory services definitions for the Common UNIX Printing System
* (CUPS) scheduler.
*
- * Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -45,7 +45,7 @@
#define BROWSE_CUPS 1 /* CUPS */
#define BROWSE_SLP 2 /* SLPv2 */
#define BROWSE_LDAP 4 /* LDAP */
-#define BROWSE_DNSSD 8 /* DNS Service Discovery aka Bonjour */
+#define BROWSE_DNSSD 8 /* DNS Service Discovery (aka Bonjour) */
#define BROWSE_ALL 15 /* All protocols */
@@ -163,16 +163,20 @@ VAR char *BrowseLDAPBindDN VALUE(NULL),
* Prototypes...
*/
+extern void cupsdDeregisterPrinter(cupsd_printer_t *p, int removeit);
extern void cupsdLoadRemoteCache(void);
+extern void cupsdRegisterPrinter(cupsd_printer_t *p);
extern void cupsdRestartPolling(void);
extern void cupsdSaveRemoteCache(void);
-extern void cupsdSendBrowseDelete(cupsd_printer_t *p);
extern void cupsdSendBrowseList(void);
extern void cupsdStartBrowsing(void);
extern void cupsdStartPolling(void);
extern void cupsdStopBrowsing(void);
extern void cupsdStopPolling(void);
extern void cupsdUpdateCUPSBrowse(void);
+#ifdef HAVE_DNSSD
+extern void cupsdUpdateDNSSDBrowse(cupsd_printer_t *p);
+#endif /* HAVE_DNSSD */
#ifdef HAVE_LDAP
extern void cupsdUpdateLDAPBrowse(void);
#endif /* HAVE_LDAP */
@@ -181,5 +185,5 @@ extern void cupsdUpdateSLPBrowse(void);
/*
- * End of "$Id: dirsvc.h 5833 2006-08-16 20:05:58Z mike $".
+ * End of "$Id: dirsvc.h 6291 2007-02-19 21:54:27Z mike $".
*/
diff --git a/scheduler/filter.c b/scheduler/filter.c
index 25d3b651e..e6ca1b518 100644
--- a/scheduler/filter.c
+++ b/scheduler/filter.c
@@ -1,9 +1,9 @@
/*
- * "$Id: filter.c 5606 2006-05-30 19:40:34Z mike $"
+ * "$Id: filter.c 6252 2007-02-10 15:34:18Z mike $"
*
* File type conversion routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -23,12 +23,12 @@
*
* Contents:
*
- * mimeAddFilter() - Add a filter to the current MIME database.
- * mimeFilter() - Find the fastest way to convert from one type to
- * another.
- * compare_filters() - Compare two filters...
- * find_filters() - Find the filters to convert from one type to another.
- * lookup() - Lookup a filter...
+ * mimeAddFilter() - Add a filter to the current MIME database.
+ * mimeFilter() - Find the fastest way to convert from one type to
+ * another.
+ * mimeFilterLookup() - Lookup a filter...
+ * compare_filters() - Compare two filters...
+ * find_filters() - Find the filters to convert from one type to another.
*/
/*
@@ -64,7 +64,6 @@ static int compare_srcs(mime_filter_t *, mime_filter_t *);
static cups_array_t *find_filters(mime_t *mime, mime_type_t *src,
mime_type_t *dst, int *cost,
_mime_typelist_t *visited);
-static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
/*
@@ -93,7 +92,7 @@ mimeAddFilter(mime_t *mime, /* I - MIME database */
* destination...
*/
- if ((temp = lookup(mime, src, dst)) != NULL)
+ if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
{
/*
* Yup, does the existing filter have a higher cost? If so, copy the
@@ -194,6 +193,25 @@ mimeFilter(mime_t *mime, /* I - MIME database */
/*
+ * 'mimeFilterLookup()' - Lookup a filter...
+ */
+
+mime_filter_t * /* O - Filter for src->dst */
+mimeFilterLookup(mime_t *mime, /* I - MIME database */
+ mime_type_t *src, /* I - Source type */
+ mime_type_t *dst) /* I - Destination type */
+{
+ mime_filter_t key; /* Key record for filter search */
+
+
+ key.src = src;
+ key.dst = dst;
+
+ return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
+}
+
+
+/*
* 'compare_filters()' - Compare two filters...
*/
@@ -260,7 +278,7 @@ find_filters(mime_t *mime, /* I - MIME database */
* See if there is a filter that can convert the files directly...
*/
- if ((current = lookup(mime, src, dst)) != NULL)
+ if ((current = mimeFilterLookup(mime, src, dst)) != NULL)
{
/*
* Got a direct filter!
@@ -392,24 +410,5 @@ find_filters(mime_t *mime, /* I - MIME database */
/*
- * 'lookup()' - Lookup a filter...
- */
-
-static mime_filter_t * /* O - Filter for src->dst */
-lookup(mime_t *mime, /* I - MIME database */
- mime_type_t *src, /* I - Source type */
- mime_type_t *dst) /* I - Destination type */
-{
- mime_filter_t key; /* Key record for filter search */
-
-
- key.src = src;
- key.dst = dst;
-
- return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
-}
-
-
-/*
- * End of "$Id: filter.c 5606 2006-05-30 19:40:34Z mike $".
+ * End of "$Id: filter.c 6252 2007-02-10 15:34:18Z mike $".
*/
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index f96d2bf13..78edc3cc8 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -1,9 +1,12 @@
/*
- * "$Id: ipp.c 6145 2006-12-06 20:10:16Z mike $"
+ * "$Id: ipp.c 6318 2007-03-06 04:36:55Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ *
+ * This file contains Kerberos support code, copyright 2006 by
+ * Jelmer Vernooij.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -79,6 +82,7 @@
* release_job() - Release a held print job.
* restart_job() - Restart an old print job.
* save_auth_info() - Save authentication information for a job.
+ * save_krb5_creds() - Save Kerberos credentials for a job.
* send_document() - Send a file to a printer or class.
* send_http_error() - Send a HTTP error back to the IPP client.
* send_ipp_status() - Send a status back to the IPP client.
@@ -101,6 +105,10 @@
#include "cupsd.h"
+#ifdef HAVE_KRB5_H
+# include <krb5.h>
+#endif /* HAVE_KRB5_H */
+
#ifdef HAVE_LIBPAPER
# include <paper.h>
#endif /* HAVE_LIBPAPER */
@@ -114,8 +122,7 @@ static void accept_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void add_class(cupsd_client_t *con, ipp_attribute_t *uri);
static int add_file(cupsd_client_t *con, cupsd_job_t *job,
mime_type_t *filetype, int compression);
-static cupsd_job_t *add_job(cupsd_client_t *con, ipp_attribute_t *uri,
- cupsd_printer_t **dprinter,
+static cupsd_job_t *add_job(cupsd_client_t *con, cupsd_printer_t *printer,
mime_type_t *filetype);
static void add_job_state_reasons(cupsd_client_t *con, cupsd_job_t *job);
static void add_job_subscriptions(cupsd_client_t *con, cupsd_job_t *job);
@@ -174,7 +181,11 @@ static void reject_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void release_job(cupsd_client_t *con, ipp_attribute_t *uri);
static void renew_subscription(cupsd_client_t *con, int sub_id);
static void restart_job(cupsd_client_t *con, ipp_attribute_t *uri);
-static void save_auth_info(cupsd_client_t *con, cupsd_job_t *job);
+static void save_auth_info(cupsd_client_t *con, cupsd_job_t *job,
+ ipp_attribute_t *auth_info);
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5_H)
+static void save_krb5_creds(cupsd_client_t *con, cupsd_job_t *job);
+#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
static void send_document(cupsd_client_t *con, ipp_attribute_t *uri);
static void send_http_error(cupsd_client_t *con, http_status_t status);
static void send_ipp_status(cupsd_client_t *con, ipp_status_t status,
@@ -233,7 +244,7 @@ cupsdProcessIPPRequest(
/*
* Then validate the request header and required attributes...
*/
-
+
if (con->request->request.any.version[0] != 1)
{
/*
@@ -250,7 +261,7 @@ cupsdProcessIPPRequest(
_("Bad request version number %d.%d!"),
con->request->request.any.version[0],
con->request->request.any.version[1]);
- }
+ }
else if (!con->request->attrs)
{
cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL,
@@ -384,7 +395,7 @@ cupsdProcessIPPRequest(
cupsdLogMessage(CUPSD_LOG_DEBUG, "Request attributes follow...");
for (attr = con->request->attrs; attr; attr = attr->next)
- cupsdLogMessage(CUPSD_LOG_DEBUG,
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
"attr \"%s\": group_tag = %x, value_tag = %x",
attr->name ? attr->name : "(null)", attr->group_tag,
attr->value_tag);
@@ -651,11 +662,8 @@ cupsdProcessIPPRequest(
con->http.data_remaining = length;
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdProcessIPPRequest: Adding fd %d to OutputSet...",
- con->http.fd);
-
- FD_SET(con->http.fd, OutputSet);
+ cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient,
+ (cupsd_selfunc_t)cupsdWriteClient, con);
/*
* Tell the caller the response header was sent successfully...
@@ -694,12 +702,6 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI], /* Method portion of URI */
- username[HTTP_MAX_URI], /* Username portion of URI */
- host[HTTP_MAX_URI], /* Host portion of URI */
- resource[HTTP_MAX_URI]; /* Resource portion of URI */
- int port; /* Port portion of URI */
- const char *name; /* Printer name */
cupsd_printer_t *printer; /* Printer data */
@@ -710,11 +712,7 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((name = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -745,12 +743,19 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */
cupsdAddPrinterHistory(printer);
if (dtype & CUPS_PRINTER_CLASS)
+ {
cupsdSaveAllClasses();
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" now accepting jobs (\"%s\").",
+ printer->name, get_username(con));
+ }
else
+ {
cupsdSaveAllPrinters();
- cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" now accepting jobs (\"%s\").", name,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" now accepting jobs (\"%s\").",
+ printer->name, get_username(con));
+ }
/*
* Everything was ok, so return OK status...
@@ -932,7 +937,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */
IPP_TAG_BOOLEAN)) != NULL)
{
if (pclass->shared && !attr->values[0].boolean)
- cupsdSendBrowseDelete(pclass);
+ cupsdDeregisterPrinter(pclass, 1);
cupsdLogMessage(CUPSD_LOG_INFO,
"Setting %s printer-is-shared to %d (was %d.)",
@@ -996,11 +1001,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */
* Search for the printer or class URI...
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if (!cupsdValidateDest(host, resource, &dtype, &member))
+ if (!cupsdValidateDest(attr->values[i].string.text, &dtype, &member))
{
/*
* Bad URI...
@@ -1137,54 +1138,25 @@ add_file(cupsd_client_t *con, /* I - Connection to client */
static cupsd_job_t * /* O - Job object */
add_job(cupsd_client_t *con, /* I - Client connection */
- ipp_attribute_t *uri, /* I - printer-uri */
- cupsd_printer_t **dprinter, /* I - Destination printer */
+ cupsd_printer_t *printer, /* I - Destination printer */
mime_type_t *filetype) /* I - First print file type, if any */
{
http_status_t status; /* Policy status */
- ipp_attribute_t *attr; /* Current attribute */
- const char *dest; /* Destination */
- cups_ptype_t dtype; /* Destination type (printer or class) */
+ ipp_attribute_t *attr, /* Current attribute */
+ *auth_info; /* auth-info attribute */
const char *val; /* Default option value */
int priority; /* Job priority */
char *title; /* Job name/title */
cupsd_job_t *job; /* Current job */
- char job_uri[HTTP_MAX_URI], /* Job URI */
- method[HTTP_MAX_URI], /* Method portion of URI */
- username[HTTP_MAX_URI], /* Username portion of URI */
- host[HTTP_MAX_URI], /* Host portion of URI */
- resource[HTTP_MAX_URI]; /* Resource portion of URI */
- int port; /* Port portion of URI */
- cupsd_printer_t *printer; /* Printer data */
+ char job_uri[HTTP_MAX_URI]; /* Job URI */
int kbytes; /* Size of print file */
int i; /* Looping var */
int lowerpagerange; /* Page range bound */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %s)", con,
- con->http.fd, uri->values[0].string.text);
-
- /*
- * Is the destination valid?
- */
-
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
- {
- /*
- * Bad URI...
- */
-
- send_ipp_status(con, IPP_NOT_FOUND,
- _("The printer or class was not found."));
- return (NULL);
- }
-
- if (dprinter)
- *dprinter = printer;
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))",
+ con, con->http.fd, printer, printer->name,
+ filetype, filetype->super, filetype->type);
/*
* Check remote printing to non-shared printer...
@@ -1222,13 +1194,13 @@ add_job(cupsd_client_t *con, /* I - Client connection */
{
send_ipp_status(con, IPP_NOT_ACCEPTING,
_("Destination \"%s\" is not accepting jobs."),
- dest);
+ printer->name);
return (NULL);
}
/*
* Validate job template attributes; for now just document-format,
- * copies, and page-ranges...
+ * copies, number-up, and page-ranges...
*/
if (filetype && printer->filetypes &&
@@ -1263,12 +1235,30 @@ add_job(cupsd_client_t *con, /* I - Client connection */
}
}
+ if ((attr = ippFindAttribute(con->request, "number-up",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ if (attr->values[0].integer != 1 &&
+ attr->values[0].integer != 2 &&
+ attr->values[0].integer != 4 &&
+ attr->values[0].integer != 6 &&
+ attr->values[0].integer != 9 &&
+ attr->values[0].integer != 16)
+ {
+ send_ipp_status(con, IPP_ATTRIBUTES, _("Bad number-up value %d."),
+ attr->values[0].integer);
+ ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER,
+ "number-up", attr->values[0].integer);
+ return (NULL);
+ }
+ }
+
if ((attr = ippFindAttribute(con->request, "page-ranges",
IPP_TAG_RANGE)) != NULL)
{
for (i = 0, lowerpagerange = 1; i < attr->num_values; i ++)
{
- if (attr->values[i].range.lower < lowerpagerange ||
+ if (attr->values[i].range.lower < lowerpagerange ||
attr->values[i].range.lower > attr->values[i].range.upper)
{
send_ipp_status(con, IPP_BAD_REQUEST,
@@ -1289,7 +1279,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */
if (MaxJobs && cupsArrayCount(Jobs) >= MaxJobs)
cupsdCleanJobs();
- if (cupsArrayCount(Jobs) >= MaxJobs && MaxJobs)
+ if (MaxJobs && cupsArrayCount(Jobs) >= MaxJobs)
{
send_ipp_status(con, IPP_NOT_POSSIBLE,
_("Too many active jobs."));
@@ -1331,11 +1321,13 @@ add_job(cupsd_client_t *con, /* I - Client connection */
if ((job = cupsdAddJob(priority, printer->name)) == NULL)
{
send_ipp_status(con, IPP_INTERNAL_ERROR,
- _("Unable to add job for destination \"%s\"!"), dest);
+ _("Unable to add job for destination \"%s\"!"),
+ printer->name);
return (NULL);
}
- job->dtype = dtype;
+ job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
job->attrs = con->request;
con->request = ippNewRequest(job->attrs->request.op.operation_id);
@@ -1350,8 +1342,6 @@ add_job(cupsd_client_t *con, /* I - Client connection */
if (attr)
cupsdSetString(&attr->values[0].string.text, con->username);
-
- save_auth_info(con, job);
}
else if (attr)
{
@@ -1374,6 +1364,30 @@ add_job(cupsd_client_t *con, /* I - Client connection */
attr->name = _cupsStrAlloc("job-originating-user-name");
}
+ auth_info = ippFindAttribute(job->attrs, "auth-info", IPP_TAG_TEXT);
+
+ if (con->username[0] || auth_info)
+ {
+ save_auth_info(con, job, auth_info);
+
+ /*
+ * Remove the auth-info attribute from the attribute data...
+ */
+
+ if (auth_info)
+ {
+ if (job->attrs->prev)
+ job->attrs->prev->next = auth_info->next;
+ else
+ job->attrs->attrs = auth_info->next;
+
+ if (job->attrs->last == auth_info)
+ job->attrs->last = job->attrs->prev;
+
+ _ippFreeAttr(auth_info);
+ }
+ }
+
if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name",
IPP_TAG_ZERO)) != NULL)
{
@@ -1440,7 +1454,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */
* the connection...
*/
- ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME,
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME,
"job-originating-host-name", NULL, con->http.hostname);
}
@@ -2266,7 +2280,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */
IPP_TAG_BOOLEAN)) != NULL)
{
if (printer->shared && !attr->values[0].boolean)
- cupsdSendBrowseDelete(printer);
+ cupsdDeregisterPrinter(printer, 1);
cupsdLogMessage(CUPSD_LOG_INFO,
"Setting %s printer-is-shared to %d (was %d.)",
@@ -2566,7 +2580,7 @@ apply_printer_defaults(
int i, /* Looping var */
num_options; /* Number of default options */
cups_option_t *options, /* Default options */
- *option; /* Current option */
+ *option; /* Current option */
/*
@@ -2600,7 +2614,8 @@ static void
authenticate_job(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *uri) /* I - Job URI */
{
- ipp_attribute_t *attr; /* Job-id attribute */
+ ipp_attribute_t *attr, /* job-id attribute */
+ *auth_info; /* auth-info attribute */
int jobid; /* Job ID */
cupsd_job_t *job; /* Current job */
char method[HTTP_MAX_URI],
@@ -2652,7 +2667,7 @@ authenticate_job(cupsd_client_t *con, /* I - Client connection */
httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
sizeof(method), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
-
+
if (strncmp(resource, "/jobs/", 6))
{
/*
@@ -2702,7 +2717,9 @@ authenticate_job(cupsd_client_t *con, /* I - Client connection */
* See if we have already authenticated...
*/
- if (!con->username[0])
+ auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT);
+
+ if (!con->username[0] && !auth_info)
{
send_ipp_status(con, IPP_NOT_AUTHORIZED,
_("No authentication information provided!"));
@@ -2723,7 +2740,7 @@ authenticate_job(cupsd_client_t *con, /* I - Client connection */
* Save the authentication information for this job...
*/
- save_auth_info(con, job);
+ save_auth_info(con, job, auth_info);
/*
* Reset the job-hold-until value to "no-hold"...
@@ -2759,11 +2776,10 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *uri) /* I - Job or Printer URI */
{
http_status_t status; /* Policy status */
- const char *dest; /* Destination */
cups_ptype_t dtype; /* Destination type */
- char method[HTTP_MAX_URI], /* Method portion of URI */
+ char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
userpass[HTTP_MAX_URI], /* Username portion of URI */
- host[HTTP_MAX_URI], /* Host portion of URI */
+ hostname[HTTP_MAX_URI], /* Host portion of URI */
resource[HTTP_MAX_URI]; /* Resource portion of URI */
int port; /* Port portion of URI */
ipp_attribute_t *attr; /* Attribute in request */
@@ -2822,16 +2838,17 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */
* And if the destination is valid...
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), userpass, sizeof(userpass), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI?
*/
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text,
+ scheme, sizeof(scheme), userpass, sizeof(userpass),
+ hostname, sizeof(hostname), &port,
+ resource, sizeof(resource));
+
if ((!strncmp(resource, "/printers/", 10) && resource[10]) ||
(!strncmp(resource, "/classes/", 9) && resource[9]))
{
@@ -2839,13 +2856,6 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */
_("The printer or class was not found."));
return;
}
- else if (strcmp(resource, "/printers/"))
- {
- send_ipp_status(con, IPP_NOT_FOUND,
- _("The printer-uri \"%s\" is not valid."),
- uri->values[0].string.text);
- return;
- }
/*
* Check policy...
@@ -2872,7 +2882,8 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */
* Check policy...
*/
- if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
+ if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
+ NULL)) != HTTP_OK)
{
send_http_error(con, status);
return;
@@ -2882,10 +2893,11 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */
* Cancel all of the jobs on the named printer...
*/
- cupsdCancelJobs(dest, username, purge);
+ cupsdCancelJobs(printer->name, username, purge);
cupsdLogMessage(CUPSD_LOG_INFO, "All jobs on \"%s\" were %s by \"%s\".",
- dest, purge ? "purged" : "canceled", get_username(con));
+ printer->name, purge ? "purged" : "canceled",
+ get_username(con));
}
con->response->request.status.status_code = IPP_OK;
@@ -2902,13 +2914,12 @@ cancel_job(cupsd_client_t *con, /* I - Client connection */
{
ipp_attribute_t *attr; /* Current attribute */
int jobid; /* Job ID */
- char method[HTTP_MAX_URI], /* Method portion of URI */
+ char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
username[HTTP_MAX_URI], /* Username portion of URI */
host[HTTP_MAX_URI], /* Host portion of URI */
resource[HTTP_MAX_URI]; /* Resource portion of URI */
int port; /* Port portion of URI */
cupsd_job_t *job; /* Job information */
- const char *dest; /* Destination */
cups_ptype_t dtype; /* Destination type (printer or class) */
cupsd_printer_t *printer; /* Printer data */
@@ -2940,11 +2951,7 @@ cancel_job(cupsd_client_t *con, /* I - Client connection */
* Find the current job on the specified printer...
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -2966,12 +2973,12 @@ cancel_job(cupsd_client_t *con, /* I - Client connection */
/*
* No, see if there are any pending jobs...
*/
-
+
for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
job;
job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
if (job->state_value <= IPP_JOB_PROCESSING &&
- !strcasecmp(job->dest, dest))
+ !strcasecmp(job->dest, printer->name))
break;
if (job)
@@ -2979,7 +2986,7 @@ cancel_job(cupsd_client_t *con, /* I - Client connection */
else
{
send_ipp_status(con, IPP_NOT_POSSIBLE, _("No active jobs on %s!"),
- dest);
+ printer->name);
return;
}
}
@@ -2991,10 +2998,10 @@ cancel_job(cupsd_client_t *con, /* I - Client connection */
* Got a job URI; parse it to get the job ID...
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
+ sizeof(scheme), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
-
+
if (strncmp(resource, "/jobs/", 6))
{
/*
@@ -3794,7 +3801,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
const char *from, /* I - Source file */
const char *to) /* I - Destination file */
{
- fd_set *input; /* select() input set */
+ fd_set input; /* select() input set */
struct timeval timeout; /* select() timeout */
int maxfd; /* Maximum file descriptor for select() */
char tempfile[1024]; /* Temporary PPD file */
@@ -3847,24 +3854,12 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
cupsdOpenPipe(temppipe);
- if ((input = calloc(1, SetSize)) == NULL)
- {
- close(tempfd);
- unlink(tempfile);
-
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "copy_model: Unable to allocate %d bytes for select()...",
- SetSize);
- return (-1);
- }
-
cupsdLogMessage(CUPSD_LOG_DEBUG,
"copy_model: Running \"cups-driverd cat %s\"...", from);
if (!cupsdStartProcess(buffer, argv, envp, -1, temppipe[1], CGIPipes[1],
- -1, 0, &temppid))
+ -1, -1, 0, &temppid))
{
- free(input);
close(tempfd);
unlink(tempfile);
return (-1);
@@ -3891,13 +3886,14 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
bytes = 0;
- FD_SET(temppipe[0], input);
- FD_SET(CGIPipes[0], input);
+ FD_ZERO(&input);
+ FD_SET(temppipe[0], &input);
+ FD_SET(CGIPipes[0], &input);
timeout.tv_sec = 30;
timeout.tv_usec = 0;
- if ((i = select(maxfd, input, NULL, NULL, &timeout)) < 0)
+ if ((i = select(maxfd, &input, NULL, NULL, &timeout)) < 0)
{
if (errno == EINTR)
continue;
@@ -3913,7 +3909,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
break;
}
- if (FD_ISSET(temppipe[0], input))
+ if (FD_ISSET(temppipe[0], &input))
{
/*
* Read the PPD file from the pipe, and write it to the PPD file.
@@ -3930,15 +3926,13 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
break;
}
- if (FD_ISSET(CGIPipes[0], input))
+ if (FD_ISSET(CGIPipes[0], &input))
cupsdUpdateCGI();
}
close(temppipe[0]);
close(tempfd);
- free(input);
-
if (!total)
{
/*
@@ -4020,13 +4014,13 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
if ((!strcmp(system_paper, "Letter") && have_letter) ||
(!strcmp(system_paper, "A4") && have_a4))
{
- num_defaults = cupsAddOption("PageSize", system_paper,
+ num_defaults = cupsAddOption("PageSize", system_paper,
num_defaults, &defaults);
- num_defaults = cupsAddOption("PageRegion", system_paper,
+ num_defaults = cupsAddOption("PageRegion", system_paper,
num_defaults, &defaults);
- num_defaults = cupsAddOption("PaperDimension", system_paper,
+ num_defaults = cupsAddOption("PaperDimension", system_paper,
num_defaults, &defaults);
- num_defaults = cupsAddOption("ImageableArea", system_paper,
+ num_defaults = cupsAddOption("ImageableArea", system_paper,
num_defaults, &defaults);
}
}
@@ -4261,7 +4255,7 @@ copy_printer_attrs(
if (!ra || cupsArrayFind(ra, "printer-state-change-time"))
ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"printer-state-change-time", printer->state_time);
-
+
if (MaxPrinterHistory > 0 && printer->num_history > 0 &&
cupsArrayFind(ra, "printer-state-history"))
{
@@ -4446,23 +4440,39 @@ static void
create_job(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *uri) /* I - Printer URI */
{
- cupsd_job_t *job; /* New job */
+ cupsd_printer_t *printer; /* Printer */
+ cupsd_job_t *job; /* New job */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", con,
con->http.fd, uri->values[0].string.text);
/*
+ * Is the destination valid?
+ */
+
+ if (!cupsdValidateDest(uri->values[0].string.text, NULL, &printer))
+ {
+ /*
+ * Bad URI...
+ */
+
+ send_ipp_status(con, IPP_NOT_FOUND,
+ _("The printer or class was not found."));
+ return;
+ }
+
+ /*
* Create the job object...
*/
- if ((job = add_job(con, uri, NULL, NULL)) == NULL)
+ if ((job = add_job(con, printer, NULL)) == NULL)
return;
/*
* Save and log the job...
*/
-
+
cupsdSaveJob(job);
cupsdLogMessage(CUPSD_LOG_INFO, "Job %d created on \"%s\" by \"%s\".",
@@ -4630,6 +4640,16 @@ create_requested_array(ipp_t *request) /* I - IPP request */
cupsArrayAdd(ra, "uri-authentication-supported");
cupsArrayAdd(ra, "uri-security-supported");
}
+ else if (!strcmp(value, "printer-defaults"))
+ {
+ char *name; /* Option name */
+
+
+ for (name = (char *)cupsArrayFirst(CommonDefaults);
+ name;
+ name = (char *)cupsArrayNext(CommonDefaults))
+ cupsArrayAdd(ra, name);
+ }
else if (!strcmp(value, "subscription-template"))
{
cupsArrayAdd(ra, "notify-attributes");
@@ -4683,6 +4703,8 @@ create_subscription(
int interval, /* notify-time-interval */
lease; /* notify-lease-duration */
unsigned mask; /* notify-events */
+ ipp_attribute_t *notify_events,/* notify-events(-default) */
+ *notify_lease; /* notify-lease-duration(-default) */
#ifdef DEBUG
@@ -4723,7 +4745,7 @@ create_subscription(
dtype = CUPS_PRINTER_CLASS;
printer = NULL;
}
- else if (!cupsdValidateDest(host, resource, &dtype, &printer))
+ else if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -4740,7 +4762,8 @@ create_subscription(
if (printer)
{
- if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
+ if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
+ NULL)) != HTTP_OK)
{
send_http_error(con, status);
return;
@@ -4790,6 +4813,23 @@ create_subscription(
jobid = 0;
mask = CUPSD_EVENT_NONE;
+ if (printer)
+ {
+ notify_events = ippFindAttribute(printer->attrs, "notify-events-default",
+ IPP_TAG_KEYWORD);
+ notify_lease = ippFindAttribute(printer->attrs,
+ "notify-lease-duration-default",
+ IPP_TAG_INTEGER);
+
+ if (notify_lease)
+ lease = notify_lease->values[0].integer;
+ }
+ else
+ {
+ notify_events = NULL;
+ notify_lease = NULL;
+ }
+
while (attr && attr->group_tag != IPP_TAG_ZERO)
{
if (!strcmp(attr->name, "notify-recipient") &&
@@ -4878,10 +4918,7 @@ create_subscription(
}
else if (!strcmp(attr->name, "notify-events") &&
attr->value_tag == IPP_TAG_KEYWORD)
- {
- for (i = 0; i < attr->num_values; i ++)
- mask |= cupsdEventValue(attr->values[i].string.text);
- }
+ notify_events = attr;
else if (!strcmp(attr->name, "notify-lease-duration") &&
attr->value_tag == IPP_TAG_INTEGER)
lease = attr->values[0].integer;
@@ -4895,6 +4932,12 @@ create_subscription(
attr = attr->next;
}
+ if (notify_events)
+ {
+ for (i = 0; i < notify_events->num_values; i ++)
+ mask |= cupsdEventValue(notify_events->values[i].string.text);
+ }
+
if (recipient)
cupsdLogMessage(CUPSD_LOG_DEBUG, "recipient=\"%s\"", recipient);
if (pullmethod)
@@ -4989,13 +5032,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *uri) /* I - URI of printer or class */
{
http_status_t status; /* Policy status */
- const char *dest; /* Destination */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI], /* Method portion of URI */
- username[HTTP_MAX_URI], /* Username portion of URI */
- host[HTTP_MAX_URI], /* Host portion of URI */
- resource[HTTP_MAX_URI]; /* Resource portion of URI */
- int port; /* Port portion of URI */
cupsd_printer_t *printer; /* Printer/class */
char filename[1024]; /* Script/PPD filename */
@@ -5007,11 +5044,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
* Do we have a valid URI?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -5036,7 +5069,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
* Remove old jobs...
*/
- cupsdCancelJobs(dest, NULL, 1);
+ cupsdCancelJobs(printer->name, NULL, 1);
/*
* Remove old subscriptions and send a "deleted printer" event...
@@ -5045,32 +5078,34 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */
cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, printer, NULL,
"%s \"%s\" deleted by \"%s\".",
(dtype & CUPS_PRINTER_CLASS) ? "Class" : "Printer",
- dest, get_username(con));
+ printer->name, get_username(con));
cupsdExpireSubscriptions(printer, NULL);
-
+
/*
* Remove any old PPD or script files...
*/
- snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot, dest);
+ snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot,
+ printer->name);
unlink(filename);
- snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest);
+ snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
+ printer->name);
unlink(filename);
if (dtype & CUPS_PRINTER_CLASS)
{
- cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" deleted by \"%s\".", dest,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" deleted by \"%s\".",
+ printer->name, get_username(con));
cupsdDeletePrinter(printer, 0);
cupsdSaveAllClasses();
}
else
{
- cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" deleted by \"%s\".", dest,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" deleted by \"%s\".",
+ printer->name, get_username(con));
cupsdDeletePrinter(printer, 0);
cupsdSaveAllPrinters();
@@ -5313,7 +5348,7 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
const char *dest; /* Destination */
cups_ptype_t dtype; /* Destination type (printer or class) */
cups_ptype_t dmask; /* Destination type mask */
- char method[HTTP_MAX_URI], /* Method portion of URI */
+ char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
username[HTTP_MAX_URI], /* Username portion of URI */
host[HTTP_MAX_URI], /* Host portion of URI */
resource[HTTP_MAX_URI]; /* Resource portion of URI */
@@ -5335,8 +5370,8 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
+ sizeof(scheme), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
if (!strcmp(resource, "/") ||
@@ -5361,7 +5396,8 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
dmask = CUPS_PRINTER_CLASS;
printer = NULL;
}
- else if ((dest = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ else if ((dest = cupsdValidateDest(uri->values[0].string.text, &dtype,
+ &printer)) == NULL)
{
/*
* Bad URI...
@@ -5383,7 +5419,8 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
if (printer)
{
- if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
+ if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
+ NULL)) != HTTP_OK)
{
send_http_error(con, status);
return;
@@ -5512,7 +5549,7 @@ get_notifications(cupsd_client_t *con) /* I - Client connection */
int interval; /* Poll interval */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_subscription_attrs(con=%p[%d])",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_notifications(con=%p[%d])",
con, con->http.fd);
/*
@@ -5720,15 +5757,6 @@ get_printer_attrs(cupsd_client_t *con, /* I - Client connection */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
- username[HTTP_MAX_URI],
- /* Username portion of URI */
- host[HTTP_MAX_URI],
- /* Host portion of URI */
- resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int port; /* Port portion of URI */
cupsd_printer_t *printer; /* Printer/class */
cups_array_t *ra; /* Requested attributes array */
@@ -5740,11 +5768,7 @@ get_printer_attrs(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if (!cupsdValidateDest(host, resource, &dtype, &printer))
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -6007,8 +6031,8 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
cups_array_t *ra; /* Requested attributes array */
ipp_attribute_t *attr; /* Attribute */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
+ char scheme[HTTP_MAX_URI],
+ /* Scheme portion of URI */
username[HTTP_MAX_URI],
/* Username portion of URI */
host[HTTP_MAX_URI],
@@ -6028,8 +6052,8 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
+ sizeof(scheme), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
if (!strcmp(resource, "/") ||
@@ -6052,7 +6076,7 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
return;
}
}
- else if (!cupsdValidateDest(host, resource, &dtype, &printer))
+ else if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -6316,7 +6340,7 @@ move_job(cupsd_client_t *con, /* I - Client connection */
const char *src; /* Source printer/class */
cups_ptype_t stype, /* Source type (printer or class) */
dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI], /* Method portion of URI */
+ char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
username[HTTP_MAX_URI], /* Username portion of URI */
host[HTTP_MAX_URI], /* Host portion of URI */
resource[HTTP_MAX_URI]; /* Resource portion of URI */
@@ -6343,12 +6367,8 @@ move_job(cupsd_client_t *con, /* I - Client connection */
_("job-printer-uri attribute missing!"));
return;
}
-
- httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
- if (!cupsdValidateDest(host, resource, &dtype, &dprinter))
+ if (!cupsdValidateDest(attr->values[0].string.text, &dtype, &dprinter))
{
/*
* Bad URI...
@@ -6363,7 +6383,8 @@ move_job(cupsd_client_t *con, /* I - Client connection */
* Check policy...
*/
- if ((status = cupsdCheckPolicy(dprinter->op_policy_ptr, con, NULL)) != HTTP_OK)
+ if ((status = cupsdCheckPolicy(dprinter->op_policy_ptr, con,
+ NULL)) != HTTP_OK)
{
send_http_error(con, status);
return;
@@ -6373,8 +6394,8 @@ move_job(cupsd_client_t *con, /* I - Client connection */
* See if we have a job URI or a printer URI...
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
+ sizeof(scheme), username, sizeof(username), host,
sizeof(host), &port, resource, sizeof(resource));
if (!strcmp(uri->name, "printer-uri"))
@@ -6390,7 +6411,8 @@ move_job(cupsd_client_t *con, /* I - Client connection */
* Move all jobs...
*/
- if ((src = cupsdValidateDest(host, resource, &stype, &sprinter)) == NULL)
+ if ((src = cupsdValidateDest(uri->values[0].string.text, &stype,
+ &sprinter)) == NULL)
{
/*
* Bad URI...
@@ -6638,6 +6660,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */
{
ipp_attribute_t *attr; /* Current attribute */
ipp_attribute_t *format; /* Document-format attribute */
+ const char *default_format; /* document-format-default value */
cupsd_job_t *job; /* New job */
char filename[1024]; /* Job filename */
mime_type_t *filetype; /* Type of file */
@@ -6695,6 +6718,21 @@ print_job(cupsd_client_t *con, /* I - Client connection */
}
/*
+ * Is the destination valid?
+ */
+
+ if (!cupsdValidateDest(uri->values[0].string.text, NULL, &printer))
+ {
+ /*
+ * Bad URI...
+ */
+
+ send_ipp_status(con, IPP_NOT_FOUND,
+ _("The printer or class was not found."));
+ return;
+ }
+
+ /*
* Is it a format we support?
*/
@@ -6705,7 +6743,8 @@ print_job(cupsd_client_t *con, /* I - Client connection */
* Grab format from client...
*/
- if (sscanf(format->values[0].string.text, "%15[^/]/%31[^;]", super, type) != 2)
+ if (sscanf(format->values[0].string.text, "%15[^/]/%31[^;]", super,
+ type) != 2)
{
send_ipp_status(con, IPP_BAD_REQUEST,
_("Could not scan type \"%s\"!"),
@@ -6713,10 +6752,26 @@ print_job(cupsd_client_t *con, /* I - Client connection */
return;
}
}
+ else if ((default_format = cupsGetOption("document-format",
+ printer->num_options,
+ printer->options)) != NULL)
+ {
+ /*
+ * Use default document format...
+ */
+
+ if (sscanf(default_format, "%15[^/]/%31[^;]", super, type) != 2)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Could not scan type \"%s\"!"),
+ default_format);
+ return;
+ }
+ }
else
{
/*
- * No document format attribute? Auto-type it!
+ * Auto-type it!
*/
strcpy(super, "application");
@@ -6739,32 +6794,35 @@ print_job(cupsd_client_t *con, /* I - Client connection */
doc_name ? doc_name->values[0].string.text : NULL,
&compression);
- if (filetype)
- {
- /*
- * Replace the document-format attribute value with the auto-typed one.
- */
+ if (!filetype)
+ filetype = mimeType(MimeDatabase, super, type);
+ }
+ else
+ filetype = mimeType(MimeDatabase, super, type);
- snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
- filetype->type);
+ if (filetype &&
+ (!format ||
+ (!strcmp(super, "application") && !strcmp(type, "octet-stream"))))
+ {
+ /*
+ * Replace the document-format attribute value with the auto-typed or
+ * default one.
+ */
- if (format)
- {
- _cupsStrFree(format->values[0].string.text);
+ snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
+ filetype->type);
- format->values[0].string.text = _cupsStrAlloc(mimetype);
- }
- else
- ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
- "document-format", NULL, mimetype);
+ if (format)
+ {
+ _cupsStrFree(format->values[0].string.text);
+
+ format->values[0].string.text = _cupsStrAlloc(mimetype);
}
else
- filetype = mimeType(MimeDatabase, super, type);
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, mimetype);
}
- else
- filetype = mimeType(MimeDatabase, super, type);
-
- if (!filetype)
+ else if (!filetype)
{
send_ipp_status(con, IPP_DOCUMENT_FORMAT,
_("Unsupported format \'%s/%s\'!"), super, type);
@@ -6793,7 +6851,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */
* Create the job object...
*/
- if ((job = add_job(con, uri, &printer, filetype)) == NULL)
+ if ((job = add_job(con, printer, filetype)) == NULL)
return;
/*
@@ -7058,12 +7116,6 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI], /* Method portion of URI */
- username[HTTP_MAX_URI], /* Username portion of URI */
- host[HTTP_MAX_URI], /* Host portion of URI */
- resource[HTTP_MAX_URI]; /* Resource portion of URI */
- int port; /* Port portion of URI */
- const char *name; /* Printer name */
cupsd_printer_t *printer; /* Printer data */
ipp_attribute_t *attr; /* printer-state-message text */
@@ -7075,11 +7127,7 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((name = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -7120,14 +7168,14 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */
cupsdSaveAllClasses();
cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" rejecting jobs (\"%s\").",
- name, get_username(con));
+ printer->name, get_username(con));
}
else
{
cupsdSaveAllPrinters();
cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" rejecting jobs (\"%s\").",
- name, get_username(con));
+ printer->name, get_username(con));
}
/*
@@ -7499,22 +7547,24 @@ restart_job(cupsd_client_t *con, /* I - Client connection */
*/
static void
-save_auth_info(cupsd_client_t *con, /* I - Client connection */
- cupsd_job_t *job) /* I - Job */
+save_auth_info(
+ cupsd_client_t *con, /* I - Client connection */
+ cupsd_job_t *job, /* I - Job */
+ ipp_attribute_t *auth_info) /* I - auth-info attribute, if any */
{
int i; /* Looping var */
char filename[1024]; /* Job authentication filename */
cups_file_t *fp; /* Job authentication file */
- char line[1024]; /* Line for file */
+ char line[2048]; /* Line for file */
/*
* This function saves the in-memory authentication information for
* a job so that it can be used to authenticate with a remote host.
* The information is stored in a file that is readable only by the
- * root user. The username and password are Base-64 encoded, each
- * on a separate line, followed by random number (up to 1024) of
- * newlines to limit the amount of information that is exposed.
+ * root user. The fields are Base-64 encoded, each on a separate line,
+ * followed by random number (up to 1024) of newlines to limit the
+ * amount of information that is exposed.
*
* Because of the potential for exposing of authentication information,
* this functionality is only enabled when running cupsd as root.
@@ -7550,19 +7600,35 @@ save_auth_info(cupsd_client_t *con, /* I - Client connection */
fchown(cupsFileNumber(fp), 0, 0);
fchmod(cupsFileNumber(fp), 0400);
- /*
- * Write the authenticated username...
- */
+ if (auth_info)
+ {
+ /*
+ * Write 1 to 4 auth values...
+ */
- httpEncode64_2(line, sizeof(line), con->username, strlen(con->username));
- cupsFilePrintf(fp, "%s\n", line);
+ for (i = 0; i < auth_info->num_values; i ++)
+ {
+ httpEncode64_2(line, sizeof(line), auth_info->values[i].string.text,
+ strlen(auth_info->values[i].string.text));
+ cupsFilePrintf(fp, "%s\n", line);
+ }
+ }
+ else
+ {
+ /*
+ * Write the authenticated username...
+ */
- /*
- * Write the authenticated password...
- */
+ httpEncode64_2(line, sizeof(line), con->username, strlen(con->username));
+ cupsFilePrintf(fp, "%s\n", line);
- httpEncode64_2(line, sizeof(line), con->password, strlen(con->password));
- cupsFilePrintf(fp, "%s\n", line);
+ /*
+ * Write the authenticated password...
+ */
+
+ httpEncode64_2(line, sizeof(line), con->password, strlen(con->password));
+ cupsFilePrintf(fp, "%s\n", line);
+ }
/*
* Write a random number of newlines to the end of the file...
@@ -7576,7 +7642,66 @@ save_auth_info(cupsd_client_t *con, /* I - Client connection */
*/
cupsFileClose(fp);
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5_H)
+ save_krb5_creds(con, job);
+#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
+}
+
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5_H)
+/*
+ * 'save_krb5_creds()' - Save Kerberos credentials for the job.
+ */
+
+static void
+save_krb5_creds(cupsd_client_t *con, /* I - Client connection */
+ cupsd_job_t *job) /* I - Job */
+{
+# ifndef __APPLE__
+ krb5_context krb_context; /* Kerberos context */
+ krb5_ccache ccache; /* Credentials cache */
+ OM_uint32 major_status, /* Major status code */
+ minor_status; /* Minor status code */
+
+
+ /*
+ * Setup a cached context for the job filters to use...
+ */
+
+ if (krb5_init_context(&krb_context))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context");
+ return;
+ }
+
+# ifdef HAVE_HEIMDAL
+ if (krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))
+# else
+ if (krb5_cc_gen_new(krb_context, &ccache))
+# endif /* HAVE_HEIMDAL */
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create new credentials");
+ return;
+ }
+
+ major_status = gss_krb5_copy_ccache(&minor_status, con->gss_delegated_cred,
+ ccache);
+
+ if (GSS_ERROR(major_status))
+ {
+ cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status,
+ "Unable to import client credentials cache");
+ krb5_cc_destroy(krb_context, ccache);
+ return;
+ }
+
+ cupsdSetStringf(&(job->ccname), "KRB5CCNAME=FILE:%s",
+ krb5_cc_get_name(krb_context, ccache));
+ krb5_cc_close(krb_context, ccache);
+# endif /* !__APPLE__ */
}
+#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
/*
@@ -7589,6 +7714,7 @@ send_document(cupsd_client_t *con, /* I - Client connection */
{
ipp_attribute_t *attr; /* Current attribute */
ipp_attribute_t *format; /* Document-format attribute */
+ const char *default_format;/* document-format-default value */
int jobid; /* Job ID number */
cupsd_job_t *job; /* Current job */
char job_uri[HTTP_MAX_URI],
@@ -7747,6 +7873,22 @@ send_document(cupsd_client_t *con, /* I - Client connection */
return;
}
}
+ else if ((default_format = cupsGetOption("document-format",
+ printer->num_options,
+ printer->options)) != NULL)
+ {
+ /*
+ * Use default document format...
+ */
+
+ if (sscanf(default_format, "%15[^/]/%31[^;]", super, type) != 2)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Could not scan type \"%s\"!"),
+ default_format);
+ return;
+ }
+ }
else
{
/*
@@ -7773,31 +7915,35 @@ send_document(cupsd_client_t *con, /* I - Client connection */
doc_name ? doc_name->values[0].string.text : NULL,
&compression);
- if (filetype)
- {
- /*
- * Replace the document-format attribute value with the auto-typed one.
- */
-
- snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
- filetype->type);
-
- if (format)
- {
- _cupsStrFree(format->values[0].string.text);
- format->values[0].string.text = _cupsStrAlloc(mimetype);
- }
- else
- ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
- "document-format", NULL, mimetype);
- }
- else
+ if (!filetype)
filetype = mimeType(MimeDatabase, super, type);
}
else
filetype = mimeType(MimeDatabase, super, type);
- if (!filetype)
+ if (filetype &&
+ (!format ||
+ (!strcmp(super, "application") && !strcmp(type, "octet-stream"))))
+ {
+ /*
+ * Replace the document-format attribute value with the auto-typed or
+ * default one.
+ */
+
+ snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
+ filetype->type);
+
+ if (format)
+ {
+ _cupsStrFree(format->values[0].string.text);
+
+ format->values[0].string.text = _cupsStrAlloc(mimetype);
+ }
+ else
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, mimetype);
+ }
+ else if (!filetype)
{
send_ipp_status(con, IPP_DOCUMENT_FORMAT,
_("Unsupported format \'%s/%s\'!"), super, type);
@@ -8035,16 +8181,6 @@ set_default(cupsd_client_t *con, /* I - Client connection */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
- username[HTTP_MAX_URI],
- /* Username portion of URI */
- host[HTTP_MAX_URI],
- /* Host portion of URI */
- resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int port; /* Port portion of URI */
- const char *name; /* Printer name */
cupsd_printer_t *printer; /* Printer */
@@ -8055,11 +8191,7 @@ set_default(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((name = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -8092,8 +8224,8 @@ set_default(cupsd_client_t *con, /* I - Client connection */
cupsdWritePrintcap();
cupsdLogMessage(CUPSD_LOG_INFO,
- "Default destination set to \"%s\" by \"%s\".", name,
- get_username(con));
+ "Default destination set to \"%s\" by \"%s\".",
+ printer->name, get_username(con));
/*
* Everything was ok, so return OK status...
@@ -8613,10 +8745,6 @@ set_printer_defaults(
attr->values[0].string.text);
cupsdSetString(&printer->error_policy, attr->values[0].string.text);
}
- else if (!strcmp(attr->name, "document-format-default") ||
- !strcmp(attr->name, "notify-lease-duration-default") ||
- !strcmp(attr->name, "notify-events-default"))
- continue;
/*
* Skip any other non-default attributes...
@@ -8717,16 +8845,6 @@ start_printer(cupsd_client_t *con, /* I - Client connection */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
- username[HTTP_MAX_URI],
- /* Username portion of URI */
- host[HTTP_MAX_URI],
- /* Host portion of URI */
- resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int port; /* Port portion of URI */
- const char *name; /* Printer name */
cupsd_printer_t *printer; /* Printer data */
@@ -8737,11 +8855,7 @@ start_printer(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((name = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -8771,11 +8885,11 @@ start_printer(cupsd_client_t *con, /* I - Client connection */
cupsdStartPrinter(printer, 1);
if (dtype & CUPS_PRINTER_CLASS)
- cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" started by \"%s\".", name,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" started by \"%s\".",
+ printer->name, get_username(con));
else
- cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" started by \"%s\".", name,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" started by \"%s\".",
+ printer->name, get_username(con));
cupsdCheckJobs();
@@ -8797,16 +8911,6 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */
{
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
- username[HTTP_MAX_URI],
- /* Username portion of URI */
- host[HTTP_MAX_URI],
- /* Host portion of URI */
- resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int port; /* Port portion of URI */
- const char *name; /* Printer name */
cupsd_printer_t *printer; /* Printer data */
ipp_attribute_t *attr; /* printer-state-message attribute */
@@ -8818,11 +8922,7 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((name = cupsdValidateDest(host, resource, &dtype, &printer)) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -8859,11 +8959,11 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */
cupsdStopPrinter(printer, 1);
if (dtype & CUPS_PRINTER_CLASS)
- cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" stopped by \"%s\".", name,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" stopped by \"%s\".",
+ printer->name, get_username(con));
else
- cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" stopped by \"%s\".", name,
- get_username(con));
+ cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" stopped by \"%s\".",
+ printer->name, get_username(con));
/*
* Everything was ok, so return OK status...
@@ -8989,15 +9089,6 @@ validate_job(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *attr; /* Current attribute */
ipp_attribute_t *format; /* Document-format attribute */
cups_ptype_t dtype; /* Destination type (printer or class) */
- char method[HTTP_MAX_URI],
- /* Method portion of URI */
- username[HTTP_MAX_URI],
- /* Username portion of URI */
- host[HTTP_MAX_URI],
- /* Host portion of URI */
- resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int port; /* Port portion of URI */
char super[MIME_MAX_SUPER],
/* Supertype of file */
type[MIME_MAX_TYPE];
@@ -9057,11 +9148,7 @@ validate_job(cupsd_client_t *con, /* I - Client connection */
* Is the destination valid?
*/
- httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
- sizeof(method), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if (cupsdValidateDest(host, resource, &dtype, &printer) == NULL)
+ if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
{
/*
* Bad URI...
@@ -9105,7 +9192,7 @@ validate_name(const char *name) /* I - Name to check */
*/
for (ptr = name; *ptr; ptr ++)
- if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
+ if ((*ptr > 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
return (0);
/*
@@ -9161,5 +9248,5 @@ validate_user(cupsd_job_t *job, /* I - Job */
/*
- * End of "$Id: ipp.c 6145 2006-12-06 20:10:16Z mike $".
+ * End of "$Id: ipp.c 6318 2007-03-06 04:36:55Z mike $".
*/
diff --git a/scheduler/job.c b/scheduler/job.c
index f219c6980..3c876a649 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -1,9 +1,9 @@
/*
- * "$Id: job.c 6234 2007-02-05 20:25:50Z mike $"
+ * "$Id: job.c 6318 2007-03-06 04:36:55Z mike $"
*
* Job management routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -127,6 +127,8 @@ cupsdAddJob(int priority, /* I - Job priority */
job->back_pipes[1] = -1;
job->print_pipes[0] = -1;
job->print_pipes[1] = -1;
+ job->side_pipes[0] = -1;
+ job->side_pipes[1] = -1;
job->status_pipes[0] = -1;
job->status_pipes[1] = -1;
@@ -461,7 +463,6 @@ cupsdCleanJobs(void)
void
cupsdFinishJob(cupsd_job_t *job) /* I - Job */
{
- int job_history; /* Did cupsdCancelJob() keep the job? */
cupsd_printer_t *printer; /* Current printer */
@@ -478,11 +479,7 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
* Close the pipe and clear the input bit.
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdFinishJob: Removing fd %d from InputSet...",
- job->status_buffer->fd);
-
- FD_CLR(job->status_buffer->fd, InputSet);
+ cupsdRemoveSelect(job->status_buffer->fd);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdFinishJob: Closing status pipes [ %d %d ]...",
@@ -711,8 +708,6 @@ cupsdFinishJob(cupsd_job_t *job) /* I - Job */
* Close out this job...
*/
- job_history = JobHistory && !(job->dtype & CUPS_PRINTER_REMOTE);
-
cupsdCancelJob(job, 0, IPP_JOB_COMPLETED);
cupsdCheckJobs();
}
@@ -921,13 +916,6 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */
cups_file_t *fp; /* Job file */
int fileid; /* Current file ID */
ipp_attribute_t *attr; /* Job attribute */
- char scheme[32], /* Scheme portion of URI */
- username[64], /* Username portion of URI */
- host[HTTP_MAX_HOST],
- /* Host portion of URI */
- resource[HTTP_MAX_URI];
- /* Resource portion of URI */
- int port; /* Port portion of URI */
const char *dest; /* Destination */
mime_type_t **filetypes; /* New filetypes array */
int *compressions; /* New compressions array */
@@ -1011,11 +999,7 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */
return;
}
- httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, scheme,
- sizeof(scheme), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
-
- if ((dest = cupsdValidateDest(host, resource, &(job->dtype),
+ if ((dest = cupsdValidateDest(attr->values[0].string.text, &(job->dtype),
NULL)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -1427,7 +1411,7 @@ cupsdSetJobHoldUntil(cupsd_job_t *job, /* I - Job */
job->hold_until = curtime +
((17 - curdate->tm_hour) * 60 + 59 -
curdate->tm_min) * 60 + 60 - curdate->tm_sec;
- }
+ }
else if (!strcmp(when, "second-shift"))
{
/*
@@ -1443,7 +1427,7 @@ cupsdSetJobHoldUntil(cupsd_job_t *job, /* I - Job */
job->hold_until = curtime +
((15 - curdate->tm_hour) * 60 + 59 -
curdate->tm_min) * 60 + 60 - curdate->tm_sec;
- }
+ }
else if (!strcmp(when, "third-shift"))
{
/*
@@ -1459,7 +1443,7 @@ cupsdSetJobHoldUntil(cupsd_job_t *job, /* I - Job */
job->hold_until = curtime +
((23 - curdate->tm_hour) * 60 + 59 -
curdate->tm_min) * 60 + 60 - curdate->tm_sec;
- }
+ }
else if (!strcmp(when, "weekend"))
{
/*
@@ -1622,17 +1606,19 @@ cupsdStopJob(cupsd_job_t *job, /* I - Job */
cupsdClosePipe(job->back_pipes);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdStopJob: Closing side pipes [ %d %d ]...",
+ job->side_pipes[0], job->side_pipes[1]);
+
+ cupsdClosePipe(job->side_pipes);
+
if (job->status_buffer)
{
/*
* Close the pipe and clear the input bit.
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopJob: Removing fd %d from InputSet...",
- job->status_buffer->fd);
-
- FD_CLR(job->status_buffer->fd, InputSet);
+ cupsdRemoveSelect(job->status_buffer->fd);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdStopJob: Closing status pipes [ %d %d ]...",
@@ -1710,7 +1696,7 @@ cupsdUpdateJob(cupsd_job_t *job) /* I - Job to check */
}
else if (!sscanf(message, "%*d%d", &copies))
copies = 1;
-
+
job->sheets->values[0].integer += copies;
if (job->printer->page_limit)
@@ -1734,7 +1720,18 @@ cupsdUpdateJob(cupsd_job_t *job) /* I - Job to check */
* Set attribute(s)...
*/
- /**** TODO ****/
+ int num_attrs; /* Number of attributes */
+ cups_option_t *attrs; /* Attributes */
+ const char *attr; /* Attribute */
+
+
+ num_attrs = cupsParseOptions(message, 0, &attrs);
+
+ if ((attr = cupsGetOption("auth-info-required", num_attrs,
+ attrs)) != NULL)
+ cupsdSetAuthInfoRequired(job->printer, attr, NULL);
+
+ cupsFreeOptions(num_attrs, attrs);
}
#ifdef __APPLE__
else if (!strncmp(message, "recoverable:", 12))
@@ -1853,6 +1850,9 @@ free_job(cupsd_job_t *job) /* I - Job */
{
cupsdClearString(&job->username);
cupsdClearString(&job->dest);
+#ifdef HAVE_GSSAPI
+ cupsdClearString(&job->ccname);
+#endif /* HAVE_GSSAPI */
if (job->num_files > 0)
{
@@ -1867,7 +1867,7 @@ free_job(cupsd_job_t *job) /* I - Job */
/*
- * 'ipp_length()' - Compute the size of the buffer needed to hold
+ * 'ipp_length()' - Compute the size of the buffer needed to hold
* the textual IPP attributes.
*/
@@ -2082,6 +2082,8 @@ load_job_cache(const char *filename) /* I - job.cache filename */
job->back_pipes[1] = -1;
job->print_pipes[0] = -1;
job->print_pipes[1] = -1;
+ job->side_pipes[0] = -1;
+ job->side_pipes[1] = -1;
job->status_pipes[0] = -1;
job->status_pipes[1] = -1;
@@ -2337,6 +2339,8 @@ load_request_root(void)
job->back_pipes[1] = -1;
job->print_pipes[0] = -1;
job->print_pipes[1] = -1;
+ job->side_pipes[0] = -1;
+ job->side_pipes[1] = -1;
job->status_pipes[0] = -1;
job->status_pipes[1] = -1;
@@ -2388,7 +2392,7 @@ set_time(cupsd_job_t *job, /* I - Job to update */
* 'set_hold_until()' - Set the hold time and update job-hold-until attribute...
*/
-static void
+static void
set_hold_until(cupsd_job_t *job, /* I - Job to update */
time_t holdtime) /* I - Hold until time */
{
@@ -2414,7 +2418,7 @@ set_hold_until(cupsd_job_t *job, /* I - Job to update */
*/
holddate = gmtime(&holdtime);
- snprintf(holdstr, sizeof(holdstr), "%d:%d:%d", holddate->tm_hour,
+ snprintf(holdstr, sizeof(holdstr), "%d:%d:%d", holddate->tm_hour,
holddate->tm_min, holddate->tm_sec);
if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
@@ -2445,8 +2449,10 @@ start_job(cupsd_job_t *job, /* I - Job ID */
{
int i; /* Looping var */
int slot; /* Pipe slot */
- cups_array_t *filters; /* Filters for job */
+ cups_array_t *filters, /* Filters for job */
+ *prefilters; /* Filters with prefilters */
mime_filter_t *filter, /* Current filter */
+ *prefilter, /* Prefilter */
port_monitor; /* Port monitor filter */
char method[255], /* Method for output */
*optptr, /* Pointer to options */
@@ -2466,7 +2472,7 @@ start_job(cupsd_job_t *job, /* I - Job ID */
title[IPP_MAX_NAME],
/* Job title string */
copies[255], /* # copies string */
- *envp[MAX_ENV + 11],
+ *envp[MAX_ENV + 12],
/* Environment variables */
charset[255], /* CHARSET env variable */
class_name[255],/* CLASS env variable */
@@ -2579,6 +2585,33 @@ start_job(cupsd_job_t *job, /* I - Job ID */
cupsArrayDelete(filters);
filters = NULL;
}
+
+ /*
+ * If this printer has any pre-filters, insert the required pre-filter
+ * in the filters array...
+ */
+
+ if (printer->prefiltertype && filters)
+ {
+ prefilters = cupsArrayNew(NULL, NULL);
+
+ for (filter = (mime_filter_t *)cupsArrayFirst(filters);
+ filter;
+ filter = (mime_filter_t *)cupsArrayNext(filters))
+ {
+ if ((prefilter = mimeFilterLookup(MimeDatabase, filter->src,
+ printer->prefiltertype)))
+ {
+ cupsArrayAdd(prefilters, prefilter);
+ job->cost += prefilter->cost;
+ }
+
+ cupsArrayAdd(prefilters, filter);
+ }
+
+ cupsArrayDelete(filters);
+ filters = prefilters;
+ }
}
/*
@@ -2707,6 +2740,18 @@ start_job(cupsd_job_t *job, /* I - Job ID */
fcntl(job->back_pipes[1], F_SETFL,
fcntl(job->back_pipes[1], F_GETFL) | O_NONBLOCK);
+
+ /*
+ * Create the side-channel pipes and make them non-blocking...
+ */
+
+ socketpair(AF_LOCAL, SOCK_STREAM, 0, job->side_pipes);
+
+ fcntl(job->side_pipes[0], F_SETFL,
+ fcntl(job->side_pipes[0], F_GETFL) | O_NONBLOCK);
+
+ fcntl(job->side_pipes[1], F_SETFL,
+ fcntl(job->side_pipes[1], F_GETFL) | O_NONBLOCK);
}
/*
@@ -3083,6 +3128,11 @@ start_job(cupsd_job_t *job, /* I - Job ID */
envp[envc ++] = class_name;
}
+#ifdef HAVE_GSSAPI
+ if (job->ccname)
+ envp[envc ++] = job->ccname;
+#endif /* HAVE_GSSAPI */
+
envp[envc] = NULL;
for (i = 0; i < envc; i ++)
@@ -3115,19 +3165,19 @@ start_job(cupsd_job_t *job, /* I - Job ID */
strerror(errno));
snprintf(printer->state_message, sizeof(printer->state_message),
"Unable to create status pipes - %s.", strerror(errno));
-
+
cupsdAddPrinterHistory(printer);
-
+
cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
"Job canceled because the server could not create the job "
"status pipes.");
-
+
goto abort_job;
}
-
+
cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job: status_pipes = [ %d %d ]",
job->status_pipes[0], job->status_pipes[1]);
-
+
job->status_buffer = cupsdStatBufNew(job->status_pipes[0], "[Job %d]",
job->id);
}
@@ -3244,7 +3294,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
- job->back_pipes[0], 0, job->filters + i);
+ job->back_pipes[0], job->side_pipes[0], 0,
+ job->filters + i);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"start_job: Closing filter pipes for slot %d "
@@ -3314,8 +3365,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */
pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0],
filterfds[slot][1], job->status_pipes[1],
- job->back_pipes[1], backroot,
- &(job->backend));
+ job->back_pipes[1], job->side_pipes[1],
+ backroot, &(job->backend));
if (pid == 0)
{
@@ -3354,6 +3405,12 @@ start_job(cupsd_job_t *job, /* I - Job ID */
cupsdClosePipe(job->back_pipes);
cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "start_job: Closing side pipes [ %d %d ]...",
+ job->side_pipes[0], job->side_pipes[1]);
+
+ cupsdClosePipe(job->side_pipes);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
"start_job: Closing status output pipe %d...",
job->status_pipes[1]);
@@ -3397,11 +3454,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */
free(argv);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_job: Adding fd %d to InputSet...",
- job->status_buffer->fd);
-
- FD_SET(job->status_buffer->fd, InputSet);
+ cupsdAddSelect(job->status_buffer->fd, (cupsd_selfunc_t)cupsdUpdateJob, NULL,
+ job);
cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job, "Job #%d started.",
job->id);
@@ -3467,5 +3521,5 @@ unload_job(cupsd_job_t *job) /* I - Job */
/*
- * End of "$Id: job.c 6234 2007-02-05 20:25:50Z mike $".
+ * End of "$Id: job.c 6318 2007-03-06 04:36:55Z mike $".
*/
diff --git a/scheduler/job.h b/scheduler/job.h
index 5c1b540eb..4b8e399f1 100644
--- a/scheduler/job.h
+++ b/scheduler/job.h
@@ -1,5 +1,5 @@
/*
- * "$Id: job.h 5970 2006-09-19 20:11:08Z mike $"
+ * "$Id: job.h 6170 2007-01-02 17:26:41Z mike $"
*
* Print job definitions for the Common UNIX Printing System (CUPS) scheduler.
*
@@ -46,6 +46,7 @@ typedef struct cupsd_job_s
ipp_t *attrs; /* Job attributes */
int print_pipes[2], /* Print data pipes */
back_pipes[2], /* Backchannel pipes */
+ side_pipes[2], /* Sidechannel pipes */
status_pipes[2];/* Status pipes */
cupsd_statbuf_t *status_buffer; /* Status buffer for this job */
int cost; /* Filtering cost */
@@ -55,6 +56,9 @@ typedef struct cupsd_job_s
int status; /* Status code from filters */
cupsd_printer_t *printer; /* Printer this job is assigned to */
int tries; /* Number of tries for this job */
+#ifdef HAVE_GSSAPI
+ char *ccname; /* KRB5CCNAME environment variable */
+#endif /* HAVE_GSSAPI */
} cupsd_job_t;
@@ -122,5 +126,5 @@ extern void cupsdUpdateJob(cupsd_job_t *job);
/*
- * End of "$Id: job.h 5970 2006-09-19 20:11:08Z mike $".
+ * End of "$Id: job.h 6170 2007-01-02 17:26:41Z mike $".
*/
diff --git a/scheduler/listen.c b/scheduler/listen.c
index 2c5ad2bd7..258e292f7 100644
--- a/scheduler/listen.c
+++ b/scheduler/listen.c
@@ -1,5 +1,5 @@
/*
- * "$Id: listen.c 5970 2006-09-19 20:11:08Z mike $"
+ * "$Id: listen.c 6123 2006-11-21 15:36:04Z mike $"
*
* Server listening routines for the Common UNIX Printing System (CUPS)
* scheduler.
@@ -90,14 +90,7 @@ cupsdPauseListening(void)
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
lis;
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- if (lis->fd >= 0)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdPauseListening: Removing fd %d from InputSet...",
- lis->fd);
-
- FD_CLR(lis->fd, InputSet);
- }
+ cupsdRemoveSelect(lis->fd);
}
@@ -123,13 +116,7 @@ cupsdResumeListening(void)
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
lis;
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- if (lis->fd >= 0)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdResumeListening: Adding fd %d to InputSet...",
- lis->fd);
- FD_SET(lis->fd, InputSet);
- }
+ cupsdAddSelect(lis->fd, (cupsd_selfunc_t)cupsdAcceptClient, NULL, lis);
}
@@ -444,5 +431,5 @@ cupsdStopListening(void)
/*
- * End of "$Id: listen.c 5970 2006-09-19 20:11:08Z mike $".
+ * End of "$Id: listen.c 6123 2006-11-21 15:36:04Z mike $".
*/
diff --git a/scheduler/log.c b/scheduler/log.c
index 3839dc878..11c3cbcfe 100644
--- a/scheduler/log.c
+++ b/scheduler/log.c
@@ -1,5 +1,5 @@
/*
- * "$Id: log.c 6027 2006-10-11 21:04:58Z mike $"
+ * "$Id: log.c 6328 2007-03-12 14:45:42Z mike $"
*
* Log file routines for the Common UNIX Printing System (CUPS).
*
@@ -23,11 +23,12 @@
*
* Contents:
*
- * cupsdGetDateTime() - Returns a pointer to a date/time string.
- * cupsdLogMessage() - Log a message to the error log file.
- * cupsdLogPage() - Log a page to the page log file.
- * cupsdLogRequest() - Log an HTTP request in Common Log Format.
- * check_log_file() - Open/rotate a log file if it needs it.
+ * cupsdGetDateTime() - Returns a pointer to a date/time string.
+ * cupsdLogGSSMessage() - Log a GSSAPI error...
+ * cupsdLogMessage() - Log a message to the error log file.
+ * cupsdLogPage() - Log a page to the page log file.
+ * cupsdLogRequest() - Log an HTTP request in Common Log Format.
+ * check_log_file() - Open/rotate a log file if it needs it.
*/
/*
@@ -107,6 +108,56 @@ cupsdGetDateTime(time_t t) /* I - Time value */
}
+#ifdef HAVE_GSSAPI
+/*
+ * 'cupsdLogGSSMessage()' - Log a GSSAPI error...
+ */
+
+int /* O - 1 on success, 0 on error */
+cupsdLogGSSMessage(
+ int level, /* I - Log level */
+ int major_status, /* I - Major GSSAPI status */
+ int minor_status, /* I - Minor GSSAPI status */
+ const char *message, /* I - printf-style message string */
+ ...) /* I - Additional args as needed */
+{
+ OM_uint32 err_major_status, /* Major status code for display */
+ err_minor_status; /* Minor status code for display */
+ OM_uint32 msg_ctx; /* Message context */
+ gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER,
+ /* Major status message */
+ minor_status_string = GSS_C_EMPTY_BUFFER;
+ /* Minor status message */
+ int ret; /* Return value */
+
+
+ msg_ctx = 0;
+ err_major_status = gss_display_status(&err_minor_status,
+ major_status,
+ GSS_C_GSS_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &major_status_string);
+
+ if (!GSS_ERROR(err_major_status))
+ err_major_status = gss_display_status(&err_minor_status,
+ minor_status,
+ GSS_C_MECH_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx,
+ &minor_status_string);
+
+ ret = cupsdLogMessage(level, "%s: %s, %s", message,
+ (char *)major_status_string.value,
+ (char *)minor_status_string.value);
+ gss_release_buffer(&err_minor_status, &major_status_string);
+ gss_release_buffer(&err_minor_status, &minor_status_string);
+
+ return (ret);
+}
+#endif /* HAVE_GSSAPI */
+
+
/*
* 'cupsdLogMessage()' - Log a message to the error log file.
*/
@@ -414,9 +465,10 @@ static int /* O - 1 if log file open */
check_log_file(cups_file_t **lf, /* IO - Log file */
const char *logname) /* I - Log filename */
{
- char backname[1024], /* Backup log filename */
- filename[1024], /* Formatted log filename */
- *ptr; /* Pointer into filename */
+ char backname[1024], /* Backup log filename */
+ filename[1024], /* Formatted log filename */
+ *ptr; /* Pointer into filename */
+ const char *logptr; /* Pointer into log filename */
/*
@@ -448,17 +500,17 @@ check_log_file(cups_file_t **lf, /* IO - Log file */
else
filename[0] = '\0';
- for (ptr = filename + strlen(filename);
- *logname && ptr < (filename + sizeof(filename) - 1);
- logname ++)
- if (*logname == '%')
+ for (logptr = logname, ptr = filename + strlen(filename);
+ *logptr && ptr < (filename + sizeof(filename) - 1);
+ logptr ++)
+ if (*logptr == '%')
{
/*
* Format spec...
*/
- logname ++;
- if (*logname == 's')
+ logptr ++;
+ if (*logptr == 's')
{
/*
* Insert the server name...
@@ -473,11 +525,11 @@ check_log_file(cups_file_t **lf, /* IO - Log file */
* Otherwise just insert the character...
*/
- *ptr++ = *logname;
+ *ptr++ = *logptr;
}
}
else
- *ptr++ = *logname;
+ *ptr++ = *logptr;
*ptr = '\0';
}
@@ -551,5 +603,5 @@ check_log_file(cups_file_t **lf, /* IO - Log file */
/*
- * End of "$Id: log.c 6027 2006-10-11 21:04:58Z mike $".
+ * End of "$Id: log.c 6328 2007-03-12 14:45:42Z mike $".
*/
diff --git a/scheduler/main.c b/scheduler/main.c
index 434cacf89..8591cc0f3 100644
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -1,9 +1,9 @@
/*
- * "$Id: main.c 6090 2006-11-14 16:35:27Z mike $"
+ * "$Id: main.c 6326 2007-03-11 17:50:18Z mike $"
*
* Scheduler main loop for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -32,10 +32,9 @@
* cupsdSetStringf() - Set a formatted string value.
* launchd_checkin() - Check-in with launchd and collect the
* listening fds.
+ * launchd_checkout() - Check-out with launchd.
* launchd_create_dict() - Create a dictionary representing the launchd
* config file org.cups.cupsd.plist.
- * launchd_reload() - Tell launchd to reload the configuration
- * file to pick up the new listening directives.
* launchd_sync_conf() - Re-write the launchd config file
* org.cups.cupsd.plist based on cupsd.conf.
* parent_handler() - Catch USR1/CHLD signals...
@@ -62,6 +61,17 @@
#ifdef HAVE_LAUNCH_H
# include <launch.h>
# include <libgen.h>
+# define CUPS_KEEPALIVE CUPS_STATEDIR "/org.cups.cupsd"
+ /* Name of the launchd KeepAlive file */
+# ifndef LAUNCH_JOBKEY_KEEPALIVE
+# define LAUNCH_JOBKEY_KEEPALIVE "KeepAlive"
+# endif /* !LAUNCH_JOBKEY_KEEPALIVE */
+# ifndef LAUNCH_JOBKEY_PATHSTATE
+# define LAUNCH_JOBKEY_PATHSTATE "PathState"
+# endif /* !LAUNCH_JOBKEY_PATHSTATE */
+# ifndef LAUNCH_JOBKEY_SERVICEIPC
+# define LAUNCH_JOBKEY_SERVICEIPC "ServiceIPC"
+# endif /* !LAUNCH_JOBKEY_SERVICEIPC */
#endif /* HAVE_LAUNCH_H */
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
@@ -78,8 +88,8 @@
#ifdef HAVE_LAUNCHD
static void launchd_checkin(void);
+static void launchd_checkout(void);
static CFDictionaryRef launchd_create_dict(void);
-static void launchd_reload(void);
static int launchd_sync_conf(void);
#endif /* HAVE_LAUNCHD */
static void parent_handler(int sig);
@@ -126,8 +136,6 @@ main(int argc, /* I - Number of command-line args */
char *opt; /* Option character */
int fg; /* Run in the foreground */
int fds; /* Number of ready descriptors */
- fd_set *input, /* Input set for select() */
- *output; /* Output set for select() */
cupsd_client_t *con; /* Current client */
cupsd_job_t *job; /* Current job */
cupsd_listener_t *lis; /* Current listener */
@@ -136,14 +144,11 @@ main(int argc, /* I - Number of command-line args */
browse_time, /* Next browse send time */
senddoc_time, /* Send-Document time */
expire_time, /* Subscription expire time */
-#ifndef __APPLE__
- netif_time, /* Network interface poll time */
-#endif /* !__APPLE__ */
mallinfo_time; /* Malloc information time */
size_t string_count, /* String count */
alloc_bytes, /* Allocated string bytes */
total_bytes; /* Total string bytes */
- struct timeval timeout; /* select() timeout */
+ long timeout; /* Timeout for cupsdDoSelect() */
struct rlimit limit; /* Runtime limit */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Actions for POSIX signals */
@@ -372,33 +377,23 @@ main(int argc, /* I - Number of command-line args */
getrlimit(RLIMIT_NOFILE, &limit);
+#if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE)
if (limit.rlim_max > FD_SETSIZE)
MaxFDs = FD_SETSIZE;
else
+#endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */
+#ifdef RLIM_INFINITY
+ if (limit.rlim_max == RLIM_INFINITY)
+ MaxFDs = 16384;
+ else
+#endif /* RLIM_INFINITY */
MaxFDs = limit.rlim_max;
limit.rlim_cur = MaxFDs;
setrlimit(RLIMIT_NOFILE, &limit);
- /*
- * Allocate memory for the input and output sets...
- */
-
- SetSize = (MaxFDs + 31) / 8 + 4;
- if (SetSize < sizeof(fd_set))
- SetSize = sizeof(fd_set);
-
- InputSet = (fd_set *)calloc(1, SetSize);
- OutputSet = (fd_set *)calloc(1, SetSize);
- input = (fd_set *)calloc(1, SetSize);
- output = (fd_set *)calloc(1, SetSize);
-
- if (InputSet == NULL || OutputSet == NULL || input == NULL || output == NULL)
- {
- syslog(LOG_LPR, "Unable to allocate memory for select() sets - exiting!");
- return (1);
- }
+ cupsdStartSelect();
/*
* Read configuration...
@@ -415,22 +410,15 @@ main(int argc, /* I - Number of command-line args */
if (Launchd)
{
/*
- * If we were started by launchd make sure the cupsd plist file contains the
- * same listeners as cupsd.conf; If it didn't then reload it before getting
- * the list of listening file descriptors...
+ * If we were started by launchd, make sure the cupsd plist file contains
+ * the same listeners as cupsd.conf.
*/
- if (launchd_sync_conf())
- {
- launchd_reload();
-
- /*
- * Until rdar://3854821 is fixed we have to exit after the reload...
- */
+ launchd_sync_conf();
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "Exiting on launchd_reload");
- exit(0);
- }
+ /*
+ * Then get the file descriptors from launchd...
+ */
launchd_checkin();
}
@@ -551,9 +539,6 @@ main(int argc, /* I - Number of command-line args */
senddoc_time = time(NULL);
expire_time = time(NULL);
fds = 1;
-#ifndef __APPLE__
- netif_time = 0;
-#endif /* !__APPLE__ */
while (!stop_scheduler)
{
@@ -632,19 +617,7 @@ main(int argc, /* I - Number of command-line args */
#if HAVE_LAUNCHD
if (Launchd)
{
- if (launchd_sync_conf())
- {
- launchd_reload();
-
- /*
- * Until rdar://3854821 is fixed we have to exit after the reload...
- */
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "Exiting on launchd_reload");
- stop_scheduler = 1;
- break;
- }
-
+ launchd_sync_conf();
launchd_checkin();
}
#endif /* HAVE_LAUNCHD */
@@ -658,18 +631,15 @@ main(int argc, /* I - Number of command-line args */
}
/*
- * Check for available input or ready output. If select() returns
- * 0 or -1, something bad happened and we should exit immediately.
+ * Check for available input or ready output. If cupsdDoSelect()
+ * returns 0 or -1, something bad happened and we should exit
+ * immediately.
*
* Note that we at least have one listening socket open at all
* times.
*/
- memcpy(input, InputSet, SetSize);
- memcpy(output, OutputSet, SetSize);
-
- timeout.tv_sec = select_timeout(fds);
- timeout.tv_usec = 0;
+ timeout = select_timeout(fds);
#if HAVE_LAUNCHD
/*
@@ -678,71 +648,40 @@ main(int argc, /* I - Number of command-line args */
* inactivity...
*/
- if (timeout.tv_sec == 86400 && Launchd && LaunchdTimeout && !NumPolled &&
- (!Browsing || !(BrowseLocalProtocols & BROWSE_DNSSD) ||
- cupsArrayCount(Printers) == 0))
+ if (timeout == 86400 && Launchd && LaunchdTimeout && !NumPolled &&
+ (!Browsing ||
+ (!BrowseRemoteProtocols &&
+ (!NumBrowsers || !BrowseLocalProtocols ||
+ cupsArrayCount(Printers) == 0))))
{
- timeout.tv_sec = LaunchdTimeout;
+ timeout = LaunchdTimeout;
launchd_idle_exit = 1;
}
else
launchd_idle_exit = 0;
#endif /* HAVE_LAUNCHD */
- if (timeout.tv_sec < 86400) /* Only use timeout for < 1 day */
- fds = select(MaxFDs, input, output, NULL, &timeout);
- else
- fds = select(MaxFDs, input, output, NULL, NULL);
-
- if (fds < 0)
+ if ((fds = cupsdDoSelect(timeout)) < 0)
{
- char s[16384], /* String buffer */
- *sptr; /* Pointer into buffer */
- int slen; /* Length of string buffer */
-
-
/*
* Got an error from select!
*/
- if (errno == EINTR) /* Just interrupted by a signal */
+#ifdef HAVE_DNSSD
+ cupsd_printer_t *p; /* Current printer */
+#endif /* HAVE_DNSSD */
+
+
+ if (errno == EINTR) /* Just interrupted by a signal */
continue;
/*
* Log all sorts of debug info to help track down the problem.
*/
- cupsdLogMessage(CUPSD_LOG_EMERG, "select() failed - %s!",
+ cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!",
strerror(errno));
- strcpy(s, "InputSet =");
- slen = 10;
- sptr = s + 10;
-
- for (i = 0; i < MaxFDs; i ++)
- if (FD_ISSET(i, InputSet))
- {
- snprintf(sptr, sizeof(s) - slen, " %d", i);
- slen += strlen(sptr);
- sptr += strlen(sptr);
- }
-
- cupsdLogMessage(CUPSD_LOG_EMERG, "%s", s);
-
- strcpy(s, "OutputSet =");
- slen = 11;
- sptr = s + 11;
-
- for (i = 0; i < MaxFDs; i ++)
- if (FD_ISSET(i, OutputSet))
- {
- snprintf(sptr, sizeof(s) - slen, " %d", i);
- slen += strlen(sptr);
- sptr += strlen(sptr);
- }
-
- cupsdLogMessage(CUPSD_LOG_EMERG, "%s", s);
-
for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients);
con;
i ++, con = (cupsd_client_t *)cupsArrayNext(Clients))
@@ -772,6 +711,15 @@ main(int argc, /* I - Number of command-line args */
job->status_buffer ? job->status_buffer->fd : -1,
job->print_pipes[0], job->print_pipes[1],
job->back_pipes[0], job->back_pipes[1]);
+
+#ifdef HAVE_DNSSD
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] %d", p->name,
+ p->dnssd_ipp_fd);
+#endif /* HAVE_DNSSD */
+
break;
}
@@ -794,67 +742,6 @@ main(int argc, /* I - Number of command-line args */
#endif /* HAVE_LAUNCHD */
/*
- * Check for status info from job filters...
- */
-
- for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
- job;
- job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
- if (job->status_buffer && FD_ISSET(job->status_buffer->fd, input))
- {
- /*
- * Clear the input bit to avoid updating the next job
- * using the same status pipe file descriptor...
- */
-
- FD_CLR(job->status_buffer->fd, input);
-
- /*
- * Read any status messages from the filters...
- */
-
- cupsdUpdateJob(job);
- }
-
- /*
- * Update CGI messages as needed...
- */
-
- if (CGIPipes[0] >= 0 && FD_ISSET(CGIPipes[0], input))
- cupsdUpdateCGI();
-
- /*
- * Handle system management events as needed...
- */
-
-#ifdef __APPLE__
- /*
- * Mac OS X provides the SystemConfiguration framework for system
- * configuration change events...
- */
-
- if (SysEventPipes[0] >= 0 && FD_ISSET(SysEventPipes[0], input))
- cupsdUpdateSystemMonitor();
-#else
- /*
- * All other operating systems need to poll for changes...
- */
-
- if ((current_time - netif_time) >= 60)
- {
- NetIFUpdate = 1;
- netif_time = current_time;
- }
-#endif /* __APPLE__ */
-
- /*
- * Update notifier messages as needed...
- */
-
- if (NotifierPipes[0] >= 0 && FD_ISSET(NotifierPipes[0], input))
- cupsdUpdateNotifierStatus();
-
- /*
* Expire subscriptions and unload completed jobs as needed...
*/
@@ -872,14 +759,8 @@ main(int argc, /* I - Number of command-line args */
* Update the browse list as needed...
*/
- if (Browsing && BrowseRemoteProtocols)
+ if (Browsing)
{
- if (BrowseSocket >= 0 && FD_ISSET(BrowseSocket, input))
- cupsdUpdateCUPSBrowse();
-
- if (PollPipe >= 0 && FD_ISSET(PollPipe, input))
- cupsdUpdatePolling();
-
#ifdef HAVE_LIBSLP
if ((BrowseRemoteProtocols & BROWSE_SLP) &&
BrowseSLPRefresh <= current_time)
@@ -900,17 +781,20 @@ main(int argc, /* I - Number of command-line args */
}
/*
- * Check for new connections on the "listen" sockets...
+ * Update the root certificate once every 5 minutes if we have client
+ * connections...
*/
- for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
- lis;
- lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
- if (lis->fd >= 0 && FD_ISSET(lis->fd, input))
- {
- FD_CLR(lis->fd, input);
- cupsdAcceptClient(lis);
- }
+ if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration &&
+ !RunUser && cupsArrayCount(Clients))
+ {
+ /*
+ * Update the root certificate...
+ */
+
+ cupsdDeleteCert(0);
+ cupsdAddCert(0, "root");
+ }
/*
* Check for new data on the client sockets...
@@ -921,61 +805,13 @@ main(int argc, /* I - Number of command-line args */
con = (cupsd_client_t *)cupsArrayNext(Clients))
{
/*
- * Process the input buffer...
- */
-
- if (FD_ISSET(con->http.fd, input) || con->http.used)
- {
- int fd = con->file;
-
-
- FD_CLR(con->http.fd, input);
-
- if (!cupsdReadClient(con))
- {
- if (fd >= 0)
- FD_CLR(fd, input);
-
- continue;
- }
- }
-
- /*
- * Write data as needed...
+ * Process pending data in the input buffer...
*/
- if (con->pipe_pid && FD_ISSET(con->file, input))
- {
- /*
- * Keep track of pending input from the file/pipe separately
- * so that we don't needlessly spin on select() when the web
- * client is not ready to receive data...
- */
-
- FD_CLR(con->file, input);
- con->file_ready = 1;
-
-#ifdef DEBUG
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "main: Data ready file %d!",
- con->file);
-#endif /* DEBUG */
-
- if (!FD_ISSET(con->http.fd, output))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "main: Removing fd %d from InputSet...", con->file);
- FD_CLR(con->file, input);
- FD_CLR(con->file, InputSet);
- }
- }
-
- if (FD_ISSET(con->http.fd, output))
+ if (con->http.used)
{
- FD_CLR(con->http.fd, output);
-
- if (!con->pipe_pid || con->file_ready)
- if (!cupsdWriteClient(con))
- continue;
+ cupsdReadClient(con);
+ continue;
}
/*
@@ -1032,22 +868,6 @@ main(int argc, /* I - Number of command-line args */
}
/*
- * Update the root certificate once every 5 minutes if we have client
- * connections...
- */
-
- if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration &&
- !RunUser && cupsArrayCount(Clients))
- {
- /*
- * Update the root certificate...
- */
-
- cupsdDeleteCert(0);
- cupsdAddCert(0, "root");
- }
-
- /*
* Handle OS-specific event notification for any events that have
* accumulated. Don't send these more than once a second...
*/
@@ -1114,13 +934,17 @@ main(int argc, /* I - Number of command-line args */
* Update the launchd config file as needed...
*/
- launchd_sync_conf();
+ if (Launchd)
+ {
+ launchd_checkout();
+ launchd_sync_conf();
- if (launchd_conf_url)
- CFRelease(launchd_conf_url);
+ if (launchd_conf_url)
+ CFRelease(launchd_conf_url);
- if (launchd_conf_dict)
- CFRelease(launchd_conf_dict);
+ if (launchd_conf_dict)
+ CFRelease(launchd_conf_dict);
+ }
#endif /* HAVE_LAUNCHD */
#ifdef __sgi
@@ -1135,14 +959,7 @@ main(int argc, /* I - Number of command-line args */
unlink("/var/spool/lp/SCHEDLOCK");
#endif /* __sgi */
- /*
- * Free memory used by FD sets and return...
- */
-
- free(InputSet);
- free(OutputSet);
- free(input);
- free(output);
+ cupsdStopSelect();
return (!stop_scheduler);
}
@@ -1364,6 +1181,8 @@ launchd_checkin(void)
cupsd_listener_t *lis; /* Listeners array */
http_addr_t addr; /* Address variable */
socklen_t addrlen; /* Length of address */
+ int fd; /* File descriptor */
+ char s[256]; /* String addresss */
cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid());
@@ -1417,56 +1236,77 @@ launchd_checkin(void)
if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY)
{
- /*
- * Free the listeners array built from cupsd.conf...
- */
-
- cupsdDeleteAllListeners();
-
- /*
- * Create a new array of listeners from the launchd data...
- */
-
- Listeners = cupsArrayNew(NULL, NULL);
- count = launch_data_array_get_count(ld_array);
+ count = launch_data_array_get_count(ld_array);
for (i = 0; i < count; i ++)
{
/*
- * Copy the current address and log it...
+ * Get the launchd file descriptor and address...
*/
- if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+ tmp = launch_data_array_get_index(ld_array, i);
+ fd = launch_data_get_fd(tmp);
+ addrlen = sizeof(addr);
+
+ if (getsockname(fd, (struct sockaddr *)&addr, &addrlen))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to allocate listener - %s.",
- strerror(errno));
- exit(EXIT_FAILURE);
+ "launchd_checkin: Unable to get local address - %s",
+ strerror(errno));
+ continue;
}
- cupsArrayAdd(Listeners, lis);
+ /*
+ * Try to match the launchd socket address to one of the listeners...
+ */
- tmp = launch_data_array_get_index(ld_array, i);
- lis->fd = launch_data_get_fd(tmp);
- addrlen = sizeof(lis->address);
+ for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+ lis;
+ lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+ if (httpAddrEqual(&lis->address, &addr))
+ break;
+
+ /*
+ * Add a new listener If there's no match...
+ */
- if (getsockname(lis->fd, (struct sockaddr *)&(lis->address), &addrlen))
+ if (lis)
{
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_checkin: Unable to get local address - %s",
- strerror(errno));
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "launchd_checkin: Matched existing listener %s with fd %d...",
+ httpAddrString(&(lis->address), s, sizeof(s)), fd);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "launchd_checkin: Adding new listener %s with fd %d...",
+ httpAddrString(&addr, s, sizeof(s)), fd);
+
+ if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "launchd_checkin: Unable to allocate listener - %s.",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ cupsArrayAdd(Listeners, lis);
+
+ memcpy(&lis->address, &addr, sizeof(lis->address));
}
+ lis->fd = fd;
+
# ifdef HAVE_SSL
portnum = 0;
# ifdef AF_INET6
- if (addr.addr.sa_family == AF_INET6)
- portnum = ntohs(addr.ipv6.sin6_port);
+ if (lis->address.addr.sa_family == AF_INET6)
+ portnum = ntohs(lis->address.ipv6.sin6_port);
else
# endif /* AF_INET6 */
- if (addr.addr.sa_family == AF_INET)
- portnum = ntohs(addr.ipv4.sin_port);
+ if (lis->address.addr.sa_family == AF_INET)
+ portnum = ntohs(lis->address.ipv4.sin_port);
if (portnum == 443)
lis->encryption = HTTP_ENCRYPT_ALWAYS;
@@ -1512,6 +1352,43 @@ launchd_checkin(void)
/*
+ * 'launchd_checkout()' - Update the launchd KeepAlive file as needed.
+ */
+
+static void
+launchd_checkout(void)
+{
+ int fd; /* File descriptor */
+
+
+ /*
+ * Create or remove the launchd KeepAlive file based on whether
+ * there are active jobs, polling, browsing for remote printers or
+ * shared printers to advertise...
+ */
+
+ if ((cupsArrayCount(ActiveJobs) || NumPolled ||
+ (Browsing &&
+ (BrowseRemoteProtocols ||
+ (BrowseLocalProtocols && NumBrowsers && cupsArrayCount(Printers))))))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Creating launchd keepalive file \"" CUPS_KEEPALIVE "\"...");
+
+ if ((fd = open(CUPS_KEEPALIVE, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) >= 0)
+ close(fd);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Removing launchd keepalive file \"" CUPS_KEEPALIVE "\"...");
+
+ unlink(CUPS_KEEPALIVE);
+ }
+}
+
+
+/*
* 'launchd_create_dict()' - Create a dictionary representing the launchd
* config file org.cups.cupsd.plist.
*/
@@ -1519,24 +1396,26 @@ launchd_checkin(void)
static CFDictionaryRef /* O - CFDictionary */
launchd_create_dict(void)
{
- int portnum; /* Port number */
- bool runatload; /* Run at load? */
- CFMutableDictionaryRef cupsd_dict, /* org.cups.cupsd.plist dictionary */
- sockets, /* Sockets dictionary */
- listener; /* Listener dictionary */
- CFMutableArrayRef array; /* Array */
- CFNumberRef socket_mode; /* Domain socket mode bits */
- CFStringRef socket_path; /* Domain socket path */
- CFTypeRef value; /* CF values */
- cupsd_listener_t *lis; /* Current listening socket */
- struct servent *service; /* Services data base entry */
- char temp[1024]; /* Temporary buffer for value */
+ int portnum; /* Port number */
+ bool runatload; /* Run at load? */
+ CFMutableDictionaryRef cupsd_dict, /* org.cups.cupsd.plist dictionary */
+ keepalive, /* KeepAlive dictionary */
+ pathstate, /* PathState dictionary */
+ sockets, /* Sockets dictionary */
+ listener; /* Listener dictionary */
+ CFMutableArrayRef array; /* Array */
+ CFNumberRef socket_mode; /* Domain socket mode bits */
+ CFStringRef socket_path; /* Domain socket path */
+ CFTypeRef value; /* CF values */
+ cupsd_listener_t *lis; /* Current listening socket */
+ struct servent *service; /* Services data base entry */
+ char temp[1024]; /* Temporary buffer for value */
if ((cupsd_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks)) == NULL)
- return NULL;
+ return (NULL);
CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_LABEL),
CFSTR("org.cups.cupsd"));
@@ -1544,20 +1423,35 @@ launchd_create_dict(void)
kCFBooleanTrue);
/*
- * Run-at-load if there are active jobs, polling or shared printers
- * to advertise...
+ * Use run-at-load and/or KeepAlive if there are active jobs, polling or
+ * shared printers to advertise...
*/
-
+
+ if ((keepalive = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks)) != NULL)
+ {
+ if ((pathstate = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks)) != NULL)
+ {
+ CFDictionaryAddValue(pathstate, CFSTR(CUPS_KEEPALIVE), kCFBooleanTrue);
+ CFDictionaryAddValue(keepalive, CFSTR(LAUNCH_JOBKEY_PATHSTATE),
+ pathstate);
+ }
+
+ CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_KEEPALIVE),
+ keepalive);
+ }
+
runatload = (cupsArrayCount(ActiveJobs) || NumPolled ||
(Browsing && BrowseLocalProtocols &&
NumBrowsers && cupsArrayCount(Printers))) ? true : false;
CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD),
runatload ? kCFBooleanTrue : kCFBooleanFalse);
-# ifdef LAUNCH_JOBKEY_SERVICEIPC
CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SERVICEIPC),
kCFBooleanTrue);
-# endif /* LAUNCH_JOBKEY_SERVICEIPC */
if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 2,
&kCFTypeArrayCallBacks)) != NULL)
@@ -1728,106 +1622,6 @@ launchd_create_dict(void)
/*
- * 'launchd_reload()' - Tell launchd to reload the configuration file to pick
- * up the new listening directives.
- */
-
-static void
-launchd_reload(void)
-{
- int child_status; /* Exit status of child process */
- pid_t child_pid, /* Child PID */
- waitpid_status; /* Child process exit status */
- char *argv[4]; /* Argument strings */
-
-
- /*
- * The current launchd doesn't support a reload option (rdar://3854821).
- * Until this is fixed we need to reload the config file by execing launchctl
- * twice (to unload then load). NOTE: This will cause us to exit on SIGTERM
- * which will cancel all client & job activity.
- *
- * After this is fixed we'll be able to tell launchd to reload the file
- * and pick up the new listening descriptors without disrupting current
- * activity.
- */
-
- /*
- * Unloading the current configuration will cause launchd to send us a SIGTERM;
- * block it for now so we can get our work done...
- */
-
- cupsdHoldSignals();
-
- /*
- * Set up the unload arguments to launchctl...
- */
-
- argv[0] = "/bin/launchctl";
- argv[1] = "unload";
- argv[2] = LaunchdConf;
- argv[3] = NULL;
-
- if (cupsdStartProcess(argv[0], argv, NULL, -1, -1, -1, -1, 1, &child_pid) < 0)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_reload: Unable to execute %s - %s", argv[0],
- strerror(errno));
- else
- {
- do
- {
- waitpid_status = waitpid(child_pid, &child_status, 0);
- }
- while (waitpid_status == (pid_t)-1 && errno == EINTR);
-
- if (WIFSIGNALED(child_status))
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d crashed on signal %d!",
- basename(argv[0]), child_pid, WTERMSIG(child_status));
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d stopped with status %d!",
- basename(argv[0]), child_pid, WEXITSTATUS(child_status));
-
- /*
- * Do it again with the load command...
- */
-
- argv[1] = "load";
-
- if (cupsdStartProcess(argv[0], argv, NULL, -1, -1, -1, -1, 1,
- &child_pid) < 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "launchd_reload: Unable to fork for %s - %s", argv[0],
- strerror(errno));
- }
- else
- {
- do
- {
- waitpid_status = waitpid(child_pid, &child_status, 0);
- } while (waitpid_status == (pid_t)-1 && errno == EINTR);
-
- if (WIFSIGNALED(child_status))
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d crashed on signal %d!",
- basename(argv[0]), child_pid, WTERMSIG(child_status));
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "launchd_reload: %s pid %d stopped with status %d",
- basename(argv[0]), child_pid,
- WEXITSTATUS(child_status));
- }
- }
-
- /*
- * Leave signals blocked since exit() will be called momentarily anyways...
- */
-}
-
-
-/*
* 'launchd_sync_conf()' - Rewrite the launchd config file
* org.cups.cupsd.plist based on cupsd.conf.
*/
@@ -1890,7 +1684,7 @@ launchd_sync_conf(void)
if (!CFEqual(cupsd_dict, launchd_conf_dict))
{
if ((resourceData = CFPropertyListCreateXMLData(kCFAllocatorDefault,
- cupsd_dict)))
+ cupsd_dict)))
{
if (CFURLWriteDataAndPropertiesToResource(launchd_conf_url, resourceData,
NULL, &errorCode))
@@ -2174,12 +1968,12 @@ select_timeout(int fds) /* I - Number of descriptors returned */
return (0);
/*
- * If select has been active in the last second (fds != 0) or we have
+ * If select has been active in the last second (fds > 0) or we have
* many resources in use then don't bother trying to optimize the
* timeout, just make it 1 second.
*/
- if (fds || cupsArrayCount(Clients) > 50)
+ if (fds > 0 || cupsArrayCount(Clients) > 50)
return (1);
/*
@@ -2225,7 +2019,7 @@ select_timeout(int fds) /* I - Number of descriptors returned */
}
#endif /* HAVE_LDAP */
- if (BrowseLocalProtocols & BROWSE_CUPS)
+ if ((BrowseLocalProtocols & BROWSE_CUPS) && NumBrowsers)
{
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
@@ -2239,7 +2033,7 @@ select_timeout(int fds) /* I - Number of descriptors returned */
why = "browse timeout a printer";
}
}
- else if (!(p->type & CUPS_PRINTER_IMPLICIT))
+ else if (p->shared && !(p->type & CUPS_PRINTER_IMPLICIT))
{
if (BrowseInterval && (p->browse_time + BrowseInterval) < timeout)
{
@@ -2313,8 +2107,8 @@ select_timeout(int fds) /* I - Number of descriptors returned */
* Log and return the timeout value...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "select_timeout: %ld seconds to %s",
- timeout, why);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "select_timeout(%d): %ld seconds to %s",
+ fds, timeout, why);
return (timeout);
}
@@ -2340,5 +2134,5 @@ usage(int status) /* O - Exit status */
/*
- * End of "$Id: main.c 6090 2006-11-14 16:35:27Z mike $".
+ * End of "$Id: main.c 6326 2007-03-11 17:50:18Z mike $".
*/
diff --git a/scheduler/mime.c b/scheduler/mime.c
index 2e98d0b3f..052b42922 100644
--- a/scheduler/mime.c
+++ b/scheduler/mime.c
@@ -1,5 +1,5 @@
/*
- * "$Id: mime.c 5606 2006-05-30 19:40:34Z mike $"
+ * "$Id: mime.c 5605 2006-05-30 19:38:02Z mike $"
*
* MIME database file routines for the Common UNIX Printing System (CUPS).
*
@@ -738,5 +738,5 @@ load_types(mime_t *mime, /* I - MIME database */
/*
- * End of "$Id: mime.c 5606 2006-05-30 19:40:34Z mike $".
+ * End of "$Id: mime.c 5605 2006-05-30 19:38:02Z mike $".
*/
diff --git a/scheduler/mime.h b/scheduler/mime.h
index 2b44bf121..16e9a3d7c 100644
--- a/scheduler/mime.h
+++ b/scheduler/mime.h
@@ -1,9 +1,9 @@
/*
- * "$Id: mime.h 5771 2006-07-20 18:06:20Z mike $"
+ * "$Id: mime.h 6252 2007-02-10 15:34:18Z mike $"
*
* MIME type/conversion database definitions for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -143,6 +143,8 @@ extern mime_filter_t *mimeAddFilter(mime_t *mime, mime_type_t *src,
extern void mimeDeleteFilter(mime_t *mime, mime_filter_t *filter);
extern cups_array_t *mimeFilter(mime_t *mime, mime_type_t *src,
mime_type_t *dst, int *cost);
+extern mime_filter_t *mimeFilterLookup(mime_t *mime, mime_type_t *src,
+ mime_type_t *dst);
extern mime_filter_t *mimeFirstFilter(mime_t *mime);
extern mime_filter_t *mimeNextFilter(mime_t *mime);
extern int mimeNumFilters(mime_t *mime);
@@ -153,5 +155,5 @@ extern int mimeNumFilters(mime_t *mime);
#endif /* !_CUPS_MIME_H_ */
/*
- * End of "$Id: mime.h 5771 2006-07-20 18:06:20Z mike $".
+ * End of "$Id: mime.h 6252 2007-02-10 15:34:18Z mike $".
*/
diff --git a/scheduler/network.c b/scheduler/network.c
index e63d4f44e..b7057d7b4 100644
--- a/scheduler/network.c
+++ b/scheduler/network.c
@@ -1,5 +1,5 @@
/*
- * "$Id: network.c 6090 2006-11-14 16:35:27Z mike $"
+ * "$Id: network.c 6086 2006-11-14 15:43:55Z mike $"
*
* Network interface functions for the Common UNIX Printing System
* (CUPS) scheduler.
@@ -314,5 +314,5 @@ compare_netif(cupsd_netif_t *a, /* I - First network interface */
/*
- * End of "$Id: network.c 6090 2006-11-14 16:35:27Z mike $".
+ * End of "$Id: network.c 6086 2006-11-14 15:43:55Z mike $".
*/
diff --git a/scheduler/network.h b/scheduler/network.h
index 5d8c83f8a..c26e8dbb2 100644
--- a/scheduler/network.h
+++ b/scheduler/network.h
@@ -1,5 +1,5 @@
/*
- * "$Id: network.h 6090 2006-11-14 16:35:27Z mike $"
+ * "$Id: network.h 6086 2006-11-14 15:43:55Z mike $"
*
* Network interface definitions for the Common UNIX Printing System
* (CUPS) scheduler.
@@ -57,5 +57,5 @@ extern void cupsdNetIFUpdate(void);
/*
- * End of "$Id: network.h 6090 2006-11-14 16:35:27Z mike $".
+ * End of "$Id: network.h 6086 2006-11-14 15:43:55Z mike $".
*/
diff --git a/scheduler/policy.c b/scheduler/policy.c
index 606978e3e..668bbff6f 100644
--- a/scheduler/policy.c
+++ b/scheduler/policy.c
@@ -1,5 +1,5 @@
/*
- * "$Id: policy.c 5838 2006-08-17 14:41:42Z mike $"
+ * "$Id: policy.c 5837 2006-08-17 14:37:40Z mike $"
*
* Policy routines for the Common UNIX Printing System (CUPS).
*
@@ -330,5 +330,5 @@ cupsdFindPolicyOp(cupsd_policy_t *p, /* I - Policy */
/*
- * End of "$Id: policy.c 5838 2006-08-17 14:41:42Z mike $".
+ * End of "$Id: policy.c 5837 2006-08-17 14:37:40Z mike $".
*/
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 936c9d0be..9a33a2221 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -1,9 +1,9 @@
/*
- * "$Id: printers.c 5970 2006-09-19 20:11:08Z mike $"
+ * "$Id: printers.c 6318 2007-03-06 04:36:55Z mike $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -70,7 +70,8 @@
*/
static void add_printer_defaults(cupsd_printer_t *p);
-static void add_printer_filter(cupsd_printer_t *p, const char *filter);
+static void add_printer_filter(cupsd_printer_t *p, mime_type_t *type,
+ const char *filter);
static void add_printer_formats(cupsd_printer_t *p);
static int compare_printers(void *first, void *second, void *data);
static void delete_printer_filters(cupsd_printer_t *p);
@@ -412,10 +413,6 @@ cupsdCreateCommonData(void)
/* copies-supported */
ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies);
- /* document-format-default */
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
- "document-format-default", NULL, "application/octet-stream");
-
/* generated-natural-language-supported */
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
"generated-natural-language-supported", NULL, DefaultLanguage);
@@ -495,10 +492,6 @@ cupsdCreateCommonData(void)
(int)(sizeof(notify_attrs) / sizeof(notify_attrs[0])),
NULL, notify_attrs);
- /* notify-lease-duration-default */
- ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
- "notify-lease-duration-default", DefaultLeaseDuration);
-
/* notify-lease-duration-supported */
ippAddRange(CommonData, IPP_TAG_PRINTER,
"notify-lease-duration-supported", 0,
@@ -508,10 +501,6 @@ cupsdCreateCommonData(void)
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"notify-max-events-supported", MaxEvents);
- /* notify-events-default */
- ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "notify-events-default", NULL, "job-completed");
-
/* notify-events-supported */
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"notify-events-supported",
@@ -703,13 +692,18 @@ cupsdDeletePrinter(
}
/*
- * Remove this printer from any classes and send a browse delete message...
+ * Remove this printer from any classes...
*/
if (!(p->type & CUPS_PRINTER_IMPLICIT))
{
cupsdDeletePrinterFromClasses(p);
- cupsdSendBrowseDelete(p);
+
+ /*
+ * Deregister from any browse protocols...
+ */
+
+ cupsdDeregisterPrinter(p, 1);
}
/*
@@ -735,6 +729,7 @@ cupsdDeletePrinter(
delete_printer_filters(p);
mimeDeleteType(MimeDatabase, p->filetype);
+ mimeDeleteType(MimeDatabase, p->prefiltertype);
cupsdFreePrinterUsers(p);
cupsdFreeQuotas(p);
@@ -752,6 +747,11 @@ cupsdDeletePrinter(
cupsdClearString(&p->op_policy);
cupsdClearString(&p->error_policy);
+#ifdef HAVE_DNSSD
+ cupsdClearString(&p->product);
+ cupsdClearString(&p->pdl);
+#endif /* HAVE_DNSSD */
+
cupsArrayDelete(p->filetypes);
if (p->browse_attrs)
@@ -954,6 +954,13 @@ cupsdLoadAllPrinters(void)
"Syntax error on line %d of printers.conf.", linenum);
return;
}
+ else if (!strcasecmp(line, "AuthInfoRequired"))
+ {
+ if (!cupsdSetAuthInfoRequired(p, value, NULL))
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad AuthInfoRequired on line %d of printers.conf.",
+ linenum);
+ }
else if (!strcasecmp(line, "Info"))
{
if (value)
@@ -1247,6 +1254,9 @@ cupsdRenamePrinter(
mimeDeleteType(MimeDatabase, p->filetype);
p->filetype = mimeAddType(MimeDatabase, "printer", name);
+ mimeDeleteType(MimeDatabase, p->prefiltertype);
+ p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", name);
+
/*
* Rename the printer...
*/
@@ -1286,6 +1296,7 @@ cupsdSaveAllPrinters(void)
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
cups_option_t *option; /* Current option */
+ const char *ptr; /* Pointer into info/location */
/*
@@ -1359,12 +1370,49 @@ cupsdSaveAllPrinters(void)
else
cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
+ if (printer->num_auth_info_required > 0)
+ {
+ cupsFilePrintf(fp, "AuthInfoRequired %s", printer->auth_info_required[0]);
+ for (i = 1; i < printer->num_auth_info_required; i ++)
+ cupsFilePrintf(fp, ",%s", printer->auth_info_required[i]);
+ cupsFilePutChar(fp, '\n');
+ }
+
if (printer->info)
- cupsFilePrintf(fp, "Info %s\n", printer->info);
+ {
+ if ((ptr = strchr(printer->info, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the info string...
+ */
+
+ cupsFilePuts(fp, "Info ");
+ cupsFileWrite(fp, printer->info, ptr - printer->info);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Info %s\n", printer->info);
+ }
if (printer->location)
- cupsFilePrintf(fp, "Location %s\n", printer->location);
+ {
+ if ((ptr = strchr(printer->info, '#')) != NULL)
+ {
+ /*
+ * Need to quote the first # in the location string...
+ */
+ cupsFilePuts(fp, "Location ");
+ cupsFileWrite(fp, printer->location, ptr - printer->location);
+ cupsFilePutChar(fp, '\\');
+ cupsFilePuts(fp, ptr);
+ cupsFilePutChar(fp, '\n');
+ }
+ else
+ cupsFilePrintf(fp, "Location %s\n", printer->location);
+ }
if (printer->device_uri)
cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
@@ -1428,6 +1476,119 @@ cupsdSaveAllPrinters(void)
/*
+ * 'cupsdSetAuthInfoRequired()' - Set the required authentication info.
+ */
+
+int /* O - 1 if value OK, 0 otherwise */
+cupsdSetAuthInfoRequired(
+ cupsd_printer_t *p, /* I - Printer */
+ const char *values, /* I - Plain text value (or NULL) */
+ ipp_attribute_t *attr) /* I - IPP attribute value (or NULL) */
+{
+ int i; /* Looping var */
+
+
+ p->num_auth_info_required = 0;
+
+ /*
+ * Do we have a plain text value?
+ */
+
+ if (values)
+ {
+ /*
+ * Yes, grab the keywords...
+ */
+
+ const char *end; /* End of current value */
+
+
+ while (*values && p->num_auth_info_required < 4)
+ {
+ if ((end = strchr(values, ',')) == NULL)
+ end = values + strlen(values);
+
+ if (!strncmp(values, "none", end - values))
+ {
+ if (p->num_auth_info_required != 0 || *end)
+ return (0);
+
+ p->auth_info_required[p->num_auth_info_required] = "none";
+ p->num_auth_info_required ++;
+
+ return (1);
+ }
+ else if (!strncmp(values, "domain", end - values))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "domain";
+ p->num_auth_info_required ++;
+ }
+ else if (!strncmp(values, "password", end - values))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "password";
+ p->num_auth_info_required ++;
+ }
+ else if (!strncmp(values, "username", end - values))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "username";
+ p->num_auth_info_required ++;
+ }
+ else
+ return (0);
+ }
+
+ if (p->num_auth_info_required == 0)
+ {
+ p->auth_info_required[0] = "none";
+ p->num_auth_info_required = 1;
+ }
+
+ return (1);
+ }
+
+ /*
+ * Grab values from an attribute instead...
+ */
+
+ if (!attr || attr->num_values > 4)
+ return (0);
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (!strcmp(attr->values[i].string.text, "none"))
+ {
+ if (p->num_auth_info_required != 0 || attr->num_values != 1)
+ return (0);
+
+ p->auth_info_required[p->num_auth_info_required] = "none";
+ p->num_auth_info_required ++;
+
+ return (1);
+ }
+ else if (!strcmp(attr->values[i].string.text, "domain"))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "domain";
+ p->num_auth_info_required ++;
+ }
+ else if (!strcmp(attr->values[i].string.text, "password"))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "password";
+ p->num_auth_info_required ++;
+ }
+ else if (!strcmp(attr->values[i].string.text, "username"))
+ {
+ p->auth_info_required[p->num_auth_info_required] = "username";
+ p->num_auth_info_required ++;
+ }
+ else
+ return (0);
+ }
+
+ return (1);
+}
+
+
+/*
* 'cupsdSetPrinterAttrs()' - Set printer attributes based upon the PPD file.
*/
@@ -1552,6 +1713,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
"job-k-limit", p->k_limit);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-page-limit", p->page_limit);
+ if (p->num_auth_info_required)
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "auth-info-required", p->num_auth_info_required,
+ NULL, p->auth_info_required);
+ else
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "auth-info-required", NULL, "none");
if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_REMOTE))
{
@@ -1880,7 +2048,20 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
* handle "raw" printing by users.
*/
- add_printer_filter(p, "application/vnd.cups-raw 0 -");
+ add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
+
+ /*
+ * Add any pre-filters in the PPD file...
+ */
+
+ if ((ppdattr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
+ {
+ p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name);
+
+ for (; ppdattr; ppdattr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
+ if (ppdattr->value)
+ add_printer_filter(p, p->prefiltertype, ppdattr->value);
+ }
/*
* Add any filters in the PPD file...
@@ -1890,7 +2071,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
for (i = 0; i < ppd->num_filters; i ++)
{
DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i]));
- add_printer_filter(p, ppd->filters[i]);
+ add_printer_filter(p, p->filetype, ppd->filters[i]);
}
if (ppd->num_filters == 0)
@@ -1899,7 +2080,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
* If there are no filters, add a PostScript printing filter.
*/
- add_printer_filter(p, "application/vnd.cups-postscript 0 -");
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-postscript 0 -");
}
/*
@@ -1940,6 +2122,10 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
attr->values[i].string.text = _cupsStrAlloc("bcp");
}
+#ifdef HAVE_DNSSD
+ cupsdSetString(&p->product, ppd->product);
+#endif /* HAVE_DNSSD */
+
/*
* Close the PPD and set the type...
*/
@@ -1974,13 +2160,14 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
* handle "raw" printing by users.
*/
- add_printer_filter(p, "application/vnd.cups-raw 0 -");
+ add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
/*
* Add a PostScript filter, since this is still possibly PS printer.
*/
- add_printer_filter(p, "application/vnd.cups-postscript 0 -");
+ add_printer_filter(p, p->filetype,
+ "application/vnd.cups-postscript 0 -");
}
else
{
@@ -1997,11 +2184,12 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
*/
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
- "printer-make-and-model", NULL, "Local System V Printer");
+ "printer-make-and-model", NULL,
+ "Local System V Printer");
snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s",
ServerRoot, p->name);
- add_printer_filter(p, filename);
+ add_printer_filter(p, p->filetype, filename);
}
else if (p->device_uri &&
!strncmp(p->device_uri, "ipp://", 6) &&
@@ -2098,12 +2286,12 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
length += 13 + strlen(p->job_sheets[0]) + strlen(p->job_sheets[1]);
length += 32;
if (BrowseLocalOptions)
- length += 12 + strlen(BrowseLocalOptions);
+ length += 12 + strlen(BrowseLocalOptions);
/*
* Allocate the new string...
*/
-
+
if ((p->browse_attrs = calloc(1, length)) == NULL)
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to allocate %d bytes for browse data!",
@@ -2173,6 +2361,12 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
write_irix_config(p);
write_irix_state(p);
#endif /* __sgi */
+
+ /*
+ * Let the browse protocols reflect the change
+ */
+
+ cupsdRegisterPrinter(p);
}
@@ -2328,6 +2522,12 @@ cupsdSetPrinterState(
cupsdAddPrinterHistory(p);
/*
+ * Let the browse protocols reflect the change...
+ */
+
+ cupsdRegisterPrinter(p);
+
+ /*
* Save the printer configuration if a printer goes from idle or processing
* to stopped (or visa-versa)...
*/
@@ -2452,18 +2652,25 @@ cupsdUpdatePrinters(void)
const char * /* O - Printer or class name */
cupsdValidateDest(
- const char *hostname, /* I - Host name */
- const char *resource, /* I - Resource name */
+ const char *uri, /* I - Printer URI */
cups_ptype_t *dtype, /* O - Type (printer or class) */
cupsd_printer_t **printer) /* O - Printer pointer */
{
cupsd_printer_t *p; /* Current printer */
char localname[1024],/* Localized hostname */
*lptr, /* Pointer into localized hostname */
- *sptr; /* Pointer into server name */
-
-
- DEBUG_printf(("cupsdValidateDest(\"%s\", \"%s\", %p, %p)\n", hostname, resource,
+ *sptr, /* Pointer into server name */
+ *rptr, /* Pointer into resource */
+ scheme[32], /* Scheme portion of URI */
+ username[64], /* Username portion of URI */
+ hostname[HTTP_MAX_HOST],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+
+
+ DEBUG_printf(("cupsdValidateDest(uri=\"%s\", dtype=%p, printer=%p)\n", uri,
dtype, printer));
/*
@@ -2473,7 +2680,16 @@ cupsdValidateDest(
if (printer)
*printer = NULL;
- *dtype = (cups_ptype_t)0;
+ if (dtype)
+ *dtype = (cups_ptype_t)0;
+
+ /*
+ * Pull the hostname and resource from the URI...
+ */
+
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
+ username, sizeof(username), hostname, sizeof(hostname),
+ &port, resource, sizeof(resource));
/*
* See if the resource is a class or printer...
@@ -2485,7 +2701,7 @@ cupsdValidateDest(
* Class...
*/
- resource += 9;
+ rptr = resource + 9;
}
else if (!strncmp(resource, "/printers/", 10))
{
@@ -2493,7 +2709,7 @@ cupsdValidateDest(
* Printer...
*/
- resource += 10;
+ rptr = resource + 10;
}
else
{
@@ -2508,17 +2724,19 @@ cupsdValidateDest(
* See if the printer or class name exists...
*/
- p = cupsdFindDest(resource);
+ p = cupsdFindDest(rptr);
- if (p == NULL && strchr(resource, '@') == NULL)
+ if (p == NULL && strchr(rptr, '@') == NULL)
return (NULL);
else if (p != NULL)
{
if (printer)
*printer = p;
- *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
- CUPS_PRINTER_REMOTE);
+ if (dtype)
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
+
return (p->name);
}
@@ -2527,7 +2745,7 @@ cupsdValidateDest(
*/
if (!strcasecmp(hostname, "localhost"))
- hostname = ServerName;
+ strlcpy(hostname, ServerName, sizeof(hostname));
strlcpy(localname, hostname, sizeof(localname));
@@ -2569,13 +2787,15 @@ cupsdValidateDest(
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
if (!strcasecmp(p->hostname, localname) &&
- !strcasecmp(p->name, resource))
+ !strcasecmp(p->name, rptr))
{
if (printer)
*printer = p;
- *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
- CUPS_PRINTER_REMOTE);
+ if (dtype)
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
+
return (p->name);
}
@@ -2793,6 +3013,27 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
/*
+ * Maintain a common array of default attribute names...
+ */
+
+ if (!CommonDefaults)
+ {
+ CommonDefaults = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("copies-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("document-format-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("finishings-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-hold-until-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-priority-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-sheets-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("media-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("number-up-default"));
+ cupsArrayAdd(CommonDefaults,
+ _cupsStrAlloc("orientation-requested-default"));
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("sides-default"));
+ }
+
+ /*
* Add all of the default options from the .conf files...
*/
@@ -2806,6 +3047,9 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
{
snprintf(name, sizeof(name), "%s-default", option->name);
num_options = cupsAddOption(name, option->value, num_options, &options);
+
+ if (!cupsArrayFind(CommonDefaults, name))
+ cupsArrayAdd(CommonDefaults, _cupsStrAlloc(name));
}
}
@@ -2824,6 +3068,10 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "copies-default",
1);
+ if (!cupsGetOption("document-format", p->num_options, p->options))
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
+ "document-format-default", NULL, "application/octet-stream");
+
if (!cupsGetOption("job-hold-until", p->num_options, p->options))
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"job-hold-until-default", NULL, "no-hold");
@@ -2839,6 +3087,14 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
if (!cupsGetOption("orientation-requested", p->num_options, p->options))
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"orientation-requested-default", IPP_PORTRAIT);
+
+ if (!cupsGetOption("notify-lease-duration", p->num_options, p->options))
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "notify-lease-duration-default", DefaultLeaseDuration);
+
+ if (!cupsGetOption("notify-events", p->num_options, p->options))
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "notify-events-default", NULL, "job-completed");
}
@@ -2849,6 +3105,7 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
static void
add_printer_filter(
cupsd_printer_t *p, /* I - Printer to add to */
+ mime_type_t *filtertype, /* I - Filter or prefilter MIME type */
const char *filter) /* I - Filter to add */
{
char super[MIME_MAX_SUPER], /* Super-type for filter */
@@ -2919,9 +3176,9 @@ add_printer_filter(
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"add_printer_filter: %s: adding filter %s/%s %s/%s %d %s",
p->name, temptype->super, temptype->type,
- p->filetype->super, p->filetype->type,
+ filtertype->super, filtertype->type,
cost, program);
- mimeAddFilter(MimeDatabase, temptype, p->filetype, cost, program);
+ mimeAddFilter(MimeDatabase, temptype, filtertype, cost, program);
}
}
@@ -3017,6 +3274,54 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
attr->values[i].string.text = _cupsStrAlloc(mimetype);
}
+
+#ifdef HAVE_DNSSD
+ {
+ char pdl[1024]; /* Buffer to build pdl list */
+ mime_filter_t *filter; /* MIME filter looping var */
+
+
+ pdl[0] = '\0';
+
+ if (mimeType(MimeDatabase, "application", "pdf"))
+ strlcat(pdl, "application/pdf,", sizeof(pdl));
+
+ if (mimeType(MimeDatabase, "application", "postscript"))
+ strlcat(pdl, "application/postscript,", sizeof(pdl));
+
+ if (mimeType(MimeDatabase, "application", "vnd.cups-raster"))
+ strlcat(pdl, "application/vnd.cups-raster,", sizeof(pdl));
+
+ /*
+ * Determine if this is a Tioga PrintJobMgr based queue...
+ */
+
+ for (filter = (mime_filter_t *)cupsArrayFirst(MimeDatabase->filters);
+ filter;
+ filter = (mime_filter_t *)cupsArrayNext(MimeDatabase->filters))
+ {
+ if (filter->dst == p->filetype && filter->filter &&
+ strstr(filter->filter, "PrintJobMgr"))
+ break;
+ }
+
+ /*
+ * We only support raw printing if this is not a Tioga PrintJobMgr based
+ * queue and if application/octet-stream is a known conversion...
+ */
+
+ if (!filter && mimeType(MimeDatabase, "application", "octet-stream"))
+ strlcat(pdl, "application/octet-stream,", sizeof(pdl));
+
+ if (mimeType(MimeDatabase, "image", "png"))
+ strlcat(pdl, "image/png,", sizeof(pdl));
+
+ if (pdl[0])
+ pdl[strlen(pdl) - 1] = '\0'; /* Remove trailing comma */
+
+ cupsdSetString(&p->pdl, pdl);
+ }
+#endif /* HAVE_DNSSD */
}
@@ -3327,5 +3632,5 @@ write_irix_state(cupsd_printer_t *p) /* I - Printer to update */
/*
- * End of "$Id: printers.c 5970 2006-09-19 20:11:08Z mike $".
+ * End of "$Id: printers.c 6318 2007-03-06 04:36:55Z mike $".
*/
diff --git a/scheduler/printers.h b/scheduler/printers.h
index acbc73800..77782359d 100644
--- a/scheduler/printers.h
+++ b/scheduler/printers.h
@@ -1,9 +1,9 @@
/*
- * "$Id: printers.h 5828 2006-08-15 21:21:45Z mike $"
+ * "$Id: printers.h 6318 2007-03-06 04:36:55Z mike $"
*
* Printer definitions for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -22,6 +22,10 @@
* WWW: http://www.cups.org
*/
+#ifdef HAVE_DNSSD
+# include <dns_sd.h>
+#endif /* HAVE_DNSSD */
+
/*
* Quota data...
*/
@@ -67,7 +71,8 @@ typedef struct cupsd_printer_s
char *port_monitor; /* Port monitor */
int raw; /* Raw queue? */
int remote; /* Remote queue? */
- mime_type_t *filetype; /* Pseudo-filetype for printer */
+ mime_type_t *filetype, /* Pseudo-filetype for printer */
+ *prefiltertype; /* Pseudo-filetype for pre-filters */
cups_array_t *filetypes; /* Supported file types */
void *job; /* Current job in queue */
ipp_t *attrs; /* Attributes supported by this printer */
@@ -86,9 +91,21 @@ typedef struct cupsd_printer_s
int sequence_number; /* Increasing sequence number */
int num_options; /* Number of default options */
cups_option_t *options; /* Default options */
+ int num_auth_info_required; /* Number of required auth fields */
+ const char *auth_info_required[4]; /* Required authentication fields */
#ifdef __APPLE__
char *recoverable; /* com.apple.print.recoverable-message */
#endif /* __APPLE__ */
+
+#ifdef HAVE_DNSSD
+ char *reg_name, /* Name used for service registration */
+ *product, /* PPD Product string */
+ *pdl, /* pdl value for TXT record */
+ *txt_record; /* TXT record contents */
+ int txt_len; /* TXT record length */
+ DNSServiceRef dnssd_ipp_ref; /* DNSServiceRegister ref for _ipp */
+ int dnssd_ipp_fd; /* File descriptor for DNSServiceRegister reference */
+#endif /* HAVE_DNSSD */
} cupsd_printer_t;
@@ -98,6 +115,8 @@ typedef struct cupsd_printer_s
VAR ipp_t *CommonData VALUE(NULL);
/* Common printer object attrs */
+VAR cups_array_t *CommonDefaults VALUE(NULL);
+ /* Common -default option names */
VAR cups_array_t *Printers VALUE(NULL),
/* Printer list */
*ImplicitPrinters VALUE(NULL);
@@ -117,7 +136,8 @@ VAR cupsd_policy_t *DefaultPolicyPtr
extern cupsd_printer_t *cupsdAddPrinter(const char *name);
extern void cupsdAddPrinterHistory(cupsd_printer_t *p);
-extern void cupsdAddPrinterUser(cupsd_printer_t *p, const char *username);
+extern void cupsdAddPrinterUser(cupsd_printer_t *p,
+ const char *username);
extern void cupsdCreateCommonData(void);
extern void cupsdDeleteAllPrinters(void);
extern void cupsdDeletePrinter(cupsd_printer_t *p, int update);
@@ -126,26 +146,31 @@ extern cupsd_printer_t *cupsdFindPrinter(const char *name);
extern void cupsdFreePrinterUsers(cupsd_printer_t *p);
extern void cupsdFreeQuotas(cupsd_printer_t *p);
extern void cupsdLoadAllPrinters(void);
-extern void cupsdRenamePrinter(cupsd_printer_t *p, const char *name);
+extern void cupsdRenamePrinter(cupsd_printer_t *p,
+ const char *name);
+extern char *cupsdSanitizeURI(const char *uri, char *buffer,
+ int buflen);
extern void cupsdSaveAllPrinters(void);
+extern int cupsdSetAuthInfoRequired(cupsd_printer_t *p,
+ const char *values,
+ ipp_attribute_t *attr);
extern void cupsdSetPrinterAttrs(cupsd_printer_t *p);
-extern void cupsdSetPrinterReasons(cupsd_printer_t *p, const char *s);
-extern void cupsdSetPrinterState(cupsd_printer_t *p, ipp_pstate_t s, int update);
+extern void cupsdSetPrinterReasons(cupsd_printer_t *p,
+ const char *s);
+extern void cupsdSetPrinterState(cupsd_printer_t *p, ipp_pstate_t s,
+ int update);
#define cupsdStartPrinter(p,u) cupsdSetPrinterState((p), IPP_PRINTER_IDLE, (u))
extern void cupsdStopPrinter(cupsd_printer_t *p, int update);
extern void cupsdUpdatePrinters(void);
-extern cupsd_quota_t *cupsdUpdateQuota(cupsd_printer_t *p, const char *username,
- int pages, int k);
-extern const char *cupsdValidateDest(const char *hostname,
- const char *resource,
+extern cupsd_quota_t *cupsdUpdateQuota(cupsd_printer_t *p,
+ const char *username, int pages,
+ int k);
+extern const char *cupsdValidateDest(const char *uri,
cups_ptype_t *dtype,
cupsd_printer_t **printer);
extern void cupsdWritePrintcap(void);
-extern char *cupsdSanitizeURI(const char *uri, char *buffer,
- int buflen);
-
/*
- * End of "$Id: printers.h 5828 2006-08-15 21:21:45Z mike $".
+ * End of "$Id: printers.h 6318 2007-03-06 04:36:55Z mike $".
*/
diff --git a/scheduler/process.c b/scheduler/process.c
index 5af7e5eef..7462472a6 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -1,9 +1,9 @@
/*
- * "$Id: process.c 5376 2006-04-06 20:32:07Z mike $"
+ * "$Id: process.c 6326 2007-03-11 17:50:18Z mike $"
*
* Process management routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -121,6 +121,7 @@ cupsdStartProcess(
int outfd, /* I - Standard output file descriptor */
int errfd, /* I - Standard error file descriptor */
int backfd, /* I - Backchannel file descriptor */
+ int sidefd, /* I - Sidechannel file descriptor */
int root, /* I - Run as root? */
int *pid) /* O - Process ID */
{
@@ -161,7 +162,7 @@ cupsdStartProcess(
linkpath);
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
- dirname(command), linkpath);
+ dirname((char *)command), linkpath);
}
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
@@ -217,6 +218,12 @@ cupsdStartProcess(
open("/dev/null", O_RDWR);
fcntl(3, F_SETFL, O_NDELAY);
}
+ if (sidefd != 4 && sidefd > 0)
+ {
+ close(4);
+ dup(sidefd);
+ fcntl(4, F_SETFL, O_NDELAY);
+ }
/*
* Change the priority of the process based on the FilterNice setting.
@@ -344,5 +351,5 @@ compare_procs(cupsd_proc_t *a, /* I - First process */
/*
- * End of "$Id: process.c 5376 2006-04-06 20:32:07Z mike $".
+ * End of "$Id: process.c 6326 2007-03-11 17:50:18Z mike $".
*/
diff --git a/scheduler/quotas.c b/scheduler/quotas.c
index 7d3e4e3eb..a51f7f08d 100644
--- a/scheduler/quotas.c
+++ b/scheduler/quotas.c
@@ -1,5 +1,5 @@
/*
- * "$Id: quotas.c 5970 2006-09-19 20:11:08Z mike $"
+ * "$Id: quotas.c 5969 2006-09-19 20:09:24Z mike $"
*
* Quota routines for the Common UNIX Printing System (CUPS).
*
@@ -230,5 +230,5 @@ find_quota(cupsd_printer_t *p, /* I - Printer */
/*
- * End of "$Id: quotas.c 5970 2006-09-19 20:11:08Z mike $".
+ * End of "$Id: quotas.c 5969 2006-09-19 20:09:24Z mike $".
*/
diff --git a/scheduler/select.c b/scheduler/select.c
new file mode 100644
index 000000000..c72adbdc9
--- /dev/null
+++ b/scheduler/select.c
@@ -0,0 +1,946 @@
+/*
+ * "$Id: select.c 6166 2006-12-29 20:35:18Z mike $"
+ *
+ * Select abstraction functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2006 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * cupsdAddSelect() - Add a file descriptor to the list.
+ * cupsdDoSelect() - Do a select-like operation.
+ * cupsdIsSelecting() - Determine whether we are monitoring a file
+ * descriptor.
+ * cupsdRemoveSelect() - Remove a file descriptor from the list.
+ * cupsdStartSelect() - Initialize the file polling engine.
+ * cupsdStopSelect() - Shutdown the file polling engine.
+ * compare_fds() - Compare file descriptors.
+ * find_fd() - Find an existing file descriptor record.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+#ifdef HAVE_EPOLL
+# include <sys/epoll.h>
+#elif defined(HAVE_KQUEUE)
+# include <sys/event.h>
+# include <sys/time.h>
+#elif defined(HAVE_POLL)
+# include <sys/poll.h>
+#elif defined(__hpux)
+# include <sys/time.h>
+#else
+# include <sys/select.h>
+#endif /* HAVE_EPOLL */
+
+
+/*
+ * Design Notes for Poll/Select API in CUPSD
+ * -----------------------------------------
+ *
+ * SUPPORTED APIS
+ *
+ * OS select poll epoll kqueue /dev/poll
+ * -------------- ------ ------ ------ ------ ---------
+ * AIX YES YES NO NO NO
+ * FreeBSD YES YES NO YES NO
+ * HP-UX YES YES NO NO NO
+ * IRIX YES YES NO NO NO
+ * Linux YES YES YES NO NO
+ * MacOS X YES YES NO YES NO
+ * NetBSD YES YES NO YES NO
+ * OpenBSD YES YES NO YES NO
+ * Solaris YES YES NO NO YES
+ * Tru64 YES YES NO NO NO
+ * Windows YES NO NO NO NO
+ *
+ *
+ * HIGH-LEVEL API
+ *
+ * typedef void (*cupsd_selfunc_t)(void *data);
+ *
+ * void cupsdStartSelect(void);
+ * void cupsdStopSelect(void);
+ * void cupsdAddSelect(int fd, cupsd_selfunc_t read_cb,
+ * cupsd_selfunc_t write_cb, void *data);
+ * void cupsdRemoveSelect(int fd);
+ * int cupsdDoSelect(int timeout);
+ *
+ *
+ * IMPLEMENTATION STRATEGY
+ *
+ * 0. Common Stuff
+ * a. CUPS array of file descriptor to callback functions
+ * and data.
+ * b. cupsdStartSelect() creates the array
+ * c. cupsdStopSelect() destroys the array and all elements.
+ * d. cupsdAddSelect() adds to the array and allocates a
+ * new callback element.
+ * e. cupsdRemoveSelect() removes from the array and frees
+ * the callback element.
+ * f. _cupsd_fd_t provides a reference-counted structure for
+ * tracking file descriptors that are monitored.
+ *
+ * 1. select() O(n)
+ * a. Input/Output fd_set variables, copied to working
+ * copies and then used with select().
+ * b. Loop through CUPS array, using FD_ISSET and calling
+ * the read/write callbacks as needed.
+ * c. cupsdRemoveSelect() clears fd_set bit from main and
+ * working sets.
+ * d. cupsdStopSelect() frees all of the memory used by the
+ * CUPS array and fd_set's.
+ *
+ * 2. poll() - O(n log n)
+ * a. Regular array of pollfd, sorted the same as the CUPS
+ * array.
+ * b. Loop through pollfd array, call the corresponding
+ * read/write callbacks as needed.
+ * c. cupsdAddSelect() adds first to CUPS array and flags the
+ * pollfd array as invalid.
+ * d. cupsdDoSelect() rebuilds pollfd array as needed, calls
+ * poll(), then loops through the pollfd array looking up
+ * as needed.
+ * e. cupsdRemoveSelect() flags the pollfd array as invalid.
+ * f. cupsdStopSelect() frees all of the memory used by the
+ * CUPS array and pollfd array.
+ *
+ * 3. epoll() - O(n)
+ * a. cupsdStartSelect() creates epoll file descriptor using
+ * epoll_create() with the maximum fd count, and
+ * allocates an events buffer for the maximum fd count.
+ * b. cupsdAdd/RemoveSelect() uses epoll_ctl() to add
+ * (EPOLL_CTL_ADD) or remove (EPOLL_CTL_DEL) a single
+ * event using the level-triggered semantics. The event
+ * user data field is a pointer to the new callback array
+ * element.
+ * c. cupsdDoSelect() uses epoll_wait() with the global event
+ * buffer allocated in cupsdStartSelect() and then loops
+ * through the events, using the user data field to find
+ * the callback record.
+ * d. cupsdStopSelect() closes the epoll file descriptor and
+ * frees all of the memory used by the event buffer.
+ *
+ * 4. kqueue() - O(n)
+ * b. cupsdStartSelect() creates kqueue file descriptor
+ * using kqyeue() function and allocates a global event
+ * buffer.
+ * c. cupsdAdd/RemoveSelect() uses EV_SET and kevent() to
+ * register the changes. The event user data field is a
+ * pointer to the new callback array element.
+ * d. cupsdDoSelect() uses kevent() to poll for events and
+ * loops through the events, using the user data field to
+ * find the callback record.
+ * e. cupsdStopSelect() closes the kqyeye() file descriptor
+ * and frees all of the memory used by the event buffer.
+ *
+ * 5. /dev/poll - O(n log n) - NOT YET IMPLEMENTED
+ * a. cupsdStartSelect() opens /dev/poll and allocates an
+ * array of pollfd structs; on failure to open /dev/poll,
+ * revert to poll() system call.
+ * b. cupsdAddSelect() writes a single pollfd struct to
+ * /dev/poll with the new file descriptor and the
+ * POLLIN/POLLOUT flags.
+ * c. cupsdRemoveSelect() writes a single pollfd struct to
+ * /dev/poll with the file descriptor and the POLLREMOVE
+ * flag.
+ * d. cupsdDoSelect() uses the DP_POLL ioctl to retrieve
+ * events from /dev/poll and then loops through the
+ * returned pollfd array, looking up the file descriptors
+ * as needed.
+ * e. cupsdStopSelect() closes /dev/poll and frees the
+ * pollfd array.
+ *
+ * PERFORMANCE
+ *
+ * In tests using the "make test" target with option 0 (keep cupsd
+ * running) and the "testspeed" program with "-c 50 -r 1000", epoll()
+ * performed 5.5% slower select(), followed by kqueue() at 16% slower
+ * than select() and poll() at 18% slower than select(). Similar
+ * results were seen with twice the number of client connections.
+ *
+ * The epoll() and kqueue() performance is likely limited by the
+ * number of system calls used to add/modify/remove file
+ * descriptors dynamically. Further optimizations may be possible
+ * in the area of limiting use of cupsdAddSelect() and
+ * cupsdRemoveSelect(), however extreme care will be needed to avoid
+ * excess CPU usage and deadlock conditions.
+ *
+ * We may be able to improve the poll() implementation simply by
+ * keeping the pollfd array sync'd with the _cupsd_fd_t array, as that
+ * will eliminate the rebuilding of the array whenever there is a
+ * change and eliminate the fd array lookups in the inner loop of
+ * cupsdDoSelect().
+ *
+ * Since /dev/poll will never be able to use a shadow array, it may
+ * not make sense to implement support for it. ioctl() overhead will
+ * impact performance as well, so my guess would be that, for CUPS,
+ * /dev/poll will yield a net performance loss.
+ */
+
+/*
+ * Local structures...
+ */
+
+typedef struct _cupsd_fd_s
+{
+ int fd, /* File descriptor */
+ use; /* Use count */
+ cupsd_selfunc_t read_cb, /* Read callback */
+ write_cb; /* Write callback */
+ void *data; /* Data pointer for callbacks */
+} _cupsd_fd_t;
+
+
+/*
+ * Local globals...
+ */
+
+static cups_array_t *cupsd_fds = NULL;
+
+#ifdef HAVE_EPOLL
+static int cupsd_epoll_fd = -1;
+static struct epoll_event *cupsd_epoll_events = NULL;
+#elif defined(HAVE_KQUEUE)
+static int cupsd_kqueue_fd = -1,
+ cupsd_kqueue_changes = 0;
+static struct kevent *cupsd_kqueue_events = NULL;
+#elif defined(HAVE_POLL)
+static int cupsd_alloc_pollfds = 0,
+ cupsd_update_pollfds = 0;
+static struct pollfd *cupsd_pollfds = NULL;
+#else /* select() */
+static fd_set cupsd_global_input,
+ cupsd_global_output,
+ cupsd_current_input,
+ cupsd_current_output;
+#endif /* HAVE_EPOLL */
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_fds(_cupsd_fd_t *a, _cupsd_fd_t *b);
+static _cupsd_fd_t *find_fd(int fd);
+#define release_fd(f) { \
+ (f)->use --; \
+ if (!(f)->use) free((f));\
+ }
+#define retain_fd(f) (f)->use++
+
+
+/*
+ * 'cupsdAddSelect()' - Add a file descriptor to the list.
+ */
+
+int /* O - 1 on success, 0 on error */
+cupsdAddSelect(int fd, /* I - File descriptor */
+ cupsd_selfunc_t read_cb, /* I - Read callback */
+ cupsd_selfunc_t write_cb,/* I - Write callback */
+ void *data) /* I - Data to pass to callback */
+{
+ _cupsd_fd_t *fdptr; /* File descriptor record */
+ int added; /* 1 if added, 0 if modified */
+
+
+ /*
+ * Range check input...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: fd=%d, read_cb=%p, write_cb=%p, data=%p",
+ fd, read_cb, write_cb, data);
+
+ if (fd < 0)
+ return (0);
+
+ /*
+ * See if this FD has already been added...
+ */
+
+ if ((fdptr = find_fd(fd)) == NULL)
+ {
+ /*
+ * No, add a new entry...
+ */
+
+ if ((fdptr = calloc(1, sizeof(_cupsd_fd_t))) == NULL)
+ return (0);
+
+ fdptr->fd = fd;
+ fdptr->use = 1;
+
+ if (!cupsArrayAdd(cupsd_fds, fdptr))
+ {
+ cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to add fd %d to array!", fd);
+ free(fdptr);
+ return (0);
+ }
+
+ added = 1;
+ }
+ else
+ added = 0;
+
+#ifdef HAVE_EPOLL
+ {
+ struct epoll_event event; /* Event data */
+
+
+ event.events = 0;
+
+ if (read_cb)
+ event.events |= EPOLLIN;
+
+ if (write_cb)
+ event.events |= EPOLLOUT;
+
+ event.data.ptr = fdptr;
+
+ epoll_ctl(cupsd_epoll_fd, added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd,
+ &event);
+ }
+
+#elif defined(HAVE_KQUEUE)
+ {
+ struct kevent event; /* Event data */
+ struct timespec timeout; /* Timeout value */
+
+
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 0;
+
+ if (fdptr->read_cb != read_cb)
+ {
+ if (read_cb)
+ EV_SET(&event, fd, EVFILT_READ, EV_ADD, 0, 0, fdptr);
+ else
+ EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, fdptr);
+
+ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: kevent() returned %s",
+ strerror(errno));
+ return (0);
+ }
+ }
+
+ if (fdptr->write_cb != write_cb)
+ {
+ if (write_cb)
+ EV_SET(&event, fd, EVFILT_WRITE, EV_ADD, 0, 0, fdptr);
+ else
+ EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, fdptr);
+
+ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: kevent() returned %s",
+ strerror(errno));
+ return (0);
+ }
+ }
+ }
+
+#elif defined(HAVE_POLL)
+ cupsd_update_pollfds = 1;
+
+#else /* select() */
+ /*
+ * Add or remove the file descriptor in the input and output sets
+ * for select()...
+ */
+
+ if (read_cb)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: Adding fd %d to input set...", fd);
+ FD_SET(fd, &cupsd_global_input);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: Removing fd %d from input set...", fd);
+ FD_CLR(fd, &cupsd_global_input);
+ FD_CLR(fd, &cupsd_current_input);
+ }
+
+ if (write_cb)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: Adding fd %d to output set...", fd);
+ FD_SET(fd, &cupsd_global_output);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddSelect: Removing fd %d from output set...", fd);
+ FD_CLR(fd, &cupsd_global_output);
+ FD_CLR(fd, &cupsd_current_output);
+ }
+#endif /* HAVE_EPOLL */
+
+ /*
+ * Save the (new) read and write callbacks...
+ */
+
+ fdptr->read_cb = read_cb;
+ fdptr->write_cb = write_cb;
+ fdptr->data = data;
+
+ return (1);
+}
+
+
+/*
+ * 'cupsdDoSelect()' - Do a select-like operation.
+ */
+
+int /* O - Number of files or -1 on error */
+cupsdDoSelect(long timeout) /* I - Timeout in seconds */
+{
+ int nfds; /* Number of file descriptors */
+ _cupsd_fd_t *fdptr; /* Current file descriptor */
+#ifdef HAVE_EPOLL
+ int i; /* Looping var */
+ struct epoll_event *event; /* Current event */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdDoSelect: polling %d fds for %ld seconds...",
+ cupsArrayCount(cupsd_fds), timeout);
+
+ if (timeout >= 0 && timeout < 86400)
+ nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
+ timeout * 1000);
+ else
+ nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs, -1);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: epoll() returned %d...",
+ nfds);
+
+ for (i = nfds, event = cupsd_epoll_events; i > 0; i --, event ++)
+ {
+ fdptr = (_cupsd_fd_t *)event->data.ptr;
+
+ retain_fd(fdptr);
+
+ if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...",
+ fdptr->fd);
+ (*(fdptr->read_cb))(fdptr->data);
+ }
+
+ if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...",
+ fdptr->fd);
+ (*(fdptr->write_cb))(fdptr->data);
+ }
+
+ release_fd(fdptr);
+ }
+
+#elif defined(HAVE_KQUEUE)
+ int i; /* Looping var */
+ struct kevent *event; /* Current event */
+ struct timespec ktimeout; /* kevent() timeout */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdDoSelect: polling %d fds for %ld seconds...",
+ cupsArrayCount(cupsd_fds), timeout);
+
+ if (timeout >= 0 && timeout < 86400)
+ {
+ ktimeout.tv_sec = timeout;
+ ktimeout.tv_nsec = 0;
+
+ nfds = kevent(cupsd_kqueue_fd, NULL, 0, cupsd_kqueue_events, MaxFDs,
+ &ktimeout);
+ }
+ else
+ nfds = kevent(cupsd_kqueue_fd, NULL, 0, cupsd_kqueue_events, MaxFDs, NULL);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdDoSelect: kevent(%d, ..., %d, ...) returned %d...",
+ cupsd_kqueue_fd, MaxFDs, nfds);
+
+ cupsd_kqueue_changes = 0;
+
+ for (i = nfds, event = cupsd_kqueue_events; i > 0; i --, event ++)
+ {
+ fdptr = (_cupsd_fd_t *)event->udata;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "event->filter=%d, event->ident=%d",
+ event->filter, (int)event->ident);
+
+ retain_fd(fdptr);
+
+ if (fdptr->read_cb && event->filter == EVFILT_READ)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...",
+ fdptr->fd);
+ (*(fdptr->read_cb))(fdptr->data);
+ }
+
+ if (fdptr->write_cb && event->filter == EVFILT_WRITE)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...",
+ fdptr->fd);
+ (*(fdptr->write_cb))(fdptr->data);
+ }
+
+ release_fd(fdptr);
+ }
+
+#elif defined(HAVE_POLL)
+ struct pollfd *pfd; /* Current pollfd structure */
+ int count; /* Number of file descriptors */
+
+
+ count = cupsArrayCount(cupsd_fds);
+
+ if (cupsd_update_pollfds)
+ {
+ /*
+ * Update the cupsd_pollfds array to match the current FD array...
+ */
+
+ cupsd_update_pollfds = 0;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Updating pollfd array...");
+
+ /*
+ * (Re)allocate memory as needed...
+ */
+
+ if (count > cupsd_alloc_pollfds)
+ {
+ int allocfds = count + 16;
+
+
+ if (cupsd_pollfds)
+ pfd = realloc(cupsd_pollfds, allocfds * sizeof(struct pollfd));
+ else
+ pfd = malloc(allocfds * sizeof(struct pollfd));
+
+ if (!pfd)
+ {
+ cupsdLogMessage(CUPSD_LOG_EMERG,
+ "Unable to allocate %d bytes for polling!",
+ (int)(allocfds * sizeof(struct pollfd)));
+
+ return (-1);
+ }
+
+ cupsd_pollfds = pfd;
+ cupsd_alloc_pollfds = allocfds;
+ }
+
+ /*
+ * Rebuild the array...
+ */
+
+ for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds), pfd = cupsd_pollfds;
+ fdptr;
+ fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds), pfd ++)
+ {
+ pfd->fd = fdptr->fd;
+ pfd->events = 0;
+
+ if (fdptr->read_cb)
+ pfd->events |= POLLIN;
+
+ if (fdptr->write_cb)
+ pfd->events |= POLLOUT;
+ }
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdDoSelect: polling %d fds for %ld seconds...",
+ count, timeout);
+
+ if (timeout >= 0 && timeout < 86400)
+ nfds = poll(cupsd_pollfds, count, timeout * 1000);
+ else
+ nfds = poll(cupsd_pollfds, count, -1);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: poll() returned %d...",
+ nfds);
+
+ if (nfds > 0)
+ {
+ /*
+ * Do callbacks for each file descriptor...
+ */
+
+ for (pfd = cupsd_pollfds; count > 0; pfd ++, count --)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdDoSelect: pollfds[%d]={fd=%d, revents=%x}",
+ pfd - cupsd_pollfds, pfd->fd, pfd->revents);
+
+ if (!pfd->revents)
+ continue;
+
+ if ((fdptr = find_fd(pfd->fd)) == NULL)
+ continue;
+
+ retain_fd(fdptr);
+
+ if (fdptr->read_cb && (pfd->revents & (POLLIN | POLLERR | POLLHUP)))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...",
+ fdptr->fd);
+ (*(fdptr->read_cb))(fdptr->data);
+ }
+
+ if (fdptr->write_cb && (pfd->revents & (POLLOUT | POLLERR | POLLHUP)))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...",
+ fdptr->fd);
+ (*(fdptr->write_cb))(fdptr->data);
+ }
+
+ release_fd(fdptr);
+ }
+ }
+
+#else /* select() */
+ struct timeval stimeout; /* Timeout for select() */
+ int maxfd; /* Maximum file descriptor */
+
+
+ /*
+ * Figure out the highest file descriptor number...
+ */
+
+ if ((fdptr = (_cupsd_fd_t *)cupsArrayLast(cupsd_fds)) == NULL)
+ maxfd = 1;
+ else
+ maxfd = fdptr->fd + 1;
+
+ /*
+ * Do the select()...
+ */
+
+ cupsd_current_input = cupsd_global_input;
+ cupsd_current_output = cupsd_global_output;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdDoSelect: selecting %d fds for %ld seconds...",
+ maxfd, timeout);
+
+ if (timeout >= 0 && timeout < 86400)
+ {
+ stimeout.tv_sec = timeout;
+ stimeout.tv_usec = 0;
+
+ nfds = select(maxfd, &cupsd_current_input, &cupsd_current_output, NULL,
+ &stimeout);
+ }
+ else
+ nfds = select(maxfd, &cupsd_current_input, &cupsd_current_output, NULL,
+ NULL);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: select() returned %d...",
+ nfds);
+
+ if (nfds > 0)
+ {
+ /*
+ * Do callbacks for each file descriptor...
+ */
+
+ for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds);
+ fdptr;
+ fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds))
+ {
+ retain_fd(fdptr);
+
+ if (fdptr->read_cb && FD_ISSET(fdptr->fd, &cupsd_current_input))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Read on fd %d...",
+ fdptr->fd);
+ (*(fdptr->read_cb))(fdptr->data);
+ }
+
+ if (fdptr->write_cb && FD_ISSET(fdptr->fd, &cupsd_current_output))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...",
+ fdptr->fd);
+ (*(fdptr->write_cb))(fdptr->data);
+ }
+
+ release_fd(fdptr);
+ }
+ }
+
+#endif /* HAVE_EPOLL */
+
+ /*
+ * Return the number of file descriptors handled...
+ */
+
+ return (nfds);
+}
+
+
+/*
+ * 'cupsdIsSelecting()' - Determine whether we are monitoring a file
+ * descriptor.
+ */
+
+int /* O - 1 if selecting, 0 otherwise */
+cupsdIsSelecting(int fd) /* I - File descriptor */
+{
+ return (find_fd(fd) != NULL);
+}
+
+
+/*
+ * 'cupsdRemoveSelect()' - Remove a file descriptor from the list.
+ */
+
+void
+cupsdRemoveSelect(int fd) /* I - File descriptor */
+{
+ _cupsd_fd_t *fdptr; /* File descriptor record */
+#ifdef HAVE_EPOLL
+ struct epoll_event event; /* Event data */
+#elif defined(HAVE_KQUEUE)
+ struct kevent event; /* Event data */
+ struct timespec timeout; /* Timeout value */
+#elif defined(HAVE_POLL)
+ /* No variables for poll() */
+#endif /* HAVE_EPOLL */
+
+
+ /*
+ * Range check input...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdRemoveSelect: fd=%d", fd);
+
+ if (fd < 0)
+ return;
+
+ /*
+ * Find the file descriptor...
+ */
+
+ if ((fdptr = find_fd(fd)) == NULL)
+ return;
+
+#ifdef HAVE_EPOLL
+ epoll_ctl(cupsd_epoll_fd, EPOLL_CTL_DEL, fd, &event);
+
+#elif defined(HAVE_KQUEUE)
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 0;
+
+ if (fdptr->read_cb)
+ {
+ EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, fdptr);
+
+ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdRemoveSelect: kevent() returned %s",
+ strerror(errno));
+ return;
+ }
+ }
+
+ if (fdptr->write_cb)
+ {
+ EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, fdptr);
+
+ if (kevent(cupsd_kqueue_fd, &event, 1, NULL, 0, &timeout))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdRemoveSelect: kevent() returned %s",
+ strerror(errno));
+ return;
+ }
+ }
+
+
+#elif defined(HAVE_POLL)
+ /*
+ * Update the pollfds array...
+ */
+
+ cupsd_update_pollfds = 1;
+
+#else /* select() */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdRemoveSelect: Removing fd %d from input and output "
+ "sets...", fd);
+ FD_CLR(fd, &cupsd_global_input);
+ FD_CLR(fd, &cupsd_global_output);
+ FD_CLR(fd, &cupsd_current_input);
+ FD_CLR(fd, &cupsd_current_output);
+#endif /* HAVE_EPOLL */
+
+ /*
+ * Remove the file descriptor for from the FD array...
+ */
+
+ cupsArrayRemove(cupsd_fds, fdptr);
+ release_fd(fdptr);
+}
+
+
+/*
+ * 'cupsdStartSelect()' - Initialize the file polling engine.
+ */
+
+void
+cupsdStartSelect(void)
+{
+ cupsd_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL);
+
+#ifdef HAVE_EPOLL
+ cupsd_epoll_fd = epoll_create(MaxFDs);
+ cupsd_epoll_events = calloc(MaxFDs, sizeof(struct epoll_event));
+
+#elif defined(HAVE_KQUEUE)
+ cupsd_kqueue_fd = kqueue();
+ cupsd_kqueue_changes = 0;
+ cupsd_kqueue_events = calloc(MaxFDs, sizeof(struct kevent));
+
+#elif defined(HAVE_POLL)
+ cupsd_update_pollfds = 0;
+
+#else /* select() */
+ FD_ZERO(&cupsd_global_input);
+ FD_ZERO(&cupsd_global_output);
+#endif /* HAVE_EPOLL */
+}
+
+
+/*
+ * 'cupsdStopSelect()' - Shutdown the file polling engine.
+ */
+
+void
+cupsdStopSelect(void)
+{
+ _cupsd_fd_t *fdptr; /* Current file descriptor */
+
+
+ for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds);
+ fdptr;
+ fdptr = (_cupsd_fd_t *)cupsArrayNext(cupsd_fds))
+ free(fdptr);
+
+ cupsArrayDelete(cupsd_fds);
+ cupsd_fds = NULL;
+
+#ifdef HAVE_EPOLL
+ if (cupsd_epoll_events)
+ {
+ free(cupsd_epoll_events);
+ cupsd_epoll_events = NULL;
+ }
+
+ if (cupsd_epoll_fd >= 0)
+ {
+ close(cupsd_epoll_fd);
+ cupsd_epoll_fd = -1;
+ }
+
+#elif defined(HAVE_KQUEUE)
+ if (cupsd_kqueue_events)
+ {
+ free(cupsd_kqueue_events);
+ cupsd_kqueue_events = NULL;
+ }
+
+ if (cupsd_kqueue_fd >= 0)
+ {
+ close(cupsd_kqueue_fd);
+ cupsd_kqueue_fd = -1;
+ }
+
+ cupsd_kqueue_changes = 0;
+
+#elif defined(HAVE_POLL)
+ if (cupsd_pollfds)
+ {
+ free(cupsd_pollfds);
+ cupsd_pollfds = NULL;
+ cupsd_alloc_pollfds = 0;
+ }
+
+ cupsd_update_pollfds = 0;
+
+#else /* select() */
+ FD_ZERO(&cupsd_global_input);
+ FD_ZERO(&cupsd_global_output);
+#endif /* HAVE_EPOLL */
+}
+
+
+/*
+ * 'compare_fds()' - Compare file descriptors.
+ */
+
+static int /* O - Result of comparison */
+compare_fds(_cupsd_fd_t *a, /* I - First file descriptor */
+ _cupsd_fd_t *b) /* I - Second file descriptor */
+{
+ return (a->fd - b->fd);
+}
+
+
+/*
+ * 'find_fd()' - Find an existing file descriptor record.
+ */
+
+static _cupsd_fd_t * /* O - FD record pointer or NULL */
+find_fd(int fd) /* I - File descriptor */
+{
+ _cupsd_fd_t *fdptr, /* Matching record (if any) */
+ key; /* Search key */
+
+
+ cupsArraySave(cupsd_fds);
+
+ key.fd = fd;
+ fdptr = (_cupsd_fd_t *)cupsArrayFind(cupsd_fds, &key);
+
+ cupsArrayRestore(cupsd_fds);
+
+ return (fdptr);
+}
+
+
+/*
+ * End of "$Id: select.c 6166 2006-12-29 20:35:18Z mike $".
+ */
diff --git a/scheduler/server.c b/scheduler/server.c
index bcc3c71e6..7efbbcd71 100644
--- a/scheduler/server.c
+++ b/scheduler/server.c
@@ -1,5 +1,5 @@
/*
- * "$Id: server.c 5493 2006-05-05 16:33:57Z mike $"
+ * "$Id: server.c 6123 2006-11-21 15:36:04Z mike $"
*
* Server start/stop routines for the Common UNIX Printing System (CUPS).
*
@@ -107,10 +107,7 @@ cupsdStartServer(void)
{
CGIStatusBuffer = cupsdStatBufNew(CGIPipes[0], "[CGI]");
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStartServer: Adding fd %d to InputSet...",
- CGIPipes[0]);
- FD_SET(CGIPipes[0], InputSet);
+ cupsdAddSelect(CGIPipes[0], (cupsd_selfunc_t)cupsdUpdateCGI, NULL, NULL);
}
/*
@@ -158,11 +155,7 @@ cupsdStopServer(void)
if (CGIPipes[0] >= 0)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopServer: Removing fd %d from InputSet...",
- CGIPipes[0]);
-
- FD_CLR(CGIPipes[0], InputSet);
+ cupsdRemoveSelect(CGIPipes[0]);
cupsdStatBufDelete(CGIStatusBuffer);
close(CGIPipes[1]);
@@ -211,5 +204,5 @@ cupsdStopServer(void)
/*
- * End of "$Id: server.c 5493 2006-05-05 16:33:57Z mike $".
+ * End of "$Id: server.c 6123 2006-11-21 15:36:04Z mike $".
*/
diff --git a/scheduler/statbuf.c b/scheduler/statbuf.c
index b10f63ebc..0450fa14a 100644
--- a/scheduler/statbuf.c
+++ b/scheduler/statbuf.c
@@ -1,5 +1,5 @@
/*
- * "$Id: statbuf.c 5889 2006-08-24 21:44:35Z mike $"
+ * "$Id: statbuf.c 5888 2006-08-24 21:42:47Z mike $"
*
* Status buffer routines for the Common UNIX Printing System (CUPS)
* scheduler.
@@ -330,5 +330,5 @@ cupsdStatBufUpdate(cupsd_statbuf_t *sb, /* I - Status buffer */
/*
- * End of "$Id: statbuf.c 5889 2006-08-24 21:44:35Z mike $".
+ * End of "$Id: statbuf.c 5888 2006-08-24 21:42:47Z mike $".
*/
diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c
index d0e05d9be..c077bcdeb 100644
--- a/scheduler/subscriptions.c
+++ b/scheduler/subscriptions.c
@@ -1,9 +1,9 @@
/*
- * "$Id: subscriptions.c 5991 2006-09-29 02:26:29Z mike $"
+ * "$Id: subscriptions.c 6176 2007-01-03 15:28:30Z mike $"
*
* Subscription routines for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
@@ -52,8 +52,8 @@
# include <dbus/dbus.h>
# ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
# define dbus_message_append_iter_init dbus_message_iter_init_append
-# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, v)
-# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, v)
+# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &(v))
+# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &(v))
# endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
#endif /* HAVE_DBUS */
@@ -1226,10 +1226,7 @@ cupsdStopAllNotifiers(void)
if (NotifierPipes[0] >= 0)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopAllNotifiers: Removing fd %d from InputSet...",
- NotifierPipes[0]);
- FD_CLR(NotifierPipes[0], InputSet);
+ cupsdRemoveSelect(NotifierPipes[0]);
cupsdStatBufDelete(NotifierStatusBuffer);
@@ -1362,11 +1359,11 @@ cupsd_send_dbus(cupsd_eventmask_t event,/* I - Event to send */
dbus_message_append_iter_init(message, &iter);
if (dest)
- dbus_message_iter_append_string(&iter, &(dest->name));
+ dbus_message_iter_append_string(&iter, dest->name);
if (job)
{
- dbus_message_iter_append_uint32(&iter, &(job->id));
- dbus_message_iter_append_string(&iter, &(job->username));
+ dbus_message_iter_append_uint32(&iter, job->id);
+ dbus_message_iter_append_string(&iter, job->username);
}
dbus_connection_send(con, message, NULL);
@@ -1571,11 +1568,8 @@ cupsd_start_notifier(
NotifierStatusBuffer = cupsdStatBufNew(NotifierPipes[0], "[Notifier]");
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_notifier: Adding fd %d to InputSet...",
- NotifierPipes[0]);
-
- FD_SET(NotifierPipes[0], InputSet);
+ cupsdAddSelect(NotifierPipes[0], (cupsd_selfunc_t)cupsdUpdateNotifierStatus,
+ NULL, NULL);
}
if (cupsdOpenPipe(fds))
@@ -1597,7 +1591,7 @@ cupsd_start_notifier(
*/
if (cupsdStartProcess(command, argv, envp, fds[0], -1, NotifierPipes[1],
- -1, 0, &pid) < 0)
+ -1, -1, 0, &pid) < 0)
{
/*
* Error - can't fork!
@@ -1627,5 +1621,5 @@ cupsd_start_notifier(
/*
- * End of "$Id: subscriptions.c 5991 2006-09-29 02:26:29Z mike $".
+ * End of "$Id: subscriptions.c 6176 2007-01-03 15:28:30Z mike $".
*/
diff --git a/scheduler/subscriptions.h b/scheduler/subscriptions.h
index 9671d937f..6cdd3a063 100644
--- a/scheduler/subscriptions.h
+++ b/scheduler/subscriptions.h
@@ -1,5 +1,5 @@
/*
- * "$Id: subscriptions.h 5673 2006-06-16 21:04:45Z mike $"
+ * "$Id: subscriptions.h 5672 2006-06-16 21:04:07Z mike $"
*
* Subscription definitions for the Common UNIX Printing System (CUPS) scheduler.
*
@@ -168,5 +168,5 @@ extern void cupsdUpdateNotifierStatus(void);
/*
- * End of "$Id: subscriptions.h 5673 2006-06-16 21:04:45Z mike $".
+ * End of "$Id: subscriptions.h 5672 2006-06-16 21:04:07Z mike $".
*/
diff --git a/scheduler/sysman.c b/scheduler/sysman.c
index 61f342dcb..6267b665b 100644
--- a/scheduler/sysman.c
+++ b/scheduler/sysman.c
@@ -1,5 +1,5 @@
/*
- * "$Id: sysman.c 6090 2006-11-14 16:35:27Z mike $"
+ * "$Id: sysman.c 6291 2007-02-19 21:54:27Z mike $"
*
* System management definitions for the Common UNIX Printing System (CUPS).
*
@@ -160,10 +160,8 @@ cupsdStartSystemMonitor(void)
return;
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStartSystemMonitor: Adding fd %d to InputSet...",
- SysEventPipes[0]);
- FD_SET(SysEventPipes[0], InputSet);
+ cupsdAddSelect(SysEventPipes[0], (cupsd_selfunc_t)cupsdUpdateSystemMonitor,
+ NULL, NULL);
/*
* Set non-blocking mode on the descriptor we will be receiving notification
@@ -220,12 +218,7 @@ cupsdStopSystemMonitor(void)
if (SysEventPipes[0] >= 0)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopSystemMonitor: Removing fd %d from InputSet...",
- SysEventPipes[0]);
-
- FD_CLR(SysEventPipes[0], InputSet);
-
+ cupsdRemoveSelect(SysEventPipes[0]);
cupsdClosePipe(SysEventPipes);
}
}
@@ -314,7 +307,7 @@ cupsdUpdateSystemMonitor(void)
{
cupsdLogMessage(CUPSD_LOG_DEBUG,
"Deregistering local printer \"%s\"", p->name);
- cupsdSendBrowseDelete(p);
+ cupsdDeregisterPrinter(p, 0);
}
}
@@ -370,18 +363,19 @@ cupsdUpdateSystemMonitor(void)
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
- cupsdSendBrowseDelete(p);
+ cupsdDeregisterPrinter(p, 1);
/*
* Now re-register them...
- *
- * TODO: This might need updating for MDNS.
*/
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ {
p->browse_time = 0;
+ cupsdRegisterPrinter(p);
+ }
}
else
cupsdLogMessage(CUPSD_LOG_DEBUG,
@@ -757,5 +751,5 @@ sysEventTimerNotifier(
/*
- * End of "$Id: sysman.c 6090 2006-11-14 16:35:27Z mike $".
+ * End of "$Id: sysman.c 6291 2007-02-19 21:54:27Z mike $".
*/
diff --git a/scheduler/testlpd.c b/scheduler/testlpd.c
index a49950391..65b827c25 100644
--- a/scheduler/testlpd.c
+++ b/scheduler/testlpd.c
@@ -1,5 +1,5 @@
/*
- * "$Id: testlpd.c 5868 2006-08-23 19:39:39Z mike $"
+ * "$Id: testlpd.c 6331 2007-03-12 16:07:31Z mike $"
*
* cups-lpd test program for the Common UNIX Printing System (CUPS).
*
@@ -184,6 +184,11 @@ main(int argc, /* I - Number of command-line arguments */
status = status_long(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
else if (!strcmp(op, "status-short"))
status = status_short(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
+ else
+ {
+ printf("Unknown operation \"%s\"!\n", op);
+ status = 1;
+ }
/*
* Kill the test program...
@@ -296,8 +301,8 @@ print_job(int outfd, /* I - Command file descriptor */
"Hlocalhost\n"
"P%s\n"
"J%s\n"
- "ldfA%03.3dlocalhost\n"
- "UdfA%03.3dlocalhost\n"
+ "ldfA%03dlocalhost\n"
+ "UdfA%03dlocalhost\n"
"N%s\n",
cupsUser(), jobname, sequence, sequence, jobname);
@@ -307,7 +312,7 @@ print_job(int outfd, /* I - Command file descriptor */
bytes = strlen(control);
- snprintf(command, sizeof(command), "\002%d cfA%03.3dlocalhost\n",
+ snprintf(command, sizeof(command), "\002%d cfA%03dlocalhost\n",
bytes, sequence);
if ((status = do_command(outfd, infd, command)) != 0)
@@ -344,7 +349,7 @@ print_job(int outfd, /* I - Command file descriptor */
* Send the data file...
*/
- snprintf(command, sizeof(command), "\003%d dfA%03.3dlocalhost\n",
+ snprintf(command, sizeof(command), "\003%d dfA%03dlocalhost\n",
(int)fileinfo.st_size, sequence);
if ((status = do_command(outfd, infd, command)) != 0)
@@ -546,5 +551,5 @@ usage(void)
/*
- * End of "$Id: testlpd.c 5868 2006-08-23 19:39:39Z mike $".
+ * End of "$Id: testlpd.c 6331 2007-03-12 16:07:31Z mike $".
*/
diff --git a/scheduler/testmime.c b/scheduler/testmime.c
index 460e1d587..6246b64b6 100644
--- a/scheduler/testmime.c
+++ b/scheduler/testmime.c
@@ -1,5 +1,5 @@
/*
- * "$Id: testmime.c 5606 2006-05-30 19:40:34Z mike $"
+ * "$Id: testmime.c 5605 2006-05-30 19:38:02Z mike $"
*
* MIME test program for the Common UNIX Printing System (CUPS).
*
@@ -331,5 +331,5 @@ type_dir(mime_t *mime, /* I - MIME database */
/*
- * End of "$Id: testmime.c 5606 2006-05-30 19:40:34Z mike $".
+ * End of "$Id: testmime.c 5605 2006-05-30 19:38:02Z mike $".
*/
diff --git a/scheduler/testsub.c b/scheduler/testsub.c
index 62156bd17..4c70e7839 100644
--- a/scheduler/testsub.c
+++ b/scheduler/testsub.c
@@ -1,5 +1,5 @@
/*
- * "$Id: testsub.c 5940 2006-09-11 18:30:09Z mike $"
+ * "$Id: testsub.c 5938 2006-09-11 18:23:46Z mike $"
*
* Scheduler notification tester for the Common UNIX Printing System (CUPS).
*
@@ -527,5 +527,5 @@ usage(void)
/*
- * End of "$Id: testsub.c 5940 2006-09-11 18:30:09Z mike $".
+ * End of "$Id: testsub.c 5938 2006-09-11 18:23:46Z mike $".
*/