s3-printing: pass lpq command to job_submit
[samba.git] / source3 / printing / print_generic.c
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
23 extern struct current_user current_user;
24 extern userdom_struct current_user_info;
25
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, ...)
33 {
34         char *syscmd;
35         char *arg;
36         int ret;
37         TALLOC_CTX *ctx = talloc_tos();
38         va_list ap;
39         va_start(ap, outfd);
40
41         /* check for a valid system printername and valid command to run */
42
43         if ( !printername || !*printername ) {
44                 va_end(ap);
45                 return -1;
46         }
47
48         if (!command || !*command) {
49                 va_end(ap);
50                 return -1;
51         }
52
53         syscmd = talloc_strdup(ctx, command);
54         if (!syscmd) {
55                 va_end(ap);
56                 return -1;
57         }
58
59         while ((arg = va_arg(ap, char *))) {
60                 char *value = va_arg(ap,char *);
61                 syscmd = talloc_string_sub(ctx, syscmd, arg, value);
62                 if (!syscmd) {
63                         va_end(ap);
64                         return -1;
65                 }
66         }
67         va_end(ap);
68
69         syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
70         if (!syscmd) {
71                 return -1;
72         }
73
74         if (do_sub && snum != -1) {
75                 syscmd = talloc_sub_advanced(ctx,
76                                 lp_servicename(snum),
77                                 current_user_info.unix_name,
78                                 "",
79                                 current_user.ut.gid,
80                                 get_current_username(),
81                                 current_user_info.domain,
82                                 syscmd);
83                 if (!syscmd) {
84                         return -1;
85                 }
86         }
87
88         ret = smbrun_no_sanitize(syscmd,outfd);
89
90         DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
91
92         return ret;
93 }
94
95
96 /****************************************************************************
97 delete a print job
98 ****************************************************************************/
99 static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
100 {
101         fstring jobstr;
102
103         /* need to delete the spooled entry */
104         slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
105         return print_run_command( -1, sharename, False, lprm_command, NULL,
106                    "%j", jobstr,
107                    "%T", http_timestring(talloc_tos(), pjob->starttime),
108                    NULL);
109 }
110
111 /****************************************************************************
112 pause a job
113 ****************************************************************************/
114 static int generic_job_pause(int snum, struct printjob *pjob)
115 {
116         fstring jobstr;
117         
118         /* need to pause the spooled entry */
119         slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
120         return print_run_command(snum, lp_printername(snum), True,
121                                  lp_lppausecommand(snum), NULL,
122                                  "%j", jobstr,
123                                  NULL);
124 }
125
126 /****************************************************************************
127 resume a job
128 ****************************************************************************/
129 static int generic_job_resume(int snum, struct printjob *pjob)
130 {
131         fstring jobstr;
132
133         /* need to pause the spooled entry */
134         slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
135         return print_run_command(snum, lp_printername(snum), True,
136                                  lp_lpresumecommand(snum), NULL,
137                                  "%j", jobstr,
138                                  NULL);
139 }
140
141 /****************************************************************************
142  Submit a file for printing - called from print_job_end()
143 ****************************************************************************/
144
145 static int generic_job_submit(int snum, struct printjob *pjob,
146                               enum printing_types printing_type,
147                               char *lpq_cmd)
148 {
149         int ret = -1;
150         char *current_directory = NULL;
151         char *print_directory = NULL;
152         char *wd = NULL;
153         char *p = NULL;
154         char *jobname = NULL;
155         TALLOC_CTX *ctx = talloc_tos();
156         fstring job_page_count, job_size;
157
158         /* we print from the directory path to give the best chance of
159            parsing the lpq output */
160         wd = sys_getwd();
161         if (!wd) {
162                 return -1;
163         }
164
165         current_directory = talloc_strdup(ctx, wd);
166         SAFE_FREE(wd);
167
168         if (!current_directory) {
169                 return -1;
170         }
171         print_directory = talloc_strdup(ctx, pjob->filename);
172         if (!print_directory) {
173                 return -1;
174         }
175         p = strrchr_m(print_directory,'/');
176         if (!p) {
177                 return -1;
178         }
179         *p++ = 0;
180
181         if (chdir(print_directory) != 0) {
182                 return -1;
183         }
184
185         jobname = talloc_strdup(ctx, pjob->jobname);
186         if (!jobname) {
187                 ret = -1;
188                 goto out;
189         }
190         jobname = talloc_string_sub(ctx, jobname, "'", "_");
191         if (!jobname) {
192                 ret = -1;
193                 goto out;
194         }
195         slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
196         slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);
197
198         /* send it to the system spooler */
199         ret = print_run_command(snum, lp_printername(snum), True,
200                         lp_printcommand(snum), NULL,
201                         "%s", p,
202                         "%J", jobname,
203                         "%f", p,
204                         "%z", job_size,
205                         "%c", job_page_count,
206                         NULL);
207
208  out:
209
210         if (chdir(current_directory) == -1) {
211                 smb_panic("chdir failed in generic_job_submit");
212         }
213         TALLOC_FREE(current_directory);
214         return ret;
215 }
216
217
218 /****************************************************************************
219 get the current list of queued jobs
220 ****************************************************************************/
221 static int generic_queue_get(const char *printer_name, 
222                              enum printing_types printing_type,
223                              char *lpq_command,
224                              print_queue_struct **q, 
225                              print_status_struct *status)
226 {
227         char **qlines;
228         int fd;
229         int numlines, i, qcount;
230         print_queue_struct *queue = NULL;
231         
232         /* never do substitution when running the 'lpq command' since we can't
233            get it rigt when using the background update daemon.  Make the caller 
234            do it before passing off the command string to us here. */
235
236         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
237
238         if (fd == -1) {
239                 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
240                         printer_name ));
241                 return 0;
242         }
243         
244         numlines = 0;
245         qlines = fd_lines_load(fd, &numlines,0,NULL);
246         close(fd);
247
248         /* turn the lpq output into a series of job structures */
249         qcount = 0;
250         ZERO_STRUCTP(status);
251         if (numlines && qlines) {
252                 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
253                 if (!queue) {
254                         TALLOC_FREE(qlines);
255                         *q = NULL;
256                         return 0;
257                 }
258                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
259
260                 for (i=0; i<numlines; i++) {
261                         /* parse the line */
262                         if (parse_lpq_entry(printing_type,qlines[i],
263                                             &queue[qcount],status,qcount==0)) {
264                                 qcount++;
265                         }
266                 }               
267         }
268
269         TALLOC_FREE(qlines);
270         *q = queue;
271         return qcount;
272 }
273
274 /****************************************************************************
275  pause a queue
276 ****************************************************************************/
277 static int generic_queue_pause(int snum)
278 {
279         return print_run_command(snum, lp_printername(snum), True,
280                                  lp_queuepausecommand(snum), NULL, NULL);
281 }
282
283 /****************************************************************************
284  resume a queue
285 ****************************************************************************/
286 static int generic_queue_resume(int snum)
287 {
288         return print_run_command(snum, lp_printername(snum), True,
289                                  lp_queueresumecommand(snum), NULL, NULL);
290 }
291
292 /****************************************************************************
293  * Generic printing interface definitions...
294  ***************************************************************************/
295
296 struct printif  generic_printif =
297 {
298         DEFAULT_PRINTING,
299         generic_queue_get,
300         generic_queue_pause,
301         generic_queue_resume,
302         generic_job_delete,
303         generic_job_pause,
304         generic_job_resume,
305         generic_job_submit,
306 };
307