]> arthur.barton.de Git - netatalk.git/blobdiff - etc/papd/lp.c
remove signed/unsigned gcc warning
[netatalk.git] / etc / papd / lp.c
index b90a45a5ec2eb998e66c580c360238441243900a..613993faac6764c300ac47efbf6985a53b86338d 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * $Id: lp.c,v 1.14.8.4.2.6 2009-01-21 02:33:55 didg Exp $
+ *
  * Copyright (c) 1990,1994 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
  *
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
+#endif /* HAVE_CONFIG_H */
 
 #include <sys/param.h>
-#include <sys/syslog.h>
 #include <sys/time.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
-#if defined( sun ) && defined( __svr4__ )
-#include </usr/ucbinclude/sys/file.h>
-#else sun __svr4__
+#include <ctype.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
 #include <sys/file.h>
-#endif sun __svr4__
 #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
-
+#endif /* ABS_PRINT */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <netdb.h>
+#ifdef HAVE_FCNTL_H
 #include <fcntl.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"
 
-char   hostname[ MAXHOSTNAMELEN ];
+#ifdef HAVE_CUPS
+#include  "print_cups.h"
+#endif
 
-extern struct sockaddr_at *sat;
 
-/* initialize printing interface */
-int    lp_init();
-/* cancel current job */
-int    lp_cancel();
-/* print current job */
-int    lp_print();
+/* These functions aren't used outside of lp.c */
+int lp_conn_inet();
+int lp_disconn_inet( int );
+int lp_conn_unix();
+int lp_disconn_unix( int );
+
+char   hostname[ MAXHOSTNAMELEN ];
 
-/* open a file for spooling */
-int    lp_open();
-/* open a buffer to the current open file */
-int    lp_write();
-/* close current spooling file */
-int    lp_close();
+extern struct sockaddr_at *sat;
 
 struct lp {
     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 size_t quote(char *dest, char *src, const size_t bsize, size_t len)
+{
+size_t used = 0;
+
+    while (len && used < bsize ) {
+        switch (*src) {
+          case '$':
+          case '\\':
+          case '"':
+          case '`':
+            if (used + 2 > bsize )
+              return used;
+            *dest = '\\';
+            dest++;
+            used++;
+            break;
+        }
+        *dest = *src;
+        src++;
+        dest++;
+        len--;
+        used++;
+    }
+    return used;
+}
+
+
+static char* pipexlate(char *src)
+{
+    char *p, *q, *dest; 
+    static char destbuf[MAXPATHLEN +1];
+    size_t destlen = MAXPATHLEN;
+    int len = 0;
+   
+    dest = destbuf; 
+
+    if (!src)
+       return NULL;
+
+    memset(dest, 0, MAXPATHLEN +1);
+    if ((p = strchr(src, '%')) == NULL) { /* nothing to do */
+        strncpy(dest, src, MAXPATHLEN);
+        return destbuf;
+    }
+    /* first part of the path. copy and forward to the next variable. */
+    len = MIN((size_t)(p - src), destlen);
+    if (len > 0) {
+        strncpy(dest, src, len);
+        destlen -= len;
+        dest += len;
+    }
 
-lp_person( person )
+    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 = "%";
+        } 
+
+        /* copy the stuff over. if we don't understand something that we
+         * should, just skip it over. */
+        if (q) {
+            len = MIN(strlen(q), destlen);
+            len = quote(dest, q, destlen, len);
+        }
+        else {
+            len = MIN(2, 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;
 {
     if ( lp.lp_person != NULL ) {
        free( lp.lp_person );
     }
     if (( lp.lp_person = (char *)malloc( strlen( person ) + 1 )) == NULL ) {
-       syslog( LOG_ERR, "malloc: %m" );
+       LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
        exit( 1 );
     }
     strcpy( lp.lp_person, person );
 }
 
 #ifdef ABS_PRINT
-lp_pagecost()
+int lp_pagecost()
 {
     char       cost[ 22 ];
     char       balance[ 22 ];
@@ -136,55 +329,66 @@ lp_pagecost()
     printer->p_balance = atof( balance ) + atof( cost );
     return( err < 0 ? -1 : 0 );
 }
-#endif ABS_PRINT
+#endif /* ABS_PRINT */
 
-lp_host( host )
+void lp_host( host )
     char       *host;
 {
     if ( lp.lp_host != NULL ) {
        free( lp.lp_host );
     }
     if (( lp.lp_host = (char *)malloc( strlen( host ) + 1 )) == NULL ) {
-       syslog( LOG_ERR, "malloc: %m" );
+       LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
        exit( 1 );
     }
     strcpy( lp.lp_host, host );
+    LOG(log_debug, logtype_papd, "host: %s", lp.lp_host );
 }
 
-lp_job( job )
+/* 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 ) {
-       syslog( LOG_ERR, "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);
 }
 
-lp_init( out, sat )
+
+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 ];
-#endif ABS_PRINT
+#endif /* ABS_PRINT */
 
     if ( printer->p_flags & P_AUTH ) {
        authenticated = 0;
@@ -195,31 +399,38 @@ lp_init( out, sat )
            int addr_net = ntohs( sat->sat_addr.s_net );
            int addr_node  = sat->sat_addr.s_node;
            char addr_filename[256];
-           char username[32];
+           char auth_string[256];
+           char *username, *afpdpid;
            struct stat cap_st;
            FILE *cap_file;
 
+           memset( auth_string, 0, 256 );
            sprintf(addr_filename, "%s/net%d.%dnode%d", 
                printer->p_authprintdir, addr_net/256, addr_net%256, 
                addr_node);
            if (stat(addr_filename, &cap_st) == 0) {
                if ((cap_file = fopen(addr_filename, "r")) != NULL) {
-                   if (fscanf(cap_file, "%s", username) != EOF) {
+                   if (fgets(auth_string, 256, cap_file) != NULL) {
+                       username = auth_string;
+                       if ((afpdpid = strrchr( auth_string, ':' )) != NULL) {
+                           *afpdpid = '\0';
+                           afpdpid++;
+                       }
                        if (getpwnam(username) != NULL ) {
-                           syslog(LOG_INFO, "CAP authenticated %s", username);
+                           LOG(log_info, logtype_papd, "CAP authenticated %s", username);
                            lp_person(username);
                            authenticated = 1;
                        } else {
-                           syslog(LOG_INFO, "CAP error: invalid username: '%s'", username);
+                           LOG(log_info, logtype_papd, "CAP error: invalid username: '%s'", username);
                        }
                    } else {
-                       syslog(LOG_INFO, "CAP error: could not read username");
+                       LOG(log_info, logtype_papd, "CAP error: could not read username");
                    }
                } else {
-                   syslog(LOG_INFO, "CAP error: %m");
+                   LOG(log_info, logtype_papd, "CAP error: %s", strerror(errno));
                }
            } else {
-               syslog(LOG_INFO, "CAP error: %m");
+               LOG(log_info, logtype_papd, "CAP error: %s", strerror(errno));
            }
        }
 
@@ -230,7 +441,7 @@ lp_init( out, sat )
        }
 
        if ( authenticated == 0 ) {
-           syslog( LOG_ERR, "lp_init: must authenticate" );
+           LOG(log_error, logtype_papd, "lp_init: must authenticate" );
            spoolerror( out, "Authentication required." );
            return( -1 );
        }
@@ -239,20 +450,20 @@ lp_init( out, sat )
        if (( printer->p_flags & P_ACCOUNT ) && printer->p_pagecost > 0 &&
                ! ABS_canprint( lp.lp_person, printer->p_role,
                printer->p_srvid, cost, balance )) {
-           syslog( LOG_ERR, "lp_init: no ABS funds" );
+           LOG(log_error, logtype_papd, "lp_init: no ABS funds" );
            spoolerror( out, "No ABS funds available." );
            return( -1 );
        }
-#endif ABS_PRINT
+#endif /* ABS_PRINT */
     }
 
     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
-       syslog( LOG_ERR, "gethostname: %m" );
+       LOG(log_error, logtype_papd, "gethostname: %s", strerror(errno) );
        exit( 1 );
     }
 
     if ( lp.lp_flags & LP_INIT ) {
-       syslog( LOG_ERR, "lp_init: already inited, die!" );
+       LOG(log_error, logtype_papd, "lp_init: already inited, die!" );
        abort();
     }
 
@@ -261,33 +472,37 @@ lp_init( out, sat )
     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 ) {
-           syslog( LOG_ERR, "lp_init: %s: %m", printer->p_lock );
+           LOG(log_error, logtype_papd, "lp_init: %s: %s", printer->p_lock, strerror(errno) );
            spoolerror( out, NULL );
            return( -1 );
        }
        if ( st.st_mode & 010 ) {
-           syslog( LOG_INFO, "lp_init: queuing is disabled" );
+           LOG(log_info, logtype_papd, "lp_init: queuing is disabled" );
            spoolerror( out, "Queuing is disabled." );
            return( -1 );
        }
 
        if (( fd = open( ".seq", O_RDWR|O_CREAT, 0661 )) < 0 ) {
-           syslog( LOG_ERR, "lp_init: can't create .seq" );
+           LOG(log_error, logtype_papd, "lp_init: can't create .seq" );
            spoolerror( out, NULL );
            return( -1 );
        }
 
+#ifndef SOLARIS /* flock is unsupported, I doubt this stuff works anyway with newer solaris so ignore for now */
        if ( flock( fd, LOCK_EX ) < 0 ) {
-           syslog( LOG_ERR, "lp_init: can't lock .seq" );
+           LOG(log_error, logtype_papd, "lp_init: can't lock .seq" );
            spoolerror( out, NULL );
            return( -1 );
        }
+#endif
 
        n = 0;
        if (( len = read( fd, buf, sizeof( buf ))) < 0 ) {
-           syslog( LOG_ERR, "lp_init read: %m" );
+           LOG(log_error, logtype_papd, "lp_init read: %s", strerror(errno) );
            spoolerror( out, NULL );
            return( -1 );
        }
@@ -306,6 +521,16 @@ lp_init( out, sat )
        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();
@@ -315,7 +540,7 @@ lp_init( out, sat )
     return( 0 );
 }
 
-lp_open( out, sat )
+int lp_open( out, sat )
     struct papfile     *out;
     struct sockaddr_at *sat;
 {
@@ -323,103 +548,198 @@ lp_open( out, sat )
     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 ) {
-       syslog( LOG_ERR, "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) {
                if(setreuid(pwent->pw_uid, pwent->pw_uid) != 0) {
-                   syslog(LOG_INFO, "setreuid error: %m");
+                   LOG(log_info, logtype_papd, "setreuid error: %s", strerror(errno));
                }
            } else {
-               syslog(LOG_INFO, "Error getting username (%s)", lp.lp_person);
+               LOG(log_info, logtype_papd, "Error getting username (%s)", lp.lp_person);
            }
        }
-       if (( lp.lp_stream = popen( printer->p_printer, "w" )) == NULL ) {
-           syslog( LOG_ERR, "lp_open popen %s: %m", printer->p_printer );
+
+       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: %s", printer->p_printer, strerror(errno) );
            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 );
 
        if (( fd = open( name, O_WRONLY|O_CREAT|O_EXCL, 0660 )) < 0 ) {
-           syslog( LOG_ERR, "lp_open %s: %m", name );
+           LOG(log_error, logtype_papd, "lp_open %s: %s", name, strerror(errno) );
            spoolerror( out, NULL );
            return( -1 );
        }
 
+       if ( NULL == (lp.lp_spoolfile = (char *) malloc (strlen (name) +1)) ) {
+           LOG(log_error, logtype_papd, "malloc: %s", strerror(errno));
+           exit(1);
+       }
+       strcpy ( lp.lp_spoolfile, name);        
+
        if (lp.lp_person != NULL) {
            if ((pwent = getpwnam(lp.lp_person)) == NULL) {
-               syslog(LOG_ERR, "getpwnam %s: no such user", lp.lp_person);
+               LOG(log_error, logtype_papd, "getpwnam %s: no such user", lp.lp_person);
                spoolerror( out, NULL );
                return( -1 );
            }
        } else {
            if ((pwent = getpwnam(printer->p_operator)) == NULL) {
-               syslog(LOG_ERR, "getpwnam %s: no such user", printer->p_operator);
+               LOG(log_error, logtype_papd, "getpwnam %s: no such user", printer->p_operator);
                spoolerror( out, NULL );
                return( -1 );
            }
        }
 
        if (fchown(fd, pwent->pw_uid, -1) < 0) {
-           syslog(LOG_ERR, "chown %s %s: %m", pwent->pw_name, name);
+           LOG(log_error, logtype_papd, "chown %s %s: %s", pwent->pw_name, name, strerror(errno));
            spoolerror( out, NULL );
            return( -1 );
        }
 
        if (( lp.lp_stream = fdopen( fd, "w" )) == NULL ) {
-           syslog( LOG_ERR, "lp_open fdopen: %m" );
+           LOG(log_error, logtype_papd, "lp_open fdopen: %s", strerror(errno) );
            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 );
 }
 
-lp_close()
+int lp_close()
 {
     if (( lp.lp_flags & LP_INIT ) == 0 || ( lp.lp_flags & LP_OPEN ) == 0 ) {
-       return;
+       return 0;
     }
     fclose( lp.lp_stream );
     lp.lp_stream = NULL;
     lp.lp_flags &= ~LP_OPEN;
-    return;
+    lp.lp_flags |= LP_JOBPENDING;
+    return 0;
 }
 
-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: %s", strerror(errno) );
+            abort();
+        }
+        bufpos=0;
     }
 
-    if ( fwrite( buf, 1, len, lp.lp_stream ) != len ) {
-       syslog( LOG_ERR, "lp_write: %m" );
+    if ( fwrite( tbuf, 1, len, lp.lp_stream ) != len ) {
+       LOG(log_error, logtype_papd, "lp_write: %s", strerror(errno) );
        abort();
     }
     return( 0 );
 }
 
-lp_cancel()
+int lp_cancel()
 {
     char       name[ MAXPATHLEN ];
     char       letter;
 
     if (( lp.lp_flags & LP_INIT ) == 0 || lp.lp_letter == 'A' ) {
-       return;
+       return 0;
     }
 
     if ( lp.lp_flags & LP_OPEN ) {
@@ -429,11 +749,11 @@ lp_cancel()
     for ( letter = 'A'; letter < lp.lp_letter; letter++ ) {
        sprintf( name, "df%c%03d%s", letter, lp.lp_seq, hostname );
        if ( unlink( name ) < 0 ) {
-           syslog( LOG_ERR, "lp_cancel unlink %s: %m", name );
+           LOG(log_error, logtype_papd, "lp_cancel unlink %s: %s", name, strerror(errno) );
        }
     }
 
-    return;
+    return 0;
 }
 
 /*
@@ -442,29 +762,33 @@ lp_cancel()
  *
  * XXX piped?
  */
-lp_print()
+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;
+       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 ) {
-           syslog( LOG_ERR, "lp_print %s: %m", tfname );
-           return;
+           LOG(log_error, logtype_papd, "lp_print %s: %s", tfname, strerror(errno) );
+           return 0;
        }
        if (( cfile = fdopen( fd, "w" )) == NULL ) {
-           syslog( LOG_ERR, "lp_print %s: %m", tfname );
-           return;
+           LOG(log_error, logtype_papd, "lp_print %s: %s", tfname, strerror(errno) );
+           return 0;
        }
        fprintf( cfile, "H%s\n", hostname );    /* XXX lp_host? */
 
@@ -504,59 +828,79 @@ lp_print()
 
        sprintf( cfname, "cfA%03d%s", lp.lp_seq, hostname );
        if ( link( tfname, cfname ) < 0 ) {
-           syslog( LOG_ERR, "lp_print can't link %s to %s: %m", cfname,
-                   tfname );
-           return;
+           LOG(log_error, logtype_papd, "lp_print can't link %s to %s: %s", cfname,
+                   tfname, strerror(errno) );
+           return 0;
        }
        unlink( tfname );
 
        if (( s = lp_conn_unix()) < 0 ) {
-           syslog( LOG_ERR, "lp_print: lp_conn_unix: %m" );
-           return;
+           LOG(log_error, logtype_papd, "lp_print: lp_conn_unix: %s", strerror(errno) );
+           return 0;
        }
 
        sprintf( buf, "\1%s\n", printer->p_printer );
        n = strlen( buf );
        if ( write( s, buf, n ) != n ) {
-           syslog( LOG_ERR, "lp_print write: %m" );
-           return;
+           LOG(log_error, logtype_papd, "lp_print write: %s" , strerror(errno));
+           return 0;
        }
        if ( read( s, buf, 1 ) != 1 ) {
-           syslog( LOG_ERR, "lp_print read: %m" );
-           return;
+           LOG(log_error, logtype_papd, "lp_print read: %s" , strerror(errno));
+           return 0;
        }
 
        lp_disconn_unix( s );
 
        if ( buf[ 0 ] != '\0' ) {
-           syslog( LOG_ERR, "lp_print lpd said %c: %m", buf[ 0 ] );
-           return;
+           LOG(log_error, logtype_papd, "lp_print lpd said %c: %s", buf[ 0 ], strerror(errno) );
+           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*/
     }
-    syslog( LOG_INFO, "lp_print queued" );
-    return;
+    LOG(log_info, logtype_papd, "lp_print queued" );
+    return 0;
 }
 
-lp_disconn_unix( fd )
+#ifndef HAVE_CUPS
+int lp_disconn_unix( int fd )
 {
     return( close( fd ));
 }
 
-lp_conn_unix()
+int lp_conn_unix()
 {
     int                        s;
     struct sockaddr_un saun;
 
     if (( s = socket( AF_UNIX, SOCK_STREAM, 0 )) < 0 ) {
-       syslog( LOG_ERR, "lp_conn_unix socket: %m" );
+       LOG(log_error, logtype_papd, "lp_conn_unix socket: %s", strerror(errno) );
        return( -1 );
     }
-    bzero( &saun, sizeof( struct sockaddr_un ));
+    memset( &saun, 0, sizeof( struct sockaddr_un ));
     saun.sun_family = AF_UNIX;
     strcpy( saun.sun_path, _PATH_DEVPRINTER );
     if ( connect( s, (struct sockaddr *)&saun,
            strlen( saun.sun_path ) + 2 ) < 0 ) {
-       syslog( LOG_ERR, "lp_conn_unix connect %s: %m", saun.sun_path );
+       LOG(log_error, logtype_papd, "lp_conn_unix connect %s: %s", saun.sun_path, strerror(errno) );
        close( s );
        return( -1 );
     }
@@ -564,12 +908,12 @@ lp_conn_unix()
     return( s );
 }
 
-lp_disconn_inet( fd )
+int lp_disconn_inet( int fd )
 {
     return( close( fd ));
 }
 
-lp_conn_inet()
+int lp_conn_inet()
 {
     int                        privfd, port = IPPORT_RESERVED - 1;
     struct sockaddr_in sin;
@@ -577,35 +921,35 @@ lp_conn_inet()
     struct hostent     *hp;
 
     if (( sp = getservbyname( "printer", "tcp" )) == NULL ) {
-       syslog( LOG_ERR, "printer/tcp: unknown service\n" );
+       LOG(log_error, logtype_papd, "printer/tcp: unknown service" );
        return( -1 );
     }
 
     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
-       syslog( LOG_ERR, "gethostname: %m" );
+       LOG(log_error, logtype_papd, "gethostname: %s", strerror(errno) );
        exit( 1 );
     }
 
     if (( hp = gethostbyname( hostname )) == NULL ) {
-       syslog( LOG_ERR, "%s: unknown host\n", hostname );
+       LOG(log_error, logtype_papd, "%s: unknown host", hostname );
        return( -1 );
     }
 
     if (( privfd = rresvport( &port )) < 0 ) {
-       syslog( LOG_ERR, "lp_connect: socket: %m" );
+       LOG(log_error, logtype_papd, "lp_connect: socket: %s", strerror(errno) );
        close( privfd );
        return( -1 );
     }
 
-    bzero( &sin, sizeof( struct sockaddr_in ));
+    memset( &sin, 0, sizeof( struct sockaddr_in ));
     sin.sin_family = AF_INET;
 /*    sin.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); */
-    bcopy( hp->h_addr, &sin.sin_addr, hp->h_length );
+    memcpy( &sin.sin_addr, hp->h_addr, hp->h_length );
     sin.sin_port = sp->s_port;
 
     if ( connect( privfd, (struct sockaddr *)&sin,
            sizeof( struct sockaddr_in )) < 0 ) {
-       syslog( LOG_ERR, "lp_connect: %m" );
+       LOG(log_error, logtype_papd, "lp_connect: %s", strerror(errno) );
        close( privfd );
        return( -1 );
     }
@@ -613,14 +957,14 @@ lp_conn_inet()
     return( privfd );
 }
 
-lp_rmjob( job )
+int lp_rmjob( job )
     int                job;
 {
     char       buf[ 1024 ];
     int                n, s;
 
     if (( s = lp_conn_inet()) < 0 ) {
-       syslog( LOG_ERR, "lp_rmjob: %m" );
+       LOG(log_error, logtype_papd, "lp_rmjob: %s", strerror(errno) );
        return( -1 );
     }
 
@@ -631,12 +975,12 @@ lp_rmjob( job )
     sprintf( buf, "\5%s %s %d\n", printer->p_printer, lp.lp_person, job );
     n = strlen( buf );
     if ( write( s, buf, n ) != n ) {
-       syslog( LOG_ERR, "lp_rmjob write: %m" );
+       LOG(log_error, logtype_papd, "lp_rmjob write: %s", strerror(errno) );
        lp_disconn_inet( s );
        return( -1 );
     }
     while (( n = read( s, buf, sizeof( buf ))) > 0 ) {
-       syslog( LOG_DEBUG, "read %.*s", n, buf );
+       LOG(log_debug, logtype_papd, "read %.*s", n, buf );
     }
 
     lp_disconn_inet( s );
@@ -653,23 +997,25 @@ char      *tag_files = "files: ";
 char   *tag_size = "size: ";
 char   *tag_status = "status: ";
 
-lp_queue( out )
+int lp_queue( out )
     struct papfile     *out;
 {
     char                       buf[ 1024 ], *start, *stop, *p, *q;
     int                                linelength, crlflength;
     static struct papfile      pf;
-    int                                n, len, s;
+    int                                s;
+    size_t                     len;
+    ssize_t                    n;
        
     if (( s = lp_conn_unix()) < 0 ) {
-       syslog( LOG_ERR, "lp_queue: %m" );
+       LOG(log_error, logtype_papd, "lp_queue: %s", strerror(errno) );
        return( -1 );
     }
 
     sprintf( buf, "\3%s\n", printer->p_printer );
     n = strlen( buf );
     if ( write( s, buf, n ) != n ) {
-       syslog( LOG_ERR, "lp_queue write: %m" );
+       LOG(log_error, logtype_papd, "lp_queue write: %s", strerror(errno) );
        lp_disconn_unix( s );
        return( -1 );
     }
@@ -803,3 +1149,4 @@ lp_queue( out )
        }
     }
 }
+#endif /* HAVE_CUPS */