summaryrefslogtreecommitdiff
path: root/support/dktools/printqdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/dktools/printqdc.c')
-rw-r--r--support/dktools/printqdc.c1563
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)) */
+