s3:param: make "servicename" a substituted option
[Samba.git] / source3 / printing / print_generic.c
blob0059fad23c568587e68a78100cbfa79520fe9c05
1 /*
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/>.
20 #include "includes.h"
21 #include "printing.h"
22 #include "smbd/proto.h"
24 extern userdom_struct current_user_info;
26 /****************************************************************************
27 Run a given print command
28 a null terminated list of value/substitute pairs is provided
29 for local substitution strings
30 ****************************************************************************/
31 static int print_run_command(int snum, const char* printername, bool do_sub,
32 const char *command, int *outfd, ...)
34 const struct loadparm_substitution *lp_sub =
35 loadparm_s3_global_substitution();
36 char *syscmd;
37 char *arg;
38 int ret;
39 TALLOC_CTX *ctx = talloc_tos();
40 va_list ap;
41 va_start(ap, outfd);
43 /* check for a valid system printername and valid command to run */
45 if ( !printername || !*printername ) {
46 va_end(ap);
47 return -1;
50 if (!command || !*command) {
51 va_end(ap);
52 return -1;
55 syscmd = talloc_strdup(ctx, command);
56 if (!syscmd) {
57 va_end(ap);
58 return -1;
61 DBG_DEBUG("Incoming command '%s'\n", syscmd);
63 while ((arg = va_arg(ap, char *))) {
64 char *value = va_arg(ap,char *);
65 syscmd = talloc_string_sub(ctx, syscmd, arg, value);
66 if (!syscmd) {
67 va_end(ap);
68 return -1;
71 va_end(ap);
73 syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
74 if (!syscmd) {
75 return -1;
78 syscmd = lpcfg_substituted_string(ctx, lp_sub, syscmd);
79 if (syscmd == NULL) {
80 return -1;
83 if (do_sub && snum != -1) {
84 syscmd = talloc_sub_advanced(ctx,
85 lp_servicename(talloc_tos(), lp_sub, snum),
86 current_user_info.unix_name,
87 "",
88 get_current_gid(NULL),
89 syscmd);
90 if (!syscmd) {
91 return -1;
95 ret = smbrun_no_sanitize(syscmd, outfd, NULL);
97 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
99 return ret;
103 /****************************************************************************
104 delete a print job
105 ****************************************************************************/
106 static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
108 fstring jobstr;
110 /* need to delete the spooled entry */
111 slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
112 return print_run_command( -1, sharename, False, lprm_command, NULL,
113 "%j", jobstr,
114 "%T", http_timestring(talloc_tos(), pjob->starttime),
115 NULL);
118 /****************************************************************************
119 pause a job
120 ****************************************************************************/
121 static int generic_job_pause(int snum, struct printjob *pjob)
123 const struct loadparm_substitution *lp_sub =
124 loadparm_s3_global_substitution();
125 fstring jobstr;
127 /* need to pause the spooled entry */
128 slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
129 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
130 lp_lppause_command(snum), NULL,
131 "%j", jobstr,
132 NULL);
135 /****************************************************************************
136 resume a job
137 ****************************************************************************/
138 static int generic_job_resume(int snum, struct printjob *pjob)
140 const struct loadparm_substitution *lp_sub =
141 loadparm_s3_global_substitution();
142 fstring jobstr;
144 /* need to pause the spooled entry */
145 slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
146 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
147 lp_lpresume_command(snum), NULL,
148 "%j", jobstr,
149 NULL);
152 /****************************************************************************
153 get the current list of queued jobs
154 ****************************************************************************/
155 static int generic_queue_get(const char *printer_name,
156 enum printing_types printing_type,
157 char *lpq_command,
158 print_queue_struct **q,
159 print_status_struct *status)
161 char **qlines;
162 int fd;
163 int numlines, i, qcount;
164 print_queue_struct *queue = NULL;
166 /* never do substitution when running the 'lpq command' since we can't
167 get it rigt when using the background update daemon. Make the caller
168 do it before passing off the command string to us here. */
170 print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
172 if (fd == -1) {
173 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
174 printer_name ));
175 return 0;
178 numlines = 0;
179 qlines = fd_lines_load(fd, &numlines,0,NULL);
180 close(fd);
182 /* turn the lpq output into a series of job structures */
183 qcount = 0;
184 ZERO_STRUCTP(status);
185 if (numlines && qlines) {
186 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
187 if (!queue) {
188 TALLOC_FREE(qlines);
189 *q = NULL;
190 return 0;
192 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
194 for (i=0; i<numlines; i++) {
195 /* parse the line */
196 if (parse_lpq_entry(printing_type,qlines[i],
197 &queue[qcount],status,qcount==0)) {
198 qcount++;
203 TALLOC_FREE(qlines);
204 *q = queue;
205 return qcount;
208 /****************************************************************************
209 Submit a file for printing - called from print_job_end()
210 ****************************************************************************/
212 static int generic_job_submit(int snum, struct printjob *pjob,
213 enum printing_types printing_type,
214 char *lpq_cmd)
216 int ret = -1;
217 const struct loadparm_substitution *lp_sub =
218 loadparm_s3_global_substitution();
219 char *current_directory = NULL;
220 char *print_directory = NULL;
221 char *wd = NULL;
222 char *p = NULL;
223 char *jobname = NULL;
224 TALLOC_CTX *ctx = talloc_tos();
225 fstring job_page_count, job_size;
226 print_queue_struct *q;
227 print_status_struct status;
229 /* we print from the directory path to give the best chance of
230 parsing the lpq output */
231 wd = sys_getwd();
232 if (!wd) {
233 return -1;
236 current_directory = talloc_strdup(ctx, wd);
237 SAFE_FREE(wd);
239 if (!current_directory) {
240 return -1;
242 print_directory = talloc_strdup(ctx, pjob->filename);
243 if (!print_directory) {
244 return -1;
246 p = strrchr_m(print_directory,'/');
247 if (!p) {
248 return -1;
250 *p++ = 0;
252 if (chdir(print_directory) != 0) {
253 return -1;
256 jobname = talloc_strdup(ctx, pjob->jobname);
257 if (!jobname) {
258 ret = -1;
259 goto out;
261 jobname = talloc_string_sub(ctx, jobname, "'", "_");
262 if (!jobname) {
263 ret = -1;
264 goto out;
266 slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
267 slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);
269 /* send it to the system spooler */
270 ret = print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
271 lp_print_command(snum), NULL,
272 "%s", p,
273 "%J", jobname,
274 "%f", p,
275 "%z", job_size,
276 "%c", job_page_count,
277 NULL);
278 if (ret != 0) {
279 ret = -1;
280 goto out;
284 * check the queue for the newly submitted job, this allows us to
285 * determine the backend job identifier (sysjob).
287 pjob->sysjob = -1;
288 ret = generic_queue_get(lp_printername(talloc_tos(), lp_sub, snum),
289 printing_type, lpq_cmd, &q, &status);
290 if (ret > 0) {
291 int i;
292 for (i = 0; i < ret; i++) {
293 if (strcmp(q[i].fs_file, p) == 0) {
294 pjob->sysjob = q[i].sysjob;
295 DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
296 pjob->jobid, jobname, pjob->sysjob));
297 break;
300 SAFE_FREE(q);
301 ret = 0;
303 if (pjob->sysjob == -1) {
304 DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
305 "Unix job\n", pjob->jobid, jobname));
309 out:
311 if (chdir(current_directory) == -1) {
312 smb_panic("chdir failed in generic_job_submit");
314 TALLOC_FREE(current_directory);
315 return ret;
318 /****************************************************************************
319 pause a queue
320 ****************************************************************************/
321 static int generic_queue_pause(int snum)
323 const struct loadparm_substitution *lp_sub =
324 loadparm_s3_global_substitution();
326 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
327 lp_queuepause_command(snum), NULL, NULL);
330 /****************************************************************************
331 resume a queue
332 ****************************************************************************/
333 static int generic_queue_resume(int snum)
335 const struct loadparm_substitution *lp_sub =
336 loadparm_s3_global_substitution();
338 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
339 lp_queueresume_command(snum), NULL, NULL);
342 /****************************************************************************
343 * Generic printing interface definitions...
344 ***************************************************************************/
346 struct printif generic_printif =
348 DEFAULT_PRINTING,
349 generic_queue_get,
350 generic_queue_pause,
351 generic_queue_resume,
352 generic_job_delete,
353 generic_job_pause,
354 generic_job_resume,
355 generic_job_submit,