s3: printing needs parts of smbd.
[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 {
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, lp_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         if (chdir(wd) == -1) {
209                 smb_panic("chdir failed in generic_job_submit");
210         }
211         TALLOC_FREE(current_directory);
212         return ret;
213 }
214
215
216 /****************************************************************************
217 get the current list of queued jobs
218 ****************************************************************************/
219 static int generic_queue_get(const char *printer_name, 
220                              enum printing_types printing_type,
221                              char *lpq_command,
222                              print_queue_struct **q, 
223                              print_status_struct *status)
224 {
225         char **qlines;
226         int fd;
227         int numlines, i, qcount;
228         print_queue_struct *queue = NULL;
229         
230         /* never do substitution when running the 'lpq command' since we can't
231            get it rigt when using the background update daemon.  Make the caller 
232            do it before passing off the command string to us here. */
233
234         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
235
236         if (fd == -1) {
237                 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
238                         printer_name ));
239                 return 0;
240         }
241         
242         numlines = 0;
243         qlines = fd_lines_load(fd, &numlines,0,NULL);
244         close(fd);
245
246         /* turn the lpq output into a series of job structures */
247         qcount = 0;
248         ZERO_STRUCTP(status);
249         if (numlines && qlines) {
250                 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
251                 if (!queue) {
252                         TALLOC_FREE(qlines);
253                         *q = NULL;
254                         return 0;
255                 }
256                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
257
258                 for (i=0; i<numlines; i++) {
259                         /* parse the line */
260                         if (parse_lpq_entry(printing_type,qlines[i],
261                                             &queue[qcount],status,qcount==0)) {
262                                 qcount++;
263                         }
264                 }               
265         }
266
267         TALLOC_FREE(qlines);
268         *q = queue;
269         return qcount;
270 }
271
272 /****************************************************************************
273  pause a queue
274 ****************************************************************************/
275 static int generic_queue_pause(int snum)
276 {
277         return print_run_command(snum, lp_printername(snum), True,
278                                  lp_queuepausecommand(snum), NULL, NULL);
279 }
280
281 /****************************************************************************
282  resume a queue
283 ****************************************************************************/
284 static int generic_queue_resume(int snum)
285 {
286         return print_run_command(snum, lp_printername(snum), True,
287                                  lp_queueresumecommand(snum), NULL, NULL);
288 }
289
290 /****************************************************************************
291  * Generic printing interface definitions...
292  ***************************************************************************/
293
294 struct printif  generic_printif =
295 {
296         DEFAULT_PRINTING,
297         generic_queue_get,
298         generic_queue_pause,
299         generic_queue_resume,
300         generic_job_delete,
301         generic_job_pause,
302         generic_job_resume,
303         generic_job_submit,
304 };
305