LCOV - code coverage report
Current view: top level - source3/printing - print_generic.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 108 153 70.6 %
Date: 2024-05-31 13:13:24 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    printing command routines
       4             :    Copyright (C) Andrew Tridgell 1992-2000
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "lib/util/util_file.h"
      22             : #include "printing.h"
      23             : #include "smbd/proto.h"
      24             : #include "source3/lib/substitute.h"
      25             : 
      26             : extern userdom_struct current_user_info;
      27             : 
      28             : /****************************************************************************
      29             :  Run a given print command
      30             :  a null terminated list of value/substitute pairs is provided
      31             :  for local substitution strings
      32             : ****************************************************************************/
      33        3105 : static int print_run_command(int snum, const char* printername, bool do_sub,
      34             :                              const char *command, int *outfd, ...)
      35             : {
      36           0 :         const struct loadparm_substitution *lp_sub =
      37        3105 :                 loadparm_s3_global_substitution();
      38           0 :         char *syscmd;
      39           0 :         char *arg;
      40           0 :         int ret;
      41        3105 :         TALLOC_CTX *ctx = talloc_tos();
      42           0 :         va_list ap;
      43        3105 :         va_start(ap, outfd);
      44             : 
      45             :         /* check for a valid system printername and valid command to run */
      46             : 
      47        3105 :         if ( !printername || !*printername ) {
      48           0 :                 va_end(ap);
      49           0 :                 return -1;
      50             :         }
      51             : 
      52        3105 :         if (!command || !*command) {
      53           0 :                 va_end(ap);
      54           0 :                 return -1;
      55             :         }
      56             : 
      57        3105 :         syscmd = talloc_strdup(ctx, command);
      58        3105 :         if (!syscmd) {
      59           0 :                 va_end(ap);
      60           0 :                 return -1;
      61             :         }
      62             : 
      63        3105 :         DBG_DEBUG("Incoming command '%s'\n", syscmd);
      64             : 
      65        7169 :         while ((arg = va_arg(ap, char *))) {
      66        4064 :                 char *value = va_arg(ap,char *);
      67        4064 :                 syscmd = talloc_string_sub(ctx, syscmd, arg, value);
      68        4064 :                 if (!syscmd) {
      69           0 :                         va_end(ap);
      70           0 :                         return -1;
      71             :                 }
      72             :         }
      73        3105 :         va_end(ap);
      74             : 
      75        3105 :         syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
      76        3105 :         if (!syscmd) {
      77           0 :                 return -1;
      78             :         }
      79             : 
      80        3105 :         syscmd = lpcfg_substituted_string(ctx, lp_sub, syscmd);
      81        3105 :         if (syscmd == NULL) {
      82           0 :                 return -1;
      83             :         }
      84             : 
      85        3105 :         if (do_sub && snum != -1) {
      86        1644 :                 syscmd = talloc_sub_advanced(ctx,
      87         822 :                                 lp_servicename(talloc_tos(), lp_sub, snum),
      88             :                                 current_user_info.unix_name,
      89             :                                 "",
      90             :                                 get_current_gid(NULL),
      91             :                                 syscmd);
      92         822 :                 if (!syscmd) {
      93           0 :                         return -1;
      94             :                 }
      95             :         }
      96             : 
      97        3105 :         ret = smbrun_no_sanitize(syscmd, outfd, NULL);
      98             : 
      99        3105 :         DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
     100             : 
     101        3105 :         return ret;
     102             : }
     103             : 
     104             : 
     105             : /****************************************************************************
     106             : delete a print job
     107             : ****************************************************************************/
     108         335 : static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
     109             : {
     110           0 :         fstring jobstr;
     111             : 
     112             :         /* need to delete the spooled entry */
     113         335 :         fstr_sprintf(jobstr, "%d", pjob->sysjob);
     114         335 :         return print_run_command( -1, sharename, False, lprm_command, NULL,
     115             :                    "%j", jobstr,
     116             :                    "%T", http_timestring(talloc_tos(), pjob->starttime),
     117             :                    NULL);
     118             : }
     119             : 
     120             : /****************************************************************************
     121             : pause a job
     122             : ****************************************************************************/
     123          32 : static int generic_job_pause(int snum, struct printjob *pjob)
     124             : {
     125           0 :         const struct loadparm_substitution *lp_sub =
     126          32 :                 loadparm_s3_global_substitution();
     127           0 :         fstring jobstr;
     128             :         
     129             :         /* need to pause the spooled entry */
     130          32 :         fstr_sprintf(jobstr, "%d", pjob->sysjob);
     131          32 :         return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
     132             :                                  lp_lppause_command(snum), NULL,
     133             :                                  "%j", jobstr,
     134             :                                  NULL);
     135             : }
     136             : 
     137             : /****************************************************************************
     138             : resume a job
     139             : ****************************************************************************/
     140          32 : static int generic_job_resume(int snum, struct printjob *pjob)
     141             : {
     142           0 :         const struct loadparm_substitution *lp_sub =
     143          32 :                 loadparm_s3_global_substitution();
     144           0 :         fstring jobstr;
     145             : 
     146             :         /* need to pause the spooled entry */
     147          32 :         fstr_sprintf(jobstr, "%d", pjob->sysjob);
     148          32 :         return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
     149             :                                  lp_lpresume_command(snum), NULL,
     150             :                                  "%j", jobstr,
     151             :                                  NULL);
     152             : }
     153             : 
     154             : /****************************************************************************
     155             : get the current list of queued jobs
     156             : ****************************************************************************/
     157        1948 : static int generic_queue_get(const char *printer_name,
     158             :                              enum printing_types printing_type,
     159             :                              char *lpq_command,
     160             :                              print_queue_struct **q,
     161             :                              print_status_struct *status)
     162             : {
     163           0 :         char **qlines;
     164           0 :         int fd;
     165           0 :         int numlines, i, qcount;
     166        1948 :         print_queue_struct *queue = NULL;
     167             : 
     168             :         /* never do substitution when running the 'lpq command' since we can't
     169             :            get it right when using the background update daemon.  Make the caller
     170             :            do it before passing off the command string to us here. */
     171             : 
     172        1948 :         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
     173             : 
     174        1948 :         if (fd == -1) {
     175           0 :                 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
     176             :                         printer_name ));
     177           0 :                 return 0;
     178             :         }
     179             : 
     180        1948 :         numlines = 0;
     181        1948 :         qlines = fd_lines_load(fd, &numlines,0,NULL);
     182        1948 :         close(fd);
     183             : 
     184             :         /* turn the lpq output into a series of job structures */
     185        1948 :         qcount = 0;
     186        1948 :         ZERO_STRUCTP(status);
     187        1948 :         if (numlines && qlines) {
     188        1948 :                 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
     189        1948 :                 if (!queue) {
     190           0 :                         TALLOC_FREE(qlines);
     191           0 :                         *q = NULL;
     192           0 :                         return 0;
     193             :                 }
     194        1948 :                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
     195             : 
     196        7723 :                 for (i=0; i<numlines; i++) {
     197             :                         /* parse the line */
     198        5775 :                         if (parse_lpq_entry(printing_type,qlines[i],
     199        5775 :                                             &queue[qcount],status,qcount==0)) {
     200        3827 :                                 qcount++;
     201             :                         }
     202             :                 }
     203             :         }
     204             : 
     205        1948 :         TALLOC_FREE(qlines);
     206        1948 :         *q = queue;
     207        1948 :         return qcount;
     208             : }
     209             : 
     210             : /****************************************************************************
     211             :  Submit a file for printing - called from print_job_end()
     212             : ****************************************************************************/
     213             : 
     214         666 : static int generic_job_submit(int snum, struct printjob *pjob,
     215             :                               enum printing_types printing_type,
     216             :                               char *lpq_cmd)
     217             : {
     218         666 :         int ret = -1;
     219           0 :         const struct loadparm_substitution *lp_sub =
     220         666 :                 loadparm_s3_global_substitution();
     221         666 :         char *current_directory = NULL;
     222         666 :         char *print_directory = NULL;
     223         666 :         char *wd = NULL;
     224         666 :         char *p = NULL;
     225         666 :         char *jobname = NULL;
     226         666 :         TALLOC_CTX *ctx = talloc_tos();
     227           0 :         fstring job_page_count, job_size;
     228           0 :         print_queue_struct *q;
     229           0 :         print_status_struct status;
     230             : 
     231             :         /* we print from the directory path to give the best chance of
     232             :            parsing the lpq output */
     233         666 :         wd = sys_getwd();
     234         666 :         if (!wd) {
     235           0 :                 return -1;
     236             :         }
     237             : 
     238         666 :         current_directory = talloc_strdup(ctx, wd);
     239         666 :         SAFE_FREE(wd);
     240             : 
     241         666 :         if (!current_directory) {
     242           0 :                 return -1;
     243             :         }
     244         666 :         print_directory = talloc_strdup(ctx, pjob->filename);
     245         666 :         if (!print_directory) {
     246           0 :                 return -1;
     247             :         }
     248         666 :         p = strrchr_m(print_directory,'/');
     249         666 :         if (!p) {
     250           0 :                 return -1;
     251             :         }
     252         666 :         *p++ = 0;
     253             : 
     254         666 :         if (chdir(print_directory) != 0) {
     255           0 :                 return -1;
     256             :         }
     257             : 
     258         666 :         jobname = talloc_strdup(ctx, pjob->jobname);
     259         666 :         if (!jobname) {
     260           0 :                 ret = -1;
     261           0 :                 goto out;
     262             :         }
     263         666 :         jobname = talloc_string_sub(ctx, jobname, "'", "_");
     264         666 :         if (!jobname) {
     265           0 :                 ret = -1;
     266           0 :                 goto out;
     267             :         }
     268         666 :         fstr_sprintf(job_page_count, "%d", pjob->page_count);
     269         666 :         fstr_sprintf(job_size, "%zu", pjob->size);
     270             : 
     271             :         /* send it to the system spooler */
     272         666 :         ret = print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
     273             :                         lp_print_command(snum), NULL,
     274             :                         "%s", p,
     275             :                         "%J", jobname,
     276             :                         "%f", p,
     277             :                         "%z", job_size,
     278             :                         "%c", job_page_count,
     279             :                         NULL);
     280         666 :         if (ret != 0) {
     281         292 :                 ret = -1;
     282         292 :                 goto out;
     283             :         }
     284             : 
     285             :         /*
     286             :          * check the queue for the newly submitted job, this allows us to
     287             :          * determine the backend job identifier (sysjob).
     288             :          */
     289         374 :         pjob->sysjob = -1;
     290         374 :         ret = generic_queue_get(lp_printername(talloc_tos(), lp_sub, snum),
     291             :                                 printing_type, lpq_cmd, &q, &status);
     292         374 :         if (ret > 0) {
     293             :                 int i;
     294        1462 :                 for (i = 0; i < ret; i++) {
     295        1462 :                         if (strcmp(q[i].fs_file, p) == 0) {
     296         340 :                                 pjob->sysjob = q[i].sysjob;
     297         340 :                                 DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
     298             :                                           pjob->jobid, jobname, pjob->sysjob));
     299         340 :                                 break;
     300             :                         }
     301             :                 }
     302         340 :                 SAFE_FREE(q);
     303         340 :                 ret = 0;
     304             :         }
     305         374 :         if (pjob->sysjob == -1) {
     306          34 :                 DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
     307             :                           "Unix job\n", pjob->jobid, jobname));
     308             :         }
     309             : 
     310             : 
     311         340 :  out:
     312             : 
     313         666 :         if (chdir(current_directory) == -1) {
     314           0 :                 smb_panic("chdir failed in generic_job_submit");
     315             :         }
     316         666 :         TALLOC_FREE(current_directory);
     317         666 :         return ret;
     318             : }
     319             : 
     320             : /****************************************************************************
     321             :  pause a queue
     322             : ****************************************************************************/
     323          52 : static int generic_queue_pause(int snum)
     324             : {
     325           0 :         const struct loadparm_substitution *lp_sub =
     326          52 :                 loadparm_s3_global_substitution();
     327             : 
     328          52 :         return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
     329             :                                  lp_queuepause_command(snum), NULL, NULL);
     330             : }
     331             : 
     332             : /****************************************************************************
     333             :  resume a queue
     334             : ****************************************************************************/
     335          40 : static int generic_queue_resume(int snum)
     336             : {
     337           0 :         const struct loadparm_substitution *lp_sub =
     338          40 :                 loadparm_s3_global_substitution();
     339             : 
     340          40 :         return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
     341             :                                  lp_queueresume_command(snum), NULL, NULL);
     342             : }
     343             : 
     344             : /****************************************************************************
     345             :  * Generic printing interface definitions...
     346             :  ***************************************************************************/
     347             : 
     348             : struct printif  generic_printif =
     349             : {
     350             :         DEFAULT_PRINTING,
     351             :         generic_queue_get,
     352             :         generic_queue_pause,
     353             :         generic_queue_resume,
     354             :         generic_job_delete,
     355             :         generic_job_pause,
     356             :         generic_job_resume,
     357             :         generic_job_submit,
     358             : };
     359             : 

Generated by: LCOV version 1.14