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