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

Generated by: LCOV version 1.14