/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: wprclean.ctr */ /* Copyright (C) 2013, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file wprclean.c The wprclean module. */ #line 8 "wprclean.ctr" #include "dk3all.h" #include "dk3print.h" #include "dk3prcfg.h" #include "dkt-version.h" #line 17 "wprclean.ctr" /** Job structure. */ typedef struct { dk3_app_t *app; /**< Application structure. */ dkChar const * const *msg; /**< Localized texts. */ dkChar const * const *nlmsg; /**< Not localized texts. */ dk3_option_set_t *opt; /**< Options. */ dk3_print_conf_t *pc; /**< Print configuration. */ int cmd; /**< Command to execute. */ int comp; /**< Only jobs from this machine. */ int exval; /**< Exit status code. */ } WPC_JOB; #if DK3_ON_WINDOWS /** Information required to delete a print job. */ typedef struct { DWORD position; /**< Position in queue. */ DWORD jobid; /**< Job ID. */ } wprclean_printjob_t; #endif #ifndef WPRCLEAN_QUEUE_JOB_LIST_SIZE /** Buffer size for job list. */ #define WPRCLEAN_QUEUE_JOB_LIST_SIZE 4096 #endif #ifndef WPRCLEAN_NUM_JOBS /** Number of jobs to retrieve at once. */ #define WPRCLEAN_NUM_JOBS 64 #endif /** Texts used by the program, not localized. */ static dkChar const * const wprclean_nlmsg[] = { /* 0 */ dkT("dkt-3"), /* 1 */ dkT("wprclean.str"), /* 2 */ dkT("wprclean.txt"), NULL #line 81 "wprclean.ctr" }; /** Texts used by the program, replaced by localized versions. */ static dkChar const * const wprclean_msg[] = { /* 0 */ dkT("Print job "), /* 1 */ dkT(" deleted."), /* 2 */ dkT("Failed to delete print job "), /* 3 */ dkT(", reason: "), /* 4 */ dkT("."), /* 5 */ dkT("Failed to open printer \""), /* 6 */ dkT("\"!"), /* 7 */ dkT("Printer \""), /* 8 */ dkT("\" not found!"), NULL #line 111 "wprclean.ctr" }; /** Options for the wprclean program. */ static dk3_option_t wprclean_options[] = { { dkT('h'), dkT("help"), 0 }, { dkT('v'), dkT("version"), 0 }, { dkT('L'), dkT("license"), 0 }, { dkT('c'), dkT("computer"), 0} }; /** Number of options in wprclean_options. */ static size_t const wprclean_sz_options = sizeof(wprclean_options)/sizeof(dk3_option_t); /** Default help text shown if help file not found. */ static dkChar const * const wprclean_text_help[] = { dkT(""), dkT("NAME"), dkT(""), dkT(" wprclean - Windows print cleanup"), dkT(""), dkT("SYNOPSIS"), dkT(""), dkT(" wprclean [-c] []"), dkT(" wprclean [-h] [-v] [-L]"), dkT(""), dkT("DESCRIPTION"), dkT(""), dkT("The wprclean program deletes all print jobs created by the current user."), dkT("It is intended for use in computer labs or PC classrooms in schools and"), dkT("universities."), dkT(""), dkT("OPTIONS"), dkT(""), dkT("-c"), dkT("--computer"), dkT("\tremoves only print jobs created on the current computer."), dkT(""), dkT("-h"), dkT("--help"), dkT("\tshows this help text."), dkT(""), dkT("-v"), dkT("--version"), dkT("\tshows version information."), dkT(""), dkT("-L"), dkT("--license"), dkT("\tshows the license terms."), dkT(""), dkT("RETURN VALUE"), dkT(""), dkT("The program returns exit status code 0 on success, all other status"), dkT("codes indicate an error."), dkT(""), dkT("FILES"), dkT(""), dkT("The dk3print.conf file can be used to conigure short alias names for"), dkT("Windows print queues."), dkT(""), dkT("AUTHOR"), dkT(""), dkT("Dirk Krause"), dkT(""), dkT("COPYRIGHT AND LICENSE"), dkT(""), dkT("Run"), dkT(" wprclean --license"), dkT("to see the license conditions."), dkT(""), dkT("SEE ALSO"), dkT(""), dkT("http://dktools.sourceforge.net"), dkT(""), NULL #line 195 "wprclean.ctr" }; /** License conditions. */ static dkChar const * const wprclean_text_license[] = { dkT(""), dkT("Copyright (c) 2013, Dirk Krause"), dkT("All rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions are met:"), dkT(""), dkT("* Redistributions of source code must retain the above copyright notice,"), dkT(" this list of conditions and the following disclaimer."), dkT("* Redistributions in binary form must reproduce the above copyright"), dkT(" notice, this list of conditions and the following disclaimer in the"), dkT(" documentation and/or other materials provided with the distribution."), dkT("* Neither the name of the copyright holder(s) nor the names of"), dkT(" contributors may be used to endorse or promote products derived from "), dkT(" this software without specific prior written permission."), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"), dkT("\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"), dkT("LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"), dkT("A PARTICULAR PURPOSE ARE DISCLAIMED."), dkT(""), dkT("IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY"), dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"), dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS"), dkT("OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)"), dkT("HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,"), dkT("STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING"), dkT("IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE"), dkT("POSSIBILITY OF SUCH DAMAGE."), dkT(""), NULL #line 234 "wprclean.ctr" }; /** Version information. */ static dkChar const wprclean_version[] = { DKT_VERSION }; #if DK3_ON_WINDOWS /** Delete print job information. @param jptr Print job to delete. */ static void wprclean_printjob_delete(wprclean_printjob_t *jptr) { dk3_release(jptr) } static wprclean_printjob_t * wprclean_printjob_new(DWORD pos, DWORD jid, dk3_app_t *app) { wprclean_printjob_t *back = NULL; back = dk3_new_app(wprclean_printjob_t,1,app); if(back) { back->position = pos; back->jobid = jid; } return back; } /** Compare print jobs by position, largest number first. @param l Left job. @param r Right job. @param cr Comparison criteria (ignored). @return Comparison result. */ static int wprclean_compare_printjobs(void *l, void *r, int cr) { wprclean_printjob_t *pl; /* Left print job. */ wprclean_printjob_t *pr; /* Right print job. */ int back = 0; if(l) { if(r) { pl = (wprclean_printjob_t *)l; pr = (wprclean_printjob_t *)r; if(pl->position > pr->position) { back = 1; } else { if(pl->position < pr->position) { back = -1; } } } else { back = 1; } } else { if(r) { back = -1; } } /* Invert. */ switch(back) { case 1: { back = -1; } break; case -1: { back = 1; } break; } return back; } #endif /* DK3_ON_WINDOWS */ /** Delete the current users jobs from the printer. @param job Job structure. @param pr Printer. */ static void wprclean_windows_printer(WPC_JOB *job, dk3_printer_t *pr) { #if DK3_ON_WINDOWS dkChar cn[DK3_MAX_PATH]; /* Current computer name. */ dkChar nb1[64]; /* Job ID as text. */ dkChar nb2[64]; /* Last error as text. */ char peb[WPRCLEAN_QUEUE_JOB_LIST_SIZE]; /* Buffer for enumeration. */ #if DK3_CHAR_SIZE > 1 JOB_INFO_1W *jobptr; /* Current print job. */ #else JOB_INFO_1A *jobptr; /* Current print job. */ #endif wprclean_printjob_t *pj; /* Current job to mark for deletion. */ dk3_sto_t *sJobs; /* Storage for jobs to delete. */ dk3_sto_it_t *iJobs; /* Iterator through storage. */ wprclean_printjob_t *jptr; /* Current job to delete. */ dkChar const *logname; /* Current users login name. */ HANDLE hPr; /* Handle for printer. */ DWORD szpeb; /* Size of peb buffer. */ DWORD cbNeeded; /* Number of bytes needed. */ DWORD cbReturned; /* Number of print jobs returned. */ DWORD startindex; /* Start index for enumeration. */ DWORD i; /* Index of current job. */ DWORD le; /* Last error code. */ BOOL bres; /* Operation result. */ BOOL cc; /* Flag: Can continue. */ BOOL mustsave; /* Flag: Must mark job for deletion. */ #line 361 "wprclean.ctr" logname = dk3app_get_logname(job->app); if(logname) { #line 363 "wprclean.ctr" if(dk3sf_get_hostname_app(cn,DK3_MAX_PATH,job->app)) { #line 364 "wprclean.ctr" sJobs = dk3sto_open_app(job->app); if(sJobs) { #line 366 "wprclean.ctr" dk3sto_set_comp(sJobs, wprclean_compare_printjobs, 0); iJobs = dk3sto_it_open(sJobs); if(iJobs) { #line 369 "wprclean.ctr" hPr = INVALID_HANDLE_VALUE; #if DK3_CHAR_SIZE > 1 bres = OpenPrinterW((dkChar *)(pr->name), &hPr, NULL); #else bres = OpenPrinterA((dkChar *)(pr->name), &hPr, NULL); #endif if(bres) { #line 376 "wprclean.ctr" dk3sf_initialize_stdout(); dk3sf_fputs(pr->name, stdout); dk3sf_fputc(dkT('\n'), stdout); fflush(stdout); /* Enumerate print jobs. */ cc = TRUE; startindex = 0; while(cc) { cbNeeded = 0; cbReturned = 0; szpeb = sizeof(peb); #if DK3_CHAR_SIZE > 1 bres = EnumJobsW( hPr, startindex, (DWORD)WPRCLEAN_NUM_JOBS, 1, (LPBYTE)peb, szpeb, &cbNeeded, &cbReturned ); #else bres = EnumJobsA( hPr, startindex, (DWORD)WPRCLEAN_NUM_JOBS, 1, (LPBYTE)peb, szpeb, &cbNeeded, &cbReturned ); #endif if(bres) { #line 398 "wprclean.ctr" if(cbReturned > 0) { #line 399 "wprclean.ctr" #if DK3_CHAR_SIZE > 1 jobptr = (JOB_INFO_1W *)peb; #else jobptr = (JOB_INFO_1A *)peb; #endif for(i = 0; i < cbReturned; i++) { mustsave = FALSE; if(jobptr->pUserName) { #line 407 "wprclean.ctr" if(dk3str_casecmp(logname, jobptr->pUserName) == 0) { #line 409 "wprclean.ctr" if(job->comp) { if(jobptr->pMachineName) { #line 412 "wprclean.ctr" if(dk3str_casecmp(cn, jobptr->pMachineName) == 0) { #line 414 "wprclean.ctr" mustsave = TRUE; } else { if(dkT('\\') == (jobptr->pMachineName)[0]) { if(dkT('\\') == (jobptr->pMachineName)[1]) { if(dk3str_casecmp(cn, &((jobptr->pMachineName)[2])) == 0) { mustsave = TRUE; } } } } } else { #line 425 "wprclean.ctr" mustsave = TRUE; } } else { mustsave = TRUE; } } } if(mustsave) { #line 433 "wprclean.ctr" pj = wprclean_printjob_new( jobptr->Position, jobptr->JobId, job->app ); if(pj) { #line 437 "wprclean.ctr" if(!dk3sto_add(sJobs, (void *)pj)) { wprclean_printjob_delete(pj); #line 439 "wprclean.ctr" job->exval = 1; } } else { #line 442 "wprclean.ctr" job->exval = 1; } } jobptr++; } startindex += cbReturned; } else { #line 449 "wprclean.ctr" cc = FALSE; } } else { #line 452 "wprclean.ctr" cc = FALSE; } } /* Remove saved print jobs from queue. */ dk3sto_it_reset(iJobs); while(NULL != (jptr = (wprclean_printjob_t *)dk3sto_it_next(iJobs))) { #line 461 "wprclean.ctr" dk3sf_sprintf3(nb1,dkT("%lu"),(unsigned long)(jptr->jobid)); #if DK3_CHAR_SIZE > 1 bres = SetJobW(hPr, jptr->jobid, 0, NULL, JOB_CONTROL_DELETE); #else bres = SetJobA(hPr, jptr->jobid, 0, NULL, JOB_CONTROL_DELETE); #endif if(bres) { /* DELETED */ dk3sf_fputc(dkT('\t'), stdout); dk3sf_fputs((job->msg)[0], stdout); dk3sf_fputs(nb1, stdout); dk3sf_fputs((job->msg)[1], stdout); dk3sf_fputc(dkT('\n'), stdout); fflush(stdout); } else { /* FAILED */ le = GetLastError(); dk3sf_fputc(dkT('\t'), stdout); dk3sf_sprintf3(nb2,dkT("%lu"),(unsigned long)le); dk3sf_fputs((job->msg)[2], stdout); dk3sf_fputs(nb1, stdout); dk3sf_fputs((job->msg)[3], stdout); dk3sf_fputs(nb2, stdout); dk3sf_fputs((job->msg)[4], stdout); dk3sf_fputc(dkT('\n'), stdout); fflush(stdout); job->exval = 1; } } ClosePrinter(hPr); } else { #line 493 "wprclean.ctr" /* ERROR: Failed to open printer! */ dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 5, 6, pr->name); job->exval = 1; } /* Release saved jobs. */ dk3sto_it_reset(iJobs); while(NULL != (jptr = (wprclean_printjob_t *)dk3sto_it_next(iJobs))) { wprclean_printjob_delete(jptr); } dk3sto_it_close(iJobs); } else { job->exval = 1; } dk3sto_close(sJobs); } else { job->exval = 1; } } else { /* ERROR: Failed to find host name */ job->exval = 1; } } else { /* ERROR: Failed to find log name */ job->exval = 1; } #line 520 "wprclean.ctr" #endif } /** Clean up all printers on the system. @param job Job structure. */ static void wprclean_cleanup_all_printers(WPC_JOB *job) { void *vptr; /* Current printer as returned from iterator. */ dk3_printer_t *pr; /* Current printer. */ dk3sto_it_reset((job->pc)->iPrinters); while(NULL != (vptr = dk3sto_it_next((job->pc)->iPrinters))) { pr = (dk3_printer_t *)vptr; if(DK3_PRINTER_TYPE_WINDOWS == pr->t_p) { wprclean_windows_printer(job, pr); } } } /** Clean up the named printers. @param job Job structure. @param numargs Number of command line arguments. */ static void wprclean_cleanup_named_printers(WPC_JOB *job, int numargs) { dkChar const *pn; /* Printer name. */ dk3_printer_t *pr; /* Printer. */ int i; /* Index of current printer. */ /* Pass 1: Local Windows printers. */ for(i = 0; i < numargs; i++) { pn = dk3opt_get_arg(job->opt, i); if(pn) { pr = dk3print_get_printer(job->pc, pn); if(pr) { if(DK3_PRINTER_TYPE_WINDOWS == pr->t_p) { wprclean_windows_printer(job, pr); } } else { job->exval = 1; /* ERROR: Printer not found! */ dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 7, 8, pn); } } } } /** Do cleanup. @param job Job structure. */ static void wprclean_do_cleanup(WPC_JOB *job) { int numargs; /* Number of command line arguments. */ job->pc = dk3print_conf_open(job->app, 1); if(job->pc) { numargs = dk3opt_get_num_args(job->opt); job->exval = 0; if(0 == numargs) { wprclean_cleanup_all_printers(job); } else { wprclean_cleanup_named_printers(job, numargs); } dk3print_conf_close(job->pc); job->pc = NULL; } } /** Run with a configured job structure. @param job Job structure. */ static void wprclean_run(WPC_JOB *job) { job->opt = dk3opt_open_from_app( wprclean_options, wprclean_sz_options, dkT('\0'), NULL, job->app ); if(job->opt) { if(0 == dk3opt_get_error_code(job->opt)) { if(dk3opt_is_set(job->opt, dkT('h'))) { job->cmd |= DK3_APP_CMD_HELP; } if(dk3opt_is_set(job->opt, dkT('v'))) { job->cmd |= DK3_APP_CMD_VERSION; } if(dk3opt_is_set(job->opt, dkT('L'))) { job->cmd |= DK3_APP_CMD_LICENSE; } if(dk3opt_is_set(job->opt, dkT('c'))) { job->comp = 1; } if(0 == job->cmd) { wprclean_do_cleanup(job); } else { job->exval = 0; dk3sf_initialize_stdout(); if((job->cmd) & DK3_APP_CMD_VERSION) { dk3sf_fputs(wprclean_version, stdout); dk3sf_fputc(dkT('\n'), stdout); } if((job->cmd) & DK3_APP_CMD_LICENSE) { dk3sf_fputt(wprclean_text_license, stdout); } if((job->cmd) & DK3_APP_CMD_HELP) { dk3app_help(job->app, wprclean_nlmsg[2], wprclean_text_help); } } } dk3opt_close(job->opt); job->opt = NULL; } } /** Program entry point. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, any other value indicates an error. */ DK3_MAIN { WPC_JOB job; /* wprclean job. */ int exval = 1; /* Exit status code. */ #line 662 "wprclean.ctr" #line 663 "wprclean.ctr" job.app = dk3app_open_command( argc, (dkChar const * const *)argv, wprclean_nlmsg[0] ); if(job.app) { job.msg = dk3app_messages( job.app, wprclean_nlmsg[1], (dkChar const **)wprclean_msg ); job.nlmsg = wprclean_nlmsg; job.cmd = 0; job.comp = 0; job.exval = 1; job.pc = NULL; wprclean_run(&job); exval = job.exval; dk3app_close(job.app); } else { fputs("wprclean: ERROR: Not enough memory!\n", stderr); fflush(stderr); } #line 683 "wprclean.ctr" #line 684 "wprclean.ctr" exit(exval); return exval; }