diff options
Diffstat (limited to 'support/dktools/printqdc.c')
-rw-r--r-- | support/dktools/printqdc.c | 1563 |
1 files changed, 1563 insertions, 0 deletions
diff --git a/support/dktools/printqdc.c b/support/dktools/printqdc.c new file mode 100644 index 0000000000..3be104d3a3 --- /dev/null +++ b/support/dktools/printqdc.c @@ -0,0 +1,1563 @@ +/* + 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: printqdc.ctr +*/ + +/* +Copyright (C) 2016-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 printqdc.c The printqdc module. +*/ + + +#line 10 "printqdc.ctr" + +#include "dk4conf.h" +#include "dk4types.h" + +#include <stdio.h> + +#if DK4_HAVE_STDLIB_H +#ifndef STDLIB_H_INCLUDED +#include <stdlib.h> +#define STDLIB_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_UNISTD_H +#ifndef UNISTD_H_INCLUDED +#include <unistd.h> +#define UNISTD_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_PROCESS_H +#ifndef PROCESS_H_INCLUDED +#include <process.h> +#define PROCESS_H_INCLUDED 1 +#endif +#endif + + + +/** Requirements to build this program: + * Use 8 bit characters, so we can use the directories from dk4inst.c. + * Signal handling mechanism. +*/ +#if (DK4_CHAR_SIZE == 1) && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) + + + +#if DK4_HAVE_MATH_H +#ifndef MATH_H_INCLUDED +#include <math.h> +#define MATH_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_ERRNO_H +#ifndef ERRNO_H_INCLUDED +#include <errno.h> +#define ERRNO_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_SYS_TYPES_H +#ifndef SYS_TYPES_H_INCLUDED +#include <sys/types.h> +#define SYS_TYPES_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_IO_H +#ifndef IO_H_INCLUDED +#include <io.h> +#define IO_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_FCNTL_H +#ifndef FCNTL_H_INCLUDED +#include <fcntl.h> +#define FCNTL_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_STRING_H +#ifndef STRING_H_INCLUDED +#include <string.h> +#define STRING_H_INCLUDED 1 +#endif +#endif + +#include "dk4inst.h" +#include "dk4mpl.h" +#include "dk4mem.h" +#include "dk4mai8ddu.h" +#include "dk4mai8dus.h" +#include "dk4str8.h" +#include "dk4lprng.h" +#include "dk4opt.h" +#include "dk4sock.h" +#include "dk4vers.h" + + + + + +#line 103 "printqdc.ctr" + + + +/** Information from one LPRng accounting line. +*/ +typedef struct { + char *username; + char *queuename; + char *jobtitle; + char *pagecount; +} lprng_info_t; + + + + +/** Command line options for program. +*/ +static dk4_option_t options[] = { + { { dkT('i'), dkT("interactive"), DK4_OPT_ARG_NONE }, { NULL }, 0}, + { { dkT('s'), dkT("socket"), DK4_OPT_ARG_STRING }, { NULL }, 0}, + { { dkT('h'), dkT("host"), DK4_OPT_ARG_STRING }, { NULL }, 0}, + { { dkT('p'), dkT("port"), DK4_OPT_ARG_UNSIGNED }, { NULL }, 0}, + { { dkT('\0'),dkT("help"), DK4_OPT_ARG_NONE}, { NULL }, 0}, + { { dkT('\0'),dkT("version"), DK4_OPT_ARG_NONE}, { NULL }, 0}, + { { dkT('\0'),dkT("license"), DK4_OPT_ARG_NONE}, { NULL }, 0} +}; + + + +/** Help text. +*/ +static const char * const help_text[] = { +"", +"Print quota daemon client", +"", +"printqdc [-i] [-s path] | [-h host -p port]", +"", +"-i\t\t\tInteractive mode instead of default pipe mode.", +"--interactive", +"", +"-s path\t\t\tPath name for local UNIX domain socket.", +"--socket=path", +"", +"-h host\t\t\tHost name of remote host.", +"--host=host", +"", +"-p port\t\t\tPort number at remote host.", +"--port=port", +"", +"--help\t\t\tShow this help text.", +"--version\t\tShow version number.", +"--license\t\tShow license information.", +"", +NULL + + +#line 158 "printqdc.ctr" +}; + + + +/** License conditions text. +*/ +static const char * const license_text[] = { +"", +"This software uses code from the following projects, either directly or as", +"a library:", +"", +"dktools\t\tDirk Krause's tools and libraries.", +"\t\tSee http://dktools.sourceforge.net/ for more information.", +"", +"DK tools and libraries license", +"==============================", +"Copyright (c) 2015-2016, Dirk Krause", +"All rights reserved.", +"", +"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 copyright", +" 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 Dirk Krause 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.", +"", +NULL + + +#line 204 "printqdc.ctr" +}; + + + +/** Version information. +*/ +static const char version_text[] = { DKT_VERSION_C8 }; + + + +/** Constant text keywords used by the module. +*/ +static const char * const pqdc_kw[] = { +/* 0 */ +"\n", + +/* 1 */ +" ", + +/* 2 */ +"x@x+1", + +/* 3 */ +"Print job", + +/* 4 */ +"-> ", + +/* 5 */ +"<- \"", + +/* 6 */ +"\"\n", + +/* 7 */ +"printqdc: ", + +/* 8 */ +"ERROR: Port number too large!\n", + +/* 9 */ +"ERROR: Port number required!\n", + +/* 10 */ +"ERROR: Host name required!\n", + +/* 11 */ +"ERROR: Failed to shut down socket!\n", + +/* 12 */ +"ERROR: Failed to send data!\n", + +/* 13 */ +"ERROR: Failed to open connection to accounting system!\n", + +/* 14 */ +"ERROR: Failed to construct request (would be too long)!\n", + +/* 15 */ +"ERROR: Incomplete information to construct request!\n", + +/* 16 */ +"ERROR: Pagecounter not numeric!\n", + +/* 17 */ +"ERROR: Too few arguments for request!\n", + +/* 18 */ +"ERROR: Unknown command keyword!\n", + +/* 19 */ +"ERROR: Missing arguments!\n", + +/* 20 */ +"ERROR: Interrupted by signal!\n", + +/* 21 */ +"ERROR: Failed to install signal handlers!\n", + +/* 22 */ +"ERROR: Failed to restore signal handlers!\n", + +/* 23 */ +"ERROR: Failed to initialize socket subsystem!\n", + +NULL + + +#line 276 "printqdc.ctr" +}; + + + +/** Default socket name. +*/ +static const char def_sock_name[] = { + DK4_INST_DIR_VAR "/run/printqd/printqd.sock" +}; + + + +/** Protocol keywords at start of accounting line. +*/ +static const char * const command_names[] = { +/* 0 */ +"jobstart", + +/* 1 */ +"jobend", + +/* 2 */ +"start", + +/* 3 */ +"end", + +/* 4 */ +"filestart", + +/* 5 */ +"fileend", + +/* 6 */ +"info", + +/* 7 */ +"acct-check", + +/* 8 */ +"acct-start", + +/* 9 */ +"acct-end", + +/* 10 */ +"acct-charge", + +/* 11 */ +"control", + +NULL + + +#line 311 "printqdc.ctr" +}; + + +/** Responses from printqd +*/ +static const char * const responses[] = { +/* 0 */ +"ACCEPT", + +/* 1 */ +"HOLD", + +/* 2 */ +"REMOVE", + +NULL + + +#line 322 "printqdc.ctr" +}; + +/** Data exchange buffer. +*/ +static char inbuf[4096]; + + +/** Copy for inspection. +*/ +static char cpbuf[sizeof(inbuf)]; + + +/** Host name for network connection. +*/ +static char *host_name = NULL; + + +/** Socket file name for local connection. +*/ +static char *sock_name = NULL; + + +/** Number of options. +*/ +static size_t szoptions = sizeof(options)/sizeof(dk4_option_t); + + +/** Normal exit value (when run as pipe). +*/ +static int exval = LPRNG_EXIT_SUCCESS; + + + +/** Help (1), version (2), license (4). +*/ +static int hvl = 0; + + + +/** Exit value for interactive mode. +*/ +static int iexval = EXIT_FAILURE; + + +/** Flag: Interactive mode (-i option). +*/ +static int intera = 0; + + +/** Flag: EOF was found. +*/ +static int eof_found = 0; + + +/** Flag: Response already found and processed. +*/ +static int found_response = 0; + + +#ifdef SIGPIPE +/** Indicator: SIGPIPE signal received. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t sig_had_pipe = 0; +#endif + + +/** Indicator: SIGINT signal received. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t sig_had_int = 0; + + +/** Indicator: SIGTERM signal received. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t sig_had_term = 0; + + + +/** Port number for network connection. +*/ +static unsigned short portno = 0U; + + +/** Pass pointer through. + Use of this function is recommended by CERT C coding standard + to avoid optimizing out. + @param ptr Pointer to pass through. + @return The ptr argument. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t * +sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr) +{ + return ptr; +} + + +#ifdef SIGPIPE +/** Handler for SIGPIPE signal. + @param signo Signal number (always SIGPIPE, ignored). +*/ +static +void +sig_handler_pipe(int signo) +{ + *sig_pass_pointer(&sig_had_pipe) = 1; +} +#endif + + +/** Handler for SIGINT signal. + @param signo Signal number (always SIGINT, ignored). +*/ +static +void +sig_handler_int(int signo) +{ + *sig_pass_pointer(&sig_had_int) = 1; +} + + +/** Handler for SIGTERM signal. + @param signo Signal number (always SIGTERM, ignored). +*/ +static +void +sig_handler_term(int signo) +{ + *sig_pass_pointer(&sig_had_term) = 1; +} + + +/** Read value from volatile atomic type. + This function is necessary as some compilers mis-optimize + direct access to volatile variables (at least if you believe + one of the coding standards). + @param ap Pointer to volatile atomic variable. + @return Contents of the variable. +*/ +static +dk4_sig_atomic_t +sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap) +{ + return (*ap); +} + + +/** Check whether we can continue or must abort due to signal. + @param dopipe Flag: Check for SIGPIPE too. + @return 1 if we can continue, 0 otherwise. +*/ +static +int +can_continue(void) +{ + int back = 1; + if (0 != sig_read_atomic(&sig_had_term)) { back = 0; } + if (0 != sig_read_atomic(&sig_had_int)) { back = 0; } + return back; +} + + + +/** Log one-component message to stderr. + @param kwind Index of text in printqdc_kw array. +*/ +static +void +log_1(size_t kwind) +{ + if (0 != intera) { + fputs(pqdc_kw[7], stderr); + fputs(pqdc_kw[kwind], stderr); + fflush(stderr); + } +} + + +/** Eat up input to avoid broken pipe in feeder. +*/ +static +void +eatup_input(void) +{ + size_t rdb; + int cc = 1; + do { + if (0 != can_continue()) { + rdb = fread(inbuf, 1, sizeof(inbuf), stdin); + if (0 == rdb) { + cc = 0; + } + } else { + cc = -1; + } + } while(1 == cc); +} + + + +/** Process command line arguments. + @param argc Number of command line arguments. + @param argv Command line arguments array. + @return 1 on success, 0 on error. +*/ +static +int +cmd_line_args(int argc, char *argv[]) +{ + dkChar *filenames[32]; + size_t szfilenames = DK4_SIZEOF(filenames,DK4_PDKCHAR); + int back; + back = dk4opt_process_argv( + options, szoptions, argc, argv, filenames, &szfilenames, + 1, 0, NULL + ); + if (1 == back) { + if (0 != options[4].found) { + hvl |= 1; + } + if (0 != options[5].found) { + hvl |= 2; + } + if (0 != options[6].found) { + hvl |= 4; + } + if (0 != options[0].found) { + intera = 1; + } + if (0 != options[1].found) { + sock_name = options[1].val.t; + } + if (0 != options[2].found) { + host_name = options[2].val.t; + } + if (0 != options[3].found) { + if ((dk4_um_t)0x0000FFFFUL >= options[3].val.u) { + portno = (unsigned short)(options[3].val.u); + } else { + back = 0; + /* ERROR: Port number to large! */ + log_1(8); + } + } + if ((NULL != host_name) && (0 == portno)) { + back = 0; + /* ERROR: Port number required */ + log_1(9); + } + if ((NULL == host_name) && (0 != portno)) { + back = 0; + /* ERROR: Host name required */ + log_1(10); + } + } else { + if (0 != options[0].found) { + (void)dk4opt_process_argv( + options, szoptions, argc, argv, filenames, &szfilenames, + 1, 1, NULL + ); + } + } + return back; +} + + + +/** Data exchange with accounting system. + @param pres Flag: Process response, 0=no, 1=acct-check, 2=info. +*/ +static +void +process_data(int pres) +{ + const char *ep; /* End pointer for text to number conversions */ + char *ptr; /* Traverse data line */ + dk4_um_t um; /* Number obtained from text */ + size_t sl; /* Input buffer string length */ + size_t wrb; /* Bytes we still have to write */ + dk4_socket_t sock; /* Connection to accounting/quota daemon */ + int res; /* Operation result */ + int cc; /* Flag: Can continue */ + + +#line 611 "printqdc.ctr" + wrb = sl = strlen(inbuf); + /* LOG/SHOW: Request */ + if (0 != intera) { + +#line 614 "printqdc.ctr" + fputs(pqdc_kw[4], stdout); + if (0 < sl) { + fputs(inbuf, stdout); + if (0 < sl) { + if ('\n' != inbuf[sl - 1]) { + fputc('\n', stdout); + } + } else { + fputc('\n', stdout); + } + } + fflush(stdout); + } + if ((0 < sl) && (0 != can_continue())) { + +#line 628 "printqdc.ctr" + if ((NULL != host_name) && (0 < portno)) { + +#line 629 "printqdc.ctr" + sock = dk4socket_c8_tcp_client_host_port( + host_name, portno, 0, 0L, 0L, NULL + ); + } else { + +#line 633 "printqdc.ctr" + sock = dk4socket_c8_unix_client( + ((NULL != sock_name) ? sock_name : def_sock_name), NULL + ); + } + if (INVALID_SOCKET != sock) { + +#line 638 "printqdc.ctr" + if (0 != can_continue()) { + +#line 639 "printqdc.ctr" + res = dk4socket_send(sock, inbuf, &wrb, 0, 0L, 0L, NULL); + if ((DK4_SOCKET_RESULT_SUCCESS == res) && (wrb == sl)) { + +#line 641 "printqdc.ctr" + if (0 != can_continue()) { + +#line 642 "printqdc.ctr" + res = dk4socket_shutdown(sock, DK4_SOCKET_SHUT_WRITE, NULL); + if (DK4_SOCKET_RESULT_SUCCESS == res) { + +#line 644 "printqdc.ctr" + cc = 1; + do { + if (0 != can_continue()) { + +#line 647 "printqdc.ctr" + wrb = sizeof(inbuf); + res = dk4socket_recv(sock, inbuf, &wrb, 0, 0L, 0L, NULL); + if ((DK4_SOCKET_RESULT_SUCCESS==res)&&(0 != can_continue())) { + if (0 < wrb) { + +#line 651 "printqdc.ctr" + if (0 != pres) { + +#line 652 "printqdc.ctr" + if (sizeof(inbuf) > wrb) { + inbuf[wrb] = '\0'; + } else { + iexval = EXIT_FAILURE; + inbuf[sizeof(inbuf)-1] = '\0'; + } + dk4str8_normalize(inbuf, NULL); + /* LOG/SHOW: Response */ + if (0 != intera) { + fputs(pqdc_kw[5], stdout); + fputs(inbuf, stdout); + fputs(pqdc_kw[6], stdout); + fflush(stdout); + } + switch (pres) { + case 1: { + if (0 == found_response) { + switch (dk4str8_array_index(responses,inbuf,0)) { + case 1: { + exval = LPRNG_EXIT_HOLD; + } break; + case 2: { + exval = LPRNG_EXIT_REMOVE; + } break; + } + } + found_response = 1; + } break; + case 2: { + if (0 == found_response) { + um = (dk4_um_t)0UL; + ep = NULL; + ptr = dk4str8_start(inbuf, NULL); + if (NULL != ptr) { + ptr = dk4str8_next(ptr, NULL); + if (NULL != ptr) { + ptr = dk4str8_next(ptr, NULL); + if (NULL != ptr) { + ptr = dk4str8_next(ptr, NULL); + if (NULL != ptr) { + res = dk4ma_input_c8_dec_dk4_um_t( + &um, ptr, &ep, 1, NULL + ); + if (0 == res) { + um = (dk4_um_t)0UL; + } + } + } + } + } + if ((dk4_um_t)0UL == um) { + exval = LPRNG_EXIT_REMOVE; + } + } + found_response = 1; + } break; + } + } else { + +#line 710 "printqdc.ctr" + } + } else { + +#line 712 "printqdc.ctr" + cc = 0; + } + } else { + +#line 715 "printqdc.ctr" + iexval = EXIT_FAILURE; + cc = -1; + } + } else { + +#line 719 "printqdc.ctr" + cc = -1; + } + } while (1 == cc); + } else { + +#line 723 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Failed to shut down socket */ + log_1(11); + } + } else { + +#line 728 "printqdc.ctr" + } + } else { + +#line 730 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Sending data failed */ + log_1(12); + } + } else { + +#line 735 "printqdc.ctr" + } + dk4socket_close(sock, NULL); + } else { + +#line 738 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Failed to open socket */ + log_1(13); + } + } else { + +#line 743 "printqdc.ctr" + } + + +#line 745 "printqdc.ctr" +} + + + +/** Find final quote for current word. + @param str String to find quote in. + @param quote Quote character. + @return Pointer to found quote on success, NULL on error. +*/ +static +char * +lprng_final_quote(char *str, char quote) +{ + char *back = NULL; + + +#line 760 "printqdc.ctr" + while (('\0' != *str) && (NULL == back)) { + if (quote == *str) { + *str = '\0'; + back = str; + back++; + back = dk4str8_start(back, NULL); + } else { + if ('\\' == *str) { + if ('\0' != str[1]) { + dk4str8_cpy_to_left(str, &(str[1])); + str++; + } else { + *str = '\0'; + } + } else { + str++; + } + } + } + + +#line 780 "printqdc.ctr" + return back; +} + + +/** Find start of next text word in LPRng accounting line. + @param str Current word (remaining text) in accounting line. + @return Pointer to next word if found, NULL on error. +*/ +static +char * +lprng_next_word(char *str) +{ + char *back = NULL; + + +#line 794 "printqdc.ctr" + switch (*str) { + case '\'' : { + back = lprng_final_quote(&(str[1]), '\''); + } break; + case '"' : { + back = lprng_final_quote(&(str[1]), '"'); + } break; + default : { + back = dk4str8_next(str, NULL); + } break; + } + +#line 805 "printqdc.ctr" + return back; +} + + + +/** Fill data structure from LPRng accounting line. + @param liptr Structure to fill. + @param textline The text line to use. + @return 1 on success, 0 on error. +*/ +static +int +lprng_info_from_line(lprng_info_t *liptr, char *textline) +{ + char *next; + int back = 1; + + +#line 822 "printqdc.ctr" + DK4_MEMRES(liptr, sizeof(lprng_info_t)); + liptr->username = NULL; liptr->queuename = NULL; + liptr->jobtitle = NULL; liptr->pagecount = NULL; + while (NULL != textline) { + next = lprng_next_word(textline); + if (('\'' == *textline) || ('"' == *textline)) { + textline++; + } + if ('-' == *textline) { + textline++; + switch (*textline) { + case 'n': { + liptr->username = ++textline; + } break; + case 'P': { + liptr->queuename = ++textline; + } break; + case 'J': { + liptr->jobtitle = ++textline; + } break; + case 'p': { + liptr->pagecount = ++textline; + } break; + } + } else { + +#line 847 "printqdc.ctr" +#if 0 + /* 2016-02-15 Simply ignore non-option text. + */ + back = 0; + /* ERROR: No minus sign */ +#endif + } + textline = next; + } + + +#line 857 "printqdc.ctr" + return back; +} + + + +/** Process one line received from LPRng. + @param cmd Index in command names array. + @param args Further arguments in line. +*/ +static +void +lprng_line(int cmd, char *args) +{ + lprng_info_t li; /* All relevant components of line */ + const char *ep = NULL; /* End pointer for numeric conversion */ + const char *jt; /* Job title */ + dk4_um_t um; /* Text to number conversion result */ + int res; /* Operation result */ + int ok = 0; /* Flag: Can process line */ + + +#line 877 "printqdc.ctr" + if (0 != lprng_info_from_line(&li, args)) { + switch (cmd) { + case 0: { + if ((NULL != li.username) && (NULL != li.queuename)) { + if (0 != dk4str8_cpy_s(inbuf,sizeof(inbuf),command_names[7], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),li.queuename, NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),li.username, NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[0], NULL)) { + ok = 1; + +#line 888 "printqdc.ctr" + } + } + } + } + } + } + if (0 != ok) { + process_data(1); + } else { + +#line 897 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Failed to construct request */ + log_1(14); + } + } else { + +#line 902 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Incomplete information */ + log_1(15); + } + } break; + default: { + if ((NULL != li.username) && (NULL != li.queuename)) { + if (NULL != li.pagecount) { + res = dk4ma_input_c8_dec_dk4_um_t(&um, li.pagecount, &ep, 1, NULL); + if (0 != res) { + cmd += 4; + if(0 !=dk4str8_cpy_s(inbuf,sizeof(inbuf),command_names[cmd],NULL)) + { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),li.queuename, NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),li.username, NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),li.pagecount, NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[2], NULL)) { + if (0 != dk4str8_cat_s(inbuf,sizeof(inbuf),pqdc_kw[1], NULL)) { + jt = li.jobtitle; + if (NULL == jt) { jt = pqdc_kw[3]; } + if (0 != dk4str8_cat_s(inbuf, sizeof(inbuf), jt, NULL)) { + if (0 != dk4str8_cat_s(inbuf, sizeof(inbuf), pqdc_kw[0], NULL)) { + ok = 1; + } + } + } + } + } + } + } + } + } + } + } + } + if (0 != ok) { + +#line 942 "printqdc.ctr" + process_data(0); + } else { + +#line 944 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Failed to construct request */ + log_1(14); + } + } else { + +#line 949 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Pagecounter not numeric */ + log_1(16); + } + } else { + +#line 954 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Incomplete information */ + log_1(15); + } + } else { + +#line 959 "printqdc.ctr" + iexval = EXIT_FAILURE; + /* ERROR: Incomplete information */ + log_1(15); + } + } break; + } + } else { + iexval = EXIT_FAILURE; + } + + +#line 969 "printqdc.ctr" +} + + + +/** Process one line containing printqd style data. + @param args Arguments text. + @param minargs Minimum required number of arguments. + @param num3 Flag: Argument 3 must be unsigned number. + @param pres Flag: Process response. +*/ +static +void +printqd_line(char *args, size_t minargs, int num3, int pres) +{ + const char *ep = NULL; /* End of usable data */ + char *next; /* Start of arguments */ + dk4_um_t um = (dk4_um_t)0UL; /* Numeric conversion result */ + size_t i; /* Current argument index */ + int res; /* Operation result */ + int errnum = 0; /* Flag: Numeric error */ + + +#line 990 "printqdc.ctr" + dk4str8_normalize(args, NULL); + i = 0; + +#line 992 "printqdc.ctr" + while(args) { + i++; + next = dk4str8_next(args, NULL); + if ((3 == i) && (0 != num3)) { + +#line 996 "printqdc.ctr" + res = dk4ma_input_c8_dec_dk4_um_t(&um, args, &ep, 1, NULL); + if (0 == res) { errnum = 1; } + } + args = next; + } + +#line 1001 "printqdc.ctr" + if ((i >= minargs) && (0 == errnum)) { + process_data(pres); + } else { + if (i < minargs) { + /* ERROR: Too few arguments */ + log_1(17); + } + if (0 != errnum) { + /* ERROR: Page counter not numeric */ + log_1(16); + } + iexval = EXIT_FAILURE; + } + + +#line 1015 "printqdc.ctr" +} + + + +/** Process input from stdin. +*/ +static +void +process_input(void) +{ + char *args; /* Start of arguments after command */ + int cc; /* Flag: Can continue */ + int res; /* Operation result for numeric conversions */ + + +#line 1029 "printqdc.ctr" + cc = 1; + do { + if (0 != can_continue()) { + +#line 1032 "printqdc.ctr" + if (fgets(inbuf, sizeof(inbuf), stdin)) { + +#line 1033 "printqdc.ctr" + dk4str8_cpy_s(cpbuf, sizeof(cpbuf), inbuf, NULL); + dk4str8_delnl(cpbuf); + if (NULL != dk4str8_start(cpbuf, NULL)) { + if (0 != intera) { + +#line 1037 "printqdc.ctr" + fputs(cpbuf, stdout); + fputc('\n', stdout); + fflush(stdout); + } + args = dk4str8_next(cpbuf, NULL); + if (NULL != args) { + +#line 1043 "printqdc.ctr" + res = dk4str8_array_index(command_names, cpbuf, 0); + if (0 != can_continue()) { + switch (res) { + case 0: { + lprng_line(res, args); + } break; + case 1: { + } break; + case 2: { + } break; + case 3: { + } break; + case 4: { + lprng_line(res, args); + } break; + case 5: { + lprng_line(res, args); + } break; + case 6: { + printqd_line(args, 2, 0, 2); + } break; + case 7: { + printqd_line(args, 2, 0, 1); + } break; + case 8: { + printqd_line(args, 4, 1, 0); + } break; + case 9: { + printqd_line(args, 4, 1, 0); + } break; + case 10: { + printqd_line(args, 3, 1, 0); + } break; + case 11: { + printqd_line(args, 1, 0, 0); + } break; + default: { + iexval = EXIT_FAILURE; + /* ERROR: Unknown keyword */ + log_1(18); + } break; + } + } else { + cc = -1; + } + } else { + +#line 1089 "printqdc.ctr" + /* ERROR: No arguments */ + log_1(19); + iexval = EXIT_FAILURE; + } + } else { + +#line 1094 "printqdc.ctr" + } + } else { + +#line 1096 "printqdc.ctr" + eof_found = 1; + cc = 0; + } + } else { + +#line 1100 "printqdc.ctr" + cc = -1; + } + } while (1 == cc); + + +#line 1104 "printqdc.ctr" +} + + + +/** Show a text paragraph on standard output. + @param txt Text to show. +*/ +static +void +show_text(const char * const *txt) +{ + if (NULL != txt) { + while (NULL != *txt) { + fputs(*(txt++), stdout); + fputc('\n', stdout); + } + fflush(stdout); + } +} + + + +/** Handle --help, --version, --license options. +*/ +static +void +run_hvl(void) +{ + if (0 != (1 & hvl)) { + show_text(help_text); + } + if (0 != (2 & hvl)) { + fputs(version_text, stdout); + fputc('\n', stdout); + fflush(stdout); + } + if (0 != (4 & hvl)) { + show_text(license_text); + } +} + + + +/** Main program. + @param argc Number of command line arguments. + @param argv Command line arguments array. + @return Exit status code. +*/ +int +main(int argc, char *argv[]) +{ +#ifdef DK4_HAVE_SIGACTION +#ifdef SIGPIPE + struct sigaction opipe; + struct sigaction npipe; +#endif + struct sigaction oint; + struct sigaction nint; + struct sigaction oterm; + struct sigaction nterm; +#else +#ifdef SIGPIPE + dk4_sig_handler_t *opipe = NULL; +#endif + dk4_sig_handler_t *oterm = NULL; + dk4_sig_handler_t *oint = NULL; +#endif +#ifdef DK4_HAVE_SIGACTION +#ifdef SIGPIPE + int spipe = 0; +#endif + int sint = 0; + int sterm = 0; + int s_f_i = 0; + int s_f_r = 0; +#endif + int socki = 0; + + /* Set signal handlers + */ +#if DK4_HAVE_SIGACTION +#ifdef SIGPIPE + DK4_MEMRES(&npipe, sizeof(npipe)); + npipe.sa_handler = sig_handler_pipe; + npipe.sa_flags = 0; + if (0 != sigemptyset(&npipe.sa_mask)) { + s_f_i = 1; + goto finished; + } + if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { + s_f_i = 1; + goto finished; + } + if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { + s_f_i = 1; + goto finished; + } + spipe = 1; +#endif + DK4_MEMRES(&nterm, sizeof(nterm)); + nterm.sa_handler = sig_handler_term; + nterm.sa_flags = 0; + if (0 != sigemptyset(&nterm.sa_mask)) { + s_f_i = 1; + goto finished; + } + if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { + s_f_i = 1; + goto finished; + } + if (0 != sigaction(SIGTERM, &nterm, &oterm)) { + s_f_i = 1; + goto finished; + } + sterm = 1; + DK4_MEMRES(&nint, sizeof(nint)); + nint.sa_handler = sig_handler_int; + nint.sa_flags = 0; + if (0 != sigemptyset(&nint.sa_mask)) { + s_f_i = 1; + goto finished; + } + if (0 != sigaddset(&nint.sa_mask, SIGINT)) { + s_f_i = 1; + goto finished; + } + if (0 != sigaction(SIGINT, &nint, &oint)) { + s_f_i = 1; + goto finished; + } + sint = 1; +#else +#ifdef SIGPIPE + opipe = sigset(SIGPIPE, sig_handler_pipe); +#endif + oint = sigset(SIGINT, sig_handler_int); + oterm = sigset(SIGTERM, sig_handler_term); +#endif + + /* Start tracing + */ + + +#line 1246 "printqdc.ctr" + + +#line 1247 "printqdc.ctr" + + /* Process command line arguments + */ + if (0 == cmd_line_args(argc, argv)) { goto finished; } + + /* Help, version, license. + */ + if (0 != hvl) { + run_hvl(); + goto finished; + } + + /* Bring socket subsystem up. + */ + if (DK4_SOCKET_RESULT_SUCCESS != dk4socket_up(NULL)) { + /* ERROR: Failed to initialize socket subsystem */ + log_1(23); + goto finished; + } + socki = 1; + + iexval = EXIT_SUCCESS; + + +#line 1270 "printqdc.ctr" + process_input(); + + finished: + + /* Eat up remaining input, if any. + */ + if ((0 == hvl) && (0 == eof_found)) { eatup_input(); } + + /* Log notification about abort by signal. + */ + if (0 == can_continue()) { + /* LOG: Interrupted by signal */ + log_1(20); + iexval = EXIT_FAILURE; + } + + /* Release socket subsystem. + */ + if (0 != socki) { (void)dk4socket_down(NULL); } + + /* Restore signal handlers + */ +#if DK4_HAVE_SIGACTION + if (0 != s_f_i) { + /* ERROR: Failed to install signal handlers */ + log_1(21); + iexval = EXIT_FAILURE; + } + if (0 != sint) { + if (0 != sigaction(SIGINT, &oint, NULL)) { + s_f_r = 1; + } + } + if (0 != sterm) { + if (0 != sigaction(SIGTERM, &oterm, NULL)) { + s_f_r = 1; + } + } +#ifdef SIGPIPE + if (0 != spipe) { + if (0 != sigaction(SIGPIPE, &opipe, NULL)) { + s_f_r = 1; + } + } +#endif + if (0 != s_f_r) { + /* ERROR: Failed to restore signal handlers */ + log_1(22); + iexval = EXIT_FAILURE; + } +#else + if (NULL != oterm) { sigset(SIGTERM, oterm); } + if (NULL != oint ) { sigset(SIGINT, oint ); } +#ifdef SIGPIPE + if (NULL != opipe) { sigset(SIGPIPE, opipe); } +#endif +#endif + + /* Set exit status code depending on interactive mode + */ + if (0 != intera) { exval = iexval; } + + /* Finish tracing + */ + + +#line 1335 "printqdc.ctr" + + +#line 1336 "printqdc.ctr" + + /* Exit + */ + exit(exval); return exval; +} + +#else +/* if (DK4_CHAR_SIZE == 1) && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) */ + +/** Main program. + @param argc Number of command line arguments. + @param argv Command line arguments array. + @return Exit status code. +*/ +int main(int argc, char *argv[]) +{ + fputs("printqdc: ERROR: Program can not be used on this system!\n", stderr); + fflush(stderr); + exit(EXIT_FAILURE); return EXIT_FAILURE; +} + +#endif +/* if (DK4_CHAR_SIZE == 1) && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) */ + |