r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
[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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "printing.h"
23
24
25 /****************************************************************************
26 run a given print command 
27 a null terminated list of value/substitute pairs is provided
28 for local substitution strings
29 ****************************************************************************/
30 static int print_run_command(int snum, const char* printername, BOOL do_sub,
31                              const char *command, int *outfd, ...)
32 {
33         extern struct current_user current_user;
34         extern userdom_struct current_user_info;
35         
36         pstring syscmd;
37         char *arg;
38         int ret;
39         va_list ap;
40         va_start(ap, outfd);
41
42         /* check for a valid system printername and valid command to run */
43
44         if ( !printername || !*printername ) 
45                 return -1;
46
47         if (!command || !*command) 
48                 return -1;
49
50         pstrcpy(syscmd, command);
51
52         while ((arg = va_arg(ap, char *))) {
53                 char *value = va_arg(ap,char *);
54                 pstring_sub(syscmd, arg, value);
55         }
56         va_end(ap);
57   
58         pstring_sub( syscmd, "%p", printername );
59
60         if ( do_sub && snum != -1 )
61                 standard_sub_advanced(lp_servicename(snum),
62                                       current_user_info.unix_name, "",
63                                       current_user.ut.gid,
64                                       get_current_username(),
65                                       current_user_info.domain,
66                                       syscmd, sizeof(syscmd));
67                 
68         ret = smbrun(syscmd,outfd);
69
70         DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
71
72         return ret;
73 }
74
75
76 /****************************************************************************
77 delete a print job
78 ****************************************************************************/
79 static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
80 {
81         fstring jobstr;
82
83         /* need to delete the spooled entry */
84         slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
85         return print_run_command( -1, sharename, False, lprm_command, NULL,
86                    "%j", jobstr,
87                    "%T", http_timestring(pjob->starttime),
88                    NULL);
89 }
90
91 /****************************************************************************
92 pause a job
93 ****************************************************************************/
94 static int generic_job_pause(int snum, struct printjob *pjob)
95 {
96         fstring jobstr;
97         
98         /* need to pause the spooled entry */
99         slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
100         return print_run_command(snum, PRINTERNAME(snum), True,
101                                  lp_lppausecommand(snum), NULL,
102                                  "%j", jobstr,
103                                  NULL);
104 }
105
106 /****************************************************************************
107 resume a job
108 ****************************************************************************/
109 static int generic_job_resume(int snum, struct printjob *pjob)
110 {
111         fstring jobstr;
112         
113         /* need to pause the spooled entry */
114         slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
115         return print_run_command(snum, PRINTERNAME(snum), True,
116                                  lp_lpresumecommand(snum), NULL,
117                                  "%j", jobstr,
118                                  NULL);
119 }
120
121 /****************************************************************************
122  Submit a file for printing - called from print_job_end()
123 ****************************************************************************/
124
125 static int generic_job_submit(int snum, struct printjob *pjob)
126 {
127         int ret;
128         pstring current_directory;
129         pstring print_directory;
130         char *wd, *p;
131         pstring jobname;
132         fstring job_page_count, job_size;
133
134         /* we print from the directory path to give the best chance of
135            parsing the lpq output */
136         wd = sys_getwd(current_directory);
137         if (!wd)
138                 return 0;
139
140         pstrcpy(print_directory, pjob->filename);
141         p = strrchr_m(print_directory,'/');
142         if (!p)
143                 return 0;
144         *p++ = 0;
145
146         if (chdir(print_directory) != 0)
147                 return 0;
148
149         pstrcpy(jobname, pjob->jobname);
150         pstring_sub(jobname, "'", "_");
151         slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
152         slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);
153
154         /* send it to the system spooler */
155         ret = print_run_command(snum, PRINTERNAME(snum), True,
156                         lp_printcommand(snum), NULL,
157                         "%s", p,
158                         "%J", jobname,
159                         "%f", p,
160                         "%z", job_size,
161                         "%c", job_page_count,
162                         NULL);
163
164         chdir(wd);
165
166         return ret;
167 }
168
169
170 /****************************************************************************
171 get the current list of queued jobs
172 ****************************************************************************/
173 static int generic_queue_get(const char *printer_name, 
174                              enum printing_types printing_type,
175                              char *lpq_command,
176                              print_queue_struct **q, 
177                              print_status_struct *status)
178 {
179         char **qlines;
180         int fd;
181         int numlines, i, qcount;
182         print_queue_struct *queue = NULL;
183         
184         /* never do substitution when running the 'lpq command' since we can't
185            get it rigt when using the background update daemon.  Make the caller 
186            do it before passing off the command string to us here. */
187
188         print_run_command(-1, printer_name, False, lpq_command, &fd, NULL);
189
190         if (fd == -1) {
191                 DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n",
192                         printer_name ));
193                 return 0;
194         }
195         
196         numlines = 0;
197         qlines = fd_lines_load(fd, &numlines,0);
198         close(fd);
199
200         /* turn the lpq output into a series of job structures */
201         qcount = 0;
202         ZERO_STRUCTP(status);
203         if (numlines && qlines) {
204                 queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
205                 if (!queue) {
206                         file_lines_free(qlines);
207                         *q = NULL;
208                         return 0;
209                 }
210                 memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
211
212                 for (i=0; i<numlines; i++) {
213                         /* parse the line */
214                         if (parse_lpq_entry(printing_type,qlines[i],
215                                             &queue[qcount],status,qcount==0)) {
216                                 qcount++;
217                         }
218                 }               
219         }
220
221         file_lines_free(qlines);
222         *q = queue;
223         return qcount;
224 }
225
226 /****************************************************************************
227  pause a queue
228 ****************************************************************************/
229 static int generic_queue_pause(int snum)
230 {
231         return print_run_command(snum, PRINTERNAME(snum), True, lp_queuepausecommand(snum), NULL, NULL);
232 }
233
234 /****************************************************************************
235  resume a queue
236 ****************************************************************************/
237 static int generic_queue_resume(int snum)
238 {
239         return print_run_command(snum, PRINTERNAME(snum), True, lp_queueresumecommand(snum), NULL, NULL);
240 }
241
242 /****************************************************************************
243  * Generic printing interface definitions...
244  ***************************************************************************/
245
246 struct printif  generic_printif =
247 {
248         DEFAULT_PRINTING,
249         generic_queue_get,
250         generic_queue_pause,
251         generic_queue_resume,
252         generic_job_delete,
253         generic_job_pause,
254         generic_job_resume,
255         generic_job_submit,
256 };
257