lib: Give lib/util/util_file.c its own header file
[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 "lib/util/util_file.h"
22 #include "printing.h"
23 #include "smbd/proto.h"
24 #include "source3/lib/substitute.h"
25
26 extern userdom_struct current_user_info;
27
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, ...)
35 {
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);
44
45         /* check for a valid system printername and valid command to run */
46
47         if ( !printername || !*printername ) {
48                 va_end(ap);
49                 return -1;
50         }
51
52         if (!command || !*command) {
53                 va_end(ap);
54                 return -1;
55         }
56
57         syscmd = talloc_strdup(ctx, command);
58         if (!syscmd) {
59                 va_end(ap);
60                 return -1;
61         }
62
63         DBG_DEBUG("Incoming command '%s'\n", syscmd);
64
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;
71                 }
72         }
73         va_end(ap);
74
75         syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
76         if (!syscmd) {
77                 return -1;
78         }
79
80         syscmd = lpcfg_substituted_string(ctx, lp_sub, syscmd);
81         if (syscmd == NULL) {
82                 return -1;
83         }
84
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;
94                 }
95         }
96
97         ret = smbrun_no_sanitize(syscmd, outfd, NULL);
98
99         DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
100
101         return ret;
102 }
103
104
105 /****************************************************************************
106 delete a print job
107 ****************************************************************************/
108 static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
109 {
110         fstring jobstr;
111
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);
118 }
119
120 /****************************************************************************
121 pause a job
122 ****************************************************************************/
123 static int generic_job_pause(int snum, struct printjob *pjob)
124 {
125         const struct loadparm_substitution *lp_sub =
126                 loadparm_s3_global_substitution();
127         fstring jobstr;
128         
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);
135 }
136
137 /****************************************************************************
138 resume a job
139 ****************************************************************************/
140 static int generic_job_resume(int snum, struct printjob *pjob)
141 {
142         const struct loadparm_substitution *lp_sub =
143                 loadparm_s3_global_substitution();
144         fstring jobstr;
145
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);
152 }
153
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)
162 {
163         char **qlines;
164         int fd;
165         int numlines, i, qcount;
166         print_queue_struct *queue = NULL;
167
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. */
171
172         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
173
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;
178         }
179
180         numlines = 0;
181         qlines = fd_lines_load(fd, &numlines,0,NULL);
182         close(fd);
183
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;
193                 }
194                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
195
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++;
201                         }
202                 }
203         }
204
205         TALLOC_FREE(qlines);
206         *q = queue;
207         return qcount;
208 }
209
210 /****************************************************************************
211  Submit a file for printing - called from print_job_end()
212 ****************************************************************************/
213
214 static int generic_job_submit(int snum, struct printjob *pjob,
215                               enum printing_types printing_type,
216                               char *lpq_cmd)
217 {
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;
230
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;
236         }
237
238         current_directory = talloc_strdup(ctx, wd);
239         SAFE_FREE(wd);
240
241         if (!current_directory) {
242                 return -1;
243         }
244         print_directory = talloc_strdup(ctx, pjob->filename);
245         if (!print_directory) {
246                 return -1;
247         }
248         p = strrchr_m(print_directory,'/');
249         if (!p) {
250                 return -1;
251         }
252         *p++ = 0;
253
254         if (chdir(print_directory) != 0) {
255                 return -1;
256         }
257
258         jobname = talloc_strdup(ctx, pjob->jobname);
259         if (!jobname) {
260                 ret = -1;
261                 goto out;
262         }
263         jobname = talloc_string_sub(ctx, jobname, "'", "_");
264         if (!jobname) {
265                 ret = -1;
266                 goto out;
267         }
268         fstr_sprintf(job_page_count, "%d", pjob->page_count);
269         fstr_sprintf(job_size, "%zu", pjob->size);
270
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;
283         }
284
285         /*
286          * check the queue for the newly submitted job, this allows us to
287          * determine the backend job identifier (sysjob).
288          */
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;
300                         }
301                 }
302                 SAFE_FREE(q);
303                 ret = 0;
304         }
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));
308         }
309
310
311  out:
312
313         if (chdir(current_directory) == -1) {
314                 smb_panic("chdir failed in generic_job_submit");
315         }
316         TALLOC_FREE(current_directory);
317         return ret;
318 }
319
320 /****************************************************************************
321  pause a queue
322 ****************************************************************************/
323 static int generic_queue_pause(int snum)
324 {
325         const struct loadparm_substitution *lp_sub =
326                 loadparm_s3_global_substitution();
327
328         return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
329                                  lp_queuepause_command(snum), NULL, NULL);
330 }
331
332 /****************************************************************************
333  resume a queue
334 ****************************************************************************/
335 static int generic_queue_resume(int snum)
336 {
337         const struct loadparm_substitution *lp_sub =
338                 loadparm_s3_global_substitution();
339
340         return print_run_command(snum, lp_printername(talloc_tos(), lp_sub, snum), True,
341                                  lp_queueresume_command(snum), NULL, NULL);
342 }
343
344 /****************************************************************************
345  * Generic printing interface definitions...
346  ***************************************************************************/
347
348 struct printif  generic_printif =
349 {
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,
358 };
359