s3:idmap_ad: add support for ADS_AUTH_SASL_{STARTTLS,LDAPS}
[Samba.git] / source3 / printing / print_generic.c
bloba8bf9aff972527fb6337c6c139ffde5df68b4efe
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 "lib/util/util_file.h"
22 #include "printing.h"
23 #include "smbd/proto.h"
24 #include "source3/lib/substitute.h"
26 extern userdom_struct current_user_info;
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 static int print_run_command(int snum, const char* printername, bool do_sub,
34 const char *command, int *outfd, ...)
36 const struct loadparm_substitution *lp_sub =
37 loadparm_s3_global_substitution();
38 char *syscmd;
39 char *arg;
40 int ret;
41 TALLOC_CTX *ctx = talloc_tos();
42 va_list ap;
43 va_start(ap, outfd);
45 /* check for a valid system printername and valid command to run */
47 if ( !printername || !*printername ) {
48 va_end(ap);
49 return -1;
52 if (!command || !*command) {
53 va_end(ap);
54 return -1;
57 syscmd = talloc_strdup(ctx, command);
58 if (!syscmd) {
59 va_end(ap);
60 return -1;
63 DBG_DEBUG("Incoming command '%s'\n", syscmd);
65 while ((arg = va_arg(ap, char *))) {
66 char *value = va_arg(ap,char *);
67 syscmd = talloc_string_sub(ctx, syscmd, arg, value);
68 if (!syscmd) {
69 va_end(ap);
70 return -1;
73 va_end(ap);
75 syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
76 if (!syscmd) {
77 return -1;
80 syscmd = lpcfg_substituted_string(ctx, lp_sub, syscmd);
81 if (syscmd == NULL) {
82 return -1;
85 if (do_sub && snum != -1) {
86 syscmd = talloc_sub_advanced(ctx,
87 lp_servicename(talloc_tos(), lp_sub, snum),
88 current_user_info.unix_name,
89 "",
90 get_current_gid(NULL),
91 syscmd);
92 if (!syscmd) {
93 return -1;
97 ret = smbrun_no_sanitize(syscmd, outfd, NULL);
99 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
101 return ret;
105 /****************************************************************************
106 delete a print job
107 ****************************************************************************/
108 static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
110 fstring jobstr;
112 /* need to delete the spooled entry */
113 fstr_sprintf(jobstr, "%d", pjob->sysjob);
114 return print_run_command( -1, sharename, False, lprm_command, NULL,
115 "%j", jobstr,
116 "%T", http_timestring(talloc_tos(), pjob->starttime),
117 NULL);
120 /****************************************************************************
121 pause a job
122 ****************************************************************************/
123 static int generic_job_pause(int snum, struct printjob *pjob)
125 const struct loadparm_substitution *lp_sub =
126 loadparm_s3_global_substitution();
127 fstring jobstr;
129 /* need to pause the spooled entry */
130 fstr_sprintf(jobstr, "%d", pjob->sysjob);
131 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
132 lp_lppause_command(snum), NULL,
133 "%j", jobstr,
134 NULL);
137 /****************************************************************************
138 resume a job
139 ****************************************************************************/
140 static int generic_job_resume(int snum, struct printjob *pjob)
142 const struct loadparm_substitution *lp_sub =
143 loadparm_s3_global_substitution();
144 fstring jobstr;
146 /* need to pause the spooled entry */
147 fstr_sprintf(jobstr, "%d", pjob->sysjob);
148 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
149 lp_lpresume_command(snum), NULL,
150 "%j", jobstr,
151 NULL);
154 /****************************************************************************
155 get the current list of queued jobs
156 ****************************************************************************/
157 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)
163 char **qlines;
164 int fd;
165 int numlines, i, qcount;
166 print_queue_struct *queue = NULL;
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. */
172 print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
174 if (fd == -1) {
175 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
176 printer_name ));
177 return 0;
180 numlines = 0;
181 qlines = fd_lines_load(fd, &numlines,0,NULL);
182 close(fd);
184 /* turn the lpq output into a series of job structures */
185 qcount = 0;
186 ZERO_STRUCTP(status);
187 if (numlines && qlines) {
188 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
189 if (!queue) {
190 TALLOC_FREE(qlines);
191 *q = NULL;
192 return 0;
194 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
196 for (i=0; i<numlines; i++) {
197 /* parse the line */
198 if (parse_lpq_entry(printing_type,qlines[i],
199 &queue[qcount],status,qcount==0)) {
200 qcount++;
205 TALLOC_FREE(qlines);
206 *q = queue;
207 return qcount;
210 /****************************************************************************
211 Submit a file for printing - called from print_job_end()
212 ****************************************************************************/
214 static int generic_job_submit(int snum, struct printjob *pjob,
215 enum printing_types printing_type,
216 char *lpq_cmd)
218 int ret = -1;
219 const struct loadparm_substitution *lp_sub =
220 loadparm_s3_global_substitution();
221 char *current_directory = NULL;
222 char *print_directory = NULL;
223 char *wd = NULL;
224 char *p = NULL;
225 char *jobname = NULL;
226 TALLOC_CTX *ctx = talloc_tos();
227 fstring job_page_count, job_size;
228 print_queue_struct *q;
229 print_status_struct status;
231 /* we print from the directory path to give the best chance of
232 parsing the lpq output */
233 wd = sys_getwd();
234 if (!wd) {
235 return -1;
238 current_directory = talloc_strdup(ctx, wd);
239 SAFE_FREE(wd);
241 if (!current_directory) {
242 return -1;
244 print_directory = talloc_strdup(ctx, pjob->filename);
245 if (!print_directory) {
246 return -1;
248 p = strrchr_m(print_directory,'/');
249 if (!p) {
250 return -1;
252 *p++ = 0;
254 if (chdir(print_directory) != 0) {
255 return -1;
258 jobname = talloc_strdup(ctx, pjob->jobname);
259 if (!jobname) {
260 ret = -1;
261 goto out;
263 jobname = talloc_string_sub(ctx, jobname, "'", "_");
264 if (!jobname) {
265 ret = -1;
266 goto out;
268 fstr_sprintf(job_page_count, "%d", pjob->page_count);
269 fstr_sprintf(job_size, "%zu", pjob->size);
271 /* send it to the system spooler */
272 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 if (ret != 0) {
281 ret = -1;
282 goto out;
286 * check the queue for the newly submitted job, this allows us to
287 * determine the backend job identifier (sysjob).
289 pjob->sysjob = -1;
290 ret = generic_queue_get(lp_printername(talloc_tos(), lp_sub, snum),
291 printing_type, lpq_cmd, &q, &status);
292 if (ret > 0) {
293 int i;
294 for (i = 0; i < ret; i++) {
295 if (strcmp(q[i].fs_file, p) == 0) {
296 pjob->sysjob = q[i].sysjob;
297 DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
298 pjob->jobid, jobname, pjob->sysjob));
299 break;
302 SAFE_FREE(q);
303 ret = 0;
305 if (pjob->sysjob == -1) {
306 DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
307 "Unix job\n", pjob->jobid, jobname));
311 out:
313 if (chdir(current_directory) == -1) {
314 smb_panic("chdir failed in generic_job_submit");
316 TALLOC_FREE(current_directory);
317 return ret;
320 /****************************************************************************
321 pause a queue
322 ****************************************************************************/
323 static int generic_queue_pause(int snum)
325 const struct loadparm_substitution *lp_sub =
326 loadparm_s3_global_substitution();
328 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
329 lp_queuepause_command(snum), NULL, NULL);
332 /****************************************************************************
333 resume a queue
334 ****************************************************************************/
335 static int generic_queue_resume(int snum)
337 const struct loadparm_substitution *lp_sub =
338 loadparm_s3_global_substitution();
340 return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
341 lp_queueresume_command(snum), NULL, NULL);
344 /****************************************************************************
345 * Generic printing interface definitions...
346 ***************************************************************************/
348 struct printif generic_printif =
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,