-dnl $Id: configure.in,v 1.179.2.3.2.28 2004-05-18 23:42:30 bfernhomberg Exp $
+dnl $Id: configure.in,v 1.179.2.3.2.29 2004-06-09 01:25:52 bfernhomberg Exp $
dnl configure.in for netatalk
AC_INIT(etc/afpd/main.c)
]
)
+NETATALK_AC_CUPS
+
dnl --------------------------------------------------------------------------
dnl FHS stuff has to be done last because it overrides other defaults
dnl --------------------------------------------------------------------------
Makefile
Makefile.in
papd
+showppd
.deps
.libs
# Makefile.am for etc/papd/
pkgconfdir = @PKGCONFDIR@
+spooldir = @SPOOLDIR@
sbin_PROGRAMS = papd
-#bin_PROGRAMS = showppd
+bin_PROGRAMS = showppd
papd_SOURCES = main.c printcap.c session.c file.c comment.c lp.c ppd.c \
- magics.c headers.c queries.c auth.c uam.c
-papd_LDADD = $(top_builddir)/libatalk/libatalk.la
-papd_LDFLAGS = -export-dynamic
+ magics.c headers.c queries.c auth.c uam.c print_cups.c
-#showppd_SOURCES = showppd.c ppd.c
-#showppd_LDADD = $(top_builddir)/libatalk/libatalk.la
+papd_LDADD = $(top_builddir)/libatalk/libatalk.la @PAM_LIBS@ @CUPS_LIBS@
+papd_LDFLAGS = -export-dynamic @CUPS_LDFLAGS@
+
+showppd_SOURCES = showppd.c ppd.c
+showppd_CFLAGS = @CFLAGS@ -DSHOWPPD
+showppd_LDADD = $(top_builddir)/libatalk/libatalk.la
noinst_HEADERS = \
comment.h \
printcap.h \
printer.h \
session.h \
+ print_cups.h \
uam_auth.h
CFLAGS = \
-I$(top_srcdir)/include -I$(top_srcdir)/sys \
@CFLAGS@ \
-D_PATH_PAPDCONF=\"$(pkgconfdir)/papd.conf\" \
- -D_PATH_PAPDUAMPATH=\"$(UAMS_PATH)/\"
+ -D_PATH_PAPDUAMPATH=\"$(UAMS_PATH)/\" \
+ -DSPOOLDIR=\"$(spooldir)/\"
-#LIBS = @PAM_LIBS@
+if USE_SPOOLDIR
+install-exec-hook:
+ echo "Creating SPOOLDIR $(spooldir)..."
+ $(mkinstalldirs) $(spooldir)
+ chmod 0777 $(spooldir)
+endif
/*
- * $Id: file.h,v 1.6 2001-06-25 20:13:45 rufustfirefly Exp $
+ * $Id: file.h,v 1.6.14.1 2004-06-09 01:25:53 bfernhomberg Exp $
*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
int pf_datalen;
char *pf_buf;
char *pf_data;
+ int origin;
};
#define PF_BOT (1<<0)
#define PF_EOF (1<<1)
#define PF_QUERY (1<<2)
+#define PF_STW (1<<3)
+#define PF_TRANSLATE (1<<4)
#define CONSUME( pf, len ) { (pf)->pf_data += (len); \
(pf)->pf_datalen -= (len); \
/*
- * $Id: headers.c,v 1.9 2002-01-04 04:45:47 sibaz Exp $
+ * $Id: headers.c,v 1.9.10.1 2004-06-09 01:25:53 bfernhomberg Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "config.h"
#endif /* HAVE_CONFIG_H */
-#include <atalk/logger.h>
#include <sys/param.h>
+#include <string.h>
#include <stdio.h>
#include <netatalk/at.h>
+#include <atalk/logger.h>
#include "file.h"
#include "comment.h"
#include "lp.h"
int ch_title( struct papfile *, struct papfile * );
+int ch_for( struct papfile *, struct papfile * );
+
+
+int ch_for( in, out )
+ struct papfile *in, *out;
+{
+ char *start, *stop, *p, *q, c;
+ int linelength, crlflength;
+
+ switch ( markline( in, &start, &linelength, &crlflength )) {
+ case 0 :
+ return( 0 );
+
+ case -1 :
+ return( CH_MORE );
+ }
+
+ stop = start + linelength;
+ for ( p = start; p < stop; p++ ) {
+ if ( *p == ':' ) {
+ break;
+ }
+ }
+
+ for ( ; p < stop; p++ ) {
+ if ( *p == '(' ) {
+ break;
+ }
+ }
+
+ for ( q = p; q < stop; q++ ) {
+ if ( *q == ')' ) {
+ break;
+ }
+ }
+
+ if ( q < stop && p < stop ) {
+ p++;
+ c = *q;
+ *q = '\0';
+ lp_for ( p );
+ *q = c;
+ }
+
+ in->pf_state |= PF_TRANSLATE;
+ lp_write( in, start, linelength + crlflength );
+ in->pf_state &= ~PF_TRANSLATE;
+ compop();
+ CONSUME( in, linelength + crlflength );
+ return( CH_DONE );
+}
int ch_title( in, out )
struct papfile *in, *out;
return( CH_MORE );
}
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "Parsing %%Title");
+#endif
+
stop = start + linelength;
for ( p = start; p < stop; p++ ) {
if ( *p == ':' ) {
*q = c;
}
- lp_write( start, linelength + crlflength );
+ in->pf_state |= PF_TRANSLATE;
+ lp_write( in, start, linelength + crlflength );
+ in->pf_state &= ~PF_TRANSLATE;
compop();
CONSUME( in, linelength + crlflength );
return( CH_DONE );
}
+static int guess_creator ( char *creator )
+{
+ if (strstr(creator, "LaserWriter"))
+ return 1;
+ if (strstr(creator, "cgpdftops"))
+ return 2;
+
+ return 0;
+}
+
+
+int ch_creator( in, out )
+ struct papfile *in, *out;
+{
+ char *start, *stop, *p, *q, c;
+ int linelength, crlflength;
+
+ switch ( markline( in, &start, &linelength, &crlflength )) {
+ case 0 :
+ return( 0 );
+
+ case -1 :
+ return( CH_MORE );
+ }
+
+ stop = start + linelength;
+ for ( p = start; p < stop; p++ ) {
+ if ( *p == ':' ) {
+ break;
+ }
+ }
+
+ for ( ; p < stop; p++ ) {
+ if ( *p == '(' ) {
+ break;
+ }
+ }
+
+ for ( q = p; q < stop; q++ ) {
+ if ( *q == ')' ) {
+ break;
+ }
+ }
+
+ if ( q < stop && p < stop ) {
+ p++;
+ c = *q;
+ *q = '\0';
+ in->origin = guess_creator ( p );
+ lp_origin(in->origin);
+ *q = c;
+ }
+
+ in->pf_state |= PF_TRANSLATE;
+ lp_write( in, start, linelength + crlflength );
+ in->pf_state &= ~PF_TRANSLATE;
+ compop();
+ CONSUME( in, linelength + crlflength );
+ return( CH_DONE );
+}
+
+int ch_endcomm( in, out )
+ struct papfile *in, *out;
+{
+ char *start;
+ int linelength, crlflength;
+
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "End Comment");
+#endif
+ in->pf_state |= PF_STW;
+
+ switch ( markline( in, &start, &linelength, &crlflength )) {
+ case 0 :
+ return( 0 );
+
+ case -1 :
+ return( CH_MORE );
+ }
+
+ in->pf_state |= PF_TRANSLATE;
+ lp_write( in, start, linelength + crlflength );
+ in->pf_state &= ~PF_TRANSLATE;
+ compop();
+ CONSUME( in, linelength + crlflength );
+ return ( CH_DONE);
+}
+
+int ch_starttranslate(in,out)
+ struct papfile *in, *out;
+{
+ char *start;
+ int linelength, crlflength;
+
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "Start translate");
+#endif
+
+ switch ( markline( in, &start, &linelength, &crlflength )) {
+ case 0 :
+ return( 0 );
+
+ case -1 :
+ return( CH_MORE );
+ }
+
+ in->pf_state |= PF_TRANSLATE;
+ lp_write( in, start, linelength + crlflength );
+ compop();
+ CONSUME( in, linelength + crlflength );
+ return ( CH_DONE);
+}
+
+int ch_endtranslate(in,out)
+ struct papfile *in, *out;
+{
+ char *start;
+ int linelength, crlflength;
+
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "EndTranslate");
+#endif
+
+ switch ( markline( in, &start, &linelength, &crlflength )) {
+ case 0 :
+ return( 0 );
+
+ case -1 :
+ return( CH_MORE );
+ }
+
+ lp_write( in, start, linelength + crlflength );
+ in->pf_state &= ~PF_TRANSLATE;
+ compop();
+ CONSUME( in, linelength + crlflength );
+ return ( CH_DONE);
+}
+
+int ch_translateone(in,out)
+ struct papfile *in, *out;
+{
+ char *start;
+ int linelength, crlflength;
+
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "TranslateOne");
+#endif
+
+ switch ( markline( in, &start, &linelength, &crlflength )) {
+ case 0 :
+ return( 0 );
+
+ case -1 :
+ return( CH_MORE );
+ }
+
+ in->pf_state |= PF_TRANSLATE;
+ lp_write( in, start, linelength + crlflength );
+ in->pf_state &= ~PF_TRANSLATE;
+ compop();
+ CONSUME( in, linelength + crlflength );
+ return ( CH_DONE);
+}
+
+
+
+
/*
* "Header" comments.
*/
struct papd_comment headers[] = {
{ "%%Title:", 0, ch_title, 0 },
+ { "%%For:", 0, ch_for, 0 },
+ { "%%Creator:", 0, ch_creator, 0 },
+ { "%%EndComments", 0, ch_endcomm, 0 },
+ { "%%BeginFeature", 0, ch_starttranslate, 0 },
+ { "%%EndFeature", 0, ch_endtranslate, 0 },
+ { "%%BeginPageSetup", 0, ch_starttranslate, 0 },
+ { "%%EndPageSetup", 0, ch_endtranslate, 0 },
+#if 0
+ { "%%BeginSetup", 0, ch_translateone, 0 },
+ { "%%EndSetup", 0, ch_translateone, 0 },
+ { "%%BeginProlog", 0, ch_translateone, 0 },
+ { "%%EndProlog", 0, ch_translateone, 0 },
+ { "%%Page:", 0, ch_translateone, 0 },
+ { "%%PageTrailer", 0, ch_translateone, 0 },
+ { "%%Trailer", 0, ch_translateone, 0 },
+ { "%%EOF", 0, ch_translateone, 0 },
+#endif
+ { "%%", 0, ch_translateone, 0 },
{ 0 },
};
/*
- * $Id: lp.c,v 1.14.8.2 2004-05-12 21:21:49 didg Exp $
+ * $Id: lp.c,v 1.14.8.3 2004-06-09 01:25:53 bfernhomberg Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#endif /* HAVE_CONFIG_H */
#include <sys/param.h>
-#include <atalk/logger.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#undef s_net
-#include <netatalk/at.h>
-#include <atalk/atp.h>
-#include <atalk/paths.h>
#ifdef ABS_PRINT
#include <math.h>
#endif /* ABS_PRINT */
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif /* HAVE_FCNTL_H */
#include <pwd.h>
+#include <atalk/logger.h>
+#include <netatalk/at.h>
+#include <atalk/atp.h>
+#include <atalk/paths.h>
+#include <atalk/unicode.h>
+
#include "printer.h"
#include "file.h"
#include "lp.h"
+#ifdef HAVE_CUPS
+#include "print_cups.h"
+#endif
+
+
/* These functions aren't used outside of lp.c */
int lp_conn_inet();
int lp_disconn_inet( int );
int lp_flags;
FILE *lp_stream;
int lp_seq;
+ int lp_origin;
char lp_letter;
char *lp_person;
+ char *lp_created_for; /* Holds the content of the Postscript %%For Comment if available */
char *lp_host;
char *lp_job;
+ char *lp_spoolfile;
} lp;
#define LP_INIT (1<<0)
#define LP_OPEN (1<<1)
#define LP_PIPE (1<<2)
#define LP_CONNECT (1<<3)
#define LP_QUEUE (1<<4)
+#define LP_JOBPENDING (1<<5)
+
+void lp_origin (int origin)
+{
+ lp.lp_origin = origin;
+}
+
+/* the converted string should always be shorter, but ... FIXME! */
+static void convert_octal (char *string, charset_t dest)
+{
+ unsigned char *p, *q;
+ char temp[4];
+ long int ch;
+
+ q=p=string;
+ while ( *p != '\0' ) {
+ ch = 0;
+ if ( *p == '\\' ) {
+ p++;
+ if (dest && isdigit(*p) && isdigit(*(p+1)) && isdigit(*(p+2)) ) {
+ temp[0] = *p;
+ temp[1] = *(p+1);
+ temp[2] = *(p+2);
+ temp[3] = 0;
+ ch = strtol( temp, NULL, 8);
+ if ( ch && ch < 0xff)
+ *q = ch;
+ else
+ *q = '.';
+ p += 2;
+ }
+ else
+ *q = '.';
+ }
+ else {
+ *q = *p;
+ }
+ p++;
+ q++;
+ }
+ *q = 0;
+}
+
+
+static void translate(charset_t from, charset_t dest, char **option)
+{
+ char *translated;
+
+ if (*option != NULL) {
+ convert_octal(*option, from);
+ if (from) {
+ if ((size_t) -1 != (convert_string_allocate(from, dest, *option, strlen(*option), &translated)) ) {
+ free (*option);
+ *option = translated;
+ }
+ }
+ }
+}
+
+
+static void lp_setup_comments (charset_t dest)
+{
+ charset_t from=0;
+
+ switch (lp.lp_origin) {
+ case 1:
+ from=CH_MAC;
+ break;
+ case 2:
+ from=CH_UTF8_MAC;
+ break;
+ }
+
+ if (lp.lp_job) {
+#ifdef DEBUG1
+ LOG(log_debug, logtype_papd, "job: %s", lp.lp_job );
+#endif
+ translate(from, dest, &lp.lp_job);
+ }
+ if (lp.lp_created_for) {
+#ifdef DEBUG1
+ LOG(log_debug, logtype_papd, "for: %s", lp.lp_created_for );
+#endif
+ translate(from, dest, &lp.lp_created_for);
+ }
+ if (lp.lp_person) {
+#ifdef DEBUG1
+ LOG(log_debug, logtype_papd, "person: %s", lp.lp_person );
+#endif
+ translate(from, dest, &lp.lp_person);
+ }
+}
+
+#define is_var(a, b) (strncmp((a), (b), 2) == 0)
+
+static char* pipexlate(char *src)
+{
+ char *p, *q, *dest;
+ static char destbuf[MAXPATHLEN];
+ size_t destlen = MAXPATHLEN;
+ int len = 0;
+
+ dest = destbuf;
+
+ if (!src)
+ return NULL;
+
+ strncpy(dest, src, MAXPATHLEN);
+ if ((p = strchr(src, '%')) == NULL) /* nothing to do */
+ return destbuf;
+
+ /* first part of the path. just forward to the next variable. */
+ len = MIN((size_t)(p - src), destlen);
+ if (len > 0) {
+ destlen -= len;
+ dest += len;
+ }
+
+ while (p && destlen > 0) {
+ /* now figure out what the variable is */
+ q = NULL;
+ if (is_var(p, "%U")) {
+ q = lp.lp_person;
+ } else if (is_var(p, "%C") || is_var(p, "%J") ) {
+ q = lp.lp_job;
+ } else if (is_var(p, "%F")) {
+ q = lp.lp_created_for;
+ } else if (is_var(p, "%%")) {
+ q = "%";
+ } else
+ q = p;
+
+ /* copy the stuff over. if we don't understand something that we
+ * should, just skip it over. */
+ if (q) {
+ len = MIN(p == q ? 2 : strlen(q), destlen);
+ strncpy(dest, q, len);
+ dest += len;
+ destlen -= len;
+ }
+
+ /* stuff up to next $ */
+ src = p + 2;
+ p = strchr(src, '$');
+ len = p ? MIN((size_t)(p - src), destlen) : destlen;
+ if (len > 0) {
+ strncpy(dest, src, len);
+ dest += len;
+ destlen -= len;
+ }
+ }
+ return destbuf;
+}
+
void lp_person( person )
char *person;
exit( 1 );
}
strcpy( lp.lp_host, host );
+ LOG(log_debug, logtype_papd, "host: %s", lp.lp_host );
}
+/* Currently lp_job and lp_for will not handle the
+ * conversion of macroman chars > 0x7f correctly
+ * This should be added.
+ */
+
void lp_job( job )
char *job;
{
- char *p, *q;
-
if ( lp.lp_job != NULL ) {
free( lp.lp_job );
}
- if (( lp.lp_job = (char *)malloc( strlen( job ) + 1 )) == NULL ) {
- LOG(log_error, logtype_papd, "malloc: %m" );
- exit( 1 );
- }
- for ( p = job, q = lp.lp_job; *p != '\0'; p++, q++ ) {
- if ( !isascii( *p ) || !isprint( *p ) || *p == '\\' ) {
- *q = '.';
- } else {
- *q = *p;
- }
+
+ lp.lp_job = strdup(job);
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "job: %s", lp.lp_job );
+#endif
+
+}
+
+void lp_for ( lpfor )
+ char *lpfor;
+{
+ if ( lp.lp_created_for != NULL ) {
+ free( lp.lp_created_for );
}
- *q = '\0';
+
+ lp.lp_created_for = strdup(lpfor);
}
+
int lp_init( out, sat )
struct papfile *out;
struct sockaddr_at *sat;
{
+ int authenticated = 0;
+#ifndef HAVE_CUPS
int fd, n, len;
char *cp, buf[ BUFSIZ ];
struct stat st;
- int authenticated = 0;
+#endif /* HAVE_CUPS */
#ifdef ABS_PRINT
char cost[ 22 ];
char balance[ 22 ];
lp.lp_letter = 'A';
if ( printer->p_flags & P_SPOOLED ) {
+
+#ifndef HAVE_CUPS
/* check if queuing is enabled: mode & 010 on lock file */
if ( stat( printer->p_lock, &st ) < 0 ) {
LOG(log_error, logtype_papd, "lp_init: %s: %m", printer->p_lock );
return( -1 );
}
-#ifndef SOLARIS /* flock is unsupported, I doubt this stuff work anyway with newer solaris so ignore for now */
+#ifndef SOLARIS /* flock is unsupported, I doubt this stuff works anyway with newer solaris so ignore for now */
if ( flock( fd, LOCK_EX ) < 0 ) {
LOG(log_error, logtype_papd, "lp_init: can't lock .seq" );
spoolerror( out, NULL );
lseek( fd, 0L, 0 );
write( fd, buf, strlen( buf ));
close( fd );
+#else
+
+ if (cups_get_printer_status ( printer ) == 0)
+ {
+ spoolerror( out, "Queuing is disabled." );
+ return( -1 );
+ }
+
+ lp.lp_seq = getpid();
+#endif /* HAVE CUPS */
} else {
lp.lp_flags |= LP_PIPE;
lp.lp_seq = getpid();
int fd;
struct passwd *pwent;
+#ifdef DEBUG
+ LOG (log_debug, logtype_papd, "lp_open");
+#endif
+
+ if ( lp.lp_flags & LP_JOBPENDING ) {
+ lp_print();
+ }
+
if (( lp.lp_flags & LP_INIT ) == 0 && lp_init( out, sat ) != 0 ) {
return( -1 );
}
if ( lp.lp_flags & LP_OPEN ) {
- LOG(log_error, logtype_papd, "lp_open already open" );
- abort();
+ /* LOG(log_error, logtype_papd, "lp_open already open" ); */
+ /* abort(); */
+ return (-1);
}
if ( lp.lp_flags & LP_PIPE ) {
+
/* go right to program */
if (lp.lp_person != NULL) {
if((pwent = getpwnam(lp.lp_person)) != NULL) {
LOG(log_info, logtype_papd, "Error getting username (%s)", lp.lp_person);
}
}
- if (( lp.lp_stream = popen( printer->p_printer, "w" )) == NULL ) {
+
+ lp_setup_comments(CH_UNIX);
+ if (( lp.lp_stream = popen( pipexlate(printer->p_printer), "w" )) == NULL ) {
LOG(log_error, logtype_papd, "lp_open popen %s: %m", printer->p_printer );
spoolerror( out, NULL );
return( -1 );
}
+ LOG(log_debug, logtype_papd, "lp_open: opened %s", pipexlate(printer->p_printer) );
} else {
sprintf( name, "df%c%03d%s", lp.lp_letter++, lp.lp_seq, hostname );
return( -1 );
}
+ if ( NULL == (lp.lp_spoolfile = (char *) malloc (strlen (name) +1)) ) {
+ LOG(log_error, logtype_papd, "malloc: %m");
+ exit(1);
+ }
+ strcpy ( lp.lp_spoolfile, name);
+
if (lp.lp_person != NULL) {
if ((pwent = getpwnam(lp.lp_person)) == NULL) {
LOG(log_error, logtype_papd, "getpwnam %s: no such user", lp.lp_person);
spoolerror( out, NULL );
return( -1 );
}
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "lp_open: opened %s", name );
+#endif
}
lp.lp_flags |= LP_OPEN;
-
return( 0 );
}
fclose( lp.lp_stream );
lp.lp_stream = NULL;
lp.lp_flags &= ~LP_OPEN;
+ lp.lp_flags |= LP_JOBPENDING;
return 0;
}
-int lp_write( buf, len )
+
+
+int lp_write(in, buf, len )
+ struct papfile *in;
char *buf;
- int len;
+ size_t len;
{
+#define BUFSIZE 32768
+ static char tempbuf[BUFSIZE];
+ static char tempbuf2[BUFSIZE];
+ static size_t bufpos = 0;
+ static int last_line_translated = 1; /* if 0, append a \n a the start */
+ char *tbuf = buf;
+
+ /* Before we write out anything check for a pending job, e.g. cover page */
+ if (lp.lp_flags & LP_JOBPENDING)
+ lp_print();
+
+ /* foomatic doesn't handle mac line endings, so we convert them for
+ * the Postscript headers
+ * REALLY ugly hack, remove ASAP again */
+ if ((printer->p_flags & P_FOOMATIC_HACK) && (in->pf_state & PF_TRANSLATE) &&
+ (buf[len-1] != '\n') ) {
+ if (len <= BUFSIZE) {
+ if (!last_line_translated) {
+ tempbuf2[0] = '\n';
+ memcpy(tempbuf2+1, buf, len++);
+ }
+ else
+ memcpy(tempbuf2, buf, len);
+
+ if (tempbuf2[len-1] == '\r')
+ tempbuf2[len-1] = '\n';
+ tempbuf2[len] = 0;
+ tbuf = tempbuf2;
+ last_line_translated = 1;
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "lp_write: %s", tbuf );
+#endif
+ }
+ else {
+ LOG(log_error, logtype_papd, "lp_write: conversion buffer too small" );
+ abort();
+ }
+ }
+ else {
+ if (printer->p_flags & P_FOOMATIC_HACK && buf[len-1] == '\n') {
+ last_line_translated = 1;
+ }
+ else
+ last_line_translated = 0;
+ }
+
+ /* To be able to do commandline substitutions on piped printers
+ * we store the start of the print job in a buffer.
+ * %%EndComment triggers writing to file */
if (( lp.lp_flags & LP_OPEN ) == 0 ) {
- return( -1 );
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "lp_write: writing to temporary buffer" );
+#endif
+ if ((bufpos+len) > BUFSIZE) {
+ LOG(log_error, logtype_papd, "lp_write: temporary buffer too small" );
+ /* FIXME: call lp_open here? abort isn't nice... */
+ abort();
+ }
+ else {
+ memcpy(tempbuf + bufpos, tbuf, len);
+ bufpos += len;
+ if (bufpos > BUFSIZE/2)
+ in->pf_state |= PF_STW; /* we used half of the buffer, start writing */
+ return(0);
+ }
+ }
+ else if ( bufpos) {
+ if ( fwrite( tempbuf, 1, bufpos, lp.lp_stream ) != bufpos ) {
+ LOG(log_error, logtype_papd, "lp_write: %m" );
+ abort();
+ }
+ bufpos=0;
}
- if ( fwrite( buf, 1, len, lp.lp_stream ) != len ) {
+ if ( fwrite( tbuf, 1, len, lp.lp_stream ) != len ) {
LOG(log_error, logtype_papd, "lp_write: %m" );
abort();
}
*/
int lp_print()
{
+#ifndef HAVE_CUPS
char buf[ MAXPATHLEN ];
char tfname[ MAXPATHLEN ];
char cfname[ MAXPATHLEN ];
char letter;
int fd, n, s;
FILE *cfile;
+#endif /* HAVE_CUPS */
if (( lp.lp_flags & LP_INIT ) == 0 || lp.lp_letter == 'A' ) {
return 0;
}
lp_close();
+ lp.lp_flags &= ~LP_JOBPENDING;
if ( printer->p_flags & P_SPOOLED ) {
+#ifndef HAVE_CUPS
sprintf( tfname, "tfA%03d%s", lp.lp_seq, hostname );
if (( fd = open( tfname, O_WRONLY|O_EXCL|O_CREAT, 0660 )) < 0 ) {
LOG(log_error, logtype_papd, "lp_print %s: %m", tfname );
LOG(log_error, logtype_papd, "lp_print lpd said %c: %m", buf[ 0 ] );
return 0;
}
+#else
+ if ( ! (lp.lp_job && *lp.lp_job) ) {
+ lp.lp_job = strdup("Mac Job");
+ }
+
+ lp_setup_comments(add_charset(cups_get_language ()));
+
+ if (lp.lp_person != NULL) {
+ cups_print_job ( printer->p_printer, lp.lp_spoolfile, lp.lp_job, lp.lp_person, printer->p_cupsoptions);
+ } else if (lp.lp_created_for != NULL) {
+ cups_print_job ( printer->p_printer, lp.lp_spoolfile, lp.lp_job, lp.lp_created_for, printer->p_cupsoptions);
+ } else {
+ cups_print_job ( printer->p_printer, lp.lp_spoolfile, lp.lp_job, printer->p_operator, printer->p_cupsoptions);
+ }
+
+ /*LOG(log_info, logtype_papd, "lp_print unlink %s", lp.lp_spoolfile );*/
+ //unlink ( lp.lp_spoolfile );
+ return 0;
+#endif /* HAVE_CUPS*/
}
LOG(log_info, logtype_papd, "lp_print queued" );
return 0;
}
+#ifndef HAVE_CUPS
int lp_disconn_unix( fd )
{
return( close( fd ));
}
}
}
+#endif /* HAVE_CUPS */
/*
- * $Id: lp.h,v 1.3 2001-06-25 20:13:45 rufustfirefly Exp $
+ * $Id: lp.h,v 1.3.14.1 2004-06-09 01:25:53 bfernhomberg Exp $
*/
#ifndef PAPD_LP_H
int lp_pagecost __P(( void ));
void lp_host __P(( char * ));
void lp_job __P(( char * ));
+void lp_for __P(( char * ));
+void lp_origin __P(( int ));
int lp_rmjob __P(( int ));
int lp_queue __P(( struct papfile * ));
/* open a file for spooling */
int lp_open __P(( struct papfile *, struct sockaddr_at * ));
/* open a buffer to the current open file */
-int lp_write __P(( char *, int ));
+int lp_write __P(( struct papfile *,char *, size_t ));
/* close current spooling file */
int lp_close __P(( void ));
/*
- * $Id: magics.c,v 1.11 2003-02-17 01:34:35 srittau Exp $
+ * $Id: magics.c,v 1.11.6.1 2004-06-09 01:25:53 bfernhomberg Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "comment.h"
#include "lp.h"
+static int state=0;
+
int ps( infile, outfile, sat )
struct papfile *infile, *outfile;
struct sockaddr_at *sat;
struct papd_comment *comment;
for (;;) {
+ if ( infile->pf_state & PF_STW ) {
+ infile->pf_state &= ~PF_STW;
+ /* set up spool file */
+ if ( lp_open( outfile, sat ) < 0 && !state) {
+ LOG(log_error, logtype_papd, "lp_open failed" );
+ spoolerror( outfile, "Ignoring job." );
+ }
+ state = 1;
+ }
if ( (comment = compeek()) ) {
switch( (*comment->c_handler)( infile, outfile, sat )) {
case CH_DONE :
default :
return( CH_ERROR );
}
-
} else {
switch ( markline( infile, &start, &linelength, &crlflength )) {
case 0 :
}
/* write to file */
- lp_write( start, linelength + crlflength );
+ lp_write( infile, start, linelength + crlflength );
CONSUME( infile, linelength + crlflength );
}
}
case -1 :
return( CH_MORE );
}
-
if ( in->pf_state & PF_BOT ) {
in->pf_state &= ~PF_BOT;
+#if 0
if ( lp_open( out, sat ) < 0 ) {
LOG(log_error, logtype_papd, "lp_open failed" );
spoolerror( out, "Ignoring job." );
}
+#endif
} else {
if (( comment = commatch( start, start + linelength, headers )) != NULL ) {
compush( comment );
}
}
- lp_write( start, linelength + crlflength );
+ lp_write( in, start, linelength + crlflength );
CONSUME( in, linelength + crlflength );
}
}
return( CH_DONE );
}
+
struct papd_comment magics[] = {
{ "%!PS-Adobe-3.0 Query", 0, cm_psquery, C_FULL },
{ "%!PS-Adobe-3.0", 0, cm_psadobe, C_FULL },
/*
- * $Id: main.c,v 1.18.6.1 2004-05-12 21:21:49 didg Exp $
+ * $Id: main.c,v 1.18.6.2 2004-06-09 01:25:53 bfernhomberg Exp $
*
* Copyright (c) 1990,1995 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <atalk/paths.h>
#include <atalk/util.h>
#include <atalk/nbp.h>
+#include <atalk/unicode.h>
#include "printer.h"
#include "printcap.h"
#include "session.h"
#include "uam_auth.h"
+#include "print_cups.h"
#define _PATH_PAPDPPDFILE ".ppd"
pr->p_type, pr->p_zone );
papd_exit( n + 1 );
}
- LOG(log_error, logtype_papd, "unregister %s:%s@%s", pr->p_name, pr->p_type,
+ LOG(log_info, logtype_papd, "unregister %s:%s@%s", pr->p_name, pr->p_type,
pr->p_zone );
}
+#ifdef HAVE_CUPS
+ if ( pr->p_flags & P_SPOOLED && pr->p_flags & P_CUPS_PPD ) {
+ LOG(log_info, logtype_papd, "Deleting CUPS temp PPD file for %s (%s)", pr->p_name, pr->p_ppdfile);
+ unlink (pr->p_ppdfile);
+ }
+#endif /* HAVE_CUPS */
+
}
papd_exit( n );
}
char *p, hostname[ MAXHOSTNAMELEN ];
char cbuf[ 8 ];
int c;
+ char *atname;
if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
perror( "gethostname" );
}
}
- getprinters( conffile );
switch (server_lock("papd", pidfile, debug)) {
case 0: /* open a couple things again in the child */
exit(0);
}
+#ifdef DEBUG1
+ fault_setup(NULL);
+#endif
+
/*
* Start logging.
*/
#endif /* ultrix */
LOG(log_info, logtype_papd, "restart (%s)", version );
+#ifdef HAVE_CUPS
+ LOG(log_info, logtype_papd, "CUPS support enabled (%s)", CUPS_API_VERSION );
+#endif
+
+ getprinters( conffile );
for ( pr = printers; pr; pr = pr->p_next ) {
if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) < 0 ) {
LOG(log_error, logtype_papd, "printcap problem: %s", pr->p_printer );
}
+
+ if (!(pr->p_flags & P_CUPS)) {
+ if ((size_t)-1 != convert_string_allocate(CH_UNIX, CH_MAC, pr->p_name, strlen(pr->p_name), &atname)) {
+ pr->p_u_name = pr->p_name;
+ pr->p_name = atname;
+ }
+ }
+
if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
LOG(log_error, logtype_papd, "atp_open: %m" );
papd_exit( 1 );
}
if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
pr->p_zone ) < 0 ) {
- LOG(log_error, logtype_papd, "can't register %s:%s@%s", pr->p_name, pr->p_type,
+ LOG(log_error, logtype_papd, "can't register %s:%s@%s", pr->p_u_name, pr->p_type,
pr->p_zone );
die( 1 );
}
if ( pr->p_flags & P_AUTH ) {
- LOG(log_info, logtype_papd, "Authentication enabled: %s", pr->p_name );
+ LOG(log_info, logtype_papd, "Authentication enabled: %s", pr->p_u_name );
}
else {
- LOG(log_info, logtype_papd, "Authentication disabled: %s", pr->p_name );
+ LOG(log_info, logtype_papd, "Authentication disabled: %s", pr->p_u_name );
}
- LOG(log_info, logtype_papd, "register %s:%s@%s", pr->p_name, pr->p_type,
+ LOG(log_info, logtype_papd, "register %s:%s@%s", pr->p_u_name, pr->p_type,
pr->p_zone );
pr->p_flags |= P_REGISTERED;
}
err = 1;
}
+#ifdef HAVE_CUPS
+ /*
+ * If cups is not accepting jobs, we return
+ * 0xffff to indicate we're busy
+ */
+#ifdef DEBUG
+ LOG(log_debug, logtype_papd, "CUPS: PAP_OPEN");
+#endif
+ if ( (pr->p_flags & P_SPOOLED) && (cups_get_printer_status ( pr ) == 0)) {
+ LOG(log_error, logtype_papd, "CUPS_PAP_OPEN: %s is not accepting jobs",
+ pr->p_printer );
+ rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
+ err = 1;
+ }
+#endif /* HAVE_CUPS */
+
+
/*
* If this fails, we've run out of sockets. Rather than
* just die(), let's try to continue. Maybe some sockets
case 0 : /* child */
printer = pr;
+ #ifndef HAVE_CUPS
if (( printer->p_flags & P_SPOOLED ) &&
chdir( printer->p_spool ) < 0 ) {
LOG(log_error, logtype_papd, "chdir %s: %m", printer->p_spool );
exit( 1 );
}
+ #else
+ if (( printer->p_flags & P_SPOOLED ) &&
+ chdir( SPOOLDIR ) < 0 ) {
+ LOG(log_error, logtype_papd, "chdir %s: %m", SPOOLDIR );
+ exit( 1 );
+ }
+
+ #endif
sv.sa_handler = SIG_DFL;
sigemptyset( &sv.sa_mask );
struct printer *pr;
char *buf;
{
+
+#ifdef HAVE_CUPS
+ if ( pr->p_flags & P_PIPED ) {
+ *buf = strlen( cannedstatus );
+ strncpy( &buf[ 1 ], cannedstatus, *buf );
+ return( *buf + 1 );
+ } else {
+ cups_get_printer_status( pr );
+ *buf = strlen ( pr->p_status );
+ strncpy ( &buf[1], pr->p_status, *buf);
+ return ( *buf + 1);
+ }
+#else
+
char path[ MAXPATHLEN ];
int fd = -1, rc;
*buf = rc;
return( rc + 1 );
}
+#endif /* HAVE_CUPS */
}
char *pgetstr();
else
atalk_aton(p, &pr->p_addr);
- pr->p_next = printers;
- printers = pr;
+#ifdef HAVE_CUPS
+ if ((p = pgetstr("co", &a)) != NULL ) {
+ pr->p_cupsoptions = strdup(p);
+ LOG (log_error, logtype_papd, "enabling cups-options for %s: %s", pr->p_name, pr->p_cupsoptions);
+ }
+#endif
+
+ /* convert line endings for setup sections.
+ real ugly work around for foomatic deficiencies,
+ need to get rid of this */
+ if ( pgetflag("fo") == 1 ) {
+ pr->p_flags |= P_FOOMATIC_HACK;
+ LOG (log_error, logtype_papd, "enabling foomatic hack for %s", pr->p_name);
+ }
+
+ if (strncasecmp (pr->p_name, "cupsautoadd", 11) == 0)
+ {
+#ifdef HAVE_CUPS
+ pr = cups_autoadd_printers (pr, printers);
+ printers = pr;
+#else
+ LOG (log_error, logtype_papd, "cupsautoadd: Cups support not compiled in");
+#endif /* HAVE_CUPS */
+ }
+ else {
+#ifdef HAVE_CUPS
+ if ( cups_check_printer ( pr, printers, 1) == 0)
+ {
+ pr->p_next = printers;
+ printers = pr;
+ }
+#else
+ pr->p_next = printers;
+ printers = pr;
+#endif /* HAVE_CUPS */
+ }
}
if ( c == 0 ) {
endprent();
int rprintcap( pr )
struct printer *pr;
{
+
+#ifdef HAVE_CUPS
+
+ char *p;
+
+ if ( pr->p_flags & P_SPOOLED && !(pr->p_flags & P_CUPS_AUTOADDED) ) { /* Skip check if autoadded */
+ if ( cups_printername_ok ( pr->p_printer ) != 1) {
+ LOG(log_error, logtype_papd, "No such CUPS printer: '%s'", pr->p_printer );
+ return( -1 );
+ }
+ }
+
+ /*
+ * Check for ppd file, moved here because of cups_autoadd we cannot check at the usual location
+ */
+
+ if ( pr->p_ppdfile == defprinter.p_ppdfile ) {
+ if ( (p = (char *) cups_get_printer_ppd ( pr->p_printer )) != NULL ) {
+ if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
+ LOG(log_error, logtype_papd, "malloc: %m" );
+ exit( 1 );
+ }
+ strcpy( pr->p_ppdfile, p );
+ pr->p_flags |= P_CUPS_PPD;
+ /*LOG(log_info, logtype_papd, "PPD File for %s set to %s", pr->p_printer, pr->p_ppdfile );*/
+ }
+ }
+
+
+#else
+
char buf[ 1024 ], area[ 1024 ], *a, *p;
int c;
endprent();
}
+#endif /* HAVE_CUPS */
return( 0 );
}
/*
- * $Id: ppd.c,v 1.9 2002-09-29 23:29:14 sibaz Exp $
+ * $Id: ppd.c,v 1.9.8.1 2004-06-09 01:25:54 bfernhomberg Exp $
*
* Copyright (c) 1995 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
struct ppd_feature ppd_features[] = {
{ "*LanguageLevel", 0 },
{ "*PSVersion", 0 },
+#ifdef HAVE_CUPS
+ { "*FreeVM", "33554432" },
+#else
{ "*FreeVM", 0 },
+#endif
{ "*Product", 0 },
{ "*PCFileName", 0 },
{ "*ModelName", 0 },
}
#endif /* SHOWPPD */
+
+/* quick and ugly hack to be able to read
+ ppd files with Mac line ending */
+static char* my_fgets(buf, bufsize, stream)
+ char *buf;
+ size_t bufsize;
+ FILE *stream;
+{
+ char p;
+ size_t count = 0;
+
+ while (count < bufsize && EOF != (p=fgetc(stream))) {
+ buf[count] = p;
+ count++;
+ if ( p == '\r' || p == '\n')
+ break;
+ }
+
+ if (p == EOF && count == 0)
+ return NULL;
+
+ /* translate line endings */
+ if ( buf[count - 1] == '\r')
+ buf[count - 1] = '\n';
+
+ buf[count] = 0;
+ return buf;
+}
+
struct ppdent *getppdent( stream )
FILE *stream;
{
ppdent.pe_main = ppdent.pe_option = ppdent.pe_translation =
ppdent.pe_value = NULL;
- while (( p = fgets( buf, sizeof( buf ), stream )) != NULL ) {
+ while (( p = my_fgets( buf, sizeof( buf ), stream )) != NULL ) {
if ( *p != '*' ) { /* main key word */
continue;
}
- if ( p[ strlen( p ) - 1 ] != '\n' ) {
+ if ( p[ strlen( p ) - 1 ] != '\n' && p[ strlen( p ) - 1 ] != '\r') {
LOG(log_error, logtype_papd, "getppdent: line too long" );
continue;
}
break;
}
}
- if ( pfe->pd_name && (pfe->pd_value == NULL) ) {
+ if ( pfe->pd_name ) { /*&& (pfe->pd_value == NULL) ) { */
if (( pfe->pd_value =
(char *)malloc( strlen( pe->pe_value ) + 1 )) == NULL ) {
LOG(log_error, logtype_papd, "malloc: %m" );
--- /dev/null
+/*
+ * $Id: print_cups.c,v 1.1.2.1 2004-06-09 01:25:54 bfernhomberg Exp $
+ *
+ * Copyright 2004 Bjoern Fernhomberg.
+ *
+ * Some code copied or adapted from print_cups.c for samba
+ * Copyright 1999-2003 by Michael R Sweet.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <errno.h>
+
+
+#ifdef HAVE_CUPS
+
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <atalk/unicode.h>
+#include <atalk/logger.h>
+#include <atalk/atp.h>
+#include <atalk/pap.h>
+#include <atalk/util.h>
+
+#include "printer.h"
+#include "print_cups.h"
+
+#define MAXCHOOSERLEN 31
+#define HTTP_MAX_URI 1024
+
+static const char* cups_status_msg[] = {
+ "status: busy; info: \"%s\" is rejecting jobs; ",
+ "status: idle; info: \"%s\" is stopped, accepting jobs ;",
+ "status: idle; info: \"%s\" is ready ; ",
+};
+
+/* Local functions */
+static int convert_to_mac_name ( char *encoding, char * inptr, char * outptr, size_t outlen);
+static size_t to_ascii ( char *inbuf, char **outbuf);
+static int cups_mangle_printer_name ( struct printer *pr, struct printer *printers);
+static void cups_free_printer ( struct printer *pr);
+
+
+char * cups_get_language ()
+{
+ cups_lang_t *language;
+
+ language = cupsLangDefault(); /* needed for conversion */
+ return cupsLangEncoding(language);
+}
+
+/*
+ * 'cups_passwd_cb()' - The CUPS password callback...
+ */
+
+static const char * /* O - Password or NULL */
+cups_passwd_cb(const char *prompt) /* I - Prompt */
+{
+ /*
+ * Always return NULL to indicate that no password is available...
+ */
+ return (NULL);
+}
+
+
+/*
+ * 'cups_printername_ok()' - Verify supplied printer name is a valid cups printer
+ */
+
+int /* O - 1 if printer name OK */
+cups_printername_ok(char *name) /* I - Name of printer */
+{
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ LOG(log_error, logtype_papd, "Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno));
+ return (0);
+ }
+
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes", NULL, "printer-uri");
+
+ sprintf(uri, "ipp://localhost/printers/%s", name);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) == NULL)
+ {
+ LOG(log_error, logtype_papd, "Unable to get printer status for %s - %s\n", name,
+ ippErrorString(cupsLastError()));
+ httpClose(http);
+ return (0);
+ }
+
+ httpClose(http);
+
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ {
+ LOG(log_error, logtype_papd, "Unable to get printer status for %s - %s\n", name,
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (0);
+ }
+ else
+ {
+ ippDelete(response);
+ return (1);
+ }
+
+ return (0);
+}
+
+const char *
+cups_get_printer_ppd ( char * name)
+{
+ cupsSetPasswordCB(cups_passwd_cb);
+ return cupsGetPPD( name );
+}
+
+int
+cups_get_printer_status (struct printer *pr)
+{
+
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* printer-uri attribute */
+ int status = -1;
+
+ static const char *pattrs[] = /* Requested printer attributes */
+ {
+ "printer-state",
+ "printer-state-message",
+ "printer-is-accepting-jobs"
+ };
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ {
+ LOG(log_error, logtype_papd, "Unable to connect to CUPS server %s - %s\n",
+ cupsServer(), strerror(errno));
+ return (0);
+ }
+
+ /*
+ * Generate the printer URI...
+ */
+
+ sprintf(uri, "ipp://localhost/printers/%s", pr->p_printer);
+
+
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes",
+ (sizeof(pattrs) / sizeof(pattrs[0])),
+ NULL, pattrs);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) == NULL)
+ {
+ LOG(log_error, logtype_papd, "Unable to get printer status for %s - %s\n", pr->p_printer,
+ ippErrorString(cupsLastError()));
+ httpClose(http);
+ return (0);
+ }
+
+ if (response->request.status.status_code >= IPP_OK_CONFLICT)
+ {
+ LOG(log_error, logtype_papd, "Unable to get printer status for %s - %s\n", pr->p_printer,
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ httpClose(http);
+ return (0);
+ }
+
+ /*
+ * Get the current printer status and convert it to the status values.
+ */
+
+ memset ( pr->p_status, 0 ,sizeof(pr->p_status));
+
+ if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
+ {
+ if (attr->values[0].integer == IPP_PRINTER_STOPPED)
+ status = 1;
+ else if (attr->values[0].integer == IPP_NOT_ACCEPTING)
+ status = 0;
+ else
+ status = 2;
+ }
+
+ if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN)) != NULL)
+ {
+ if ( attr->values[0].integer == 0 )
+ status = 0;
+ }
+
+ snprintf ( pr->p_status, 255, cups_status_msg[status], pr->p_printer );
+
+ if ((attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT)) != NULL)
+ strncat ( pr->p_status, attr->values[0].string.text, 255-strlen(pr->p_status));
+
+ ippDelete(response);
+
+ /*
+ * Return the print status ...
+ */
+
+ httpClose(http);
+
+ return (status);
+}
+
+
+/*------------------------------------------------------------------------*/
+
+/* pass the job to cups */
+
+int cups_print_job ( char * name, char *filename, char *job, char *username, char * cupsoptions )
+{
+ int jobid;
+ char filepath[MAXPATHLEN];
+ int num_options;
+ cups_option_t *options;
+
+ /* Initialize the options array */
+ num_options = 0;
+ options = (cups_option_t *)0;
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ if ( username != NULL )
+ {
+ /* Add options using cupsAddOption() */
+ num_options = cupsAddOption("job-originating-user-name", username, num_options, &options);
+ num_options = cupsAddOption("originating-user-name", username, num_options, &options);
+ cupsSetUser ( username );
+ }
+
+ if (cupsoptions != NULL)
+ {
+ num_options = cupsParseOptions(cupsoptions, num_options, &options);
+ }
+
+ strlcpy ( filepath, SPOOLDIR, sizeof(filepath));
+ strlcat ( filepath , "/", sizeof(filepath));
+ strlcat ( filepath , filename, sizeof(filepath));
+
+ if ((jobid = cupsPrintFile( name, filepath, job, 0, options)) == 0)
+ LOG(log_error, logtype_papd, "Unable to print job '%s' (%s) to printer '%s' for user '%s' - CUPS error : '%s'\n", job, filepath, name, username, ippErrorString(cupsLastError()));
+ else
+ LOG(log_info, logtype_papd, "Job '%s' queued to printer '%s' with id '%d'", job, name, jobid);
+
+ cupsFreeOptions(num_options, options);
+ return (jobid);
+}
+
+
+/*------------------------------------------------------------------------*/
+
+struct printer *
+cups_autoadd_printers ( struct printer *defprinter, struct printer *printers)
+{
+ struct printer *pr;
+ int num_dests,i;
+ int ret;
+ cups_dest_t *dests;
+ cups_lang_t *language;
+ char name[MAXCHOOSERLEN+1], *p;
+
+ language = cupsLangDefault(); /* needed for conversion */
+ num_dests = cupsGetDests(&dests); /* get the available destination from CUPS */
+
+ for (i=0; i< num_dests; i++)
+ {
+ if (( pr = (struct printer *)malloc( sizeof( struct printer ))) == NULL ) {
+ LOG(log_error, logtype_papd, "malloc: %m" );
+ exit( 1 );
+ }
+
+ memcpy( pr, defprinter, sizeof( struct printer ) );
+
+ /* convert from CUPS to local encoding */
+ convert_string_allocate( add_charset(cupsLangEncoding(language)), CH_UNIX,
+ dests[i].name, strlen(dests[i].name), &pr->p_u_name);
+
+ /* convert CUPS name to Mac charset */
+ if ( convert_to_mac_name ( cupsLangEncoding(language), dests[i].name, name, sizeof(name)) <= 0)
+ {
+ LOG (log_error, logtype_papd, "Conversion from CUPS to MAC name failed for %s", dests[i].name);
+ free (pr);
+ continue;
+ }
+
+ if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
+ LOG(log_error, logtype_papd, "malloc: %m" );
+ exit( 1 );
+ }
+ strcpy( pr->p_name, name );
+
+ /* set printer flags */
+ pr->p_flags &= ~P_PIPED;
+ pr->p_flags |= P_SPOOLED;
+ pr->p_flags |= P_CUPS;
+ pr->p_flags |= P_CUPS_AUTOADDED;
+
+ if (( pr->p_printer = (char *)malloc( strlen( dests[i].name ) + 1 )) == NULL ) {
+ LOG(log_error, logtype_papd, "malloc: %m" );
+ exit( 1 );
+ }
+ strcpy( pr->p_printer, dests[i].name );
+
+ if ( (p = (char *) cups_get_printer_ppd ( pr->p_printer )) != NULL ) {
+ if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
+ LOG(log_error, logtype_papd, "malloc: %m" );
+ exit( 1 );
+ }
+ strcpy( pr->p_ppdfile, p );
+ pr->p_flags |= P_CUPS_PPD;
+ }
+
+ if ( (ret = cups_check_printer ( pr, printers, 0)) == -1)
+ ret = cups_mangle_printer_name ( pr, printers );
+
+ if (ret) {
+ cups_free_printer (pr);
+ LOG(log_info, logtype_papd, "Printer %s not added: reason %d", name, ret);
+ }
+ else {
+ pr->p_next = printers;
+ printers = pr;
+ }
+ }
+
+ cupsFreeDests(num_dests, dests);
+ cupsLangFree(language);
+
+ return printers;
+}
+
+
+/*------------------------------------------------------------------------*/
+
+/* cups_mangle_printer_name
+ * Mangles the printer name if two CUPS printer provide the same Chooser Name
+ * Append '#nn' to the chooser name, if it is longer than 28 char we overwrite the last three chars
+ * Returns: 0 on Success, 2 on Error
+ */
+
+static int cups_mangle_printer_name ( struct printer *pr, struct printer *printers)
+{
+ size_t count, name_len;
+ char name[MAXCHOOSERLEN];
+
+ count = 1;
+ name_len = strlen (pr->p_name);
+ strncpy ( name, pr->p_name, MAXCHOOSERLEN-3);
+
+ /* Reallocate necessary space */
+ (name_len >= MAXCHOOSERLEN-3) ? (name_len = MAXCHOOSERLEN+1) : (name_len = name_len + 4);
+ pr->p_name = (char *) realloc (pr->p_name, name_len );
+
+ while ( ( cups_check_printer ( pr, printers, 0 )) && count < 100)
+ {
+ memset ( pr->p_name, 0, name_len);
+ strncpy ( pr->p_name, name, MAXCHOOSERLEN-3);
+ sprintf ( pr->p_name, "%s#%2.2u", pr->p_name, count++);
+ }
+
+ if ( count > 99)
+ return (2);
+
+ return (0);
+}
+
+/*------------------------------------------------------------------------*/
+
+/* fallback ASCII conversion */
+
+static size_t
+to_ascii ( char *inptr, char **outptr)
+{
+ char *out, *osav;
+
+ if ( NULL == (out = (char*) malloc ( strlen ( inptr) + 1 )) ) {
+ LOG(log_error, logtype_papd, "malloc: %m" );
+ exit (1);
+ }
+
+ osav = out;
+
+ while ( *inptr != '\0' ) {
+ if ( *inptr & 0x80 ) {
+ *out = '_';
+ out++;
+ inptr++;
+ }
+ else
+ *out++ = *inptr++;
+ }
+ *out = '\0';
+ *outptr = osav;
+ return ( strlen (osav) );
+}
+
+
+/*------------------------------------------------------------------------*/
+
+/* convert_to_mac_name
+ * 1) Convert from encoding to MacRoman
+ * 2) Shorten to MAXCHOOSERLEN (31)
+ * 3) Replace @ and _ as they are illegal
+ * Returns: -1 on failure, length of name on success; outpr contains name in MacRoman
+ */
+
+static int convert_to_mac_name ( char * encoding, char * inptr, char * outptr, size_t outlen)
+{
+ char *outbuf;
+ char *soptr;
+ size_t name_len = 0;
+ size_t i;
+ charset_t chCups;
+
+ /* Change the encoding */
+ if ((charset_t)-1 != (chCups = add_charset(encoding))) {
+ name_len = convert_string_allocate( chCups, CH_MAC, inptr, strlen(inptr), &outbuf);
+ }
+
+ if (name_len == 0 || name_len == (size_t)-1) {
+ /* charset conversion failed, use ascii fallback */
+ name_len = to_ascii ( inptr, &outbuf );
+ }
+
+ soptr = outptr;
+
+ for ( i=0; i< name_len && i < outlen-1 ; i++)
+ {
+ if ( outbuf[i] == '_' )
+ *soptr = ' '; /* Replace '_' with a space (just for the looks) */
+ else if ( outbuf[i] == '@' || outbuf[i] == ':' )
+ *soptr = '_'; /* Replace @ and : with '_' as they are illegal chars */
+ else
+ *soptr = outbuf[i];
+ soptr++;
+ }
+ *soptr = '\0';
+ free (outbuf);
+ return (i);
+}
+
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * cups_check_printer:
+ * check if a printer with this name already exists.
+ * if yes, and replace = 1 the existing printer is replaced with
+ * the new one. This allows to overwrite printer settings
+ * created by cupsautoadd. It also used by cups_mangle_printer.
+ */
+
+int cups_check_printer ( struct printer *pr, struct printer *printers, int replace)
+{
+ struct printer *listptr, *listprev;
+
+ listptr = printers;
+ listprev = NULL;
+
+ while ( listptr != NULL) {
+ if ( strcasecmp (pr->p_name, listptr->p_name) == 0) {
+ if ( pr->p_flags & P_CUPS_AUTOADDED ) { /* Check if printer has been autoadded */
+ if ( listptr->p_flags & P_CUPS_AUTOADDED )
+ return (-1); /* Conflicting Cups Auto Printer (mangling issue?) */
+ else
+ return (1); /* Never replace a hand edited printer with auto one */
+ }
+
+ if ( replace ) {
+ /* Replace printer */
+ if ( listprev != NULL) {
+ pr->p_next = listptr->p_next;
+ listprev->p_next = pr;
+ cups_free_printer (listptr);
+ }
+ else {
+ printers = pr;
+ printers->p_next = listptr->p_next;
+ cups_free_printer (listptr);
+ }
+ }
+ return (1); /* Conflicting Printers */
+ }
+ listprev = listptr;
+ listptr = listptr->p_next;
+ }
+ return (0); /* No conflict */
+}
+
+
+/*------------------------------------------------------------------------*/
+
+
+void
+cups_free_printer ( struct printer *pr)
+{
+ if ( pr->p_name != NULL)
+ free (pr->p_name);
+ if ( pr->p_printer != NULL)
+ free (pr->p_printer);
+ if ( pr->p_ppdfile != NULL)
+ free (pr->p_ppdfile);
+
+ /* CUPS autoadded printers share the other informations
+ * so if the printer is autoadded we won't free them.
+ * We might leak some bytes here though.
+ */
+ if ( pr->p_flags & P_CUPS_AUTOADDED ) {
+ free (pr);
+ return;
+ }
+
+ if ( pr->p_operator != NULL )
+ free (pr->p_operator);
+ if ( pr->p_zone != NULL )
+ free (pr->p_zone);
+ if ( pr->p_type != NULL )
+ free (pr->p_type);
+ if ( pr->p_authprintdir != NULL )
+ free (pr->p_authprintdir);
+
+ free ( pr );
+ return;
+
+}
+
+#endif /* HAVE_CUPS*/
--- /dev/null
+\r
+#ifndef PAPD_CUPS_H\r
+#define PAPD_CUPS_H 1\r
+\r
+#ifdef HAVE_CUPS\r
+#include <sys/cdefs.h>\r
+\r
+struct cups_status {\r
+ int pr_status;\r
+ char * status_message;\r
+};\r
+\r
+int cups_printername_ok __P((char * ));\r
+const char * cups_get_printer_ppd __P(( char * ));\r
+int cups_get_printer_status __P((struct printer *pr));\r
+int cups_print_job __P(( char *, char *, char *, char *, char *));\r
+struct printer * cups_autoadd_printers __P(( struct printer *, struct printer *));\r
+int cups_check_printer __P(( struct printer *, struct printer *, int));\r
+char *cups_get_language __P(());\r
+#endif /* HAVE_CUPS */\r
+#endif /* PAPD_CUPS_H */\r
/*
- * $Id: printer.h,v 1.5 2001-06-25 20:13:45 rufustfirefly Exp $
+ * $Id: printer.h,v 1.5.14.1 2004-06-09 01:25:54 bfernhomberg Exp $
*
* Copyright (c) 1990,1995 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
char *p_name;
char *p_type;
char *p_zone;
+ char *p_u_name;
#ifdef notdef
char *p_fonts;
char *p_psetdir;
#endif /* notdef */
char *p_ppdfile;
+ char p_status[255];
char *p_authprintdir;
int p_flags;
struct at_addr p_addr;
char *pu_cmd;
} p_un;
ATP p_atp;
+#ifdef HAVE_CUPS
+ char *p_cupsoptions;
+#endif
struct printer *p_next;
};
#define p_cmd p_un.pu_cmd
#define P_AUTH (1<<5)
#define P_AUTH_PSSP (1<<6)
#define P_AUTH_CAP (1<<7)
+#define P_CUPS (1<<8)
+#define P_CUPS_PPD (1<<9)
+#define P_CUPS_AUTOADDED (1<<10)
+#define P_FOOMATIC_HACK (1<<11)
extern struct printer *printer;
/*
- * $Id: queries.c,v 1.16.2.1 2003-09-03 20:40:50 didg Exp $
+ * $Id: queries.c,v 1.16.2.1.2.1 2004-06-09 01:25:54 bfernhomberg Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
int cq_feature( struct papfile *, struct papfile * );
int cq_printer( struct papfile *, struct papfile * );
int cq_rmjob( struct papfile *, struct papfile * );
+#ifndef HAVE_CUPS
int cq_listq( struct papfile *, struct papfile * );
int cq_rbilogin( struct papfile *, struct papfile * );
+#endif /* HAVE_CUPS */
}
}
+#ifndef HAVE_CUPS
+
static const char *rmjobfailed = "Failed\n";
static const char *rmjobok = "Ok\n";
CONSUME( in, linelength + crlflength );
return( CH_DONE );
}
+#endif /* HAVE_CUPS */
/*
{ "%%Login: UMICHKerberosIV", 0, cq_k4login, 0 },
{ "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth, C_FULL },
#endif /* KRB */
+#ifndef HAVE_CUPS
{ "%UMICHListQueue", 0, cq_listq, C_FULL },
{ "%UMICHDeleteJob", 0, cq_rmjob, 0 },
+#endif /* HAVE_CUPS */
{ "%%?BeginQuery: RBILogin ", "%%?EndQuery", cq_rbilogin, 0 },
{ "%%?BeginQuery", "%%?EndQuery", cq_query, 0 },
{ "%%?BeginFeatureQuery", "%%?EndFeatureQuery", cq_feature, 0 },
/*
- * $Id: showppd.c,v 1.5 2002-01-04 04:45:48 sibaz Exp $
+ * $Id: showppd.c,v 1.5.10.1 2004-06-09 01:25:54 bfernhomberg Exp $
*
* Copyright (c) 1995 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
extern struct ppd_feature ppd_features[];
-main( ac, av )
+int main( ac, av )
int ac;
char **av;
{
printf( "Font: %s\n", pfo->pd_font );
}
for ( pfe = ppd_features; pfe->pd_name; pfe++ ) {
- printf( "Feature: %s %s\n", pfe->pd_name, pfe->pd_value );
+ printf( "Feature: %s %s\n", pfe->pd_name, (pfe->pd_value)?pfe->pd_value:"NULL" );
}
- exit( 0 );
+ exit ( 0 );
}