diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/printqda.ctr |
Initial commit
Diffstat (limited to 'support/dktools/printqda.ctr')
-rw-r--r-- | support/dktools/printqda.ctr | 1038 |
1 files changed, 1038 insertions, 0 deletions
diff --git a/support/dktools/printqda.ctr b/support/dktools/printqda.ctr new file mode 100644 index 0000000000..0e33a91351 --- /dev/null +++ b/support/dktools/printqda.ctr @@ -0,0 +1,1038 @@ +%% options + +copyright owner = Dirk Krause +copyright year = 2012-xxxx +license = bsd + + + +%% header + + +/** Printqda job structure. +*/ +typedef struct { + pqd_conf_t cfg; /**< Configuration. */ + dk3_app_t *app; /**< Application structure. */ + char const * const *lmsg; /**< Localized message texts. */ + char const * const *cmsg; /**< Localized messages for config. */ + char **up; /**< Uppercase option arguments. */ + char **lo; /**< Lowercase option arguments. */ + int exval; /**< Exit status code. */ + int fadm; /**< Flag: Running as printqda. */ + int fcerr; /**< Flag: Connection error occured. */ +} pqda_job_t; + + + +%% module + +#include "printqd.h" +#include "printqda.h" + + + +$!trace-include + + +/** 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[] = { +$!string-table +# +# 0 Program name when running as administrator. +# +printqda +# +# 1 Program group name. +# +dktools +# +# 2 Space to separate arguments in line +# + +# +# 3 Request keyword +# +acct-check +# +# 4 Request keyword +# +acct-start +# +# 5 Request keyword +# +acct-end +# +# 6 Program running as multiplexor +# +printqdc +$!end +}; + + + +/** Localized message texts used by the program. +*/ +static char const * const pqda_loc[] = { +$!string-table +# +# 0 Name of localized message texts file. +# +printqda.str +# +# 1 2 Option was already set! +# +Option was already set: " +"! +# +# 3 4 Option not started by a character! +# +Option not started by a character: " +"! +# +# 5 6 Empty option! +# +Empty option: " +"! +# +# 7 Syntax error in request! +# +Syntax error in request! +# +# 8 Syntax error, string not finalized! +# +Syntax error, string not finalized! +# +# 9 Request contents too long! +# +Request contents too long! +# +# 10 Incomplete request! +# +Incomplete request! Missing one from:\nuser name, printer name, page count, job name, or job title! +# +# 11 Too few arguments in request! +# +Too few arguments in request! +# +# 12 Incomplete request! +# +Incomplete request, missing either user or printer name! +# +# 13 14 Illegal control sub-request! +# +Illegal control sub-request: " +"! +# +# 15 +# +Connection failed, skipping all remaining input! +# +# 16 17 +# +Name of system configuration directory too long:\n" +"! +# +# 18 +# +Failed to find system configuration directory! +# +# 19 +# +Only printqda can process control requests, not printqdc! +$!end +}; + + + +/** Request types (first word in request line). +*/ +static char const * const pqda_request_types[] = { +$!string-table +info +acct-check +acct-start +acct-end +jobstart +filestart +fileend +jobend +control +$!end +}; + + + +/** Possible responses to LPRng jobstart requests. +*/ +static char const * const pqda_decisions[] = { +$!string-table +ACCEPT +REMOVE +HOLD +$!end +}; + + + +/** Subrequests of control request. +*/ +static char const * const pqda_control_sub_requests[] = { +$!string-table +r$eset +a$dd +d$atabase-cleanup +$!end +}; + + + + +/** Initialize job structure. + @param job Job structure to initialize. +*/ +static +void +pqda_job_init(pqda_job_t *job) +{ + $? "+ pqda_job_init" + dk3mem_res((void *)job, sizeof(pqda_job_t)); + job->app = NULL; + job->lmsg = NULL; + job->cmsg = NULL; + job->exval = 3; $? ". exval = 3" + job->fadm = 0; $? ". fadm = 0" + job->fcerr = 0; + job->up = NULL; + job->lo = NULL; + $? "- pqda_job_init" +} + + + +/** Clean up job structure before exiting program. + @param job Job structure to clean up. +*/ +static +void +pqda_job_cleanup(pqda_job_t *job) +{ + $? "+ pqda_job_cleanup" + if(job->app) { + dk3app_close(job->app); job->app = NULL; + } $? "- pqda_job_cleanup" +} + + + +/** 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. */ + $? "+ pqda_check_admin" + 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'; } $? ". \"%!8s\"==\"%!8s\"", p1, pqda_c8_kw[0] + if(0 == strcmp(p1, pqda_c8_kw[0])) { + job->fadm = 1; $? ". fadm = 1" + } + } + } $? "- pqda_check_admin %d", job->fadm +} + + + +/** 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; + $? "+ pqda_lprng_set_option %!8c \"%!8s\"", kc, TR_8STR(v) + 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; + } + } $? "- pqda_lprng_set_option %d", back + 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; + $? "+ pqda_lprng_get_option %!8c", kc + if(('a' <= kc) && ('z' >= kc)) { + back = (job->lo)[kc - 'a']; + } else { + if(('A' <= kc) && ('Z' >= kc)) { + back = (job->up)[kc - 'A']; + } + } $? "- pqda_lprng_get_option \"%!8s\"", TR_8STR(back) + 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. */ + $? "+ pqda_lprng_options \"%!8s\"", p2 + for(i = 0; i < 26; i++) { (job->up)[i] = NULL; (job->lo)[i] = NULL; } + st = 0; + ptr = p2; + ps = NULL; + while(*ptr) { $? ". st = %d c = %!8c", st, *ptr + switch(st) { + case 0: { /* in space before a string. */ + if('\'' == *ptr) { + st = 1; + ps = ptr; + } + } break; + case 1: { /* in string. */ + switch(*ptr) { + case '\'': { $? ". string end" + *ptr = '\0'; + st = 0; + if(ps) { $? ". ps" + ps++; + if('-' == ps[0]) { + if('\0' != ps[1]) { + if(!pqda_lprng_set_option(job, ps[1], &(ps[2]))) { + back = 0; $? "! failed to save" + if(job->fadm) { + /* ERROR: Not a character */ + dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 3, 4, ps); + } + } + } else { $? "! error in string" + back = 0; + if(job->fadm) { + /* ERROR in string, empty option */ + dk3app_log_3(job->app, DK3_LL_ERROR, job->lmsg, 5, 6, ps); + } + } + } + } else { $? "! ps" + back = 0; + if(job->fadm) { + /* ERROR in input! */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 7); + } + } + } break; + case '\\': { $? ". backslash" + st = 2; + } break; + } + } break; + case 2: { /* in string, backslash found. */ + st = 1; + } break; + } + ptr++; + } + if(0 != st) { $? "! wrong state" + back = 0; + if(job->fadm) { + /* ERROR: Incorrect input! */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->lmsg, 8); + } + } $? "- pqda_lprng_options %d", back + 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; + $? "+ pqda_file_startend" + 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); + } + } $? "- pqda_file_startend %d", back + 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; + $? "+ pqda_daemon_input \"%!8s\"", p2 + 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; $? ". exval = 1" + 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 + $? "- pqda_daemon_input %d ib3 = \"%!8s\"", back, ib3 + 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; + $? "+ pqda_daemon_output" + ib3[0] = '\0'; + switch(act) { + case 0: { $? ". info" + back = 1; + } break; + case 1: { $? ". acct-check" + back = 1; + } break; + case 4: { $? ". jobstart" + back = 1; + } break; + } + if(back) { + strcpy(ib3, ib2); + dk3str_c8_delnl(ib3); + if(!(strlen(ib3) > 0)) { + back = 0; + } + } + $? "- pqda_daemon_output %d", back + 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. */ + $? "+ pqda_process_input" + 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)) { $? ". check \"%!8s\"", ib3 + switch(dk3str_c8_array_index(pqda_decisions, ib3, 0)) { + case 1: { + job->exval = 3; $? ". exval = 3" + } break; + case 2: { + job->exval = 6; $? ". exval = 3" + } break; + } + } else { $? ". feel as printqda" + } + } + } + } + } + dk3socket_close(sock, NULL, NULL); +#if VERSION_BEFORE_20150821 + sock = INVALID_SOCKET; +#endif + } else { + job->fcerr = 1; + job->exval = 1; $? ". exval = 1" + /* 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 { $? "! pqda_daemon_input \"%!8s\"", ib1 + } + } + } + } + } + $? "- pqda_process_input" +} + + + +/** 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; + $? "+ pqda_run_with_config_filename \"%!8s\"", TR_8STR(cfgfilename) + res = pqdconf_read( + &(job->cfg), + cfgfilename, + ((job->fadm) ? PQD_PROGRAM_TYPE_ADMIN : PQD_PROGRAM_TYPE_MULTIPLEXOR), + job->app, job->cmsg + ); + if(res) { $? ". config read ok" + res = pqdconf_check( + &(job->cfg), + ((job->fadm) ? PQD_PROGRAM_TYPE_ADMIN : PQD_PROGRAM_TYPE_MULTIPLEXOR), + job->app, job->cmsg + ); + if(res) { $? ". config check ok" + $? ". configuration was read successfully" + job->exval = 0; $? ". exval = 0" + pqda_process_input(job); + } else { $? "! config check" + /* ERROR: Check failed! */ + } + } else { $? "! config read" + /* ERROR: Failed to read configuration! */ + } + pqdconf_cleanup(&(job->cfg)); + $? "- pqda_run_with_config_filename" +} + + + +/** 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. */ + $? "+ pqda_search_for_config_filename" + 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 + } + } $? "- pqda_search_for_config_filename" +} + + + +/** 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. */ + $? "+ pqda_run_with_app" + 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); + } + $? "- pqda_run_with_app" +} + + + +/** 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. */ + $? "+ pqda_run_for_daemon" + 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! */ + } $? "- pqda_run_for_daemon" +} +#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. */ + $!trace-init /tmp/printqda.deb + $? "+ main" + 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); + $? "- main %d", exval + $!trace-end + 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 + |