0c05915bd8f85a60496a9e8bc8983a6dd32dc175
[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, 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, 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 {
147         int ret = -1;
148         char *current_directory = NULL;
149         char *print_directory = NULL;
150         char *wd = NULL;
151         char *p = NULL;
152         char *jobname = NULL;
153         TALLOC_CTX *ctx = talloc_tos();
154         fstring job_page_count, job_size;
155
156         /* we print from the directory path to give the best chance of
157            parsing the lpq output */
158         current_directory = TALLOC_ARRAY(ctx,
159                                         char,
160                                         PATH_MAX+1);
161         if (!current_directory) {
162                 return -1;
163         }
164         wd = sys_getwd(current_directory);
165         if (!wd) {
166                 return -1;
167         }
168
169         print_directory = talloc_strdup(ctx, pjob->filename);
170         if (!print_directory) {
171                 return -1;
172         }
173         p = strrchr_m(print_directory,'/');
174         if (!p) {
175                 return -1;
176         }
177         *p++ = 0;
178
179         if (chdir(print_directory) != 0) {
180                 return -1;
181         }
182
183         jobname = talloc_strdup(ctx, pjob->jobname);
184         if (!jobname) {
185                 ret = -1;
186                 goto out;
187         }
188         jobname = talloc_string_sub(ctx, jobname, "'", "_");
189         if (!jobname) {
190                 ret = -1;
191                 goto out;
192         }
193         slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
194         slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);
195
196         /* send it to the system spooler */
197         ret = print_run_command(snum, PRINTERNAME(snum), True,
198                         lp_printcommand(snum), NULL,
199                         "%s", p,
200                         "%J", jobname,
201                         "%f", p,
202                         "%z", job_size,
203                         "%c", job_page_count,
204                         NULL);
205
206  out:
207
208         chdir(wd);
209         TALLOC_FREE(current_directory);
210         return ret;
211 }
212
213
214 /****************************************************************************
215 get the current list of queued jobs
216 ****************************************************************************/
217 static int generic_queue_get(const char *printer_name, 
218                              enum printing_types printing_type,
219                              char *lpq_command,
220                              print_queue_struct **q, 
221                              print_status_struct *status)
222 {
223         char **qlines;
224         int fd;
225         int numlines, i, qcount;
226         print_queue_struct *queue = NULL;
227         
228         /* never do substitution when running the 'lpq command' since we can't
229            get it rigt when using the background update daemon.  Make the caller 
230            do it before passing off the command string to us here. */
231
232         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
233
234         if (fd == -1) {
235                 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
236                         printer_name ));
237                 return 0;
238         }
239         
240         numlines = 0;
241         qlines = fd_lines_load(fd, &numlines,0);
242         close(fd);
243
244         /* turn the lpq output into a series of job structures */
245         qcount = 0;
246         ZERO_STRUCTP(status);
247         if (numlines && qlines) {
248                 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
249                 if (!queue) {
250                         file_lines_free(qlines);
251                         *q = NULL;
252                         return 0;
253                 }
254                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
255
256                 for (i=0; i<numlines; i++) {
257                         /* parse the line */
258                         if (parse_lpq_entry(printing_type,qlines[i],
259                                             &queue[qcount],status,qcount==0)) {
260                                 qcount++;
261                         }
262                 }               
263         }
264
265         file_lines_free(qlines);
266         *q = queue;
267         return qcount;
268 }
269
270 /****************************************************************************
271  pause a queue
272 ****************************************************************************/
273 static int generic_queue_pause(int snum)
274 {
275         return print_run_command(snum, PRINTERNAME(snum), True, lp_queuepausecommand(snum), NULL, NULL);
276 }
277
278 /****************************************************************************
279  resume a queue
280 ****************************************************************************/
281 static int generic_queue_resume(int snum)
282 {
283         return print_run_command(snum, PRINTERNAME(snum), True, lp_queueresumecommand(snum), NULL, NULL);
284 }
285
286 /****************************************************************************
287  * Generic printing interface definitions...
288  ***************************************************************************/
289
290 struct printif  generic_printif =
291 {
292         DEFAULT_PRINTING,
293         generic_queue_get,
294         generic_queue_pause,
295         generic_queue_resume,
296         generic_job_delete,
297         generic_job_pause,
298         generic_job_resume,
299         generic_job_submit,
300 };
301