/* 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: pjsnmp.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 pjsnmp.c The pjsnmp module. */ #line 10 "pjsnmp.ctr" #include "dk4conf.h" #include "dk4types.h" #include #if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) #include #include #include #include #include "dk4types.h" #include "dk4inst.h" #include "dk4maasz.h" #include "dk4maadu.h" #include "dk4mem.h" #include "dk4sto.h" #include "dk4str8.h" #include "dk4fopc8.h" #include "dk4stat.h" #include "dk4stat8.h" #include "dk4mai8dus.h" #include "dk4mai8huc.h" #include "dk4mai8dii.h" #include "dk4mai8ddu.h" #include "dk4mao8d.h" #include "dk4mao8h.h" #include "dk4time.h" #include "dk4time08.h" #include "dk4sock.h" #include "dk4isadm.h" #include "dk4lprng.h" #line 48 "pjsnmp.ctr" #endif /* if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) */ /** One status text entry from SNMP model. */ typedef struct { unsigned char *text; /**< Text pointer, not 0-terminated. */ size_t size; /**< Text size. */ int state; /**< Summary state if text was found. */ int start; /**< Flag: Text here is start text only. */ } status_text_t; #if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) /** SNMP device status. */ enum { SNMP_DEVST_UNKNOWN = 1 , /**< Status is unknown. */ SNMP_DEVST_RUNNING = 2 , /**< Running. */ SNMP_DEVST_WARNING = 3 , /**< Warning condition active. */ SNMP_DEVST_TESTING = 4 , /**< In self test. */ SNMP_DEVST_DOWN = 5 /**< Down due to error condition. */ }; /** SNMP printer status. */ enum { SNMP_PRST_OTHER = 1 , /**< Any state not mentioned below. */ SNMP_PRST_UNKNOWN = 2 , /**< Unknown. */ SNMP_PRST_IDLE = 3 , /**< Ready, waiting for next job. */ SNMP_PRST_PRINTING = 4 , /**< Printing a job. */ SNMP_PRST_WARMUP = 5 /**< Warming up. */ }; /** State summary. For accounting we would only need to distinguish between standby/idle (secure to retrieve page counter) and anything else. But we want to print human readable state summaries to status file which are shown by lpq -L. */ enum { PJSNMP_ST_UNKNOWN = 0 , /**< Failed to retrieve printer state. */ PJSNMP_ST_UNREACHABLE = 1 , /**< Printer is unreachable. */ PJSNMP_ST_ERROR = 2 , /**< Error state on printer. */ PJSNMP_ST_BUSY = 3 , /**< Printer is printing. */ PJSNMP_ST_IDLE = 4 , /**< Printer idle, can retrieve page counter. */ PJSNMP_ST_WARMUP = 5 , /**< Warming up. */ PJSNMP_ST_STANDBY = 6 , /**< Standby. */ }; /** @defgroup pdes Printer detected error states. The first byte in the octet string is the most significant byte in the unsigned long value. */ /**@{*/ /** Warning: Paper low. */ #define PDES_WARNING_PAPER_LOW 0x80000000UL /** Error: Out of paper. */ #define PDES_ERROR_NO_PAPER 0x40000000UL /** Warning: Toner low. */ #define PDES_WARNING_TONER_LOW 0x20000000UL /** Error: Out of toner. */ #define PDES_ERROR_NO_TONER 0x10000000UL /** Error: Door open. */ #define PDES_ERROR_DOOR_OPEN 0x08000000UL /** Error: Paper jam. */ #define PDES_ERROR_PAPER_JAM 0x04000000UL /** Error: Printer offline. */ #define PDES_ERROR_OFFLINE 0x02000000UL /** Warning: Service requested. */ #define PDES_WARNING_SERVICE 0x01000000UL /** Input tray removed. */ #define PDES_ERROR_INPUT_TRAY_MISSING 0x00800000UL /** Output tray removed. */ #define PDES_ERROR_OUTPUT_TRAY_MISSING 0x00400000UL /** Marker supply missing. */ #define PDES_ERROR_MARKER_SUPPLY_MISSING 0x00200000UL /** Output tray nearly full. */ #define PDES_WARNING_OUTPUT_NEAR_FULL 0x00100000UL /** Output tray full. */ #define PDES_ERROR_OUTPUT_FULL 0x00080000UL /** At least one input tray empty. */ #define PDES_WARNING_INPUT_TRAY_EMPTY 0x00040000UL /** Overdue preventive maintenance. */ #define PDES_WARNING_OVERDUE_PREVENT_MAINT 0x00020000UL /** Bitmask to check if there is any error condition. */ #define PDES_ANY_ERROR \ ( PDES_ERROR_NO_PAPER \ | PDES_ERROR_NO_TONER \ | PDES_ERROR_DOOR_OPEN \ | PDES_ERROR_PAPER_JAM \ | PDES_ERROR_OFFLINE \ | PDES_ERROR_INPUT_TRAY_MISSING \ | PDES_ERROR_OUTPUT_TRAY_MISSING \ | PDES_ERROR_MARKER_SUPPLY_MISSING \ | PDES_ERROR_OUTPUT_FULL) /** Bitmask to check if there is any warning condition. */ #define PDES_ANY_WARNING \ ( PDES_WARNING_PAPER_LOW \ | PDES_WARNING_TONER_LOW \ | PDES_WARNING_SERVICE \ | PDES_WARNING_OUTPUT_NEAR_FULL \ | PDES_WARNING_OVERDUE_PREVENT_MAINT \ | PDES_WARNING_INPUT_TRAY_EMPTY) /** Bitmask to check whether any error or warning condition is set. */ #define PDES_ANY_CONDITION ((PDES_ANY_WARNING) | (PDES_ANY_ERROR)) /**@}*/ /** Buffer for sending. Should be large to minimize number of I/O operations. */ #if DK4_SIZEOF_SIZE_T > 2 static char pjsnmp_buf[1048576]; #else static char pjsnmp_buf[16384]; #endif /** Current status text, also used in accounting. */ static char stat_text[2048]; /** Buffer for responses from printer. */ static char dummy_text[2048]; /** Previous status text. */ static char ostat_text[sizeof(stat_text)]; /** Buffer for automatically constructed job name. */ static char job_name_buf[32+(8*sizeof(dk4_um_t))]; /** Status text oid. */ static oid oid_st[MAX_OID_LEN]; /** OID for device status. */ static const oid oid_ds[] = { (oid)1, (oid)3, (oid)6, (oid)1, (oid)2, (oid)1, (oid)25, (oid)3, (oid)2, (oid)1, (oid)5, (oid)1 }; /** OID for printer status. */ static const oid oid_ps[] = { (oid)1, (oid)3, (oid)6, (oid)1, (oid)2, (oid)1, (oid)25, (oid)3, (oid)5, (oid)1, (oid)1, (oid)1 }; /** OID for pagecount value. */ static const oid oid_pc[] = { (oid)1, (oid)3, (oid)6, (oid)1, (oid)2, (oid)1, (oid)43, (oid)10, (oid)2, (oid)1, (oid)4, (oid)1, (oid)1 }; /** OID for printer detected error state. */ static const oid oid_pe[] = { (oid)1, (oid)3, (oid)6, (oid)1, (oid)2, (oid)1, (oid)25, (oid)3, (oid)5, (oid)1, (oid)2, (oid)1 }; /** Default OID for status text. */ static const oid oid_dst[] = { (oid)1, (oid)3, (oid)6, (oid)1, (oid)2, (oid)1, (oid)43, (oid)16, (oid)5, (oid)1, (oid)2, (oid)1, (oid)1 }; /** Constant texts, not localized. */ static const char * const pjsnmp_kw[] = { /* 0 */ "\n", /* 1 */ " ", /* 2 */ "PRINTCAP_ENTRY", /* 3 */ "*", /* 4 */ "pjsnmp", /* 5 */ "public", /* 6 */ "acct-check", /* 7 */ "Device and printer status: ", /* 8 */ "/", /* 9 */ "Printer detected error state: ", /* 10 */ "Current printer state: ", /* 11 */ "not found", /* 12 */ "unknown", /* 13 */ "running", /* 14 */ "warning", /* 15 */ "testing", /* 16 */ "down", /* 17 */ "not found", /* 18 */ "other", /* 19 */ "unknown", /* 20 */ "idle", /* 21 */ "printing", /* 22 */ "warmup", /* 23 */ "UNKNOWN", /* 24 */ "UNREACHABLE", /* 25 */ "ERROR", /* 26 */ "BUSY", /* 27 */ "IDLE", /* 28 */ "WARMUP", /* 29 */ "STANDBY", /* 30 */ "\"", /* 31 */ "\"\n", /* 32 */ "ERROR: ", /* 33 */ "Warning: ", /* 34 */ "Paper low (printer will run out of paper soon).\n", /* 35 */ "Out of paper!\n", /* 36 */ "Toner low (printer will run out of toner soon).\n", /* 37 */ "Out of toner!\n", /* 38 */ "Door open!\n", /* 39 */ "Paper jam!\n", /* 40 */ "Offline!\n", /* 41 */ "Service requested.\n", /* 42 */ "Input tray missing!\n", /* 43 */ "Output tray missing!\n", /* 44 */ "Marker supply missing!\n", /* 45 */ "Output tray nearly full (will be full soon).\n", /* 46 */ "Output tray full!\n", /* 47 */ "At least one input tray is empty.\n", /* 48 */ "Overdue preventive maintenance.\n", /* 49 */ "ERROR ON PRINTER, MANUAL INTERVENTION REQUIRED!\n", /* 50 */ "PRINTER PROBABLY REQUIRES MANUAL INTERVENTION!\n", /* 51 */ "acct-start", /* 52 */ "acct-end", /* 53 */ "acct-charge", /* 54 */ "print-job", /* 55 */ "Print job finished.\n", /* 56 */ "Job size: ", /* 57 */ "Data transfer: ", /* 58 */ "Processing: ", /* 59 */ "Pages: ", /* 60 */ " bytes\n", /* 61 */ " seconds\n", /* 62 */ "# ", /* 63 */ "Configuration problem (command line arguments)!\n", /* 64 */ "Configuration problem (printcap file)!\n", /* 65 */ "Configuration problem (SNMP model file)!\n", /* 66 */ "ERROR: Missing option name!\n", /* 67 */ "ERROR: Missing option argument!\n", /* 68 */ "ERROR: Non-option command line argument found!\n", /* 69 */ "ERROR: No user name specified!\n", /* 70 */ "ERROR: No print queue name specified!\n", /* 71 */ "ERROR: No print job name specified!\n", /* 72 */ "Warning: Redefinition of \"", /* 73 */ "\" to \"", /* 74 */ "\"!\n", /* 75 */ "ERROR: Empty text for option \"", /* 76 */ "\"!\n", /* 77 */ "ERROR: Missing text for \"", /* 78 */ "\"!\n", /* 79 */ "ERROR: Option \"", /* 80 */ "\" requires unsigned short number!\nIllegal text: \"", /* 81 */ "\"!", /* 82 */ "ERROR: Illegal SNMP version: \"", /* 83 */ "\"!\nAllowed: \"1\", \"2c\", \"3\"!\n", /* 84 */ "ERROR: Option \"", /* 85 */ "\" requires an integer value!\nIllegal text: \"", /* 86 */ "\"!\n", /* 87 */ "ERROR: Missing \"]\"!\n", /* 88 */ "ERROR: Missing model name!\n", /* 89 */ "ERROR: Illegal summary state: \"", /* 90 */ "\"!\n", /* 91 */ "ERROR: Illegal printer status name: \"", /* 92 */ "\"!\n", /* 93 */ "ERROR: Illegal device status name: \"", /* 94 */ "\"!", /* 95 */ "ERROR: Missing printer status name!\n", /* 96 */ "ERROR: Missing summary state name!\n", /* 97 */ "ERROR: Illegal condition name: \"", /* 98 */ "\"!\n", /* 99 */ "ERROR: OID too long!\n", /* 100 */ "ERROR: Numeric overflow for sub id: \"", /* 101 */ "\"!\n", /* 102 */ "ERROR: Not a number: \"", /* 103 */ "\"!\n", /* 104 */ "ERROR: Empty OID text!\n", /* 105 */ "ERROR: Memory allocation failed!\n", /* 106 */ "ERROR: Empty string!\n", /* 107 */ "ERROR: Incorrect string specification!\n", /* 108 */ "ERROR: Not a hexadecimal byte: \"", /* 109 */ "\"!\n", /* 110 */ "ERROR: Value required!\n", /* 111 */ "ERROR: Not a boolean: \"", /* 112 */ "\"!\n", /* 113 */ "ERROR: Illegal key: \"", /* 114 */ "\"!\n", /* 115 */ "ERROR: Model not found: \"", /* 116 */ "\"!\n", /* 117 */ "ERROR: Failed to open model file!\n\"", /* 118 */ "\"!\n", /* 119 */ "ERROR: Missing host name for printer!\n", /* 120 */ "ERROR: PRINTCAP_ENTRY not found in environment!\n", /* 121 */ "ERROR: Failed to create SNMP session!\n", /* 122 */ "ERROR: Failed to send data to accounting system!\n", /* 123 */ "ERROR: Partial success when sending data to accounting system!\n", /* 124 */ "ERROR: Failed to shut down accounting socket!\n", /* 125 */ "ERROR: Failed to connect to accounting system!\n", /* 126 */ "ERROR: Failed to start accounting program!\n", /* 127 */ "ERROR: Missing command name for accounting program!\n", /* 128 */ "ERROR: Failed to open accounting file!\n", /* 129 */ "ERROR: Can not receive response from pipe!\n", /* 130 */ "ERROR: Can not receive response from file!\n", /* 131 */ "Checking permission: user=\"", /* 132 */ "\" printer=\"", /* 133 */ "\".\n", /* 134 */ "Printing allowed.\n", /* 135 */ "ERROR: PRINTING DENIED BY ACCOUNTING/QUOTA SYSTEM!\n", /* 136 */ "ERROR: Printer unreachable too long!\n", /* 137 */ "ERROR: Network connection not writeable (timeout)!\n", /* 138 */ "ERROR: Failed to send data!\n", /* 139 */ "ERROR: Failed to read print data from standard input!\n", /* 140 */ "ERROR: Failed to connect to printer!\n", /* 141 */ "ERROR: Failed to set up signal handlers!\n", /* 142 */ "ERROR: Failed to restore signal handlers!\n", /* 143 */ ":", /* 144 */ "", /* 145 */ "Retrieving page counter at start.\n", /* 146 */ "Retrieving page counter at end.\n", /* 147 */ "Page counter at start: ", /* 148 */ "Page counter at end: ", /* 149 */ "Failed to retrieve page counter value!\n", /* 150 */ "---\n", /* 151 */ "Starting print data transfer.\n", /* 152 */ "Finished print data transfer.\n", /* 153 */ "Print data transfer aborted.\n", /* 154 */ "Transmitting accounting data via network socket.\n", /* 155 */ "Writing accounting data pipe.\n", /* 156 */ "Transmitting accounting data via local socket.\n", /* 157 */ "Writing accounting data to file.\n", /* 158 */ "Transmitting accounting data to fd 3.\n", /* 159 */ "Accounting data transmitted successfully.\n", /* 160 */ "ERROR: Failed to transmit accounting data!\n", /* 161 */ "\" requires an unsigned integer value!\nIllegal text: \"", /* 162 */ "Warning: Unusual change to idle/standby state.\nWaiting ", /* 163 */ " seconds ", /* 164 */ "for printer to resume printing.\n", /* 165 */ "ERROR: No accounting destination configured!\n", /* 166 */ "Response from accounting system: \"", /* 167 */ "\".\n", /* 168 */ "Printer in error state too long!\n", /* 169 */ "Command line arguments:\n", /* 170 */ "ERROR: Failed to initialize socket subsystem!\n", /* 171 */ "pjsnmp@localhost+", NULL #line 744 "pjsnmp.ctr" }; /** Responses from accounting system. */ static const char * const accounting_responses[] = { /* 0 */ "ACCEPT", /* 1 */ "HOLD", /* 2 */ "REMOVE", NULL #line 756 "pjsnmp.ctr" }; /** Names for configuration items in the printcap entry. */ static const char * const printcap_entry_names[] = { /* 0 */ "pjsnmp-host", /* 1 */ "pjsnmp-port", /* 2 */ "pjsnmp-ordrel", /* 3 */ "pjsnmp-accounting-enable", /* 4 */ "pjsnmp-accounting-check", /* 5 */ "pjsnmp-accounting-file", /* 6 */ "pjsnmp-accounting-host", /* 7 */ "pjsnmp-accounting-port", /* 8 */ "pjsnmp-require-printing", /* 9 */ "pjsnmp-version", /* 10 */ "pjsnmp-community", /* 11 */ "pjsnmp-during-transfer", /* 12 */ "pjsnmp-model-file", /* 13 */ "pjsnmp-model-name", /* 14 */ "pjsnmp-ignore-failed-session", /* 15 */ "pjsnmp-allow-printing-if-accounting-connection-failed", /* 16 */ "pjsnmp-pdes-always", /* 17 */ "pjsnmp-unknown-busy", /* 18 */ "pjsnmp-unreachable-timeout-start", /* 19 */ "pjsnmp-unreachable-timeout-end", /* 20 */ "pjsnmp-unreachable-timeout-printing", /* 21 */ "pjsnmp-local-port", /* 22 */ "pjsnmp-unwriteable-timeout-printing", /* 23 */ "pjsnmp-read-response", /* 24 */ "pjsnmp-force-printable-status-text", /* 25 */ "pjsnmp-error-timeout-start", /* 26 */ "pjsnmp-error-timeout-end", /* 27 */ "pjsnmp-error-timeout-printing", /* 28 */ "pjsnmp-verbose", /* 29 */ "pjsnmp-non-ascii-job-title", /* 30 */ "pjsnmp-accounting-start-end", NULL #line 891 "pjsnmp.ctr" }; /** SNMP version names, 2 and 2c are the same. */ static const char * const snmp_version_names[] = { /* 0 */ "1", /* 1 */ "2", /* 2 */ "2c", /* 3 */ "3", NULL #line 903 "pjsnmp.ctr" }; /** Keywords used in the SNMP models file. */ static const char * const model_keys[] = { /* 0 */ "map", /* 1 */ "error condition", /* 2 */ "add error condition", /* 3 */ "status text oid", /* 4 */ "text standby", /* 5 */ "start standby", /* 6 */ "text idle", /* 7 */ "start idle", /* 8 */ "always use status text", /* 9 */ "text busy", /* 10 */ "start busy", /* 11 */ "text unknown", /* 12 */ "start unknown", /* 13 */ "text error", /* 14 */ "start error", /* 15 */ "text warmup", /* 16 */ "start warmup", NULL #line 939 "pjsnmp.ctr" }; /** Summary state keywords used in the models file, can be abbreviated. */ static const char * const summary_state_names[] = { /* 0 */ "u$nknown", /* 1 */ "e$rror", /* 2 */ "b$usy", /* 3 */ "i$dle", /* 4 */ "w$armup", /* 5 */ "s$tandby", NULL #line 953 "pjsnmp.ctr" }; /** Device status names, can be abbreviated. */ static const char * const device_status_names[] = { /* 0 */ "u$nknown", /* 1 */ "r$unning", /* 2 */ "w$arning", /* 3 */ "t$esting", /* 4 */ "d$own", NULL #line 966 "pjsnmp.ctr" }; /** Printer status names, can be abbreviated. */ static const char * const printer_status_names[] = { /* 0 */ "o$ther", /* 1 */ "u$nknown", /* 2 */ "i$dle", /* 3 */ "p$rinting", /* 4 */ "w$armup", NULL #line 979 "pjsnmp.ctr" }; /** Names for the condition bits in the SNMP models file. */ static const char * const condition_names[] = { /* 0 */ "low-paper", /* 1 */ "no-paper", /* 2 */ "low-toner", /* 3 */ "no-toner", /* 4 */ "door-open", /* 5 */ "paper-jam", /* 6 */ "offline", /* 7 */ "service-requested", /* 8 */ "input-tray-missing", /* 9 */ "output-tray-missing", /* 10 */ "marker-supply-missing", /* 11 */ "output-near-full", /* 12 */ "output-full", /* 13 */ "input-tray-empty", /* 14 */ "overdue-preventive-maintenance", NULL #line 1002 "pjsnmp.ctr" }; /** Default configuration file for SNMP models. */ static const char def_model_file[] = { DK4_INST_DIR_SHARE "/dktools/print-snmp.conf" }; /** Option values for uppercase options. */ static char *upper[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /** Option values for lowercase options. */ static char *lower[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /** Mapping from device/printer status combinations to short summaries. */ static int summary_states[] = { /* unknown-other */ PJSNMP_ST_UNKNOWN , /* unknown-unknown */ PJSNMP_ST_UNKNOWN , /* unknown-idle */ PJSNMP_ST_UNKNOWN , /* unknown-printing */ PJSNMP_ST_UNKNOWN , /* unknown-warmup */ PJSNMP_ST_WARMUP , /* running-other */ PJSNMP_ST_STANDBY , /* running-unknown */ PJSNMP_ST_UNKNOWN , /* running-idle */ PJSNMP_ST_IDLE , /* running-printing */ PJSNMP_ST_BUSY , /* running-warmup */ PJSNMP_ST_WARMUP , /* warning-other */ PJSNMP_ST_STANDBY , /* warning-unknown */ PJSNMP_ST_UNKNOWN , /* warning-idle */ PJSNMP_ST_IDLE , /* warning-printing */ PJSNMP_ST_BUSY , /* warning-warmup */ PJSNMP_ST_WARMUP , /* testing-other */ PJSNMP_ST_UNKNOWN , /* testing-unknown */ PJSNMP_ST_UNKNOWN , /* testing-idle */ PJSNMP_ST_UNKNOWN , /* testing-printing */ PJSNMP_ST_UNKNOWN , /* testing-warmup */ PJSNMP_ST_WARMUP , /* down-other */ PJSNMP_ST_ERROR , /* down-unknown */ PJSNMP_ST_ERROR , /* down-idle */ PJSNMP_ST_ERROR , /* down-printing */ PJSNMP_ST_ERROR , /* down-warmup */ PJSNMP_ST_WARMUP }; /** Error report for number of bytes transferred. */ static dk4_er_t er_bytes; /** Copy of the printcap entry from PRINTCAP_ENTRY environment variable (allocated, freed during cleanup before exit). */ static char *printcap_entry = NULL; /** Printer host name (from printcap entry). */ static char *host_name = NULL; /** User name to be charged for the job (from -n or -L option). */ static char *user_name = NULL; /** Print queue name (from -P or -Q option). */ static char *queue_name = NULL; /** Job title (from -J -f or -N option). */ static char *job_title = NULL; /** Job name from -A -j -t or -D option (only needed for old accounting system). */ static char *job_name = NULL; /** File, socket, pipe or host name for accounting (from pjsnmp-accounting-file in printcap entry). */ static char *acct_name = NULL; /** Host to connect to for accounting (from pjsnmp-accounting-host in printcap entry). */ static char *acct_host = NULL; /** SNMP community name (from pjsnmp-community in printcap entry). */ static char *snmp_comm = NULL; /** File name containing SNMP models (from pjsnmp-model-file in printcap entry). */ static char *model_file = NULL; /** SNMP model name (from pjsnmp-model-name in printcap entry). */ static char *model_name = NULL; /** Status file for log messages (name obtained from -s cmd arg). */ static FILE *stt_file = NULL; /** Output file to use for log messages. This is either stt_file or stderr, but never NULL. */ static FILE *out_file = NULL; /** SNMP session. */ static struct snmp_session *snmp_sess = NULL; /** Storage for status text nodes. */ static dk4_sto_t *s_stn = NULL; /** Iterator through storage above. */ static dk4_sto_it_t *i_stn = NULL; /** Number of bytes transferred. */ static dk4_um_t bytes_trans = (dk4_um_t)0UL; /** Timeout if printer not seen printing (from pjsnmp-require-printing in printcap entry). If the first page contains a complicated graphics it might take a longer time to start printing. */ static dk4_um_t print_timeout = (dk4_um_t)600UL; /** Timeout if printer is unreachable at start of print job (from pjsnmp-unreachable-timeout-start in printcap entry). */ static dk4_um_t unto_start = (dk4_um_t)900UL; /** Timeout if printer is unreachable during data transfer (from pjsnmp-unreachable-timeout-printing in printcap entry). */ static dk4_um_t unto_print = (dk4_um_t)120UL; /** Timeout if printer socket is unwriteable during data transfer (from pjsnmp-unwriteable-timeout-printing in printcap entry). */ static dk4_um_t unwt_print = (dk4_um_t)900UL; /** Timeout if printer is unreachable at end of print job (from pjsnmp-unreachable-timeout-end in printcap entry). */ static dk4_um_t unto_end = (dk4_um_t)120UL; /** Timeout for error condition before printing to skip job. */ static dk4_um_t erto_start = (dk4_um_t)900UL; /** Timeout if printer is in error state during printing. */ static dk4_um_t erto_print = (dk4_um_t)86400UL; /** Timeout if printer is in error state after job. */ static dk4_um_t erto_end = (dk4_um_t)3600UL; /** Start time printer gone unreachable. */ static dk4_time_t start_unreach = (dk4_time_t)0UL; /** Start time printer gone error. */ static dk4_time_t start_error = (dk4_time_t)0UL; /** Size of device status OID (number of elements). */ static const size_t sz_oid_ds = sizeof(oid_ds)/sizeof(oid); /** Size of device status OID (number of bytes). */ static const size_t by_oid_ds = sizeof(oid_ds); /** Size of printer status OID (number of elements). */ static const size_t sz_oid_ps = sizeof(oid_ps)/sizeof(oid); /** Size of printer status OID (number of bytes). */ static const size_t by_oid_ps = sizeof(oid_ps); /** Size of page counter OID (number of elements). */ static const size_t sz_oid_pc = sizeof(oid_pc)/sizeof(oid); /** Size of page counter OID (number of bytes). */ static const size_t by_oid_pc = sizeof(oid_pc); /** Size of printer error OID (number of elements). */ static const size_t sz_oid_pe = sizeof(oid_pe)/sizeof(oid); /** Size of printer error OID (number of bytes). */ static const size_t by_oid_pe = sizeof(oid_pe); /** Size of printer error OID (number of elements). */ static const size_t sz_oid_dst = sizeof(oid_dst)/sizeof(oid); /** Size of printer error OID (number of bytes). */ static const size_t by_oid_dst = sizeof(oid_dst); /** Number of items in status text OID. */ static size_t sz_oid_st = sizeof(oid_dst)/sizeof(oid); /** Number of bytes in status text OID. */ static size_t by_oid_st = sizeof(oid_dst); /** Number of bytes currently stored in stat_text. */ static size_t sz_stat_text = 0; /** Number of bytes stored in ostat_text. */ static size_t sz_ostat_text = 0; /** Start of program. */ static dk4_time_t t1 = (dk4_time_t)0UL; /** Start of data transfer. */ static dk4_time_t t2 = (dk4_time_t)0UL; /** End of data transfer. */ static dk4_time_t t3 = (dk4_time_t)0UL; /** End of program. */ static dk4_time_t t4 = (dk4_time_t)0UL; /** SNMP version number (from pjsnmp-version in printcap entry). */ static long snmp_version = SNMP_VERSION_1; /** Bit mask to retrieve real error conditions from hrPrinterDetectedErrorStates (modified by error condition and add error condition in model). */ static unsigned long pdes_error = PDES_ANY_ERROR ; /** Previous printer detected error state conditions. */ static unsigned long opdes_cond = 0UL; /** Current printer detected error state conditions. */ static unsigned long pdes_cond = 0UL; /** Page counter at start of job. */ static unsigned long pc_start = 0UL; /** Unusable page counter value (start value or at last error). */ static unsigned long pc_error = 0UL; /** Page counter at end of job. */ static unsigned long pc_end = 0UL; /** Current page counter. */ static unsigned long pcnt = 0UL; #endif /* if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) */ /** Exit status code, must be one from the enum. */ static int exval = LPRNG_EXIT_REMOVE; #if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) /** Flag: Verbose */ static int verbose = 0; /** Flag: Allow non-ASCII characters in job title for accounting. */ static int allow_non_ascii = 0; /** Always use status text (default: only if summary is "unknown"). */ static int stat_always = 0; /** Flag: Always use printer detected error state (from pjsnmp-pdes-always in printcap entry), default: on. */ static int pdes_always = 1; /** Flag: Reset of pdes_error was done. */ static int pdes_reset = 0; /** Flag: Report unknown states as busy (from pjsnmp-unknown-busy in printcap entry), default: off. */ static int unkn_busy = 0; /** Flag: Do orderly release (from pjsnmp-ordrel in printcap entry). */ static int host_ordr = 0; /** Flag: Accounting enabled (from pjsnmp-accounting-enable in printcap entry). */ static int acct_enab = 0; /** Flag: Quota check enabled (from pjsnmp-accounting-check in printcap entry). */ static int acct_achk = 0; /** Flag: Use separated start/end lines for accounting. Default is to use just one charge line at end. */ static int acct_start_end = 0; /** Flag: Read printer responses (from pjsnmp-read-response in printcap entry). */ static int read_responses = 0; /** Flag: Force printable status text (from pjsnmp-force-printable-status-text in printcap entry). */ static int force_printable_status_text = 1; /** Flag: SNMP check during transfer (from pjsnmp-during-transfer in printcap entry). */ static int check_trans = 1; /** Flag: EOF found on standard input. */ static int have_eof = 0; /** Ignore failed SNMP session (from pjsnmp-ignore-failed-session in printcap entry). */ static int snmp_igfs = 0; /** Allow printing if accounting connection failed. (from pjsnmp-allow-printing-if-accounting-connection-failed). */ static int acct_apcf = 0; /** Flag: Have page counter at start. */ static int have_pcs = 0; /** Flag: Have page counter at end. */ static int have_pce = 0; /** Previous device status. */ static int odevst = 0; /** Current device status. */ static int devst = 0; /** Previous printer status. */ static int oprist = 0; /** Current printer status. */ static int prist = 0; /** Previous summary status. */ static int ostsum = PJSNMP_ST_UNKNOWN; /** Current summary status. */ static int stsum = PJSNMP_ST_UNKNOWN; /** Flag: The printer was seen in printing state. This flag is cleared if the printer was seen in error state, as some printers go from error to printing via idle. */ static int seen_printing = 0; /** Last header used for log messages. */ static int last_header = 0; /** Decision from permission check 0=unknown 1=accept 2=hold 3=remove */ static int decision = 0; /** Port number to send data to in host representation (from pjsnmp-port in printcap entry). */ static unsigned short host_port = 9100; /** Local port number. (from pjsnmp-local-port in printcap entry). */ static unsigned short local_port = 0; /** Accounting port number in host representation (from pjsnmp-accounting-port in printcap entry). */ static unsigned short acct_port = 9100; #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; /** Pass volatile pointer through to caller. The CERT C coding standard recommends to set signal indicator variables through pointers to avoid compilers from optimizing too hard (they might attempt to keep the value in a register although properly marked as volatile). @param ptr Address of volatile indicator variable. @return Same pointer as ptr. */ 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(int dopipe) { int back = 1; if (0 != sig_read_atomic(&sig_had_term)) { back = 0; } if (0 != sig_read_atomic(&sig_had_int)) { back = 0; } #ifdef SIGPIPE if (0 != dopipe) { if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; } } #endif return back; } /** Log a timestamp. @return 1 if time changed since previous log, 0 otherwise. */ static int log_timestamp(void) { char buf[64]; static dk4_time_t previous_log = (dk4_time_t)0UL; dk4_time_t current; int back = 0; #line 1647 "pjsnmp.ctr" dk4time_get(¤t); if (current != previous_log) { #line 1649 "pjsnmp.ctr" if (dk4time_as_text_c8(buf, sizeof(buf), ¤t, NULL)) { back = 1; #line 1651 "pjsnmp.ctr" fputs(pjsnmp_kw[62], out_file); fputs(buf, out_file); fputs(pjsnmp_kw[0], out_file); previous_log = current; } } #line 1657 "pjsnmp.ctr" return back; } /** Log a 1 component message with header line. @param h Header line chooser (1, 2 or 3). @param i Index of message text in pjsnmp_kw. */ static void log_1_with_header(int h, size_t i) { (void)log_timestamp(); if (last_header != h) { fputs(pjsnmp_kw[62 + h], out_file); last_header = h; } fputs(pjsnmp_kw[i], out_file); fflush(out_file); } /** Log a 3 components message with header line. @param h Header line chooser (1, 2 or 3). @param i1 Index of first text component in pjsnmp_kw. @param i2 Index of third text component in pjsnmp_kw. @param s Second text component (variable text). */ static void log_3_with_header(int n, size_t i1, size_t i2, const char *s) { (void)log_timestamp(); if (last_header != n) { fputs(pjsnmp_kw[62 + n], out_file); last_header = n; } fputs(pjsnmp_kw[i1], out_file); if (NULL != s) { fputs(s, out_file); } fputs(pjsnmp_kw[i2], out_file); fflush(out_file); } /** Log a 5 components message with header line. @param h Header line chooser (1, 2 or 3). @param i1 Index of first text component in pjsnmp_kw. @param i2 Index of third text component in pjsnmp_kw. @param i3 Index of fifth text component in pjsnmp_kw. @param s1 Second text component (variable text). @param s2 Fourth text component (variable text). */ static void log_5_with_header( int n, size_t i1, size_t i2, size_t i3, const char *s1, const char *s2 ) { (void)log_timestamp(); if (last_header != n) { fputs(pjsnmp_kw[62 + n], out_file); last_header = n; } fputs(pjsnmp_kw[i1], out_file); if (NULL != s1) { fputs(s1, out_file); } fputs(pjsnmp_kw[i2], out_file); if (NULL != s2) { fputs(s2, out_file); } fputs(pjsnmp_kw[i3], out_file); fflush(out_file); } /** Log a 1 component message without header line. @param i Index of text component in pjsnmp_kw. */ static void log_1_no_header(size_t i) { #line 1746 "pjsnmp.ctr" log_timestamp(); fputs(pjsnmp_kw[i], out_file); fflush(out_file); #line 1750 "pjsnmp.ctr" } /** Log a 3 components message without header line. @param i1 Index of first text component in pjsnmp_kw. @param i2 Index of third text component in pjsnmp_kw. @param s Second text component (variable text). */ static void log_3_no_header(size_t i1, size_t i2, const char *s) { #line 1764 "pjsnmp.ctr" log_timestamp(); fputs(pjsnmp_kw[i1], out_file); if (NULL != s) { fputs(s, out_file); } fputs(pjsnmp_kw[i2], out_file); fflush(out_file); #line 1770 "pjsnmp.ctr" } /** Log a 5 components message without header line. @param i1 Index of first text component in pjsnmp_kw. @param i2 Index of third text component in pjsnmp_kw. @param i3 Index of fifth text component in pjsnmp_kw. @param s1 Second text component (variable text). @param s2 Fourth text component (variable text). */ static void log_5_no_header( size_t i1, size_t i2, size_t i3, const char *s1, const char *s2 ) { log_timestamp(); fputs(pjsnmp_kw[i1], out_file); if (NULL != s1) { fputs(s1, out_file); } fputs(pjsnmp_kw[i2], out_file); if (NULL != s2) { fputs(s2, out_file); } fputs(pjsnmp_kw[i3], out_file); fflush(out_file); } /** Log a 1 component message related to model file. @param lineno Line number in model file to complain about. @param i Index of first text component in pjsnmp_kw. */ static void log_model_1(dk4_um_t lineno, size_t i) { char buf[8*sizeof(dk4_um_t)]; const char *fn; const char *ptr; int res; (void)log_timestamp(); if (3 != last_header) { last_header = 3; fputs(pjsnmp_kw[65], out_file); } if ((dk4_um_t)0UL < lineno) { res = dk4ma_write_c8_decimal_unsigned(buf, sizeof(buf), lineno, 0, NULL); if (0 != res) { fn = ((NULL != model_file) ? model_file : def_model_file); ptr = dk4str8_rchr(fn, '/'); if (NULL != ptr) { ptr++; } else { ptr = fn; } fputs(ptr, out_file); fputs(pjsnmp_kw[143], out_file); fputs(buf, out_file); fputs(pjsnmp_kw[143], out_file); fputs(pjsnmp_kw[1], out_file); } } fputs(pjsnmp_kw[i], out_file); fflush(out_file); } /** Log a 3 components message related to model file. @param lineno Line number in model file to complain about. @param i1 Index of first text component in pjsnmp_kw. @param i2 Index of third text component in pjsnmp_kw. @param s Second text component (variable text). */ static void log_model_3( dk4_um_t lineno, size_t i1, size_t i2, const char *s ) { char buf[8*sizeof(dk4_um_t)]; const char *fn; const char *ptr; int res; (void)log_timestamp(); if (3 != last_header) { last_header = 3; fputs(pjsnmp_kw[65], out_file); } if ((dk4_um_t)0UL < lineno) { res = dk4ma_write_c8_decimal_unsigned(buf, sizeof(buf), lineno, 0, NULL); if (0 != res) { fn = ((NULL != model_file) ? model_file : def_model_file); ptr = dk4str8_rchr(fn, '/'); if (NULL != ptr) { ptr++; } else { ptr = fn; } fputs(ptr, out_file); fputs(pjsnmp_kw[143], out_file); fputs(buf, out_file); fputs(pjsnmp_kw[143], out_file); fputs(pjsnmp_kw[1], out_file); } } fputs(pjsnmp_kw[i1], out_file); if (NULL != s) { fputs(s, out_file); } fputs(pjsnmp_kw[i2], out_file); fflush(out_file); } /** Create new status text node. @param t Text, not 0-terminated. @param tsz Text size. @param st Summary state if text is found. @param fl Flag: This is the start text only. @return Valid pointer on success, NULL on error. */ static status_text_t * stt_new( const unsigned char *t, size_t tsz, int st, int fl ) { status_text_t *back = NULL; #line 1911 "pjsnmp.ctr" if ((NULL != t) && (0 < tsz)) { back = dk4mem_new(status_text_t,1,NULL); if (NULL != back) { DK4_MEMRES(back, sizeof(status_text_t)); back->start = fl; back->state = st; back->size = tsz; back->text = dk4mem_new(unsigned char,tsz,NULL); if (NULL != back->text) { DK4_MEMCPY(back->text, t, tsz); } else { #line 1922 "pjsnmp.ctr" dk4mem_free(back); back = NULL; } } #if TRACE_DEBUG else { #line 1928 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 1933 "pjsnmp.ctr" } #endif #line 1936 "pjsnmp.ctr" return back; } /** Destroy status text node, release memory. @param ptr Node to destroy. */ static void stt_delete(status_text_t *ptr) { #line 1949 "pjsnmp.ctr" if (NULL != ptr) { #line 1950 "pjsnmp.ctr" dk4mem_release(ptr->text); dk4mem_free(ptr); } #line 1954 "pjsnmp.ctr" } /** Compare two status text nodes. While building the storage the start flag is ignored. When searching a text for a status text received via SNMP we have to consider the flag. @param l Left object. @param r Right object. @param cr Comparison criteria (0=build storage, 1=search). @return Comparison result. */ static int stt_compare(const void *l, const void *r, int cr) { const status_text_t *pl; /* Left operand */ const status_text_t *pr; /* Right operand */ size_t min; /* Minimum of both text sizes */ int back = 0; #line 1976 "pjsnmp.ctr" if (NULL != l) { if (NULL != r) { pl = (const status_text_t *)l; pr = (const status_text_t *)r; min = pl->size; if (min > pr->size) { min = pr->size; } if (0 < min) { back = dk4mem_cmp(pl->text, pr->text, min, NULL); } if (0 == back) { if ((0 == cr) || (0 == pl->start)) { if (pl->size > pr->size) { back = 1; } else { if (pl->size < pr->size) { back = -1; } } } } } else { back = 1; } } else { if (NULL != r) { back = -1; } } #line 2005 "pjsnmp.ctr" return back; } /** Set one command line option. @param Option character. @param Option argument. */ static void set_option(char c, char *val) { size_t sz = 0; /* Index of option in arguments array */ #line 2020 "pjsnmp.ctr" if (NULL != val) { if (('a' <= c) && ('z' >= c)) { sz = (size_t)(c - 'a'); if (DK4_SIZEOF(lower,DK4_PCHAR) > sz) { lower[sz] = val; #line 2025 "pjsnmp.ctr" } } else { if (('A' <= c) && ('Z' >= c)) { sz = (size_t)(c - 'A'); if (DK4_SIZEOF(upper,DK4_PCHAR) > sz) { upper[sz] = val; #line 2031 "pjsnmp.ctr" } } } } #line 2035 "pjsnmp.ctr" } /** Retrieve argument for one option. @param c Option character (option name). @return The value provided as option argument, NULL otherwise. */ static char * get_option(char c) { char *back = NULL; size_t sz = 0; /* Index of option in arguments array */ #line 2050 "pjsnmp.ctr" if (('a' <= c) && ('z' >= c)) { sz = (size_t)(c - 'a'); if (DK4_SIZEOF(lower,DK4_PCHAR) > sz) { back = lower[sz]; } } else { if (('A' <= c) && ('Z' >= c)) { sz = (size_t)(c - 'A'); if (DK4_SIZEOF(upper,DK4_PCHAR) > sz) { back = upper[sz]; } } } #line 2063 "pjsnmp.ctr" return back; } /** 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 process_command_line_arguments(int argc, char *argv[]) { char *curarg; /* Current argument to process */ char *s_name; /* Status file name */ size_t szjnb; /* Size of job name buffer */ int back = 1; int i; /* Index of current argument */ int res; /* Result for number to text conversion */ char c; /* Option name */ #line 2085 "pjsnmp.ctr" for (i = 1; i < argc; i++) { curarg = argv[i]; #line 2087 "pjsnmp.ctr" if ('-' == *curarg) { #line 2088 "pjsnmp.ctr" curarg++; if ('\0' != *curarg) { #line 2090 "pjsnmp.ctr" c = *(curarg++); if ('\0' != *curarg) { #line 2092 "pjsnmp.ctr" set_option(c, curarg); } else { #line 2094 "pjsnmp.ctr" #if VERSION_BEFORE_20160208 /* -c may appear without an argument. */ back = 0; /* ERROR: Missing option argument */ log_1_with_header(1, 67); #else set_option(c, (char *)(pjsnmp_kw[144])); #endif } } else { #line 2105 "pjsnmp.ctr" back = 0; /* ERROR: Only minus */ log_1_with_header(1, 66); } } else { #line 2110 "pjsnmp.ctr" #if 0 /* 2016-02-15 Seeing non-option arguments is not an error, the accounting file name is passed once as argument to -a and once as file name. */ back = 0; /* ERROR: Non-option argument found */ log_1_with_header(1, 68); #endif } } if (0 != back) { #line 2122 "pjsnmp.ctr" s_name = get_option('s'); if (NULL != s_name) { #line 2124 "pjsnmp.ctr" stt_file = fopen(s_name, "w"); if (NULL != stt_file) { #line 2126 "pjsnmp.ctr" out_file = stt_file; } #if TRACE_DEBUG else { #line 2130 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 2135 "pjsnmp.ctr" } #endif user_name = get_option('n'); if (NULL == user_name) user_name = get_option('L'); if (NULL != user_name) { user_name = dk4str8_start(user_name, NULL); } if (NULL != user_name) { (void)dk4str8_next(user_name, NULL); if (0 == strlen(user_name)) { user_name = NULL; } } if (NULL == user_name) { #line 2147 "pjsnmp.ctr" /* ERROR: No user name */ log_1_with_header(1, 69); back = 0; } #if TRACE_DEBUG else { #line 2153 "pjsnmp.ctr" } #endif if (0 != back) { #line 2156 "pjsnmp.ctr" queue_name = get_option('P'); if (NULL == queue_name) queue_name = get_option('Q'); if (NULL != queue_name) { queue_name = dk4str8_start(queue_name, NULL); } if (NULL != queue_name) { (void)dk4str8_next(queue_name, NULL); if (0 == strlen(queue_name)) { queue_name = NULL; } } if (NULL == queue_name) { #line 2166 "pjsnmp.ctr" /* ERROR: No queue name */ log_1_with_header(1, 70); back = 0; } #if TRACE_DEBUG else { #line 2172 "pjsnmp.ctr" } #endif } if (0 != back) { job_name = get_option('A'); #line 2177 "pjsnmp.ctr" if (NULL == job_name) job_name = get_option('j'); if (NULL == job_name) job_name = get_option('t'); if (NULL == job_name) job_name = get_option('D'); if (NULL != job_name) { job_name = dk4str8_start(job_name, NULL); } if (NULL != job_name) { (void)dk4str8_next(job_name, NULL); if (0 == strlen(job_name)) { job_name = NULL; } } if (NULL == job_name) { szjnb = sizeof(job_name_buf); if (0 != dk4str8_cpy_s(job_name_buf, szjnb, pjsnmp_kw[171], NULL)) { res = dk4ma_write_c8_decimal_unsigned( &(job_name_buf[strlen(job_name_buf)]), (szjnb - strlen(job_name_buf)), (dk4_um_t)getpid(), 0, NULL ); if (0 != res) { job_name = job_name_buf; } } } if (NULL == job_name) { #line 2200 "pjsnmp.ctr" /* ERROR: No job name */ log_1_with_header(1, 71); back = 0; } #if TRACE_DEBUG else { #line 2206 "pjsnmp.ctr" } #endif } if (0 != back) { #line 2210 "pjsnmp.ctr" job_title = get_option('J'); if (NULL == job_title) job_title = get_option('f'); if (NULL == job_title) job_title = get_option('N'); if (NULL != job_title) { job_title = dk4str8_start(job_title, NULL); } if (NULL != job_title) { dk4str8_normalize(job_title, NULL); } #if 0 /* 20160206 Allow job_title to be NULL, pjsnmp_kw[54] is used instead. */ if (NULL == job_title) { #line 2224 "pjsnmp.ctr" back = 0; } #endif #if TRACE_DEBUG else { #line 2229 "pjsnmp.ctr" } #endif } } #line 2234 "pjsnmp.ctr" return back; } /** Set string pointer. @param dptr Address of pointer to set. @param src Value. @param name Configuration entry name. @return 1 on success, 0 on error. */ static int set_string(char **dptr, char *src, const char *name) { int back = 0; #line 2251 "pjsnmp.ctr" if (NULL != src) { src = dk4str8_start(src, NULL); if (NULL != src) { #line 2254 "pjsnmp.ctr" if (NULL != *dptr) { #line 2255 "pjsnmp.ctr" /* WARNING: Redefinition */ log_5_with_header(2, 72, 73, 74, name, src); } *dptr = src; back = 1; } else { #line 2261 "pjsnmp.ctr" /* ERROR: Empty text */ log_3_with_header(2, 75, 76, name); } } else { #line 2265 "pjsnmp.ctr" /* ERROR: Text string required */ log_3_with_header(2, 77, 78, name); } #line 2268 "pjsnmp.ctr" return back; } /** Set unsigned short variable. @param dptr Address of variable to set. @param src Text containing the value. @return 1 on success, 0 on error. */ static int set_unsigned_short(unsigned short *dptr, char *src, const char *name) { const char *ep = NULL; /* First unprocessabe char */ int back = 0; int res; /* Operation result */ unsigned short us; #line 2287 "pjsnmp.ctr" if (NULL != src) { src = dk4str8_start(src, NULL); if (NULL != src) { res = dk4ma_input_c8_dec_ushort(&us, src, &ep, 1, NULL); if (0 != res) { *dptr = us; back = 1; #line 2294 "pjsnmp.ctr" } else { #line 2295 "pjsnmp.ctr" /* ERROR: Not a number! */ log_5_with_header(2, 79, 80, 81, name, src); } } else { #line 2299 "pjsnmp.ctr" /* ERROR: Empty text */ log_3_with_header(2, 75, 76, name); } } else { #line 2303 "pjsnmp.ctr" /* ERROR: Numeric value required */ log_3_with_header(2, 77, 78, name); } #line 2306 "pjsnmp.ctr" return back; } /** Set SNMP version. @param dptr Address of variable to set. @param src Text containing the SNMP version. @return 1 on success, 0 on error. */ static int set_snmp_version(long *dptr, char *src) { int back = 0; #line 2322 "pjsnmp.ctr" if (NULL != src) { src = dk4str8_start(src, NULL); if (NULL != src) { switch (dk4str8_array_index(snmp_version_names, src, 0)) { case 0: { #line 2327 "pjsnmp.ctr" *dptr = SNMP_VERSION_1; back = 1; } break; case 1: case 2: { #line 2331 "pjsnmp.ctr" *dptr = SNMP_VERSION_2c; back = 1; } break; case 3: { #line 2335 "pjsnmp.ctr" *dptr = SNMP_VERSION_3; back = 1; } break; default: { #line 2339 "pjsnmp.ctr" /* ERROR: Illegal SNMP version */ log_3_with_header(2, 82, 83, src); } break; } } else { #line 2344 "pjsnmp.ctr" /* ERROR: Empty text */ log_3_with_header(2, 75, 76, printcap_entry_names[9]); } } else { #line 2348 "pjsnmp.ctr" /* ERROR: Value required */ log_3_with_header(2, 77, 78, printcap_entry_names[9]); } #line 2352 "pjsnmp.ctr" return back; } /** Set maximum unsigned integer variable from text. @param dptr Address of destination variable. @param src Text containing the value. @param name Setting name for diagnostics. @return 1 on success, 0 on error. */ static int set_umax(dk4_um_t *dptr, char *src, const char *name) { const char *ep = NULL; /* First unprocessable character */ dk4_um_t i = 0UL; /* Result value */ int back = 0; int res; /* Operation result */ #line 2372 "pjsnmp.ctr" if (NULL != src) { res = dk4ma_input_c8_dec_dk4_um_t(&i, src, &ep, 1, NULL); if (0 != res) { *dptr = i; #line 2376 "pjsnmp.ctr" back = 1; } else { #line 2378 "pjsnmp.ctr" /* ERROR: Not a numeric value */ log_5_with_header(2, 84, 161, 86, name, src); } } else { #line 2382 "pjsnmp.ctr" /* ERROR: Value required */ log_3_with_header(2, 77, 78, name); } #line 2385 "pjsnmp.ctr" return back; } #if 0 /** Set integer variable from text. @param dptr Address of destination variable. @param src Text containing the value. @param name Setting name for diagnostics. @return 1 on success, 0 on error. */ static int set_integer(int *dptr, char *src, const char *name) { const char *ep = NULL; /* First unprocessable character */ int i = 0; /* Result value */ int back = 0; int res; /* Operation result */ #line 2407 "pjsnmp.ctr" if (NULL != src) { res = dk4ma_input_c8_dec_int(&i, src, &ep, 1, NULL); if (0 != res) { *dptr = i; #line 2411 "pjsnmp.ctr" back = 1; } else { #line 2413 "pjsnmp.ctr" /* ERROR: Not a numeric value */ log_5_with_header(2, 84, 85, 86, name, src); } } else { #line 2417 "pjsnmp.ctr" /* ERROR: Value required */ log_3_with_header(2, 77, 78, name); } #line 2420 "pjsnmp.ctr" return back; } #endif /** Process one configuration item from a printcap entry. @param ci Item to process. @return 1 on success, 0 on error. */ static int process_one_config_item(char *ci) { char *value = NULL; /* Value for config item */ int btrue = 1; /* Condition */ int back = 1; #line 2439 "pjsnmp.ctr" value = dk4str8_chr(ci, '='); if (NULL != value) { *(value++) = '\0'; value = dk4str8_start(value, NULL); #line 2443 "pjsnmp.ctr" } else { value = dk4str8_chr(ci, '@'); if (NULL != value) { #line 2446 "pjsnmp.ctr" *value = '\0'; btrue = 0; } #if TRACE_DEBUG else { #line 2451 "pjsnmp.ctr" } #endif } switch (dk4str8_array_index(printcap_entry_names, ci, 0)) { case 0: { #line 2456 "pjsnmp.ctr" if (0 == set_string(&host_name, value, printcap_entry_names[0])) { back = 0; } } break; case 1: { #line 2461 "pjsnmp.ctr" if (0 == set_unsigned_short(&host_port, value, printcap_entry_names[1])) { back = 0; } } break; case 2: { #line 2466 "pjsnmp.ctr" host_ordr = btrue; } break; case 3: { #line 2469 "pjsnmp.ctr" acct_enab = btrue; } break; case 4: { #line 2472 "pjsnmp.ctr" acct_achk = btrue; } break; case 5: { #line 2475 "pjsnmp.ctr" if (0 == set_string(&acct_name, value, printcap_entry_names[5])) { back = 0; } } break; case 6: { #line 2480 "pjsnmp.ctr" if (0 == set_string(&acct_host, value, printcap_entry_names[6])) { back = 0; } } break; case 7: { #line 2485 "pjsnmp.ctr" if (0 == set_unsigned_short(&acct_port, value, printcap_entry_names[7])) { back = 0; } } break; case 8: { #line 2490 "pjsnmp.ctr" if (NULL != value) { if (0 == set_umax(&print_timeout, value, printcap_entry_names[8])) { back = 0; } } else { if (0 == btrue) { print_timeout = (dk4_um_t)0UL; } else { back = 0; } } } break; case 9: { #line 2500 "pjsnmp.ctr" if (0 == set_snmp_version(&snmp_version, value)) { back = 0; } } break; case 10: { #line 2505 "pjsnmp.ctr" if (0 == set_string(&snmp_comm, value, printcap_entry_names[10])) { back = 0; } } break; case 11: { #line 2510 "pjsnmp.ctr" check_trans = btrue; } break; case 12: { #line 2513 "pjsnmp.ctr" if (0 == set_string(&model_file, value, printcap_entry_names[12])) { back = 0; } } break; case 13: { #line 2518 "pjsnmp.ctr" if (0 == set_string(&model_name, value, printcap_entry_names[13])) { back = 0; } } break; case 14: { #line 2523 "pjsnmp.ctr" snmp_igfs = btrue; } break; case 15: { #line 2526 "pjsnmp.ctr" acct_apcf = btrue; } break; case 16: { #line 2529 "pjsnmp.ctr" pdes_always = btrue; } break; case 17: { #line 2532 "pjsnmp.ctr" unkn_busy = btrue; } break; case 18: { #line 2535 "pjsnmp.ctr" if (NULL != value) { if (0 == set_umax(&unto_start, value, printcap_entry_names[18])) { back = 0; } } else { if (0 == btrue) { unto_start = (dk4_um_t)0UL; } else { back = 0; } } } break; case 19: { #line 2545 "pjsnmp.ctr" if (NULL != value) { if (0 == set_umax(&unto_end, value, printcap_entry_names[19])) { back = 0; } } else { if (0 == btrue) { unto_end = (dk4_um_t)0UL; } else { back = 0; } } } break; case 20: { #line 2555 "pjsnmp.ctr" if (NULL != value) { if (0 == set_umax(&unto_print, value, printcap_entry_names[20])) { back = 0; } } else { if (0 == btrue) { unto_print = (dk4_um_t)0UL; } else { back = 0; } } } break; case 21: { #line 2565 "pjsnmp.ctr" if (0 == set_unsigned_short(&local_port, value, printcap_entry_names[21])) { back = 0; #line 2568 "pjsnmp.ctr" } } break; case 22: { #line 2571 "pjsnmp.ctr" if (NULL != value) { if (0 == set_umax(&unwt_print, value, printcap_entry_names[22])) { back = 0; } } else { if (0 == btrue) { unwt_print = (dk4_um_t)0UL; } else { #line 2578 "pjsnmp.ctr" back = 0; } } } break; case 23: { #line 2583 "pjsnmp.ctr" read_responses = btrue; } break; case 24: { #line 2586 "pjsnmp.ctr" force_printable_status_text = btrue; } break; case 25: { if (NULL != value) { if (0 == set_umax(&erto_start, value, printcap_entry_names[22])) { back = 0; } } else { if (0 == btrue) { erto_start = (dk4_um_t)0UL; } else { #line 2596 "pjsnmp.ctr" back = 0; } } } break; case 26: { if (NULL != value) { if (0 == set_umax(&erto_end, value, printcap_entry_names[22])) { back = 0; } } else { if (0 == btrue) { erto_end = (dk4_um_t)0UL; } else { #line 2608 "pjsnmp.ctr" back = 0; } } } break; case 27: { if (NULL != value) { if (0 == set_umax(&erto_print, value, printcap_entry_names[22])) { back = 0; } } else { if (0 == btrue) { erto_print = (dk4_um_t)0UL; } else { #line 2620 "pjsnmp.ctr" back = 0; } } } break; case 28: { verbose = btrue; } break; case 29: { allow_non_ascii = btrue; } break; case 30: { acct_start_end = btrue; } break; } #line 2634 "pjsnmp.ctr" return back; } /** Check whether the line opens the model we are searching for. @param str Text to check. @param bptr Address of success indicator. @return 1 on success, 0 on error. */ static int check_in_model(char *str, int *bptr, dk4_um_t lineno) { char *ptr; /* Closing square bracket */ int back = 0; #line 2651 "pjsnmp.ctr" str = dk4str8_start(str, NULL); if (NULL != str) { ptr = dk4str8_chr(str, ']'); if (NULL != ptr) { *ptr = '\0'; dk4str8_normalize(str, NULL); #line 2657 "pjsnmp.ctr" if (0 == strcmp(str, model_name)) { back = 1; #line 2659 "pjsnmp.ctr" } #if TRACE_DEBUG else { #line 2662 "pjsnmp.ctr" } #endif } else { #line 2665 "pjsnmp.ctr" /* ERROR: Syntax */ log_model_1(lineno, 87); } } else { #line 2669 "pjsnmp.ctr" /* ERROR: Syntax */ log_model_1(lineno, 88); } #line 2672 "pjsnmp.ctr" return back; } /** Overwrite one mapping from device/printer status to summary state. @param devst Device status. @param prst Printer status. @param sujmst Summary state resulting from device and printer status. */ static void set_state_mapping(int devst, int prst, int sumst) { #line 2687 "pjsnmp.ctr" if ((0 < devst) && (6 > devst)) { if ((0 < prst) && (6 > prst)) { #line 2689 "pjsnmp.ctr" summary_states[5 * devst + prst - 6] = sumst; } #if TRACE_DEBUG else { #line 2693 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 2698 "pjsnmp.ctr" } #endif #line 2701 "pjsnmp.ctr" } /** Map device and printer status to summary state. @param devst Device status. @param prst Printer status. @return Summary state. */ static int get_state_mapping(int devst, int prst) { int back = PJSNMP_ST_UNKNOWN; #line 2716 "pjsnmp.ctr" if ((0 < devst) && (6 > devst)) { if ((0 < prst) && (6 > prst)) { #line 2718 "pjsnmp.ctr" back = summary_states[5 * devst + prst - 6]; #line 2720 "pjsnmp.ctr" } #if TRACE_DEBUG else { #line 2723 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 2728 "pjsnmp.ctr" } #endif #line 2731 "pjsnmp.ctr" return back; } /** Add a state mapping. @param str Mapping text. @param lineno Line number (for diagnostics). @return 1 on success, 0 on error. */ static int model_conf_map(char *str, dk4_um_t lineno) { char *psummary; /* Summary state name */ char *ppr; /* Printer status */ int stsum; /* Summary state */ int stdev; /* Device status */ int stpri; /* Printer status */ int back = 0; #line 2752 "pjsnmp.ctr" psummary = dk4str8_next(str, NULL); if (NULL != psummary) { #line 2754 "pjsnmp.ctr" ppr = dk4str8_chr(str, '/'); if (NULL != ppr) { #line 2756 "pjsnmp.ctr" *(ppr++) = '\0'; ppr = dk4str8_start(ppr, NULL); if (NULL != ppr) { #line 2759 "pjsnmp.ctr" back = 1; switch (dk4str8_abbr_index(summary_state_names, '$', psummary, 0)) { case 0: { #line 2762 "pjsnmp.ctr" stsum = PJSNMP_ST_UNKNOWN; } break; case 1: { #line 2765 "pjsnmp.ctr" stsum = PJSNMP_ST_ERROR; } break; case 2: { #line 2768 "pjsnmp.ctr" stsum = PJSNMP_ST_BUSY; } break; case 3: { #line 2771 "pjsnmp.ctr" stsum = PJSNMP_ST_IDLE; } break; case 4: { #line 2774 "pjsnmp.ctr" stsum = PJSNMP_ST_WARMUP; } break; case 5: { #line 2777 "pjsnmp.ctr" stsum = PJSNMP_ST_STANDBY; } break; default: { #line 2780 "pjsnmp.ctr" back = 0; /* ERROR: Illegal summary state */ log_model_3(lineno, 89, 90, psummary); } break; } if (0 != back) { #line 2786 "pjsnmp.ctr" if (0 == strcmp(str, pjsnmp_kw[3])) { if (0 == strcmp(ppr, pjsnmp_kw[3])) { #line 2788 "pjsnmp.ctr" for (stdev = 1; stdev < 6; stdev++) { for (stpri = 1; stpri < 6; stpri++) { set_state_mapping(stdev, stpri, stsum); } } } else { #line 2794 "pjsnmp.ctr" stpri = dk4str8_abbr_index(printer_status_names, '$', ppr, 0); if (-1 < stpri) { stpri++; #line 2797 "pjsnmp.ctr" for (stdev = 1; stdev < 6; stdev++) { set_state_mapping(stdev, stpri, stsum); } } else { #line 2801 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, illegal printer status name */ log_model_3(lineno, 91, 92, ppr); } } } else { stdev = dk4str8_abbr_index(device_status_names, '$', str, 0); if (-1 < stdev) { stdev++; #line 2810 "pjsnmp.ctr" if (0 == strcmp(ppr, pjsnmp_kw[3])) { #line 2811 "pjsnmp.ctr" for (stpri = 1; stpri < 6; stpri++) { set_state_mapping(stdev, stpri, stsum); } } else { #line 2815 "pjsnmp.ctr" stpri = dk4str8_abbr_index(printer_status_names, '$', ppr, 0); if (-1 < stpri) { stpri++; #line 2818 "pjsnmp.ctr" set_state_mapping(stdev, stpri, stsum); } else { #line 2820 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, illegal printer status name */ log_model_3(lineno, 91, 92, ppr); } } } else { #line 2826 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, illegal device status name */ log_model_3(lineno, 93, 94, ppr); } } } else { #line 2832 "pjsnmp.ctr" } } else { #line 2834 "pjsnmp.ctr" /* ERROR: Syntax, printer status missing */ log_model_1(lineno, 95); } } else { #line 2838 "pjsnmp.ctr" /* ERROR: Syntax, printer status missing */ log_model_1(lineno, 95); } } else { #line 2842 "pjsnmp.ctr" /* ERROR: Syntax, summary state missing */ log_model_1(lineno, 96); } #line 2845 "pjsnmp.ctr" return back; } /** Add a condition to the error conditions list. @param str Text for condition. @param addcond Flag: Add to existing list, do not reset. @param lineno Line number (for diagnostics). @return 1 on success, 0 on error. */ static int model_conf_error_condition(char *str, int addcond, dk4_um_t lineno) { unsigned long cond; /* Used to build condition bit */ int i; /* Index of keyword in condition_names */ int back = 0; #line 2864 "pjsnmp.ctr" if ((0 == addcond) && (0 == pdes_reset)) { pdes_error = 0UL; #line 2866 "pjsnmp.ctr" } pdes_reset = 1; dk4str8_normalize(str, NULL); i = dk4str8_array_index(condition_names, str, 0); #line 2870 "pjsnmp.ctr" if (-1 < i) { back = 1; cond = 0x80000000UL; while (0 < i--) { cond = cond / 2UL; } pdes_error |= cond; #line 2875 "pjsnmp.ctr" } else { #line 2876 "pjsnmp.ctr" /* ERROR: Syntax, illegal condition name */ log_model_3(lineno, 97, 98, str); } #line 2879 "pjsnmp.ctr" return back; } /** Set status text OID. @param str Text containing the OID. @param lineno Line number (for diagnostics). @return 1 on success, 0 on error. */ static int model_conf_status_oid(char *str, dk4_um_t lineno) { const char *ep; /* First unprocessable character */ char *np; /* Next part */ dk4_um_t num; /* Numeric value for sub-id */ size_t used = 0; /* Number of used sub-ids */ int back = 1; int res; /* Operation result */ #line 2900 "pjsnmp.ctr" dk4str8_normalize(str, NULL); if ('.' == *str) { #line 2902 "pjsnmp.ctr" str++; } while ((NULL != str) && (1 == back)) { np = dk4str8_chr(str, '.'); if (NULL != np) { *(np++) = '\0'; } #line 2909 "pjsnmp.ctr" ep = NULL; res = dk4ma_input_c8_dec_dk4_um_t(&num, str, &ep, 1, NULL); if (0 != res) { #line 2912 "pjsnmp.ctr" if ((dk4_um_t)(MAX_SUBID) >= num) { #line 2913 "pjsnmp.ctr" if (used < DK4_SIZEOF(oid_st,oid)) { #line 2914 "pjsnmp.ctr" oid_st[used++] = (oid)num; } else { #line 2916 "pjsnmp.ctr" /* ERROR: Syntax, OID too long */ log_model_1(lineno, 99); } } else { #line 2920 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, overflow */ log_model_3(lineno, 100, 101, str); } } else { #line 2925 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, not a number */ log_model_3(lineno, 102, 103, str); } str = np; } if (0 == used) { #line 2932 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, empty OID */ log_model_1(lineno, 104); } if (0 != back) { sz_oid_st = used; } else { sz_oid_st = 0; } by_oid_st = sz_oid_st * sizeof(oid); #line 2943 "pjsnmp.ctr" return back; } /** Remove final double quote from string. @param str String to modify. @return 1 on success, 0 on error. */ static int remove_final_double_quote(char *str) { char *ptr; /* Position of final double quote */ int back = 0; #line 2959 "pjsnmp.ctr" ptr = dk4str8_rchr(str, '"'); if (NULL != ptr) { #line 2961 "pjsnmp.ctr" *(ptr++) = '\0'; back = 1; while ('\0' != *ptr) { if (' ' != *ptr) { if ('\t' != *ptr) { if ('\r' != *ptr) { if ('\n' != *ptr) { back = 0; #line 2969 "pjsnmp.ctr" } } } } ptr++; } } #if TRACE_DEBUG else { #line 2978 "pjsnmp.ctr" } #endif #line 2981 "pjsnmp.ctr" return back; } /** Add a text indicating a state to the storage. @param str Indicator text. @param state State number indicated by the text. @param start Flag: This text is just the start of the real text. @param lineno Line number (for diagnostics). @return 1 on success, 0 on error. */ static int model_conf_state_text(char *str, int state, int start, dk4_um_t lineno) { status_text_t *stptr; /* New configuration node to add */ const char *ep; /* First unprocessable char when reading number */ char *cptr; /* Current word to process */ char *nptr; /* Next word (remaining text) to process */ size_t sl; /* String length */ int res; /* Operation result */ int back = 0; unsigned char uc; /* Current byte found */ #line 3006 "pjsnmp.ctr" if (NULL == s_stn) { s_stn = dk4sto_open(NULL); if (NULL != s_stn) { dk4sto_set_comp(s_stn, stt_compare, 0); } } if ((NULL != s_stn) && (NULL == i_stn)) { i_stn = dk4sto_it_open(s_stn, NULL); } if ((NULL != s_stn) && (NULL != i_stn)) { #line 3016 "pjsnmp.ctr" if (NULL != str) { #line 3017 "pjsnmp.ctr" if ('"' == *str) { #line 3018 "pjsnmp.ctr" str++; if (0 != remove_final_double_quote(str)) { sl = strlen(str); if (0 < sl) { #line 3022 "pjsnmp.ctr" stptr = stt_new((unsigned char *)str, sl, state, start); if (NULL != stptr) { #line 3024 "pjsnmp.ctr" if (0 != dk4sto_add(s_stn, stptr, NULL)) { back = 1; #line 3026 "pjsnmp.ctr" } else { #line 3027 "pjsnmp.ctr" /* ERROR: Allocation failed */ log_model_1(lineno, 105); stt_delete(stptr); } } else { #line 3032 "pjsnmp.ctr" /* ERROR: Allocation failed */ log_model_1(lineno, 105); } } else { #line 3036 "pjsnmp.ctr" /* ERROR: Syntax, string empty */ log_model_1(lineno, 106); } } else { #line 3040 "pjsnmp.ctr" /* ERROR: Syntax, closing double quote missing or text after */ log_model_1(lineno, 107); } } else { #line 3044 "pjsnmp.ctr" sl = 0; cptr = str; back = 1; while ((NULL != cptr) && (0 != back)) { nptr = dk4str8_next(cptr, NULL); ep = NULL; #line 3050 "pjsnmp.ctr" res = dk4ma_input_c8_hex_uchar(&uc, cptr, &ep, 1, NULL); if (0 != res) { str[sl++] = (char)uc; #line 3053 "pjsnmp.ctr" } else { back = 0; #line 3055 "pjsnmp.ctr" /* ERROR: Syntax, not a hexadecimal byte */ log_model_3(lineno, 108, 109, cptr); } cptr = nptr; } if (0 != back) { if (0 < sl) { #line 3062 "pjsnmp.ctr" stptr = stt_new((unsigned char *)str, sl, state, start); if (NULL != stptr) { #line 3064 "pjsnmp.ctr" if (0 == dk4sto_add(s_stn, stptr, NULL)) { back = 0; #line 3066 "pjsnmp.ctr" stt_delete(stptr); /* ERROR: Allocation failed */ log_model_1(lineno, 105); } #if TRACE_DEBUG else { #line 3072 "pjsnmp.ctr" } #endif } else { #line 3075 "pjsnmp.ctr" back = 0; /* ERROR: Memory allocation failed */ log_model_1(lineno, 105); } } else { #line 3080 "pjsnmp.ctr" /* ERROR: Syntax, empty string */ log_model_1(lineno, 106); } } } } else { #line 3086 "pjsnmp.ctr" /* ERROR: Value required */ log_model_1(lineno, 110); } } else { #line 3090 "pjsnmp.ctr" /* ERROR: Memory allocation failed */ log_model_1(lineno, 105); } #line 3093 "pjsnmp.ctr" return back; } /** Process one configuration line from model file. @param str Line to process. @param lineno Line number in the file (for diagnostics). @return 1 on success, 0 on error. */ static int process_model_line(char *str, dk4_um_t lineno) { char *valptr; /* Value in line */ int back = 0; #line 3110 "pjsnmp.ctr" valptr = dk4str8_chr(str, '='); if (NULL != valptr) { #line 3112 "pjsnmp.ctr" *(valptr++) = '\0'; dk4str8_normalize(str, NULL); valptr = dk4str8_start(valptr, NULL); if (NULL != valptr) { #line 3116 "pjsnmp.ctr" switch (dk4str8_array_index(model_keys, str, 0)) { case 0: { back = model_conf_map(valptr, lineno); } break; case 1: { back = model_conf_error_condition(valptr, 0, lineno); } break; case 2: { back = model_conf_error_condition(valptr, 1, lineno); } break; case 3: { back = model_conf_status_oid(valptr, lineno); } break; case 4: { back = model_conf_state_text(valptr, PJSNMP_ST_STANDBY, 0, lineno); } break; case 5: { back = model_conf_state_text(valptr, PJSNMP_ST_STANDBY, 1, lineno); } break; case 6: { back = model_conf_state_text(valptr, PJSNMP_ST_IDLE, 0, lineno); } break; case 7: { back = model_conf_state_text(valptr, PJSNMP_ST_IDLE, 1, lineno); } break; case 8: { back = 1; if (NULL != valptr) { valptr = dk4str8_start(valptr, NULL); if (NULL != valptr) { dk4str8_normalize(valptr, NULL); if (dk4str8_is_bool(valptr)) { stat_always = dk4str8_is_on(valptr); } else { back = 0; /* ERROR: Not a boolean */ log_model_3(lineno, 111, 112, valptr); } } else { stat_always = 1; } } else { stat_always = 1; } } break; case 9: { back = model_conf_state_text(valptr, PJSNMP_ST_BUSY, 0, lineno); } break; case 10: { back = model_conf_state_text(valptr, PJSNMP_ST_BUSY, 1, lineno); } break; case 11: { back = model_conf_state_text(valptr, PJSNMP_ST_UNKNOWN, 0, lineno); } break; case 12: { back = model_conf_state_text(valptr, PJSNMP_ST_UNKNOWN, 1, lineno); } break; case 13: { back = model_conf_state_text(valptr, PJSNMP_ST_ERROR, 0, lineno); } break; case 14: { back = model_conf_state_text(valptr, PJSNMP_ST_ERROR, 1, lineno); } break; case 15: { back = model_conf_state_text(valptr, PJSNMP_ST_WARMUP, 0, lineno); } break; case 16: { back = model_conf_state_text(valptr, PJSNMP_ST_WARMUP, 1, lineno); } break; default: { #line 3186 "pjsnmp.ctr" /* ERROR: Syntax, unknown key */ log_model_3(lineno, 113, 114, str); } break; } } else { #line 3191 "pjsnmp.ctr" /* ERROR: Syntax, missing value */ log_model_1(lineno, 110); } } else { #line 3195 "pjsnmp.ctr" /* ERROR: Syntax, missing value */ log_model_1(lineno, 110); } #line 3198 "pjsnmp.ctr" return back; } /** Configure for specified SNMP model. */ static int process_model_setup(void) { FILE *infile; /* Input file to read */ char *p1; /* Start of text in line */ dk4_um_t lineno = (dk4_um_t)0UL; int in_model = 0; /* Flag: In model to read */ int found = 0; /* Flag: Model was found */ int back = 0; #line 3216 "pjsnmp.ctr" infile = fopen(((NULL != model_file) ? model_file : def_model_file), "r"); if (NULL != infile) { #line 3218 "pjsnmp.ctr" back = 1; while (NULL != fgets(pjsnmp_buf, sizeof(pjsnmp_buf), infile)) { lineno++; #if TRACE_DEBUG dk4str8_delnl(pjsnmp_buf); #line 3223 "pjsnmp.ctr" #endif p1 = dk4str8_start(pjsnmp_buf, NULL); if (NULL != p1) { if ('[' == *p1) { in_model = check_in_model(++p1, &back, lineno); if (0 != in_model) { found = 1; } } else { if (0 != in_model) { if ('#' != *p1) { #if !TRACE_DEBUG dk4str8_delnl(pjsnmp_buf); #endif if (0 == process_model_line(p1, lineno)) { back = 0; } } } } } } fclose(infile); if (0 == found) { #line 3247 "pjsnmp.ctr" back = 0; /* ERROR: Model not found */ log_model_3((dk4_um_t)0UL, 115, 116, model_name); } } else { #line 3252 "pjsnmp.ctr" /* ERROR: Failed to open model file */ log_model_3( (dk4_um_t)0UL, 115, 116, ((NULL != model_file) ? model_file : def_model_file) ); } #line 3258 "pjsnmp.ctr" return back; } /** Process PRINTCAP_ENTRY and optionally model file. @param argc Number of command line arguments. @param argv Command line arguments array. @return 1 on success, 0 on error. */ static int process_setup(void) { char *ptr; /* Environment variable value */ char *cl; /* Current line */ char *nl; /* Next line */ char *ci; /* Current item */ char *ni; /* Next item */ int found = 0; /* Already item found */ int back = 0; #line 3281 "pjsnmp.ctr" ptr = getenv(pjsnmp_kw[2]); if (NULL != ptr) { #line 3284 "pjsnmp.ctr" printcap_entry = dk4str8_dup(ptr, NULL); if (NULL != printcap_entry) { #line 3286 "pjsnmp.ctr" back = 1; #line 3287 "pjsnmp.ctr" cl = printcap_entry; while (NULL != cl) { nl = dk4str8_chr(cl, '\n'); if (NULL != nl) { *(nl++) = '\0'; nl = dk4str8_start(nl, NULL); } #line 3294 "pjsnmp.ctr" ptr = cl; while ('\0' != *ptr) { if ('\r' == *ptr) { *ptr = '\0'; } else { ptr++; } } ci = dk4str8_start(cl, NULL); if (NULL != ci) { if ('#' != *ci) { while (NULL != ci) { ni = dk4str8_chr(ci, ':'); if (NULL != ni) { *(ni++) = '\0'; ni = dk4str8_start(ni, NULL); } #line 3306 "pjsnmp.ctr" ci = dk4str8_start(ci, NULL); if (NULL != ci) { if (0 != found) { if (0 == process_one_config_item(ci)) { back = 0; #line 3311 "pjsnmp.ctr" } } found = 1; } ci = ni; } } } cl = nl; } if (NULL == host_name) { back = 0; #line 3323 "pjsnmp.ctr" /* ERROR: Host name of printer required */ log_1_with_header(2, 119); } if (0 != back) { if (NULL != model_name) { back = process_model_setup(); #line 3329 "pjsnmp.ctr" } } if (0 != back) { if (0 != acct_achk) { #line 3333 "pjsnmp.ctr" acct_enab = 1; } if (0 != acct_enab) { if (NULL == acct_name) { if ((NULL == acct_host) || (0 == acct_port)) { log_1_with_header(2, 165); back = 0; } } } } } else { #line 3345 "pjsnmp.ctr" /* ERROR: Memory allocation failed */ log_1_with_header(2, 105); } } else { #line 3349 "pjsnmp.ctr" /* ERROR: Missing printcap entry environment variable */ log_1_with_header(2, 120); } #line 3353 "pjsnmp.ctr" return back; } /** Eat up remaining input from standard input. */ static void eatup_input(void) { size_t rdb; /* Number of read bytes */ int cc = 1; #line 3367 "pjsnmp.ctr" do { if (0 != can_continue(0)) { if (0 == have_eof) { #line 3370 "pjsnmp.ctr" rdb = fread(pjsnmp_buf, 1, sizeof(pjsnmp_buf), stdin); if (0 == rdb) { #line 3372 "pjsnmp.ctr" cc = 0; have_eof = 1; } #if TRACE_DEBUG else { #line 3377 "pjsnmp.ctr" } #endif } else { #line 3380 "pjsnmp.ctr" cc = 0; } } else { #line 3383 "pjsnmp.ctr" cc = -1; } } while (1 == cc); #line 3387 "pjsnmp.ctr" } /** Release memory for the text nodes in s_stn. */ static void relase_status_text_nodes(void) { status_text_t *ptr; /* Current node to release */ #line 3399 "pjsnmp.ctr" if (NULL != s_stn) { if (NULL != i_stn) { dk4sto_it_reset(i_stn); do { ptr = (status_text_t *)dk4sto_it_next(i_stn); if (NULL != ptr) { #line 3405 "pjsnmp.ctr" stt_delete(ptr); } } while(NULL != ptr); dk4sto_it_close(i_stn); i_stn = NULL; } dk4sto_close(s_stn); s_stn = NULL; } #line 3413 "pjsnmp.ctr" } /** Attempt to open an SNMP session. @return 1 on success, 0 on error. */ static int attempt_snmp_session(void) { struct snmp_session template; /* Template for the session */ int back = 0; #line 3427 "pjsnmp.ctr" init_snmp(pjsnmp_kw[4]); DK4_MEMRES(&template, sizeof(template)); snmp_sess_init(&template); template.version = snmp_version; template.peername = host_name; template.community = (unsigned char *)snmp_comm; if (NULL == snmp_comm) { template.community = (unsigned char *)(pjsnmp_kw[5]); } template.community_len = strlen((char *)(template.community)); snmp_sess = snmp_open(&template); if (NULL != snmp_sess) { #line 3439 "pjsnmp.ctr" back = 1; } else { #line 3441 "pjsnmp.ctr" /* ERROR: Failed to open SNMP session */ log_1_no_header(121); if (0 != snmp_igfs) { #line 3444 "pjsnmp.ctr" back = 1; } } #line 3447 "pjsnmp.ctr" return back; } /** Accounting data exchange via socket (either network socket or local UNIX domain socket) and close socket. @param sock Socket to use for data exchange. @param expect_response Flag: Response from accounting system expected. @return 1 on success, 0 on error. */ static int accounting_ex_socket(dk4_socket_t sock, int expect_response) { size_t sl; /* String length */ size_t by; /* Bytes written or read */ int res; /* Operation result */ int cutted; /* String was cutted */ int cc; /* Flag: Can continue */ int back = 0; #line 3469 "pjsnmp.ctr" cutted = 0; if (0 != can_continue(0)) { #line 3471 "pjsnmp.ctr" sl = strlen(pjsnmp_buf); by = sl; res = dk4socket_send(sock, pjsnmp_buf, &by, 0, 0L, 0L, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { #line 3475 "pjsnmp.ctr" if (by == sl) { #line 3476 "pjsnmp.ctr" back = 1; #line 3477 "pjsnmp.ctr" } else { #line 3478 "pjsnmp.ctr" /* ERROR: Partial send */ log_1_no_header(123); } } else { #line 3482 "pjsnmp.ctr" /* ERROR: Failed to send data */ log_1_no_header(122); } sl = 0; pjsnmp_buf[0] = '\0'; res = dk4socket_shutdown(sock, DK4_SOCKET_SHUT_WRITE, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { #line 3489 "pjsnmp.ctr" cc = 1; do { if (0 != can_continue(0)) { #line 3492 "pjsnmp.ctr" by = sizeof(stat_text) - 1; res = dk4socket_recv(sock, stat_text, &by, 0, 0L, 0L, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { #line 3495 "pjsnmp.ctr" if (0 < by) { #line 3496 "pjsnmp.ctr" stat_text[by] = '\0'; res = dk4str8_cat_s(pjsnmp_buf,sizeof(pjsnmp_buf),stat_text,NULL); if (0 == res) { cutted = 1; #line 3500 "pjsnmp.ctr" back = 0; } } else { #line 3503 "pjsnmp.ctr" cc = 0; } } else { #line 3506 "pjsnmp.ctr" cc = -1; } } else { #line 3509 "pjsnmp.ctr" cc = -1; back = 0; } } while(1 == cc); } else { #line 3514 "pjsnmp.ctr" back = 0; /* ERROR: Socket shutdown failed */ log_1_no_header(124); } if (0 != expect_response) { #line 3519 "pjsnmp.ctr" if (0 == strlen(pjsnmp_buf)) { #line 3520 "pjsnmp.ctr" back = 0; } if (0 != cutted) { #line 3523 "pjsnmp.ctr" back = 0; } } } else { #line 3527 "pjsnmp.ctr" pjsnmp_buf[0] = '\0'; } dk4socket_close(sock, NULL); #line 3531 "pjsnmp.ctr" return back; } /** Accounting data exchange via local UNIX domain socket. @param expect_response Flag: Response from accounting system expected. @return 1 on success, 0 on error. */ static int accounting_ex_local_socket(int expect_response) { dk4_socket_t sock; /* Socket to use for accounting */ int back = 0; #line 3547 "pjsnmp.ctr" sock = dk4socket_c8_unix_client(acct_name, NULL); if (INVALID_SOCKET != sock) { back = accounting_ex_socket(sock, expect_response); /* Socket not closed here, closed in accounting_ex_socket() */ } else { /* ERROR: Failed to open UNIX domain socket */ log_1_no_header(125); pjsnmp_buf[0] = '\0'; } #line 3557 "pjsnmp.ctr" return back; } /** Accounting data exchange via network socket. @param expect_response Flag: Response from accounting system expected. @return 1 on success, 0 on error. */ static int accounting_ex_network(int expect_response) { dk4_socket_t sock; /* Socket to use for accounting */ int back = 0; #line 3573 "pjsnmp.ctr" sock = dk4socket_c8_tcp_client_host_port(acct_host,acct_port,0,0L,0L,NULL); if (INVALID_SOCKET != sock) { back = accounting_ex_socket(sock, expect_response); /* Socket not closed here, closed in accounting_ex_socket() */ } else { /* ERROR: Failed to open network connection */ log_1_no_header(125); pjsnmp_buf[0] = '\0'; } #line 3583 "pjsnmp.ctr" return back; } /** Accounting data exchange to file. @param fipo Accounting file. @param expect_response Flag: Response from accounting system expected. @return 1 on success, 0 on error. */ static int accounting_ex_file(FILE *fipo, int expect_response) { int back = 0; #line 3599 "pjsnmp.ctr" if (EOF != fputs(pjsnmp_buf, fipo)) { #line 3600 "pjsnmp.ctr" if (EOF != fflush(fipo)) { #line 3601 "pjsnmp.ctr" back = 1; } #if TRACE_DEBUG else { #line 3605 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 3610 "pjsnmp.ctr" } #endif pjsnmp_buf[0] = '\0'; if (0 != expect_response) { #line 3614 "pjsnmp.ctr" back = 0; } #line 3616 "pjsnmp.ctr" return back; } /** Accounting data exchange via pipe. @param expect_response Flag: Response from accounting system expected. @return 1 on success, 0 on error. */ static int accounting_ex_pipe(int expect_response) { FILE *fipo = NULL; /* Connection to pipe */ char *prgn = NULL; /* Program name */ int back = 0; int pcres = 0; /* Result from pclose */ #line 3634 "pjsnmp.ctr" prgn = dk4str8_start(&(acct_name[1]), NULL); if (NULL != prgn) { #line 3636 "pjsnmp.ctr" fipo = popen(prgn, "w"); if (NULL != fipo) { #line 3638 "pjsnmp.ctr" back = accounting_ex_file(fipo, 0); pcres = pclose(fipo); pjsnmp_buf[0] = '\0'; if (0 != expect_response) { switch (pcres) { case LPRNG_EXIT_REMOVE : { decision = 3; } break; case LPRNG_EXIT_HOLD : { decision = 2; } default : { decision = 1; } break; } log_3_no_header(166, 167, accounting_responses[decision - 1]); } } else { #line 3656 "pjsnmp.ctr" /* ERROR: Failed to start program for pipe */ log_1_no_header(126); pjsnmp_buf[0] = '\0'; } } else { #line 3661 "pjsnmp.ctr" /* ERROR: Not command name found */ log_1_with_header(2, 127); pjsnmp_buf[0] = '\0'; } #line 3665 "pjsnmp.ctr" return back; } /** Accounting data exchange via file specified by name. @param expect_response Flag: Response from accounting system expected. @param crf Flag: Create new file. @return 1 on success, 0 on error. */ static int accounting_ex_filename(int expect_response, int crf) { dk4_er_t er; /* Error report */ FILE *fipo = NULL; /* File to write to */ int back = 1; int tests = DK4_FOPEN_SC_USER; /* Security tests for fopen */ #line 3684 "pjsnmp.ctr" if (0 != dk4isadmin()) { #line 3685 "pjsnmp.ctr" tests = DK4_FOPEN_SC_PRIVILEGED; } dk4error_init(&er); fipo = dk4fopen_c8(acct_name, ((0 != crf) ? "w" : "a"), tests, &er); if (NULL != fipo) { #line 3690 "pjsnmp.ctr" back = accounting_ex_file(fipo, expect_response); if(EOF == fclose(fipo)) { #line 3692 "pjsnmp.ctr" back = 0; } } else { #line 3695 "pjsnmp.ctr" /* ERROR: Failed to open accounting file name */ log_1_no_header(128); pjsnmp_buf[0] = '\0'; } #line 3699 "pjsnmp.ctr" return back; } #if 0 /* 2016-02-10: Although chapter 15.5 of the LPRng reference manual states that the :af file is opened (file, pipe or network socket) and passed as file descriptor 3 to all filters, this did not work in my tests. Text written to fd 3 did not arrive at the accounting system. */ /** Accounting data exchange via file descriptor 3. @param expect_response Flag: Response from accounting system expected. @return 1 on success, 0 on error. */ static int accounting_ex_fd3(int expect_response) { size_t sl; /* String length */ ssize_t bwr; /* Number of bytes written or read */ int back = 0; #line 3724 "pjsnmp.ctr" sl = strlen(pjsnmp_buf); bwr = write(3, pjsnmp_buf, sl); pjsnmp_buf[0] = '\0'; if (0 < bwr) { #line 3728 "pjsnmp.ctr" if (sl == (size_t)bwr) { #line 3729 "pjsnmp.ctr" back = 1; } else { #line 3731 "pjsnmp.ctr" /* ERROR: Incomplete write operation */ log_1_no_header(122); } if (0 != expect_response) { #line 3735 "pjsnmp.ctr" bwr = read(3, pjsnmp_buf, sizeof(pjsnmp_buf)); if (0 < bwr) { #line 3737 "pjsnmp.ctr" pjsnmp_buf[bwr] = '\0'; } else { #line 3739 "pjsnmp.ctr" pjsnmp_buf[0] = '\0'; back = 0; } } } else { #line 3744 "pjsnmp.ctr" /* ERROR: Write failed */ log_1_no_header(122); } #line 3747 "pjsnmp.ctr" return back; } #endif /** Data exchange with accounting system. The contents of pjsnmp_buf is sent to the accounting system, the response - if any - is stored in pjsnmp_buf. @param expect_response Flag: Accounting system should send response. @return 1 on successfull exchange, 0 on connection error. */ static int accounting_exchange(int expect_response) { dk4_stat_t stb; /* File status buffer */ int issock = 0; /* Flag: File is socket */ int back = 0; /* Function result */ int crf = 0; /* Flag: Create log file */ #line 3771 "pjsnmp.ctr" if ((NULL != acct_host) && (0 < acct_port)) { #line 3772 "pjsnmp.ctr" log_1_no_header(154); back = accounting_ex_network(expect_response); log_1_no_header((0 != back) ? 159 : 160); } else { #line 3776 "pjsnmp.ctr" if (NULL != acct_name) { #line 3777 "pjsnmp.ctr" if ('|' == *acct_name) { #line 3778 "pjsnmp.ctr" #if 0 if (0 != expect_response) { /* ERROR: Can not receive response from pipe */ log_1_with_header(2, 129); } #endif log_1_no_header(155); back = accounting_ex_pipe(expect_response); log_1_no_header((0 != back) ? 159 : 160); } else { #line 3788 "pjsnmp.ctr" if (0 != dk4stat_c8(&stb, acct_name, NULL)) { if (0 != dk4stat_is_unix_domain_socket(&stb, NULL)) { issock = 1; #line 3791 "pjsnmp.ctr" } } else { crf = 1; #line 3794 "pjsnmp.ctr" } if (0 != issock) { log_1_no_header(156); back = accounting_ex_local_socket(expect_response); log_1_no_header((0 != back) ? 159 : 160); } else { if (0 != expect_response) { /* ERROR: Can not receive response from file */ log_1_with_header(2, 130); } log_1_no_header(157); back = accounting_ex_filename(expect_response, crf); log_1_no_header((0 != back) ? 159 : 160); } } } else { #line 3810 "pjsnmp.ctr" #if 0 log_1_no_header(158); back = accounting_ex_fd3(expect_response); log_1_no_header((0 != back) ? 159 : 160); #else log_1_with_header(2, 165); #endif } } #line 3819 "pjsnmp.ctr" return back; } /** Check users permission to print on queue. @return 1 if user is allowed to print, 0 otherwise. */ static int check_permission(void) { int back = 1; int res = 0; /* Result from check */ const size_t bsz = sizeof(pjsnmp_buf); /* Buffer size */ #line 3835 "pjsnmp.ctr" if ((0 != acct_enab) && (0 != acct_achk)) { #line 3836 "pjsnmp.ctr" /* LOG: Checking print permission */ log_5_no_header(131, 132, 133, user_name, queue_name); if(0 != dk4str8_cpy_s(pjsnmp_buf, bsz, pjsnmp_kw[6], NULL)) { if(0 != dk4str8_cat_s(pjsnmp_buf, bsz, pjsnmp_kw[1], NULL)) { if(0 != dk4str8_cat_s(pjsnmp_buf, bsz, queue_name, NULL)) { if(0 != dk4str8_cat_s(pjsnmp_buf, bsz, pjsnmp_kw[1], NULL)) { if(0 != dk4str8_cat_s(pjsnmp_buf, bsz, user_name, NULL)) { if(0 != dk4str8_cat_s(pjsnmp_buf, bsz, pjsnmp_kw[0], NULL)) { back = 0; #line 3845 "pjsnmp.ctr" if (0 != accounting_exchange(1)) { #line 3846 "pjsnmp.ctr" dk4str8_normalize(pjsnmp_buf, NULL); #line 3847 "pjsnmp.ctr" if (0 < strlen(pjsnmp_buf)) { #line 3848 "pjsnmp.ctr" if (0 != decision) { res = decision - 1; } else { res = dk4str8_array_index(accounting_responses, pjsnmp_buf, 0); if (-1 < res) { decision = res + 1; } } switch (res) { case 0: { back = 1; #line 3857 "pjsnmp.ctr" } break; case 1: { #line 3859 "pjsnmp.ctr" exval = LPRNG_EXIT_HOLD; } break; } log_3_no_header(166, 167, pjsnmp_buf); } else { #line 3864 "pjsnmp.ctr" #if 0 /* 2016-02-15 An empty response indicates permission to print. */ if (0 != acct_apcf) { back = 1; } #endif back = 1; } } else { #line 3873 "pjsnmp.ctr" if (0 != acct_apcf) { back = 1; } else { decision = 3; } } } } } } } } /* LOG: Test result */ log_1_no_header((0 != back) ? 134 : 135); } #line 3885 "pjsnmp.ctr" return back; } /** Retrieve integer value from variable list. @param iptr Address of variable to set. @param var SNMP variable containing the value. @return 1 on success, 0 on error. */ static int get_int(int *iptr, struct variable_list *var) { char bu[64]; /* Buffer for numeric values as text */ const char *endptr = NULL; /* First unprocessable character */ long l; /* long value */ int i; /* int value */ int back = 0; #line 3905 "pjsnmp.ctr" switch (var->type) { case ASN_OCTET_STR : { #line 3907 "pjsnmp.ctr" if ((var->val_len > 0) && (var->val_len < sizeof(bu))) { dk4mem_cpy(bu, (void *)((var->val).string), var->val_len, NULL); bu[var->val_len] = '\0'; if (0 != dk4ma_input_c8_dec_int(&i, bu, &endptr, 1, NULL)) { *iptr = i; back = 1; } } } break; case ASN_TIMETICKS : case ASN_GAUGE : case ASN_COUNTER : case ASN_INTEGER : { #line 3920 "pjsnmp.ctr" l = *((var->val).integer); *iptr = (int)l; back = 1; } break; } #line 3926 "pjsnmp.ctr" return back; } /** Retrieve unsigned long value from variable list. @param ulptr Address of variable to set. @param var SNMP variable containing the value. @return 1 on success, 0 on error. */ static int get_ul(unsigned long *ulptr, struct variable_list *var) { unsigned long ul = 0UL; /* Result variable */ long l; /* long value */ int back = 0; #line 3944 "pjsnmp.ctr" switch (var->type) { case ASN_OCTET_STR : { #line 3946 "pjsnmp.ctr" if (0 < var->val_len) { ul |= ((((unsigned long)(((var->val).string)[0])) << 24) & 0xFF000000UL); back = 1; } if (1 < var->val_len) { ul |= ((((unsigned long)(((var->val).string)[1])) << 16) & 0x00FF0000UL); } if (2 < var->val_len) { ul |= ((((unsigned long)(((var->val).string)[2])) << 8) & 0x0000FF00UL); } if (3 < var->val_len) { ul |= ((((unsigned long)(((var->val).string)[3])) ) & 0x000000FFUL); } if (0 != back) { *ulptr = ul; } } break; case ASN_TIMETICKS : case ASN_GAUGE : case ASN_COUNTER : case ASN_INTEGER : { #line 3971 "pjsnmp.ctr" l = *((var->val).integer); if (0L <= l) { *ulptr = (unsigned long)l; back = 1; } } break; } #line 3979 "pjsnmp.ctr" return back; } /** Check whether a buffer contains non-ASCII characters. @param ptr Buffer address. @param i Buffer size. @return 1 if non-ASCII found, 0 otherwise. */ static int contains_non_ascii(const char *ptr, size_t i) { int back = 0; #line 3995 "pjsnmp.ctr" while ((0 == back) && (0 < i)) { if (0x7F < (unsigned char)(*(ptr++))) { back = 1; } i--; } #line 4001 "pjsnmp.ctr" return back; } /** Replace all non-ascii characters by question marks. */ static void no_non_ascii(char *str) { unsigned char uc; while ('\0' != *str) { uc = (unsigned char)(*str); if ((0x20 > uc) || (0x7E < uc)) { *str = '?'; } str++; } } /** Check two OIDs for equality. @param pl Left OID. @param szl Left OID size. @param pr Right OID. @param szr Right OID size. @return 1 for equal OIDs, 0 otherwise. */ static int oids_equal(const oid *pl, size_t szl, const oid *pr, size_t szr) { #if VERSION_BEFORE_20160206 size_t i; /* Index of current sub-id to compare */ #endif int back = 0; if ((szl == szr) && (0 < szl)) { #if VERSION_BEFORE_20160206 back = 1; for (i = 0; ((i < szl) && (1 == back)); i++) { if (pl[i] != pr[i]) { back = 0; } } #else /* No check for overflow necessary, max 4 * 128. */ if (0 == dk4mem_cmp(pl, pr, (szl * sizeof(oid)), NULL)) { back = 1; } #endif } return back; } /** Find OID index. @param oid Pointer to OID to check. @param sz OID size. @return 0 for hrDeviceStatus, 1 for hrPrinterStatus, 2 for page counter, 3 for hrPrinterDetectedErrorState, 4 for status text, -1 otherwise. */ static int oid_index(oid *p, size_t sz) { int back = -1; #line 4073 "pjsnmp.ctr" if (0 != oids_equal(p, sz, oid_ds, sz_oid_ds)) { back = 0; } else { if (0 != oids_equal(p, sz, oid_ps, sz_oid_ps)) { back = 1; } else { if (0 != oids_equal(p, sz, oid_pc, sz_oid_pc)) { back = 2; } else { if (0 != oids_equal(p, sz, oid_pe, sz_oid_pe)) { back = 3; } else { if (0 < sz_oid_st) { #line 4086 "pjsnmp.ctr" if (0 != oids_equal(p, sz, oid_st, sz_oid_st)) { back = 4; } } #if TRACE_DEBUG else { #line 4092 "pjsnmp.ctr" } #endif } } } } #line 4098 "pjsnmp.ctr" return back; } /** Show one active condition from hrPrinterDetectedErrorState. @param cond Condition bit (checked against the found conditions). @param cind Index of corresponding text in pjsnmp_kw. */ static void show_pdes(unsigned long cond, size_t cind) { if (0UL != (pdes_cond & cond)) { fputs(pjsnmp_kw[((0UL != (pdes_error & cond)) ? 32 : 33)], out_file); fputs(pjsnmp_kw[cind], out_file); } } static void show_text_containing_non_ascii(const unsigned char *ptr, size_t num) { while(0 < num--) { if (0x7F < *ptr) { fputc('?', out_file); } else { fputc(*ptr, out_file); } ptr++; } } /** Report status if changed. @param found Bitmask for found information. */ static void report_status_if_changed(int found) { unsigned long tcond = 0x80000000UL; /* Bit for one condition */ int must_report = 0; /* Flag: Must report change */ int i; #line 4146 "pjsnmp.ctr" /* Check whether or not to report. */ if (stsum != ostsum) { #line 4149 "pjsnmp.ctr" must_report = 1; } else { if (devst != odevst) { #line 4152 "pjsnmp.ctr" must_report = 1; } else { if (prist != oprist) { #line 4155 "pjsnmp.ctr" must_report = 1; } else { if (pdes_cond != opdes_cond) { #line 4158 "pjsnmp.ctr" must_report = 1; } else { if (0 < sz_stat_text) { if (0 != force_printable_status_text) { if (sz_ostat_text != sz_stat_text) { must_report = 1; } else { if (0 != dk4mem_cmp(stat_text,ostat_text,sz_stat_text,NULL)) { must_report = 1; } } } else { if (0 == contains_non_ascii(stat_text, sz_stat_text)) { if (sz_stat_text != sz_ostat_text) { must_report = 1; #line 4173 "pjsnmp.ctr" } else { if (0 != dk4mem_cmp(stat_text,ostat_text,sz_stat_text,NULL)) { must_report = 1; #line 4176 "pjsnmp.ctr" } } } } } } } } } /* Report if necessary. */ if (0 != must_report) { #line 4189 "pjsnmp.ctr" fputs(pjsnmp_kw[150], out_file); (void)log_timestamp(); if ((-1 < devst) && (6 > devst)) { if ((-1 < prist) && (6 > prist)) { fputs(pjsnmp_kw[7], out_file); fputs(pjsnmp_kw[11 + devst], out_file); fputs(pjsnmp_kw[8], out_file); fputs(pjsnmp_kw[17 + prist], out_file); fputs(pjsnmp_kw[0], out_file); } } fputs(pjsnmp_kw[9], out_file); for (i = 0; i < 16; i++) { if ((0 < i) && (0 == (i % 4))) { fputc('-', out_file); } fputc(((0UL != (pdes_cond & tcond)) ? '1' : '0'), out_file); tcond = tcond / 2UL; } fputs(pjsnmp_kw[0], out_file); show_pdes(PDES_ERROR_DOOR_OPEN, 38); show_pdes(PDES_ERROR_OFFLINE, 40); show_pdes(PDES_ERROR_MARKER_SUPPLY_MISSING, 44); show_pdes(PDES_ERROR_NO_TONER, 37); show_pdes(PDES_WARNING_TONER_LOW, 36); show_pdes(PDES_ERROR_INPUT_TRAY_MISSING, 42); show_pdes(PDES_WARNING_INPUT_TRAY_EMPTY, 47); show_pdes(PDES_ERROR_NO_PAPER, 35); show_pdes(PDES_WARNING_PAPER_LOW, 34); show_pdes(PDES_ERROR_OUTPUT_TRAY_MISSING, 43); show_pdes(PDES_ERROR_PAPER_JAM, 39); show_pdes(PDES_ERROR_OUTPUT_FULL, 46); show_pdes(PDES_WARNING_OUTPUT_NEAR_FULL, 45); show_pdes(PDES_WARNING_SERVICE, 41); show_pdes(PDES_WARNING_OVERDUE_PREVENT_MAINT, 48); if (0 < sz_stat_text) { if (0 != force_printable_status_text) { fputs(pjsnmp_kw[30], out_file); show_text_containing_non_ascii((unsigned char *)stat_text,sz_stat_text); fputs(pjsnmp_kw[31], out_file); } else { if (0 == contains_non_ascii(stat_text, sz_stat_text)) { fputs(pjsnmp_kw[30], out_file); fwrite(stat_text, 1, sz_stat_text, out_file); fputs(pjsnmp_kw[31], out_file); } } } if ((-1 < stsum) && (7 > stsum)) { fputs(pjsnmp_kw[10], out_file); fputs(pjsnmp_kw[23 + stsum], out_file); fputs(pjsnmp_kw[0], out_file); } if (PJSNMP_ST_ERROR == stsum) { fputs(pjsnmp_kw[49], out_file); } else { if (0UL != (pdes_cond & PDES_WARNING_SERVICE)) { if (0UL == (pdes_error & PDES_WARNING_SERVICE)) { fputs(pjsnmp_kw[50], out_file); } } } fflush(out_file); } #line 4252 "pjsnmp.ctr" } /** One SNMP data exchange. @param passno 0 before start, 1 during transfer, 2 at end. @return 1 on success, 0 on error (stop printing). */ static int one_snmp_request(int passno) { status_text_t tx; /* Used in comparison */ status_text_t *ptx = NULL; /* Text node found */ struct snmp_pdu *rq = NULL; /* Request */ struct snmp_pdu *rs = NULL; /* Response */ struct variable_list *vars = NULL; /* Response variables */ int status = 0; /* SNMP result */ int found = 0; /* Information from response */ int back = 0; #line 4273 "pjsnmp.ctr" if (0 != can_continue(0)) { #line 4274 "pjsnmp.ctr" if (NULL != snmp_sess) { #line 4275 "pjsnmp.ctr" pdes_cond = 0UL; pcnt = 0UL; devst = 0; prist = 0; stsum = PJSNMP_ST_UNREACHABLE; stat_text[0] = '\0'; sz_stat_text = 0; rq = snmp_pdu_create(SNMP_MSG_GET); if (NULL != rq) { #line 4284 "pjsnmp.ctr" back = 1; snmp_add_null_var(rq, oid_ds, sz_oid_ds); snmp_add_null_var(rq, oid_ps, sz_oid_ps); snmp_add_null_var(rq, oid_pc, sz_oid_pc); snmp_add_null_var(rq, oid_pe, sz_oid_pe); if (0 < sz_oid_st) { #line 4290 "pjsnmp.ctr" snmp_add_null_var(rq, oid_st, sz_oid_st); } status = snmp_synch_response(snmp_sess, rq, &rs); if (STAT_SUCCESS == status) { #line 4294 "pjsnmp.ctr" if (NULL != rs) { #line 4295 "pjsnmp.ctr" if (SNMP_ERR_NOERROR == rs->errstat) { #line 4296 "pjsnmp.ctr" /* Obtain response elements. */ stsum = PJSNMP_ST_UNKNOWN; vars = rs->variables; while (NULL != vars) { switch (oid_index(vars->name, vars->name_length)) { case 0: { #line 4304 "pjsnmp.ctr" if (0 != get_int(&devst, vars)) { #line 4305 "pjsnmp.ctr" found |= 1; } } break; case 1: { #line 4309 "pjsnmp.ctr" if (0 != get_int(&prist, vars)) { #line 4310 "pjsnmp.ctr" found |= 2; } } break; case 2: { #line 4314 "pjsnmp.ctr" if (0 != get_ul(&pcnt, vars)) { #line 4315 "pjsnmp.ctr" found |= 4; #line 4316 "pjsnmp.ctr" switch (passno) { case 0: { pc_start = pcnt; have_pcs = 1; } break; case 1: { /* When aborting due to timeout in error or unreachable state we use the last page counter seen. */ pc_end = pcnt; have_pce = 1; } break; case 2: { pc_end = pcnt; have_pce = 1; } break; } } } break; case 3: { #line 4337 "pjsnmp.ctr" if (0 != get_ul(&pdes_cond, vars)) { found |= 8; } } break; case 4: { #line 4340 "pjsnmp.ctr" if (0 < vars->val_len) { if (sizeof(stat_text) > vars->val_len) { #line 4342 "pjsnmp.ctr" dk4mem_cpy( stat_text, (vars->val).string, vars->val_len, NULL ); sz_stat_text = vars->val_len; } else { #line 4348 "pjsnmp.ctr" dk4mem_cpy( stat_text, (vars->val).string, sizeof(stat_text), NULL ); sz_stat_text = sizeof(stat_text); } found |= 16; } } break; } vars = vars->next_variable; } /* Build summary (1): device and printer status. */ if (3 == (3 & found)) { stsum = get_state_mapping(devst, prist); #line 4366 "pjsnmp.ctr" } /* Build summary (2): printer detected error state */ if (8 == (8 & found)) { if ((0 != pdes_always) || (PJSNMP_ST_UNKNOWN == stsum)) { if (0L != (pdes_error & pdes_cond)) { stsum = PJSNMP_ST_ERROR; #line 4374 "pjsnmp.ctr" } } } /* Build summary (3): status text line */ if (16 == (16 & found)) { if ((0 != stat_always) || (PJSNMP_ST_UNKNOWN == stsum)) { if ((NULL != s_stn) && (NULL != i_stn)) { DK4_MEMRES(&tx, sizeof(tx)); tx.text = (unsigned char *)stat_text; tx.size = sz_stat_text; tx.state = 0; tx.start = 0; ptx = (status_text_t *)dk4sto_it_find_like(i_stn, &tx, 1); if (NULL != ptx) { stsum = ptx->state; #line 4392 "pjsnmp.ctr" } } } } /* Build summary (4): Map unknown to busy if configured */ if ((0 != unkn_busy) && (PJSNMP_ST_UNKNOWN == stsum)) { stsum = PJSNMP_ST_BUSY; #line 4401 "pjsnmp.ctr" } /* For error state mark this page counter as print job not yet finished. */ switch (stsum) { case PJSNMP_ST_ERROR: { seen_printing = 0; #line 4409 "pjsnmp.ctr" if ((0 < passno) && (0UL < pcnt)) { pc_error = pcnt; #line 4411 "pjsnmp.ctr" } start_unreach = (dk4_time_t)0UL; if ((dk4_time_t)0UL == start_error) { dk4time_get(&start_error); } } break; case PJSNMP_ST_BUSY: { seen_printing = 1; #line 4419 "pjsnmp.ctr" start_unreach = (dk4_time_t)0UL; start_error = (dk4_time_t)0UL; } break; case PJSNMP_ST_UNREACHABLE : { if ((dk4_time_t)0UL == start_unreach) { dk4time_get(&start_unreach); } start_error = (dk4_time_t)0UL; } break; default : { start_unreach = (dk4_time_t)0UL; start_error = (dk4_time_t)0UL; } break; } /* On change, print new state. */ report_status_if_changed(found); /* Save data for next comparison. */ odevst = devst; oprist = prist; ostsum = stsum; opdes_cond = pdes_cond; if (0 < sz_stat_text) { DK4_MEMCPY(ostat_text, stat_text, sz_stat_text); } sz_ostat_text = sz_stat_text; } #if TRACE_DEBUG else { #line 4451 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 4456 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 4461 "pjsnmp.ctr" } #endif if (NULL != rs) { snmp_free_pdu(rs); } } #if TRACE_DEBUG else { #line 4469 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 4474 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 4479 "pjsnmp.ctr" } #endif #line 4482 "pjsnmp.ctr" return back; } /** Create accounting text line and do data exchange with accounting system. @param kwind Index of start keyword in pjsnmp_kw array. @param pc Page counter value to transmit. */ static void accounting_index_and_value(size_t kwind, unsigned long pc) { char buf[64]; /* Buffer for number as text */ const char *jt; /* Job title */ size_t szbuf = sizeof(pjsnmp_buf); /* Buffer size */ size_t sl; int res; /* Conversion result */ #line 4502 "pjsnmp.ctr" res = dk4ma_write_c8_decimal_unsigned( buf, sizeof(buf), (dk4_um_t)pc, 0, NULL ); if (0 != res) { if (0 != dk4str8_cpy_s(pjsnmp_buf, szbuf, pjsnmp_kw[kwind], NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, pjsnmp_kw[1], NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, queue_name, NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, pjsnmp_kw[1], NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, user_name, NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, pjsnmp_kw[1], NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, buf, NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, pjsnmp_kw[1], NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, job_name, NULL)) { if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, pjsnmp_kw[1], NULL)) { jt = job_title; if (NULL == jt) { jt = pjsnmp_kw[54]; } sl = strlen(pjsnmp_buf); if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, jt, NULL)) { if (0 == allow_non_ascii) { no_non_ascii(&(pjsnmp_buf[sl])); } if (0 != dk4str8_cat_s(pjsnmp_buf, szbuf, pjsnmp_kw[0], NULL)) { #line 4523 "pjsnmp.ctr" (void)accounting_exchange(0); } } } } } } } } } } } } } #line 4537 "pjsnmp.ctr" } /** Report used pages to accounting system. */ static void report_used_pages(void) { #line 4547 "pjsnmp.ctr" if (0 != acct_start_end) { accounting_index_and_value(51, pc_start); accounting_index_and_value(52, pc_end); } else { accounting_index_and_value(53, (pc_end - pc_start)); } #line 4554 "pjsnmp.ctr" } /** Do accounting before and after print job. @param passno 0=before print job, 1=after print job. @return 1 on success, 0 on error. */ static int do_accounting(int passno) { static char buf[8*sizeof(dk4_um_t)]; /* Number as text */ struct timeval to; /* Timeout for select */ dk4_time_t start_idle = (dk4_time_t)0UL; /* Start idle/standby */ dk4_time_t current_time = (dk4_time_t)0UL; /* Current time */ dk4_time_t timeout_time = (dk4_time_t)0UL; /* Timeout reached */ int res = 0; /* Conversion result */ int back = 0; int cc = 1; /* Flag: Can continue */ int uncoi = 0; /* Flag: Unconditional idle reported */ int cto = 0; /* Flag: Must check timeout */ #line 4578 "pjsnmp.ctr" if (NULL != snmp_sess) { #line 4579 "pjsnmp.ctr" /* In the loop retrieve printer status via SNMP, finish if printer is idle or in standby state. */ log_1_no_header(145+passno); do { if (0 != can_continue(0)) { #line 4585 "pjsnmp.ctr" if (0 != one_snmp_request((0 == passno) ? 0 : 2)) { #line 4587 "pjsnmp.ctr" /* In idle or standby we can retrieve the page counter if the page counter was changed or the printer was seen printing. */ switch (stsum) { case PJSNMP_ST_IDLE : case PJSNMP_ST_STANDBY : { back = 1; cc = 0; #line 4595 "pjsnmp.ctr" cto = 0; if (1 == passno) { if ((0 == seen_printing) && (0 < print_timeout)) { cto = 1; #line 4599 "pjsnmp.ctr" } else { if ((0UL != pc_error) && (1 == have_pce)) { if ((pc_end == pc_error)&&((dk4_um_t)0UL < print_timeout)) { cto = 1; #line 4603 "pjsnmp.ctr" } } } if (0 != cto) { dk4time_get(¤t_time); if ((dk4_time_t)0UL < start_idle) { if ((start_idle+(dk4_time_t)print_timeout) > current_time) { back = 0; cc = 1; #line 4611 "pjsnmp.ctr" } } else { start_idle = current_time; back = 0; cc = 1; if (0 == uncoi) { uncoi = 1; res = dk4ma_write_c8_decimal_unsigned( buf, sizeof(buf), print_timeout, 0, NULL ); log_timestamp(); fputs(pjsnmp_kw[162], out_file); if (0 != res) { fputs(buf, out_file); fputs(pjsnmp_kw[163], out_file); } fputs(pjsnmp_kw[164], out_file); fflush(out_file); } } } } } break; case PJSNMP_ST_UNREACHABLE : { start_idle = (dk4_time_t)0UL; /* not idle */ uncoi = 0; /* If printer is unreachable we abort after timeout. */ if (((0 == passno) && ((dk4_um_t)0UL != unto_start)) || ((1 == passno) && ((dk4_um_t)0UL != unto_end)) ) { if ((dk4_time_t)0UL < start_unreach) { dk4time_get(¤t_time); timeout_time = start_unreach + (dk4_time_t)((0 == passno) ? unto_start : unto_end); if (current_time > timeout_time) { #line 4648 "pjsnmp.ctr" cc = 0; /* ERROR: Timeout while printer unreachable */ log_1_no_header(136); } } else { dk4time_get(&start_unreach); } } } break; case PJSNMP_ST_ERROR : { start_idle = (dk4_time_t)0UL; /* not idle */ uncoi = 0; if ( ((0 == passno) && ((dk4_um_t)0UL < erto_start)) || ((1 == passno) && ((dk4_um_t)0UL < erto_end)) ) { if ((dk4_um_t)0UL < start_error) { dk4time_get(¤t_time); timeout_time = start_error + (dk4_time_t)((0 == passno) ? erto_start : erto_end); if (current_time > timeout_time) { cc = 0; /* ERROR: Timeout while printer in error state */ log_1_no_header(168); if (0 == passno) { back = 0; /* Do not print */ } } } else { dk4time_get(&start_error); } } } break; default: { start_idle = (dk4_time_t)0UL; /* not idle */ uncoi = 0; } break; } /* Decrease cpu and network load from polling */ if (1 == cc) { if (0 != can_continue(0)) { if (PJSNMP_ST_UNREACHABLE == stsum) { sleep(1); } else { to.tv_sec = 0L; to.tv_usec = 250000L; (void)select(0, NULL, NULL, NULL, &to); } } else { cc = -1; } } } else { #line 4706 "pjsnmp.ctr" cc = -1; } } else { #line 4709 "pjsnmp.ctr" cc = -1; } } while(1 == cc); fputs(pjsnmp_kw[150], out_file); if (((0 == passno)&&(0 != have_pcs))||((1 == passno)&&(0 != have_pce))) { #line 4715 "pjsnmp.ctr" res = dk4ma_write_c8_decimal_unsigned(buf, sizeof(buf), pcnt, 0, NULL); if (0 != res) { #line 4718 "pjsnmp.ctr" log_3_no_header((147+passno), 0, buf); #line 4720 "pjsnmp.ctr" } #line 4722 "pjsnmp.ctr" } else { #line 4724 "pjsnmp.ctr" log_1_no_header(149); #line 4726 "pjsnmp.ctr" } /* Save page counter at start to page counter unusable for print job finished. */ if (0 == passno) { if (0 != have_pcs) { pc_error = pc_start; } } /* After successful page counting at job end, report to accounting system. */ if (1 == passno) { #line 4740 "pjsnmp.ctr" if ((0 != have_pcs) && (0 != have_pce)) { #line 4741 "pjsnmp.ctr" if (pc_end > pc_start) { #line 4742 "pjsnmp.ctr" /* Report number of used pages to accounting system */ report_used_pages(); } } } } else { #line 4748 "pjsnmp.ctr" if (0 != snmp_igfs) { #line 4749 "pjsnmp.ctr" back = 1; } } #line 4752 "pjsnmp.ctr" return back; } /** Transfer data to printer. @return 1 on success, 0 on error. */ static int data_transfer(void) { fd_set wfds; /* Writable files set */ fd_set rfds; /* Readable files set */ struct timeval to; /* Timeout for select */ char *wrptr; /* Pointer to data to write */ dk4_time_t unwriteable; /* Socket started to be unwriteable */ dk4_time_t current; /* Current time */ dk4_time_t tots; /* Timestamp when timeout is reached */ size_t rdb; /* Number of bytes read from stdin */ size_t remaining; /* Remaining bytes to write to socket */ size_t wrb; /* Bytes currently written to socket */ dk4_socket_t sock; /* Network socket to printer */ int back = 0; int cc = 1; /* Flag: Can continue */ int ccwr; /* Flag: Can continue writing */ int res; /* Number conversion result */ int writable; /* Flag: Socket is writeable */ #line 4781 "pjsnmp.ctr" unwriteable = (dk4_time_t)0UL; if ((NULL != host_name) && (0 < host_port)) { sock = dk4socket_c8_tcp_client_host_port( host_name, host_port, local_port, 0L, 0L, NULL ); if (INVALID_SOCKET != sock) { exval = LPRNG_EXIT_SUCCESS; dk4time_get(&t2); back = 1; log_1_no_header(151); do { if (0 != can_continue(0)) { rdb = fread(pjsnmp_buf, 1, sizeof(pjsnmp_buf), stdin); if (0 < rdb) { wrptr = pjsnmp_buf; remaining = rdb; ccwr = 1; do { if (0 != can_continue(0)) { writable = 0; FD_ZERO(&wfds); FD_SET(sock,&wfds); if (0 != read_responses) { FD_ZERO(&rfds); FD_SET(sock,&rfds); } to.tv_sec = 0L; to.tv_usec = 250000L; if (0 != read_responses) { res = select((sock + 1), &rfds, &wfds, NULL, &to); } else { res = select((sock + 1), NULL, &wfds, NULL, &to); } if (0 < res) { if (FD_ISSET(sock,&wfds)) { writable = 1; unwriteable = (dk4_time_t)0UL; } else { if (0 != unwt_print) { dk4time_get(¤t); if ((dk4_time_t)0UL != unwriteable) { tots = unwriteable + (dk4_time_t)unwt_print; if (current > tots) { cc = ccwr = -1; /* ERROR: Timeout, socket unwriteable */ log_1_no_header(137); } } else { unwriteable = current; } } } if (0 != read_responses) { if (FD_ISSET(sock,&rfds)) { wrb = sizeof(dummy_text); res = dk4socket_recv(sock,dummy_text,&wrb,0,0L,0L,NULL); } } } if (0 != can_continue(0)) { if ((0 == writable) || (0 != check_trans)) { if (0 != one_snmp_request(1)) { switch (stsum) { case PJSNMP_ST_UNREACHABLE : { if ((dk4_um_t)0UL < unto_print) { if ((dk4_time_t)0UL < start_unreach) { tots = start_unreach + (dk4_time_t)unto_print; dk4time_get(¤t); if (current > tots) { cc = ccwr = -1; /* ERROR: Timeout, printer start_unreach */ log_1_no_header(136); } } else { dk4time_get(&start_unreach); } } } break; case PJSNMP_ST_ERROR : { if ((dk4_um_t)0UL < erto_print) { if ((dk4_time_t)0UL < start_error) { tots = start_error + (dk4_time_t)erto_print; dk4time_get(¤t); if (current > tots) { cc = ccwr = -1; /* ERROR: Timeout, printer start_unreach */ log_1_no_header(168); } } else { dk4time_get(&start_error); } } } break; } } } if (0 != can_continue(0)) { wrb = remaining; res = dk4socket_send(sock, wrptr, &wrb, 0, 0L, 0L, NULL); switch (res) { case DK4_SOCKET_RESULT_SUCCESS: case DK4_SOCKET_RESULT_IN_PROGRESS : { if (0 < wrb) { bytes_trans = dk4ma_um_add(bytes_trans,wrb,&er_bytes); if (wrb < remaining) { remaining = remaining - wrb; wrptr = &(wrptr[wrb]); } else { remaining = 0; ccwr = 0; } } } break; default: { /* ERROR: Failed to send data */ log_1_no_header(138); ccwr = -1; cc = -1; back = 0; } break; } } else { ccwr = -1; cc = -1; back = 0; } } else { ccwr = -1; cc = -1; back = 0; } } else { ccwr = -1; cc = -1; back = 0; } } while (1 == ccwr); } else { have_eof = 1; cc = 0; if (0 != ferror(stdin)) { /* ERROR: Failed to read from standard input */ log_1_no_header(139); } } } else { cc = -1; back = 0; } } while (1 == cc); log_1_no_header((0 == cc) ? 152 : 153); if (0 == cc) { if (0 != host_ordr) { res = dk4socket_shutdown(sock, DK4_SOCKET_SHUT_WRITE, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { cc = 1; do { if (0 != can_continue(0)) { wrb = sizeof(pjsnmp_buf); res = dk4socket_recv(sock, pjsnmp_buf, &wrb, 0, 0L, 0L, NULL); switch (res) { case DK4_SOCKET_RESULT_SUCCESS: { if (0 == wrb) { cc = 0; } } break; default: { cc = -1; } break; } } else { cc = -1; back = 0; } } while (1 == cc); } } } dk4socket_close(sock, NULL); dk4time_get(&t3); } else { #line 4955 "pjsnmp.ctr" /* ERROR: Failed to connect */ log_1_no_header(140); } } else { #line 4959 "pjsnmp.ctr" } #line 4961 "pjsnmp.ctr" return back; } /** Write one line of final statistics. @param b Text containing a number. @param max Maximum number width. @param i1 Index in pjsnmp_kw of text before number. @param i2 Index in pjsnmp_kw of text after number. */ static void final_stat_line(const char *b, size_t max, size_t i1, size_t i2) { size_t sl; /* String length of number */ sl = strlen(b); fputs(pjsnmp_kw[i1], out_file); while (sl++ < max) { fputc(' ', out_file); } fputs(b, out_file); fputs(pjsnmp_kw[i2], out_file); } /** Issue final statistics. */ static void final_statistics(void) { char b1[64]; /* Number of bytes */ char b2[64]; /* Transfer time */ char b3[64]; /* Processing time */ char b4[64]; /* Number of pages */ size_t max; /* Maximum of all sizes */ size_t sl; /* Current size */ int res; /* Conversion result */ int found = 0; /* Information found */ /* Initialize buffers. */ b1[0] = '\0'; b2[0] = '\0'; b3[0] = '\0'; b4[0] = '\0'; /* Convert numbers to strings. */ if (DK4_E_NONE == er_bytes.ec) { res = dk4ma_write_c8_decimal_unsigned( b1, sizeof(b1), (dk4_um_t)bytes_trans, 0, NULL ); if (0 == res) { b1[0] = '\0'; } else { found |= 1; } } if (((dk4_time_t)0UL != t2) && ((dk4_time_t)0UL != t3)) { res = dk4ma_write_c8_decimal_unsigned( b2, sizeof(b2), (dk4_um_t)(t3 - t2), 0, NULL ); if (0 == res) { b2[0] = '\0'; } else { found |= 2; } } res = dk4ma_write_c8_decimal_unsigned( b3, sizeof(b3), (dk4_um_t)(t4 - t1), 0, NULL ); if (0 == res) { b3[0] = '\0'; } else { found |= 4; } if ((0 != have_pcs) && (0 != have_pce)) { res = dk4ma_write_c8_decimal_unsigned( b4, sizeof(b4), (dk4_um_t)(pc_end - pc_start), 0, NULL ); if (0 == res) { b4[0] = '\0'; } else { found |= 8; } } /* Find maximum string length. */ max = 0; if (0 != (1 & found)) { max = sl = strlen(b1); } if (0 != (2 & found)) { sl = strlen(b2); if (sl > max) max = sl; } if (0 != (4 & found)) { sl = strlen(b3); if (sl > max) max = sl; } if (0 != (8 & found)) { sl = strlen(b4); if (sl > max) max = sl; } /* Write texts. */ fputs(pjsnmp_kw[55], out_file); (void)log_timestamp(); if (0 != (1 & found)) { final_stat_line(b1, max, 56, 60); } if (0 != (2 & found)) { final_stat_line(b2, max, 57, 61); } if (0 != (4 & found)) { final_stat_line(b3, max, 58, 61); } if (0 != (8 & found)) { final_stat_line(b4, max, 59, 0); } if (0 != found) { fflush(out_file); } } /** Initialization at startup. */ static void initialize_at_startup(void) { stat_text[0] = '\0'; sz_stat_text = 0; ostat_text[0] = '\0'; sz_ostat_text = 0; dk4error_init(&er_bytes); } static void report_at_job_start(int argc, char *argv[]) { int found = 0; char *ptr; if (0 != verbose) { int i; fputs(pjsnmp_kw[169], out_file); for (i = 1; i < argc; i++) { fputs(argv[i], out_file); fputc('\n', out_file); } fflush(out_file); } else { if (NULL != user_name) { fputs(user_name, out_file); found = 1; } if (NULL != queue_name) { if (0 != found) { fputc(' ', out_file); } fputs(queue_name, out_file); found = 1; } if (NULL != job_name) { if (0 != found) { fputc(' ', out_file); } fputs(job_name, out_file); found = 1; } if (0 != found) { fputc('\n', out_file); } if (NULL != job_title) { ptr = job_title; while ('\0' != *ptr) { if (0x80 > ((unsigned char)(*ptr))) { fputc(*ptr, out_file); } else { fputc('?', out_file); } ptr++; } fputc('\n', out_file); found = 1; } if (0 != found) { fflush(out_file); } } } #endif /* if DK4_HAVE_LIBNETSNMP && ((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, one from LPRNG_EXIT_xxx. */ int main(int argc, char *argv[]) { #if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) /* +++++ All libraries available */ #if DK4_HAVE_SIGACTION #ifdef SIGPIPE struct sigaction opipe; /* Old disposition for SIGPIPE */ struct sigaction npipe; /* New disposition for SIGPIPE */ #endif struct sigaction oint; /* Old disposition for SIGINT */ struct sigaction nint; /* New disposition for SIGINT */ struct sigaction oterm; /* Old disposition for SIGTERM */ struct sigaction nterm; /* New disposition for SIGTERM */ #else #ifdef SIGPIPE dk4_sig_handler_t *opipe = NULL; /* Old disposition for SIGPIPE */ #endif dk4_sig_handler_t *oterm = NULL; /* Old disposition for SIGTERM */ dk4_sig_handler_t *oint = NULL; /* Old disposition for SIGINT */ #endif #if DK4_HAVE_SIGACTION #ifdef SIGPIPE int set_pipe = 0; /* Flag: Disposition SIGPIPE changed */ #endif int set_int = 0; /* Flag: Disposition SIGINT changed */ int set_term = 0; /* Flag: Disposition SIGTERM changed */ int sig_i_f = 0; /* Flag: Handler installation failed */ int sig_r_f = 0; /* Flag: Handler restoration failed */ #endif int sockinit = 0; /* Flag: Socket subsys initialized */ #line 5188 "pjsnmp.ctr" #line 5189 "pjsnmp.ctr" /* Initialize output file. */ out_file = stderr; dk4time_get(&t1); /* Copy default OID for status text. */ DK4_MEMCPY(oid_st, oid_dst, by_oid_dst); sz_oid_st = sz_oid_dst; by_oid_st = sz_oid_st * sizeof(oid); /* Process command line arguments, open log file. */ if (0 == process_command_line_arguments(argc, argv)) { goto finished; } /* Set up 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)) { sig_i_f = 1; goto finished; } if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { sig_i_f = 1; goto finished; } if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { sig_i_f = 1; goto finished; } set_pipe = 1; #endif DK4_MEMRES(&nterm, sizeof(nterm)); nterm.sa_handler = sig_handler_term; nterm.sa_flags = 0; if (0 != sigemptyset(&nterm.sa_mask)) { sig_i_f = 1; goto finished; } if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { sig_i_f = 1; goto finished; } if (0 != sigaction(SIGTERM, &nterm, &oterm)) { sig_i_f = 1; goto finished; } set_term = 1; DK4_MEMRES(&nint, sizeof(nint)); nint.sa_handler = sig_handler_int; nint.sa_flags = 0; if (0 != sigemptyset(&nint.sa_mask)) { sig_i_f = 1; goto finished; } if (0 != sigaddset(&nint.sa_mask, SIGINT)) { sig_i_f = 1; goto finished; } if (0 != sigaction(SIGINT, &nint, &oint)) { sig_i_f = 1; goto finished; } set_int = 1; #else #ifdef SIGPIPE opipe = sigset(SIGPIPE, sig_handler_pipe); #endif oint = sigset(SIGINT, sig_handler_int); oterm = sigset(SIGTERM, sig_handler_term); #endif /* Process remaining setup (PRINTCAP_ENTRY, model file). */ if (0 == process_setup()) { goto finished; } /* Header files for job in log output. */ report_at_job_start(argc, argv); /* Initialize socket subsystem. */ if (DK4_SOCKET_RESULT_SUCCESS != dk4socket_up(NULL)) { log_1_no_header(170); goto finished; } sockinit = 1; /* Check users permission to print. */ if (0 == check_permission()) { goto finished; } /* Establish SNMP session. */ if (0 == attempt_snmp_session()) { goto finished; } /* Initialization. */ initialize_at_startup(); /* Accounting before job. */ if (0 == do_accounting(0)) { goto finished; } /* Data transfer. */ if (0 == data_transfer()) { goto finished; } /* Accounting after job. */ if (0 == do_accounting(1)) { goto finished; } /* Cleanup ------- */ finished: /* Clean up SNMP session. */ if (NULL != snmp_sess) { snmp_close(snmp_sess); } /* Eat up data from standard input. */ eatup_input(); /* release socket subsystem. */ if (0 != sockinit) { (void)dk4socket_down(NULL); } /* Release status text nodes, if any. */ relase_status_text_nodes(); /* Release dynamically allocated printcap entry copy. */ dk4mem_release(printcap_entry); /* Restore signal handlers */ #if DK4_HAVE_SIGACTION if (0 != sig_i_f) { /* ERROR: Failed to set up signal handlers */ log_1_no_header(141); } if (0 != set_int) { if (0 != sigaction(SIGINT, &oint, NULL)) { sig_r_f = 1; } } if (0 != set_term) { if (0 != sigaction(SIGTERM, &oterm, NULL)) { sig_r_f = 1; } } #ifdef SIGPIPE if (0 != set_pipe) { if (0 != sigaction(SIGPIPE, &opipe, NULL)) { sig_r_f = 1; } } #endif if (0 != sig_r_f) { /* ERROR: Failed to restore signal handlers */ log_1_no_header(142); } #else if (NULL != oterm) { sigset(SIGTERM, oterm); } if (NULL != oint ) { sigset(SIGINT, oint ); } #ifdef SIGPIPE if (NULL != opipe) { sigset(SIGPIPE, opipe); } #endif #endif /* Final log message, close log file */ dk4time_get(&t4); if (2 > decision) { final_statistics(); } if (NULL != stt_file) { fclose(stt_file); } out_file = stderr; #line 5342 "pjsnmp.ctr" #line 5343 "pjsnmp.ctr" /* ----- All libraries available */ #else /* if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) */ /* +++++ Missing libraries */ #if !DK4_HAVE_LIBNETSNMP fputs("ERROR: Missing Net-SNMP support!\n", stderr); #endif #if !((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) fputs("ERROR: Missing sigaction()/sigset() support!\n", stderr); #endif fflush(stderr); /* ----- Missing libraries */ #endif /* if DK4_HAVE_LIBNETSNMP && ((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) */ exit(exval); return exval; } /* 2016-02-26 Added dk4socket_up() and dk4socket_down(). */