lib: Give lib/util/util_file.c its own header file
[samba.git] / source3 / printing / print_generic.c
index 5806b292064821254d5c723ce0ff204ab98daf4e..a8bf9aff972527fb6337c6c139ffde5df68b4efe 100644 (file)
 */
 
 #include "includes.h"
+#include "lib/util/util_file.h"
 #include "printing.h"
+#include "smbd/proto.h"
+#include "source3/lib/substitute.h"
 
-extern struct current_user current_user;
 extern userdom_struct current_user_info;
 
 /****************************************************************************
@@ -31,6 +33,8 @@ extern userdom_struct current_user_info;
 static int print_run_command(int snum, const char* printername, bool do_sub,
                             const char *command, int *outfd, ...)
 {
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
        char *syscmd;
        char *arg;
        int ret;
@@ -56,6 +60,8 @@ static int print_run_command(int snum, const char* printername, bool do_sub,
                return -1;
        }
 
+       DBG_DEBUG("Incoming command '%s'\n", syscmd);
+
        while ((arg = va_arg(ap, char *))) {
                char *value = va_arg(ap,char *);
                syscmd = talloc_string_sub(ctx, syscmd, arg, value);
@@ -71,21 +77,24 @@ static int print_run_command(int snum, const char* printername, bool do_sub,
                return -1;
        }
 
+       syscmd = lpcfg_substituted_string(ctx, lp_sub, syscmd);
+       if (syscmd == NULL) {
+               return -1;
+       }
+
        if (do_sub && snum != -1) {
                syscmd = talloc_sub_advanced(ctx,
-                               lp_servicename(snum),
+                               lp_servicename(talloc_tos(), lp_sub, snum),
                                current_user_info.unix_name,
                                "",
-                               current_user.ut.gid,
-                               get_current_username(),
-                               current_user_info.domain,
+                               get_current_gid(NULL),
                                syscmd);
                if (!syscmd) {
                        return -1;
                }
        }
 
-       ret = smbrun_no_sanitize(syscmd,outfd);
+       ret = smbrun_no_sanitize(syscmd, outfd, NULL);
 
        DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
 
@@ -101,7 +110,7 @@ static int generic_job_delete( const char *sharename, const char *lprm_command,
        fstring jobstr;
 
        /* need to delete the spooled entry */
-       slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
+       fstr_sprintf(jobstr, "%d", pjob->sysjob);
        return print_run_command( -1, sharename, False, lprm_command, NULL,
                   "%j", jobstr,
                   "%T", http_timestring(talloc_tos(), pjob->starttime),
@@ -113,12 +122,14 @@ pause a job
 ****************************************************************************/
 static int generic_job_pause(int snum, struct printjob *pjob)
 {
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
        fstring jobstr;
        
        /* need to pause the spooled entry */
-       slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
-       return print_run_command(snum, PRINTERNAME(snum), True,
-                                lp_lppausecommand(snum), NULL,
+       fstr_sprintf(jobstr, "%d", pjob->sysjob);
+       return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
+                                lp_lppause_command(snum), NULL,
                                 "%j", jobstr,
                                 NULL);
 }
@@ -128,23 +139,85 @@ resume a job
 ****************************************************************************/
 static int generic_job_resume(int snum, struct printjob *pjob)
 {
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
        fstring jobstr;
 
        /* need to pause the spooled entry */
-       slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
-       return print_run_command(snum, PRINTERNAME(snum), True,
-                                lp_lpresumecommand(snum), NULL,
+       fstr_sprintf(jobstr, "%d", pjob->sysjob);
+       return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
+                                lp_lpresume_command(snum), NULL,
                                 "%j", jobstr,
                                 NULL);
 }
 
+/****************************************************************************
+get the current list of queued jobs
+****************************************************************************/
+static int generic_queue_get(const char *printer_name,
+                             enum printing_types printing_type,
+                             char *lpq_command,
+                             print_queue_struct **q,
+                             print_status_struct *status)
+{
+       char **qlines;
+       int fd;
+       int numlines, i, qcount;
+       print_queue_struct *queue = NULL;
+
+       /* never do substitution when running the 'lpq command' since we can't
+          get it right when using the background update daemon.  Make the caller
+          do it before passing off the command string to us here. */
+
+       print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
+
+       if (fd == -1) {
+               DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
+                       printer_name ));
+               return 0;
+       }
+
+       numlines = 0;
+       qlines = fd_lines_load(fd, &numlines,0,NULL);
+       close(fd);
+
+       /* turn the lpq output into a series of job structures */
+       qcount = 0;
+       ZERO_STRUCTP(status);
+       if (numlines && qlines) {
+               queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
+               if (!queue) {
+                       TALLOC_FREE(qlines);
+                       *q = NULL;
+                       return 0;
+               }
+               memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
+
+               for (i=0; i<numlines; i++) {
+                       /* parse the line */
+                       if (parse_lpq_entry(printing_type,qlines[i],
+                                           &queue[qcount],status,qcount==0)) {
+                               qcount++;
+                       }
+               }
+       }
+
+       TALLOC_FREE(qlines);
+        *q = queue;
+       return qcount;
+}
+
 /****************************************************************************
  Submit a file for printing - called from print_job_end()
 ****************************************************************************/
 
-static int generic_job_submit(int snum, struct printjob *pjob)
+static int generic_job_submit(int snum, struct printjob *pjob,
+                             enum printing_types printing_type,
+                             char *lpq_cmd)
 {
        int ret = -1;
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
        char *current_directory = NULL;
        char *print_directory = NULL;
        char *wd = NULL;
@@ -152,20 +225,22 @@ static int generic_job_submit(int snum, struct printjob *pjob)
        char *jobname = NULL;
        TALLOC_CTX *ctx = talloc_tos();
        fstring job_page_count, job_size;
+       print_queue_struct *q;
+       print_status_struct status;
 
        /* we print from the directory path to give the best chance of
            parsing the lpq output */
-       current_directory = TALLOC_ARRAY(ctx,
-                                       char,
-                                       PATH_MAX+1);
-       if (!current_directory) {
-               return -1;
-       }
-       wd = sys_getwd(current_directory);
+       wd = sys_getwd();
        if (!wd) {
                return -1;
        }
 
+       current_directory = talloc_strdup(ctx, wd);
+       SAFE_FREE(wd);
+
+       if (!current_directory) {
+               return -1;
+       }
        print_directory = talloc_strdup(ctx, pjob->filename);
        if (!print_directory) {
                return -1;
@@ -190,81 +265,56 @@ static int generic_job_submit(int snum, struct printjob *pjob)
                ret = -1;
                goto out;
        }
-       slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
-       slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);
+       fstr_sprintf(job_page_count, "%d", pjob->page_count);
+       fstr_sprintf(job_size, "%zu", pjob->size);
 
        /* send it to the system spooler */
-       ret = print_run_command(snum, PRINTERNAME(snum), True,
-                       lp_printcommand(snum), NULL,
+       ret = print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
+                       lp_print_command(snum), NULL,
                        "%s", p,
                        "%J", jobname,
                        "%f", p,
                        "%z", job_size,
                        "%c", job_page_count,
                        NULL);
-
- out:
-
-       chdir(wd);
-       TALLOC_FREE(current_directory);
-        return ret;
-}
-
-
-/****************************************************************************
-get the current list of queued jobs
-****************************************************************************/
-static int generic_queue_get(const char *printer_name, 
-                             enum printing_types printing_type,
-                             char *lpq_command,
-                             print_queue_struct **q, 
-                             print_status_struct *status)
-{
-       char **qlines;
-       int fd;
-       int numlines, i, qcount;
-       print_queue_struct *queue = NULL;
-       
-       /* never do substitution when running the 'lpq command' since we can't
-          get it rigt when using the background update daemon.  Make the caller 
-          do it before passing off the command string to us here. */
-
-       print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
-
-       if (fd == -1) {
-               DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
-                       printer_name ));
-               return 0;
+       if (ret != 0) {
+               ret = -1;
+               goto out;
        }
-       
-       numlines = 0;
-       qlines = fd_lines_load(fd, &numlines,0,NULL);
-       close(fd);
-
-       /* turn the lpq output into a series of job structures */
-       qcount = 0;
-       ZERO_STRUCTP(status);
-       if (numlines && qlines) {
-               queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
-               if (!queue) {
-                       TALLOC_FREE(qlines);
-                       *q = NULL;
-                       return 0;
-               }
-               memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
 
-               for (i=0; i<numlines; i++) {
-                       /* parse the line */
-                       if (parse_lpq_entry(printing_type,qlines[i],
-                                           &queue[qcount],status,qcount==0)) {
-                               qcount++;
+       /*
+        * check the queue for the newly submitted job, this allows us to
+        * determine the backend job identifier (sysjob).
+        */
+       pjob->sysjob = -1;
+       ret = generic_queue_get(lp_printername(talloc_tos(), lp_sub, snum),
+                               printing_type, lpq_cmd, &q, &status);
+       if (ret > 0) {
+               int i;
+               for (i = 0; i < ret; i++) {
+                       if (strcmp(q[i].fs_file, p) == 0) {
+                               pjob->sysjob = q[i].sysjob;
+                               DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
+                                         pjob->jobid, jobname, pjob->sysjob));
+                               break;
                        }
-               }               
+               }
+               SAFE_FREE(q);
+               ret = 0;
+       }
+       if (pjob->sysjob == -1) {
+               DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
+                         "Unix job\n", pjob->jobid, jobname));
        }
 
-       TALLOC_FREE(qlines);
-        *q = queue;
-       return qcount;
+
+ out:
+
+       if (chdir(current_directory) == -1) {
+               smb_panic("chdir failed in generic_job_submit");
+       }
+       TALLOC_FREE(current_directory);
+        return ret;
 }
 
 /****************************************************************************
@@ -272,7 +322,11 @@ static int generic_queue_get(const char *printer_name,
 ****************************************************************************/
 static int generic_queue_pause(int snum)
 {
-       return print_run_command(snum, PRINTERNAME(snum), True, lp_queuepausecommand(snum), NULL, NULL);
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+
+       return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
+                                lp_queuepause_command(snum), NULL, NULL);
 }
 
 /****************************************************************************
@@ -280,7 +334,11 @@ static int generic_queue_pause(int snum)
 ****************************************************************************/
 static int generic_queue_resume(int snum)
 {
-       return print_run_command(snum, PRINTERNAME(snum), True, lp_queueresumecommand(snum), NULL, NULL);
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
+
+       return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
+                                lp_queueresume_command(snum), NULL, NULL);
 }
 
 /****************************************************************************