s3:winbindd: use wb_sids2xids instead of wb_sid2gid in winbindd_sid_to_gid
[kai/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(talloc_tos(), 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(talloc_tos(), snum), True,
121                                  lp_lppausecommand(talloc_tos(), 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(talloc_tos(), snum), True,
136                                  lp_lpresumecommand(talloc_tos(), snum), NULL,
137                                  "%j", jobstr,
138                                  NULL);
139 }
140
141 /****************************************************************************
142 get the current list of queued jobs
143 ****************************************************************************/
144 static int generic_queue_get(const char *printer_name,
145                              enum printing_types printing_type,
146                              char *lpq_command,
147                              print_queue_struct **q,
148                              print_status_struct *status)
149 {
150         char **qlines;
151         int fd;
152         int numlines, i, qcount;
153         print_queue_struct *queue = NULL;
154
155         /* never do substitution when running the 'lpq command' since we can't
156            get it rigt when using the background update daemon.  Make the caller
157            do it before passing off the command string to us here. */
158
159         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
160
161         if (fd == -1) {
162                 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
163                         printer_name ));
164                 return 0;
165         }
166
167         numlines = 0;
168         qlines = fd_lines_load(fd, &numlines,0,NULL);
169         close(fd);
170
171         /* turn the lpq output into a series of job structures */
172         qcount = 0;
173         ZERO_STRUCTP(status);
174         if (numlines && qlines) {
175                 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
176                 if (!queue) {
177                         TALLOC_FREE(qlines);
178                         *q = NULL;
179                         return 0;
180                 }
181                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
182
183                 for (i=0; i<numlines; i++) {
184                         /* parse the line */
185                         if (parse_lpq_entry(printing_type,qlines[i],
186                                             &queue[qcount],status,qcount==0)) {
187                                 qcount++;
188                         }
189                 }
190         }
191
192         TALLOC_FREE(qlines);
193         *q = queue;
194         return qcount;
195 }
196
197 /****************************************************************************
198  Submit a file for printing - called from print_job_end()
199 ****************************************************************************/
200
201 static int generic_job_submit(int snum, struct printjob *pjob,
202                               enum printing_types printing_type,
203                               char *lpq_cmd)
204 {
205         int ret = -1;
206         char *current_directory = NULL;
207         char *print_directory = NULL;
208         char *wd = NULL;
209         char *p = NULL;
210         char *jobname = NULL;
211         TALLOC_CTX *ctx = talloc_tos();
212         fstring job_page_count, job_size;
213         print_queue_struct *q;
214         print_status_struct status;
215
216         /* we print from the directory path to give the best chance of
217            parsing the lpq output */
218         wd = sys_getwd();
219         if (!wd) {
220                 return -1;
221         }
222
223         current_directory = talloc_strdup(ctx, wd);
224         SAFE_FREE(wd);
225
226         if (!current_directory) {
227                 return -1;
228         }
229         print_directory = talloc_strdup(ctx, pjob->filename);
230         if (!print_directory) {
231                 return -1;
232         }
233         p = strrchr_m(print_directory,'/');
234         if (!p) {
235                 return -1;
236         }
237         *p++ = 0;
238
239         if (chdir(print_directory) != 0) {
240                 return -1;
241         }
242
243         jobname = talloc_strdup(ctx, pjob->jobname);
244         if (!jobname) {
245                 ret = -1;
246                 goto out;
247         }
248         jobname = talloc_string_sub(ctx, jobname, "'", "_");
249         if (!jobname) {
250                 ret = -1;
251                 goto out;
252         }
253         slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
254         slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);
255
256         /* send it to the system spooler */
257         ret = print_run_command(snum, lp_printername(talloc_tos(), snum), True,
258                         lp_printcommand(talloc_tos(), snum), NULL,
259                         "%s", p,
260                         "%J", jobname,
261                         "%f", p,
262                         "%z", job_size,
263                         "%c", job_page_count,
264                         NULL);
265         if (ret != 0) {
266                 ret = -1;
267                 goto out;
268         }
269
270         /*
271          * check the queue for the newly submitted job, this allows us to
272          * determine the backend job identifier (sysjob).
273          */
274         pjob->sysjob = -1;
275         ret = generic_queue_get(lp_printername(talloc_tos(), snum),
276                                 printing_type, lpq_cmd, &q, &status);
277         if (ret > 0) {
278                 int i;
279                 for (i = 0; i < ret; i++) {
280                         if (strcmp(q[i].fs_file, p) == 0) {
281                                 pjob->sysjob = q[i].sysjob;
282                                 DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
283                                           pjob->jobid, jobname, pjob->sysjob));
284                                 break;
285                         }
286                 }
287                 SAFE_FREE(q);
288                 ret = 0;
289         }
290         if (pjob->sysjob == -1) {
291                 DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
292                           "Unix job\n", pjob->jobid, jobname));
293         }
294
295
296  out:
297
298         if (chdir(current_directory) == -1) {
299                 smb_panic("chdir failed in generic_job_submit");
300         }
301         TALLOC_FREE(current_directory);
302         return ret;
303 }
304
305 /****************************************************************************
306  pause a queue
307 ****************************************************************************/
308 static int generic_queue_pause(int snum)
309 {
310         return print_run_command(snum, lp_printername(talloc_tos(), snum), True,
311                                  lp_queuepausecommand(talloc_tos(), snum), NULL, NULL);
312 }
313
314 /****************************************************************************
315  resume a queue
316 ****************************************************************************/
317 static int generic_queue_resume(int snum)
318 {
319         return print_run_command(snum, lp_printername(talloc_tos(), snum), True,
320                                  lp_queueresumecommand(talloc_tos(), snum), NULL, NULL);
321 }
322
323 /****************************************************************************
324  * Generic printing interface definitions...
325  ***************************************************************************/
326
327 struct printif  generic_printif =
328 {
329         DEFAULT_PRINTING,
330         generic_queue_get,
331         generic_queue_pause,
332         generic_queue_resume,
333         generic_job_delete,
334         generic_job_pause,
335         generic_job_resume,
336         generic_job_submit,
337 };
338