/* 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: printqda.ctr */ /* Copyright (C) 2012-2017, 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 printqda.c The printqda module. */ #line 29 "printqda.ctr" #include "printqd.h" #include "printqda.h" #line 36 "printqda.ctr" /** If this is defined to 1, each original request / daemon request pair is reported to stdout. */ #define PRINTQDA_DEBUG 0 #if DK3_CHAR_SIZE == 1 #if DK3_HAVE_STRUCT_SOCKADDR_UN /** Configuration file name relative to sysconf directory. */ static char const pqda_conffile[] = { PQD_CONFFILE }; /** Constant non-localized keywords used by the module. */ static char const * const pqda_c8_kw[] = { /* 0 */ "printqda", /* 1 */ "dktools", /* 2 */ " ", /* 3 */ "acct-check", /* 4 */ "acct-start", /* 5 */ "acct-end", /* 6 */ "printqdc", NULL #line 85 "printqda.ctr" }; /** Localized message texts used by the program. */ static char const * const pqda_loc[] = { /* 0 */ "printqda.str", /* 1 */ "Option was already set: \"", /* 2 */ "\"!", /* 3 */ "Option not started by a character: \"", /* 4 */ "\"!", /* 5 */ "Empty option: \"", /* 6 */ "\"!", /* 7 */ "Syntax error in request!", /* 8 */ "Syntax error, string not finalized!", /* 9 */ "Request contents too long!", /* 10 */ "Incomplete request! Missing one from:\nuser name, printer name, page count, job name, or job title!", /* 11 */ "Too few arguments in request!", /* 12 */ "Incomplete request, missing either user or printer name!", /* 13 */ "Illegal control sub-request: \"", /* 14 */ "\"!", /* 15 */ "Connection failed, skipping all remaining input!", /* 16 */ "Name of system configuration directory too long:\n\"", /* 17 */ "\"!", /* 18 */ "Failed to find system configuration directory!", /* 19 */ "Only printqda can process control requests, not printqdc!", NULL #line 159 "printqda.ctr" }; /** Request types (first word in request line). */ static char const * const pqda_request_types[] = { /* 0 */ "info", /* 1 */ "acct-check", /* 2 */ "acct-start", /* 3 */ "acct-end", /* 4 */ "jobstart", /* 5 */ "filestart", /* 6 */ "fileend", /* 7 */ "jobend", /* 8 */ "control", NULL #line 177 "printqda.ctr" }; /** Possible responses to LPRng jobstart requests. */ static char const * const pqda_decisions[] = { /* 0 */ "ACCEPT", /* 1 */ "REMOVE", /* 2 */ "HOLD", NULL #line 189 "printqda.ctr" }; /** Subrequests of control request. */ static char const * const pqda_control_sub_requests[] = { /* 0 */ "r$eset", /* 1 */ "a$dd", /* 2 */ "d$atabase-cleanup", NULL #line 201 "printqda.ctr" }; /** Initialize job structure. @param job Job structure to initialize. */ static void pqda_job_init(pqda_job_t *job) { #line 214 "printqda.ctr" dk3mem_res((void *)job, sizeof(pqda_job_t)); job->app = NULL; job->lmsg = NULL; job->cmsg = NULL; job->exval = 3; #line 219 "printqda.ctr" job->fadm = 0; #line 220 "printqda.ctr" job->fcerr = 0; job->up = NULL; job->lo = NULL; #line 224 "printqda.ctr" } /** Clean up job structure before exiting program. @param job Job structure to clean up. */ static void pqda_job_cleanup(pqda_job_t *job) { #line 236 "printqda.ctr" if(job->app) { dk3app_close(job->app); job->app = NULL; } #line 239 "printqda.ctr" } /** Check whether the program is run as administration program printqda or as multiplexor printqdc. The result is stored in fadm. @param job Job structure. @param exename Name of the executable file running. */ static void pqda_check_admin(pqda_job_t *job, char const *exename) { char bu[DK3_MAX_PATH]; /* Buffer for modification. */ char *p1; /* Start of program name. */ char *p2; /* File name suffix. */ #line 257 "printqda.ctr" if(exename) { if(strlen(exename) < sizeof(bu)) { strcpy(bu, exename); p1 = dk3str_rchr(bu, '/'); if(p1) { p1++; } else { p1 = bu; } p2 = dk3str_rchr(p1, '.'); if(p2) { *p2 = '\0'; } #line 268 "printqda.ctr" if(0 == strcmp(p1, pqda_c8_kw[0])) { job->fadm = 1; #line 270 "printqda.ctr" } } } #line 273 "printqda.ctr" } /** Store an LPRng option. @param job Job structure. @param kc Key character. @param v Value to store. @return 1 on success, 0 on error. */ static int pqda_lprng_set_option(pqda_job_t *job, char kc, char *v) { int back = 0; #line 289 "printqda.ctr" if(('a' <= kc) && ('z' >= kc)) { if((job->lo)[kc - 'a']) { if(job->fadm) { /* WARNING: Option set twice! */ dk3app_log_3(job->app, DK3_LL_WARNING, job->lmsg, 1, 2, v); } } (job->lo)[kc - 'a'] = v; back = 1; } else { if(('A' <= kc) && ('Z' >= kc)) { if((job->up)[kc - 'A']) { if(job->fadm) { /* WARNING: Option set twice! */ dk3app_log_3(job->app, DK3_LL_WARNING, job->lmsg, 1, 2, v); } } (job->up)[kc - 'A'] = v; back = 1; } } #line 310 "printqda.ctr" return back; } /** Retrieve one LPRng option. @param job Job structure. @param kc Key character. @return Pointer to option value if defined, NULL otherwise. */ static char * pqda_lprng_get_option(pqda_job_t *job, char kc) { char *back = NULL; #line 326 "printqda.ctr" if(('a' <= kc) && ('z' >= kc)) { back = (job->lo)[kc - 'a']; } else { if(('A' <= kc) && ('Z' >= kc)) { back = (job->up)[kc - 'A']; } } #line 333 "printqda.ctr" return back; } /** Retrieve LPRng specific options. @param job Job structure. @param p2 String containing the options. @return 1 on success, 0 on error. */ static int pqda_lprng_options(pqda_job_t *job, char *p2) { char *ptr; /* Current character to process. */ char *ps; /* Start of current string. */ int back = 1; int i; /* Traverse all up and lo pointers. */ int st; /* Current reader state. */ #line 354 "printqda.ctr" for(i = 0; i < 26; i++) { (job->up)[i] = NULL; (job->lo)[i] = NULL; } st = 0; ptr = p2; ps = NULL; while(*ptr) { #line 359 "printqda.ctr" switch(st) { case 0: { /* in space before a string. */ if('\'' == *ptr) { st = 1; ps = ptr; } } break; case 1: { /* in string. */ switch(*ptr) { case '\'': { #line 369 "printqda.ctr" *ptr = '\0'; st = 0; if(ps) { #line 372 "printqda.ctr" ps++; if('-' == ps[0]) { if('\0' != ps[1]) { if(!pqda_lprng_set_option(job, ps[1], &(ps[2]))) { back = 0; #line 377 "printqda.ctr" if(job->fadm) { /* ERROR: Not a character */ dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 3, 4, ps); } } } else { #line 383 "printqda.ctr" back = 0; if(job->fadm) { /* ERROR in string, empty option */ dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 5, 6, ps); } } } } else { #line 391 "printqda.ctr" back = 0; if(job->fadm) { /* ERROR in input! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 7); } } } break; case '\\': { #line 399 "printqda.ctr" st = 2; } break; } } break; case 2: { /* in string, backslash found. */ st = 1; } break; } ptr++; } if(0 != st) { #line 410 "printqda.ctr" back = 0; if(job->fadm) { /* ERROR: Incorrect input! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 8); } } #line 416 "printqda.ctr" return back; } /** Convert a filestart/fileend request. @param job Job structure. @param rq First request word. @param ib3 Input buffer 3 to use for response. @return 1 on success, 0 on error. */ static int pqda_file_startend(pqda_job_t *job, char const *rq, char *ib3) { char *pn; /* Printer name. */ char *un; /* User name. */ char *pc; /* Pagecount value as text. */ char *jn; /* Print job name. */ char *jt; /* Print job title. */ size_t sz; /* Size of converted request. */ int back = 0; #line 439 "printqda.ctr" un = NULL; pn = NULL; pc = NULL; jn = NULL; jt = NULL; un = pqda_lprng_get_option(job, 'n'); pn = pqda_lprng_get_option(job, 'P'); pc = pqda_lprng_get_option(job, 'p'); jt = pqda_lprng_get_option(job, 'J'); jn = pqda_lprng_get_option(job, 'A'); if(!(jn)) { jn = pqda_lprng_get_option(job, 'D'); } if(!(jn)) { jn = pn; } if(!(jt)) { jt = jn; } if((un) && (pn) && (pc) && (jt) && (jn)) { sz = 5 * strlen(pqda_c8_kw[2]); sz += strlen(rq); sz += strlen(un); sz += strlen(pn); sz += strlen(pc); sz += strlen(jt); sz += strlen(jn); if(PQD_INPUT_BUFFER_SIZE > sz) { strcpy(ib3, rq); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, pn); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, un); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, pc); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, jn); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, jt); back = 1; } else { if(job->fadm) { /* ERROR: Request contents too long! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 9); } } } else { if(job->fadm) { /* ERROR: Incomplete jobstart/jobend request! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 10); } } #line 481 "printqda.ctr" return back; } /** Prepare input for printqd. @param job Job structure. @param ib1 Original request, unmodified. @param ib3 Input buffer for printqd, our destination. @param p2 Arguments to original request, writable copy. @param act Request type. */ static int pqda_daemon_input( pqda_job_t *job, char *ib1, char *ib3, char *p2, int act ) { char *parts[16]; /* Splitted request string. */ char *un; /* User name. */ char *pn; /* Printer name. */ size_t na; /* Number of elements in nparts. */ size_t sz; /* String length of result string. */ int res; /* Operation result. */ int back = 0; #line 511 "printqda.ctr" if((act < 8) || (job->fadm)) { /* control requests only printqda. */ un = NULL; pn = NULL; switch(act) { case 0: { /* info */ na = dk3str_c8_explode(parts, 15, p2, NULL); if(2 <= na) { back = 1; } else { if(job->fadm) { /* ERROR: Too few arguments in request! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 11); } } } break; case 1: { /* acct-check */ na = dk3str_c8_explode(parts, 15, p2, NULL); if(2 <= na) { back = 1; } else { if(job->fadm) { /* ERROR: Too few arguments in request! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 11); } } } break; case 2: { /* acct-start */ na = dk3str_c8_explode(parts, 15, p2, NULL); if(5 <= na) { back = 1; } else { if(job->fadm) { /* ERROR: Too few arguments in request! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 11); } } } break; case 3: { /* acct-end */ na = dk3str_c8_explode(parts, 15, p2, NULL); if(5 <= na) { back = 1; } else { if(job->fadm) { /* ERROR: Too few arguments in request */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 11); } } } break; case 4: { /* jobstart */ if(pqda_lprng_options(job, p2)) { un = pqda_lprng_get_option(job, 'n'); pn = pqda_lprng_get_option(job, 'P'); if((un) && (pn)) { sz = strlen(pqda_c8_kw[3]); sz += 2 * strlen(pqda_c8_kw[2]); sz += strlen(un); sz += strlen(pn); if(sz < PQD_INPUT_BUFFER_SIZE) { strcpy(ib3, pqda_c8_kw[3]); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, pn); strcat(ib3, pqda_c8_kw[2]); strcat(ib3, un); back = 1; } else { if(job->fadm) { /* ERROR: Request data too long! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 9); } } } else { if(job->fadm) { /* ERROR: Incomplete information in request! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 12); } } } } break; case 5: { /* filestart */ if(pqda_lprng_options(job, p2)) { back = pqda_file_startend(job, pqda_c8_kw[4], ib3); } } break; case 6: { /* fileend */ if(pqda_lprng_options(job, p2)) { back = pqda_file_startend(job, pqda_c8_kw[5], ib3); } } break; case 7: { /* jobend */ /* Nothing to do, we ignore this request. */ } break; case 8: { /* control */ na = dk3str_c8_explode(parts, 15, p2, NULL); if(na > 0) { res = dk3str_array_abbr(pqda_control_sub_requests, parts[0], '$', 0); if(-1 < res) { back = 1; } else { if(job->fadm) { /* ERROR: Too few arguments in request! */ dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 13, 14, parts[0]); } } } else { if(job->fadm) { dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 11); } } } break; } } else { if((8 == act) && (!(job->fadm))) { job->exval = 1; #line 624 "printqda.ctr" dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 19); #if DK3_HAVE_SYSLOG openlog(pqda_c8_kw[6], LOG_PID, LOG_LPR); syslog(LOG_ERR, "Attempt to send control request to printqdc!"); closelog(); #endif } } #if PRINTQDA_DEBUG if(back) { printf("%s\n%s\n", ib1, ib3); } else { if(7 != act) { printf("!!! FAILED %s\n", ib1); } } #endif #line 642 "printqda.ctr" return back; } /** Convert daemon response to this programs response. @param job Job structure. @param ib3 Destination buffer. @param ib2 Daemon response. @param act Request type. @return 1 if we must write output to standard output, 0 otherwise. */ static int pqda_daemon_output(pqda_job_t *job, char *ib3, char *ib2, int act) { int back = 0; #line 661 "printqda.ctr" ib3[0] = '\0'; switch(act) { case 0: { #line 664 "printqda.ctr" back = 1; } break; case 1: { #line 667 "printqda.ctr" back = 1; } break; case 4: { #line 670 "printqda.ctr" back = 1; } break; } if(back) { strcpy(ib3, ib2); dk3str_c8_delnl(ib3); if(!(strlen(ib3) > 0)) { back = 0; } } #line 681 "printqda.ctr" return back; } /** Process all input lines found on standard input. @param job Job structure */ static void pqda_process_input(pqda_job_t *job) { char ib1[PQD_INPUT_BUFFER_SIZE]; /* Original input. */ char ib2[PQD_INPUT_BUFFER_SIZE]; /* Copy for test. */ char ib3[PQD_INPUT_BUFFER_SIZE]; /* Daemon input. */ char *p1; /* Request keyword. */ char *p2; /* Request arguments. */ dk3_socket_t sock; /* Socket to daemon. */ size_t sz; /* Request size. */ int act; /* Action to take. */ int bw; /* Bytes written. */ int first; /* Flag: First resp. */ int res; /* Shutdown result. */ #line 705 "printqda.ctr" while(fgets(ib1, sizeof(ib1), stdin)) { if(!(job->fcerr)) { dk3str_c8_delnl(ib1); strcpy(ib2, ib1); p1 = dk3str_c8_start(ib2, NULL); if(p1) { if(*p1 != '#') { p2 = dk3str_c8_next(p1, NULL); act = dk3str_c8_array_index(pqda_request_types, p1, 0); strcpy(ib3, ib1); if(pqda_daemon_input(job, ib1, ib3, p2, act)) { sz = strlen(ib3); sock = dk3socket_un_stream_client( (job->cfg).usn, 0L, 0L, NULL, job->app ); if(INVALID_SOCKET != sock) { bw = dk3socket_send(sock, ib3, sz, 0L, 0L, NULL, job->app); if(bw >= 0) { res = dk3socket_shutdown( sock, DK3_TCPIP_SHUTDOWN_WRITE, NULL, job->app ); if(res) { first = 1; ib2[0] = '\0'; do { bw = dk3socket_recv( sock, ib3, (sizeof(ib3) - 1), 0L, 0L, NULL, job->app ); if(bw > 0) { if(first) { first = 0; ib3[((size_t)bw < sizeof(ib3)) ? bw : (sizeof(ib3) - 1)] = '\0'; strcpy(ib2, ib3); } } } while(bw > 0); if(!(first)) { if(pqda_daemon_output(job, ib3, ib2, act)) { fputs(ib3, stdout); fputc('\n', stdout); fflush(stdout); if(!(job->fadm)) { #line 748 "printqda.ctr" switch(dk3str_c8_array_index(pqda_decisions, ib3, 0)) { case 1: { job->exval = 3; #line 751 "printqda.ctr" } break; case 2: { job->exval = 6; #line 754 "printqda.ctr" } break; } } else { #line 757 "printqda.ctr" } } } } } dk3socket_close(sock, NULL, NULL); #if VERSION_BEFORE_20150821 sock = INVALID_SOCKET; #endif } else { job->fcerr = 1; job->exval = 1; #line 769 "printqda.ctr" /* FATAL: Connection failed, skipping all remaining input */ if(job->fadm) { dk3app_log_1(job->app, DK3_LL_FATAL, job->lmsg, 15); } else { #if DK3_HAVE_SYSLOG openlog(pqda_c8_kw[6], LOG_PID, LOG_LPR); syslog(LOG_ERR, "Failed to connect to printqd! Skipping all input!"); closelog(); #endif } } } else { #line 781 "printqda.ctr" } } } } } #line 787 "printqda.ctr" } /** Process configuration file and run. @param job Job structure. @param cfgfilename Name of configuration file. */ static void pqda_run_with_config_filename(pqda_job_t *job, char const *cfgfilename) { int res; #line 801 "printqda.ctr" res = pqdconf_read( &(job->cfg), cfgfilename, ((job->fadm) ? PQD_PROGRAM_TYPE_ADMIN : PQD_PROGRAM_TYPE_MULTIPLEXOR), job->app, job->cmsg ); if(res) { #line 808 "printqda.ctr" res = pqdconf_check( &(job->cfg), ((job->fadm) ? PQD_PROGRAM_TYPE_ADMIN : PQD_PROGRAM_TYPE_MULTIPLEXOR), job->app, job->cmsg ); if(res) { #line 814 "printqda.ctr" #line 815 "printqda.ctr" job->exval = 0; #line 816 "printqda.ctr" pqda_process_input(job); } else { #line 818 "printqda.ctr" /* ERROR: Check failed! */ } } else { #line 821 "printqda.ctr" /* ERROR: Failed to read configuration! */ } pqdconf_cleanup(&(job->cfg)); #line 825 "printqda.ctr" } /** Find configuration file name and run with it. @param job Job structure. */ static void pqda_search_for_config_filename(pqda_job_t *job) { char bu[DK3_MAX_PATH]; /* Buffer to construct file name. */ char const *scd; /* System configuration directory. */ #line 839 "printqda.ctr" scd = dk3inst_get_directory(1); if(scd) { if(strlen(scd) < sizeof(bu)) { strcpy(bu, scd); if((strlen(bu) + strlen(pqda_conffile)) < sizeof(bu)) { strcat(bu, pqda_conffile); pqda_run_with_config_filename(job, bu); } else { /* ERROR: sysconfdir name too long! */ if(job->fadm) { dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 16, 17, scd); } else { #if DK3_HAVE_SYSLOG openlog(pqda_c8_kw[6], LOG_PID, LOG_LPR); syslog(LOG_ERR, "File name of sysconfdir too long!"); closelog(); #endif } } } else { /* ERROR: sysconfdir too long! */ if(job->fadm) { dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 16, 17, scd); } else { #if DK3_HAVE_SYSLOG openlog(pqda_c8_kw[6], LOG_PID, LOG_LPR); syslog(LOG_ERR, "File name of sysconfdir too long!"); closelog(); #endif } } } else { /* ERROR: Failed to obtain sysconfdir! */ if(job->fadm) { dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 18); } else { #if DK3_HAVE_SYSLOG openlog(pqda_c8_kw[6], LOG_PID, LOG_LPR); syslog(LOG_ERR, "Failed to find sysconfdir!"); closelog(); #endif } } #line 882 "printqda.ctr" } /** Run after allocating an application structure. @param job Job structure. */ static void pqda_run_with_app(pqda_job_t *job) { char const * const *xargv; /* Command line arguments array. */ int xargc; /* Number of command line arguments. */ #line 896 "printqda.ctr" job->lmsg = dk3app_messages(job->app, pqda_loc[0], pqda_loc); job->cmsg = pqdconf_get_messages(job->app); xargc = dk3app_get_argc(job->app); xargv = dk3app_get_argv(job->app); if((xargc > 1) && (job->fadm)) { pqda_run_with_config_filename(job, xargv[1]); } else { pqda_search_for_config_filename(job); } #line 906 "printqda.ctr" } /** For printqdc we use a silent application now instead of a daemon application. Multiple instance of printqdc may run at the same time, so we should not let them write all to the same log file. */ #if VERSION_BEFORE_20120526 /** When running as daemon (no output to stderr) we need the current directory. @param job Job structure. @param argc Number of command line arguments. @param argv Command line arguments array. */ static void pqda_run_for_daemon(pqda_job_t *job, int argc, char *argv[]) { char bu[DK3_MAX_PATH]; /* Buffer for current working dir. */ #line 928 "printqda.ctr" if(dk3sf_c8_getcwd_app(bu, sizeof(bu), NULL)) { job->app = dk3app_open_daemon( bu, argc, (dkChar const * const *)argv, pqda_c8_kw[1] ); if(job->app) { pqda_run_with_app(job); } } else { /* ERROR: Failed to find current directory! */ } #line 938 "printqda.ctr" } #endif /** Entry point of the program. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, any other value indicates an error. */ int main(int argc, char *argv[]) { pqda_job_t job; /* Job structure. */ char *up[26]; /* Upper case option arguments. */ char *lo[26]; /* Lower case option arguments. */ int exval; /* Exit status code. */ #line 956 "printqda.ctr" #line 957 "printqda.ctr" pqda_job_init(&job); pqda_check_admin(&job, argv[0]); job.up = up; job.lo = lo; #if VERSION_BEFORE_20120526 if(job.fadm) { job.app = dk3app_open_command( argc, (dkChar const * const *)argv, pqda_c8_kw[1] ); if(job.app) { pqda_run_with_app(&job); } else { fputs("printqda: ERROR: Not enough memory (RAM/swap)!\n", stderr); fflush(stderr); } } else { pqda_run_for_daemon(&job, argc, argv); } #endif if(job.fadm) { job.app = dk3app_open_command( argc, (dkChar const * const *)argv, pqda_c8_kw[1] ); } else { job.app = dk3app_open_silent( argc, (dkChar const * const *)argv, pqda_c8_kw[1] ); } if(job.app) { pqda_run_with_app(&job); } else { if(job.fadm) { fputs("printqda: ERROR: Not enough memory (RAM/swap)!\n", stderr); fflush(stderr); } } exval = job.exval; #if 0 /* NO, EXIT CODE MUST INDICATE ACTION TOO! */ if(!(job.fadm)) { exval = 0; } #endif pqda_job_cleanup(&job); #line 1001 "printqda.ctr" #line 1002 "printqda.ctr" fflush(stdout); exit(exval); return exval; } #else /** Program entry point. @param argc @param argv @return 0 on success, any other value indicates an error. */ int main(int argc, char *argv[]) { fprintf(stderr, "printqd: ERROR: No UNIX domain sockets available!\n"); fflush(stderr); exit(1); } #endif #else /** Program entry point. @param argc @param argv @return 0 on success, any other value indicates an error. */ int main(int argc, char *argv[]) { fprintf( stderr, "printqd: ERROR: This program does not support wide characters (%d)!\n", DK3_CHAR_SIZE ); fflush(stderr); exit(1); } #endif