db78105e5ba04975be51e7c2c3fe34a1b9f50c4c
[samba.git] / testsuite / printing / vlp.c
1 /* 
2    Unix SMB/Netbios implementation.
3
4    Virtual lp system for printer testing
5
6    Copyright (C) Tim Potter 2000
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 #define PRINT_TDB "/tmp/vlp.tdb"
25 #define PRINT_FIRSTJOB "100"
26
27 static TDB_CONTEXT *tdb;
28
29 struct vlp_job {
30         fstring owner;
31         int jobid;
32         fstring jobname;
33         int size;
34         int status;
35         time_t submit_time;
36         int deleted;
37 };
38
39 /* Print usage */
40
41 static void usage(void)
42 {
43         printf("Usage: print-test lpq|lprm|print|queuepause|queueresume|"
44                "lppause|lpresume [args]\n");
45 }
46
47 /* Return an array of vlp jobs that is the printer queue */
48
49 static void get_job_list(char *printer, struct vlp_job **job_list, 
50                          int *num_jobs)
51 {
52         fstring keystr;
53         TDB_DATA data;
54
55         slprintf(keystr, sizeof(keystr) - 1, "LPQ/%s", printer);
56         data = tdb_fetch_by_string(tdb, keystr);
57
58         *job_list = (struct vlp_job *)data.dptr;
59         *num_jobs = data.dsize / sizeof(struct vlp_job);
60 }
61
62 /* Store an array of vl jobs for the queue */
63
64 static void set_job_list(char *printer, struct vlp_job *job_list, 
65                          int num_jobs)
66 {
67         fstring keystr;
68
69         slprintf(keystr, sizeof(keystr) - 1, "LPQ/%s", printer);
70
71         tdb_store_by_string(tdb, keystr, job_list, 
72                             num_jobs * sizeof(struct vlp_job));
73 }
74
75 /* Return the next job number for a printer */
76
77 static int next_jobnum(char *printer)
78 {
79         fstring keystr;
80         int jobnum;
81
82         slprintf(keystr, sizeof(keystr) - 1, "JOBNUM/%s", printer);
83
84         tdb_lock_bystring(tdb, keystr);
85
86         jobnum = tdb_fetch_int(tdb, keystr);
87
88         /* Create next job index if none exists */
89
90         if (jobnum == -1) {
91                 jobnum = atoi(PRINT_FIRSTJOB);
92         }
93
94         jobnum++;
95         tdb_store_int(tdb, keystr, jobnum);
96
97         tdb_unlock_bystring(tdb, keystr);
98
99         return jobnum;
100 }
101
102 static void set_printer_status(char *printer, int status)
103 {
104         fstring keystr;
105         int result;
106
107         slprintf(keystr, sizeof(keystr) - 1, "STATUS/%s", printer);
108         result = tdb_store_int(tdb, keystr, status);
109 }
110
111 static int get_printer_status(char *printer)
112 {
113         fstring keystr;
114         TDB_DATA data;
115
116         slprintf(keystr, sizeof(keystr) - 1, "STATUS/%s", printer);
117
118         data.dptr = keystr;
119         data.dsize = strlen(keystr) + 1;
120
121         if (!tdb_exists(tdb, data)) {
122                 set_printer_status(printer, LPSTAT_OK);
123                 return LPSTAT_OK;
124         }
125
126         return tdb_fetch_int(tdb, keystr);
127 }
128
129 /* Display printer queue */
130
131 static int lpq_command(int argc, char **argv)
132 {
133         char *printer;
134         struct vlp_job *job_list = NULL;
135         int i, num_jobs, job_count = 0;
136
137         if (argc != 2) {
138                 printf("Usage: lpq <printername>\n");
139                 return 1;
140         }
141
142         printer = argv[1];
143
144         /* Display printer status */
145
146         switch (get_printer_status(printer)) {
147         case LPSTAT_OK:
148                 printf("enabled\n");
149                 break;
150         case LPSTAT_STOPPED:
151                 printf("disabled\n");
152                 break;
153         case LPSTAT_ERROR:
154         default:
155                 printf("error\n");
156                 break;
157         }
158
159         /* Print queued documents */
160
161         get_job_list(printer, &job_list, &num_jobs);
162
163         for (i = 0; i < num_jobs; i++) {
164                 if (job_list[i].deleted) continue;
165                 printf("%d\t%d\t%d\t%ld\t%s\t%s\n", job_list[i].jobid,
166                        job_list[i].size, 
167                        (i == 0 && job_list[i].status == LPQ_QUEUED) ? 
168                        LPQ_SPOOLING : job_list[i].status,
169                        job_list[i].submit_time, job_list[i].owner, 
170                        job_list[i].jobname);
171                 job_count++;
172         }
173
174         free(job_list);
175
176         return 0;
177 }
178
179 /* Remove a job */
180
181 static int lprm_command(int argc, char **argv)
182 {
183         char *printer;
184         int jobid, num_jobs, i;
185         struct vlp_job *job_list;
186
187         if (argc < 3) {
188                 printf("Usage: lprm <printername> <jobid>\n");
189                 return 1;
190         }
191
192         printer = argv[1];
193         jobid = atoi(argv[2]);
194
195         get_job_list(printer, &job_list, &num_jobs);
196
197         for (i = 0; i < num_jobs; i++) {
198                 if (job_list[i].jobid == jobid) {
199                         job_list[i].deleted = 1;
200                         set_job_list(printer, job_list, num_jobs);
201                         break;
202                 }
203         }
204
205         return 0;
206 }
207
208 /* print command = print-test %p %s */
209
210 static int print_command(int argc, char **argv)
211 {
212         char *printer;
213         fstring keystr;
214         struct passwd *pw;
215         TDB_DATA value;
216         struct vlp_job job;
217         int i;
218
219         if (argc < 3) {
220                 printf("Usage: print <printername> <jobname>\n");
221                 return 1;
222         }
223
224         printer = argv[1];
225
226         ZERO_STRUCT(job);
227
228         /* Create a job record */
229
230         for (i = 2; i < argc; i++) {
231                 fstrcat(job.jobname, argv[i]);
232                 if (i < argc - 1) {
233                         fstrcat(job.jobname, " ");
234                 }
235         }
236
237         if (!(pw = getpwuid(getuid()))) {
238                 return 1;
239         }
240
241         fstrcpy(job.owner, pw->pw_name);
242
243         job.jobid = next_jobnum(printer);
244         job.size = 666;
245         job.submit_time = time(NULL);
246
247         /* Store job entry in queue */
248
249         slprintf(keystr, sizeof(keystr) - 1, "LPQ/%s", printer);
250         
251         value = tdb_fetch_by_string(tdb, keystr);
252
253         if (value.dptr) {
254
255                 /* Add job to end of queue */
256
257                 value.dptr = realloc(value.dptr, value.dsize + 
258                                      sizeof(struct vlp_job));
259                 if (!value.dptr) return 1;
260
261                 memcpy(value.dptr + value.dsize, &job, sizeof(struct vlp_job));
262
263                 tdb_store_by_string(tdb, keystr, value.dptr, value.dsize +
264                                     sizeof(struct vlp_job));
265
266                 free(value.dptr);
267
268         } else {
269                 
270                 /* Create new queue */
271
272                 tdb_store_by_string(tdb, keystr, &job, sizeof(struct vlp_job));
273         }               
274
275         return 0;
276 }
277
278 /* Pause the queue */
279
280 static int queuepause_command(int argc, char **argv)
281 {
282         char *printer;
283
284         if (argc != 2) {
285                 printf("Usage: queuepause <printername>\n");
286                 return 1;
287         }
288
289         printer = argv[1];
290         set_printer_status(printer, LPSTAT_STOPPED);
291
292         return 0;
293 }
294
295 /* Resume the queue */
296
297 static int queueresume_command(int argc, char **argv)
298 {
299         char *printer;
300
301         if (argc != 2) {
302                 printf("Usage: queueresume <printername>\n");
303                 return 1;
304         }
305
306         printer = argv[1];
307         set_printer_status(printer, LPSTAT_OK);
308
309         return 0;
310 }
311
312 /* Pause a job */
313
314 static int lppause_command(int argc, char **argv)
315 {
316         struct vlp_job *job_list;
317         char *printer;
318         int jobid, num_jobs, i;
319
320         if (argc != 3) {
321                 printf("Usage: lppause <printername> <jobid>\n");
322                 return 1;
323         }
324
325         printer = argv[1];
326         jobid = atoi(argv[2]);
327
328         get_job_list(printer, &job_list, &num_jobs);
329
330         for (i = 0; i < num_jobs; i++) {
331                 if (job_list[i].jobid == jobid) {
332                         job_list[i].status = LPQ_PAUSED;
333                         set_job_list(printer, job_list, num_jobs);
334                         return 0;
335                 }
336         }
337
338         return 1;
339 }
340
341 /* Resume a job */
342
343 static int lpresume_command(int argc, char **argv)
344 {
345         struct vlp_job *job_list;
346         char *printer;
347         int jobid, num_jobs, i;
348
349         if (argc != 3) {
350                 printf("Usage: lpresume <printername> <jobid>\n");
351                 return 1;
352         }
353
354         printer = argv[1];
355         jobid = atoi(argv[2]);
356
357         get_job_list(printer, &job_list, &num_jobs);
358
359         for (i = 0; i < num_jobs; i++) {
360                 if (job_list[i].jobid == jobid) {
361                         job_list[i].status = LPQ_QUEUED;
362                         set_job_list(printer, job_list, num_jobs);
363                         return 0;
364                 }
365         }
366
367         return 1;
368 }
369
370 int main(int argc, char **argv)
371 {
372         /* Parameter check */
373
374         if (argc == 1) {
375                 usage();
376                 return 1;
377         }
378
379         /* Initialise */
380
381         if (!(tdb = tdb_open(PRINT_TDB, 0, 0, O_RDWR | O_CREAT,
382                              0666))) {
383                 printf("%s: unable to open %s\n", argv[0], PRINT_TDB);
384                 return 1;
385         }
386
387         /* Ensure we are modes 666 */
388
389         chmod(PRINT_TDB, 0666);
390
391         /* Do commands */
392
393         if (strcmp(argv[1], "lpq") == 0) {
394                 return lpq_command(argc - 1, &argv[1]);
395         }
396
397         if (strcmp(argv[1], "lprm") == 0) {
398                 return lprm_command(argc - 1, &argv[1]);
399         }
400
401         if (strcmp(argv[1], "print") == 0) {
402                 return print_command(argc - 1, &argv[1]);
403         }
404
405         if (strcmp(argv[1], "queuepause") == 0) {
406                 return queuepause_command(argc - 1, &argv[1]);
407         }
408
409         if (strcmp(argv[1], "queueresume") == 0) {
410                 return queueresume_command(argc - 1, &argv[1]);
411         }
412
413         if (strcmp(argv[1], "lppause") == 0) {
414                 return lppause_command(argc - 1, &argv[1]);
415         }
416
417         if (strcmp(argv[1], "lpresume") == 0) {
418                 return lpresume_command(argc - 1, &argv[1]);
419         }
420
421         /* Unknown command */
422
423         printf("%s: invalid command %s\n", argv[0], argv[1]);
424         return 1;
425 }