2 Unix SMB/CIFS implementation.
3 printing command routines
4 Copyright (C) Andrew Tridgell 1992-2000
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.
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.
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/>.
22 #include "smbd/proto.h"
23 #include "source3/lib/substitute.h"
25 extern userdom_struct current_user_info
;
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 static int print_run_command(int snum
, const char* printername
, bool do_sub
,
33 const char *command
, int *outfd
, ...)
35 const struct loadparm_substitution
*lp_sub
=
36 loadparm_s3_global_substitution();
40 TALLOC_CTX
*ctx
= talloc_tos();
44 /* check for a valid system printername and valid command to run */
46 if ( !printername
|| !*printername
) {
51 if (!command
|| !*command
) {
56 syscmd
= talloc_strdup(ctx
, command
);
62 DBG_DEBUG("Incoming command '%s'\n", syscmd
);
64 while ((arg
= va_arg(ap
, char *))) {
65 char *value
= va_arg(ap
,char *);
66 syscmd
= talloc_string_sub(ctx
, syscmd
, arg
, value
);
74 syscmd
= talloc_string_sub(ctx
, syscmd
, "%p", printername
);
79 syscmd
= lpcfg_substituted_string(ctx
, lp_sub
, syscmd
);
84 if (do_sub
&& snum
!= -1) {
85 syscmd
= talloc_sub_advanced(ctx
,
86 lp_servicename(talloc_tos(), lp_sub
, snum
),
87 current_user_info
.unix_name
,
89 get_current_gid(NULL
),
96 ret
= smbrun_no_sanitize(syscmd
, outfd
, NULL
);
98 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
104 /****************************************************************************
106 ****************************************************************************/
107 static int generic_job_delete( const char *sharename
, const char *lprm_command
, struct printjob
*pjob
)
111 /* need to delete the spooled entry */
112 fstr_sprintf(jobstr
, "%d", pjob
->sysjob
);
113 return print_run_command( -1, sharename
, False
, lprm_command
, NULL
,
115 "%T", http_timestring(talloc_tos(), pjob
->starttime
),
119 /****************************************************************************
121 ****************************************************************************/
122 static int generic_job_pause(int snum
, struct printjob
*pjob
)
124 const struct loadparm_substitution
*lp_sub
=
125 loadparm_s3_global_substitution();
128 /* need to pause the spooled entry */
129 fstr_sprintf(jobstr
, "%d", pjob
->sysjob
);
130 return print_run_command(snum
, lp_printername(talloc_tos(), lp_sub
, snum
), True
,
131 lp_lppause_command(snum
), NULL
,
136 /****************************************************************************
138 ****************************************************************************/
139 static int generic_job_resume(int snum
, struct printjob
*pjob
)
141 const struct loadparm_substitution
*lp_sub
=
142 loadparm_s3_global_substitution();
145 /* need to pause the spooled entry */
146 fstr_sprintf(jobstr
, "%d", pjob
->sysjob
);
147 return print_run_command(snum
, lp_printername(talloc_tos(), lp_sub
, snum
), True
,
148 lp_lpresume_command(snum
), NULL
,
153 /****************************************************************************
154 get the current list of queued jobs
155 ****************************************************************************/
156 static int generic_queue_get(const char *printer_name
,
157 enum printing_types printing_type
,
159 print_queue_struct
**q
,
160 print_status_struct
*status
)
164 int numlines
, i
, qcount
;
165 print_queue_struct
*queue
= NULL
;
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. */
171 print_run_command(-1, printer_name
, False
, lpq_command
, &fd
, NULL
);
174 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
180 qlines
= fd_lines_load(fd
, &numlines
,0,NULL
);
183 /* turn the lpq output into a series of job structures */
185 ZERO_STRUCTP(status
);
186 if (numlines
&& qlines
) {
187 queue
= SMB_MALLOC_ARRAY(print_queue_struct
, numlines
+1);
193 memset(queue
, '\0', sizeof(print_queue_struct
)*(numlines
+1));
195 for (i
=0; i
<numlines
; i
++) {
197 if (parse_lpq_entry(printing_type
,qlines
[i
],
198 &queue
[qcount
],status
,qcount
==0)) {
209 /****************************************************************************
210 Submit a file for printing - called from print_job_end()
211 ****************************************************************************/
213 static int generic_job_submit(int snum
, struct printjob
*pjob
,
214 enum printing_types printing_type
,
218 const struct loadparm_substitution
*lp_sub
=
219 loadparm_s3_global_substitution();
220 char *current_directory
= NULL
;
221 char *print_directory
= NULL
;
224 char *jobname
= NULL
;
225 TALLOC_CTX
*ctx
= talloc_tos();
226 fstring job_page_count
, job_size
;
227 print_queue_struct
*q
;
228 print_status_struct status
;
230 /* we print from the directory path to give the best chance of
231 parsing the lpq output */
237 current_directory
= talloc_strdup(ctx
, wd
);
240 if (!current_directory
) {
243 print_directory
= talloc_strdup(ctx
, pjob
->filename
);
244 if (!print_directory
) {
247 p
= strrchr_m(print_directory
,'/');
253 if (chdir(print_directory
) != 0) {
257 jobname
= talloc_strdup(ctx
, pjob
->jobname
);
262 jobname
= talloc_string_sub(ctx
, jobname
, "'", "_");
267 fstr_sprintf(job_page_count
, "%d", pjob
->page_count
);
268 fstr_sprintf(job_size
, "%zu", pjob
->size
);
270 /* send it to the system spooler */
271 ret
= print_run_command(snum
, lp_printername(talloc_tos(), lp_sub
, snum
), True
,
272 lp_print_command(snum
), NULL
,
277 "%c", job_page_count
,
285 * check the queue for the newly submitted job, this allows us to
286 * determine the backend job identifier (sysjob).
289 ret
= generic_queue_get(lp_printername(talloc_tos(), lp_sub
, snum
),
290 printing_type
, lpq_cmd
, &q
, &status
);
293 for (i
= 0; i
< ret
; i
++) {
294 if (strcmp(q
[i
].fs_file
, p
) == 0) {
295 pjob
->sysjob
= q
[i
].sysjob
;
296 DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
297 pjob
->jobid
, jobname
, pjob
->sysjob
));
304 if (pjob
->sysjob
== -1) {
305 DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
306 "Unix job\n", pjob
->jobid
, jobname
));
312 if (chdir(current_directory
) == -1) {
313 smb_panic("chdir failed in generic_job_submit");
315 TALLOC_FREE(current_directory
);
319 /****************************************************************************
321 ****************************************************************************/
322 static int generic_queue_pause(int snum
)
324 const struct loadparm_substitution
*lp_sub
=
325 loadparm_s3_global_substitution();
327 return print_run_command(snum
, lp_printername(talloc_tos(), lp_sub
, snum
), True
,
328 lp_queuepause_command(snum
), NULL
, NULL
);
331 /****************************************************************************
333 ****************************************************************************/
334 static int generic_queue_resume(int snum
)
336 const struct loadparm_substitution
*lp_sub
=
337 loadparm_s3_global_substitution();
339 return print_run_command(snum
, lp_printername(talloc_tos(), lp_sub
, snum
), True
,
340 lp_queueresume_command(snum
), NULL
, NULL
);
343 /****************************************************************************
344 * Generic printing interface definitions...
345 ***************************************************************************/
347 struct printif generic_printif
=
352 generic_queue_resume
,