third_party: Update socket_wrapper to version 1.4.2
[Samba.git] / source3 / printing / print_generic.c
blob8798a4cf34a3de30411d5107ef6051a63f6b59cf
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"
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();
37 char *syscmd;
38 char *arg;
39 int ret;
40 TALLOC_CTX *ctx = talloc_tos();
41 va_list ap;
42 va_start(ap, outfd);
44 /* check for a valid system printername and valid command to run */
46 if ( !printername || !*printername ) {
47 va_end(ap);
48 return -1;
51 if (!command || !*command) {
52 va_end(ap);
53 return -1;
56 syscmd = talloc_strdup(ctx, command);
57 if (!syscmd) {
58 va_end(ap);
59 return -1;
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);
67 if (!syscmd) {
68 va_end(ap);
69 return -1;
72 va_end(ap);
74 syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
75 if (!syscmd) {
76 return -1;
79 syscmd = lpcfg_substituted_string(ctx, lp_sub, syscmd);
80 if (syscmd == NULL) {
81 return -1;
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,
88 "",
89 get_current_gid(NULL),
90 syscmd);
91 if (!syscmd) {
92 return -1;
96 ret = smbrun_no_sanitize(syscmd, outfd, NULL);
98 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
100 return ret;
104 /****************************************************************************
105 delete a print job
106 ****************************************************************************/
107 static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
109 fstring jobstr;
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,
114 "%j", jobstr,
115 "%T", http_timestring(talloc_tos(), pjob->starttime),
116 NULL);
119 /****************************************************************************
120 pause a job
121 ****************************************************************************/
122 static int generic_job_pause(int snum, struct printjob *pjob)
124 const struct loadparm_substitution *lp_sub =
125 loadparm_s3_global_substitution();
126 fstring jobstr;
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,
132 "%j", jobstr,
133 NULL);
136 /****************************************************************************
137 resume a job
138 ****************************************************************************/
139 static int generic_job_resume(int snum, struct printjob *pjob)
141 const struct loadparm_substitution *lp_sub =
142 loadparm_s3_global_substitution();
143 fstring jobstr;
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,
149 "%j", jobstr,
150 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,
158 char *lpq_command,
159 print_queue_struct **q,
160 print_status_struct *status)
162 char **qlines;
163 int fd;
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);
173 if (fd == -1) {
174 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
175 printer_name ));
176 return 0;
179 numlines = 0;
180 qlines = fd_lines_load(fd, &numlines,0,NULL);
181 close(fd);
183 /* turn the lpq output into a series of job structures */
184 qcount = 0;
185 ZERO_STRUCTP(status);
186 if (numlines && qlines) {
187 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
188 if (!queue) {
189 TALLOC_FREE(qlines);
190 *q = NULL;
191 return 0;
193 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
195 for (i=0; i<numlines; i++) {
196 /* parse the line */
197 if (parse_lpq_entry(printing_type,qlines[i],
198 &queue[qcount],status,qcount==0)) {
199 qcount++;
204 TALLOC_FREE(qlines);
205 *q = queue;
206 return qcount;
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,
215 char *lpq_cmd)
217 int ret = -1;
218 const struct loadparm_substitution *lp_sub =
219 loadparm_s3_global_substitution();
220 char *current_directory = NULL;
221 char *print_directory = NULL;
222 char *wd = NULL;
223 char *p = 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 */
232 wd = sys_getwd();
233 if (!wd) {
234 return -1;
237 current_directory = talloc_strdup(ctx, wd);
238 SAFE_FREE(wd);
240 if (!current_directory) {
241 return -1;
243 print_directory = talloc_strdup(ctx, pjob->filename);
244 if (!print_directory) {
245 return -1;
247 p = strrchr_m(print_directory,'/');
248 if (!p) {
249 return -1;
251 *p++ = 0;
253 if (chdir(print_directory) != 0) {
254 return -1;
257 jobname = talloc_strdup(ctx, pjob->jobname);
258 if (!jobname) {
259 ret = -1;
260 goto out;
262 jobname = talloc_string_sub(ctx, jobname, "'", "_");
263 if (!jobname) {
264 ret = -1;
265 goto out;
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,
273 "%s", p,
274 "%J", jobname,
275 "%f", p,
276 "%z", job_size,
277 "%c", job_page_count,
278 NULL);
279 if (ret != 0) {
280 ret = -1;
281 goto out;
285 * check the queue for the newly submitted job, this allows us to
286 * determine the backend job identifier (sysjob).
288 pjob->sysjob = -1;
289 ret = generic_queue_get(lp_printername(talloc_tos(), lp_sub, snum),
290 printing_type, lpq_cmd, &q, &status);
291 if (ret > 0) {
292 int i;
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));
298 break;
301 SAFE_FREE(q);
302 ret = 0;
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));
310 out:
312 if (chdir(current_directory) == -1) {
313 smb_panic("chdir failed in generic_job_submit");
315 TALLOC_FREE(current_directory);
316 return ret;
319 /****************************************************************************
320 pause a queue
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 /****************************************************************************
332 resume a queue
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 =
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,