/* Copyright (C) 2016-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). 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 */ /** @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" #include "dk4unused.h" #line 49 "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 745 "pjsnmp.ctr" }; /** Responses from accounting system. */ static const char * const accounting_responses[] = { /* 0 */ "ACCEPT", /* 1 */ "HOLD", /* 2 */ "REMOVE", NULL #line 757 "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 892 "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 904 "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 940 "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 954 "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 967 "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 980 "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 1003 "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 printer status OID (number of elements). */ static const size_t sz_oid_ps = sizeof(oid_ps)/sizeof(oid); /** Size of page counter OID (number of elements). */ static const size_t sz_oid_pc = sizeof(oid_pc)/sizeof(oid); /** 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 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 DK4_ARG_UNUSED(signo) ) { DK4_UNUSED_ARG(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 DK4_ARG_UNUSED(signo) ) { DK4_UNUSED_ARG(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 DK4_ARG_UNUSED(signo) ) { DK4_UNUSED_ARG(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 1631 "pjsnmp.ctr" dk4time_get(¤t); if (current != previous_log) { #line 1633 "pjsnmp.ctr" if (dk4time_as_text_c8(buf, sizeof(buf), ¤t, NULL)) { back = 1; #line 1635 "pjsnmp.ctr" fputs(pjsnmp_kw[62], out_file); fputs(buf, out_file); fputs(pjsnmp_kw[0], out_file); previous_log = current; } } #line 1641 "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 1730 "pjsnmp.ctr" log_timestamp(); fputs(pjsnmp_kw[i], out_file); fflush(out_file); #line 1734 "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 1748 "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 1754 "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 1895 "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 1906 "pjsnmp.ctr" dk4mem_free(back); back = NULL; } } #if TRACE_DEBUG else { #line 1912 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 1917 "pjsnmp.ctr" } #endif #line 1920 "pjsnmp.ctr" return back; } /** Destroy status text node, release memory. @param ptr Node to destroy. */ static void stt_delete(status_text_t *ptr) { #line 1933 "pjsnmp.ctr" if (NULL != ptr) { #line 1934 "pjsnmp.ctr" dk4mem_release(ptr->text); dk4mem_free(ptr); } #line 1938 "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 1960 "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 1989 "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 2004 "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 2009 "pjsnmp.ctr" } } else { if (('A' <= c) && ('Z' >= c)) { sz = (size_t)(c - 'A'); if (DK4_SIZEOF(upper,DK4_PCHAR) > sz) { upper[sz] = val; #line 2015 "pjsnmp.ctr" } } } } #line 2019 "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 2034 "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 2047 "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 2069 "pjsnmp.ctr" for (i = 1; i < argc; i++) { curarg = argv[i]; #line 2071 "pjsnmp.ctr" if ('-' == *curarg) { #line 2072 "pjsnmp.ctr" curarg++; if ('\0' != *curarg) { #line 2074 "pjsnmp.ctr" c = *(curarg++); if ('\0' != *curarg) { #line 2076 "pjsnmp.ctr" set_option(c, curarg); } else { #line 2078 "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 2089 "pjsnmp.ctr" back = 0; /* ERROR: Only minus */ log_1_with_header(1, 66); } } else { #line 2094 "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 2106 "pjsnmp.ctr" s_name = get_option('s'); if (NULL != s_name) { #line 2108 "pjsnmp.ctr" stt_file = fopen(s_name, "w"); if (NULL != stt_file) { #line 2110 "pjsnmp.ctr" out_file = stt_file; } #if TRACE_DEBUG else { #line 2114 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 2119 "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 2131 "pjsnmp.ctr" /* ERROR: No user name */ log_1_with_header(1, 69); back = 0; } #if TRACE_DEBUG else { #line 2137 "pjsnmp.ctr" } #endif if (0 != back) { #line 2140 "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 2150 "pjsnmp.ctr" /* ERROR: No queue name */ log_1_with_header(1, 70); back = 0; } #if TRACE_DEBUG else { #line 2156 "pjsnmp.ctr" } #endif } if (0 != back) { job_name = get_option('A'); #line 2161 "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 2184 "pjsnmp.ctr" /* ERROR: No job name */ log_1_with_header(1, 71); back = 0; } #if TRACE_DEBUG else { #line 2190 "pjsnmp.ctr" } #endif } if (0 != back) { #line 2194 "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 2208 "pjsnmp.ctr" back = 0; } #endif #if TRACE_DEBUG else { #line 2213 "pjsnmp.ctr" } #endif } } #line 2218 "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 2235 "pjsnmp.ctr" if (NULL != src) { src = dk4str8_start(src, NULL); if (NULL != src) { #line 2238 "pjsnmp.ctr" if (NULL != *dptr) { #line 2239 "pjsnmp.ctr" /* WARNING: Redefinition */ log_5_with_header(2, 72, 73, 74, name, src); } *dptr = src; back = 1; } else { #line 2245 "pjsnmp.ctr" /* ERROR: Empty text */ log_3_with_header(2, 75, 76, name); } } else { #line 2249 "pjsnmp.ctr" /* ERROR: Text string required */ log_3_with_header(2, 77, 78, name); } #line 2252 "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 2271 "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 2278 "pjsnmp.ctr" } else { #line 2279 "pjsnmp.ctr" /* ERROR: Not a number! */ log_5_with_header(2, 79, 80, 81, name, src); } } else { #line 2283 "pjsnmp.ctr" /* ERROR: Empty text */ log_3_with_header(2, 75, 76, name); } } else { #line 2287 "pjsnmp.ctr" /* ERROR: Numeric value required */ log_3_with_header(2, 77, 78, name); } #line 2290 "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 2306 "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 2311 "pjsnmp.ctr" *dptr = SNMP_VERSION_1; back = 1; } break; case 1: case 2: { #line 2315 "pjsnmp.ctr" *dptr = SNMP_VERSION_2c; back = 1; } break; case 3: { #line 2319 "pjsnmp.ctr" *dptr = SNMP_VERSION_3; back = 1; } break; default: { #line 2323 "pjsnmp.ctr" /* ERROR: Illegal SNMP version */ log_3_with_header(2, 82, 83, src); } break; } } else { #line 2328 "pjsnmp.ctr" /* ERROR: Empty text */ log_3_with_header(2, 75, 76, printcap_entry_names[9]); } } else { #line 2332 "pjsnmp.ctr" /* ERROR: Value required */ log_3_with_header(2, 77, 78, printcap_entry_names[9]); } #line 2336 "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 2356 "pjsnmp.ctr" if (NULL != src) { res = dk4ma_input_c8_dec_dk4_um_t(&i, src, &ep, 1, NULL); if (0 != res) { *dptr = i; #line 2360 "pjsnmp.ctr" back = 1; } else { #line 2362 "pjsnmp.ctr" /* ERROR: Not a numeric value */ log_5_with_header(2, 84, 161, 86, name, src); } } else { #line 2366 "pjsnmp.ctr" /* ERROR: Value required */ log_3_with_header(2, 77, 78, name); } #line 2369 "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 2391 "pjsnmp.ctr" if (NULL != src) { res = dk4ma_input_c8_dec_int(&i, src, &ep, 1, NULL); if (0 != res) { *dptr = i; #line 2395 "pjsnmp.ctr" back = 1; } else { #line 2397 "pjsnmp.ctr" /* ERROR: Not a numeric value */ log_5_with_header(2, 84, 85, 86, name, src); } } else { #line 2401 "pjsnmp.ctr" /* ERROR: Value required */ log_3_with_header(2, 77, 78, name); } #line 2404 "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 2423 "pjsnmp.ctr" value = dk4str8_chr(ci, '='); if (NULL != value) { *(value++) = '\0'; value = dk4str8_start(value, NULL); #line 2427 "pjsnmp.ctr" } else { value = dk4str8_chr(ci, '@'); if (NULL != value) { #line 2430 "pjsnmp.ctr" *value = '\0'; btrue = 0; } #if TRACE_DEBUG else { #line 2435 "pjsnmp.ctr" } #endif } switch (dk4str8_array_index(printcap_entry_names, ci, 0)) { case 0: { #line 2440 "pjsnmp.ctr" if (0 == set_string(&host_name, value, printcap_entry_names[0])) { back = 0; } } break; case 1: { #line 2445 "pjsnmp.ctr" if (0 == set_unsigned_short(&host_port, value, printcap_entry_names[1])) { back = 0; } } break; case 2: { #line 2450 "pjsnmp.ctr" host_ordr = btrue; } break; case 3: { #line 2453 "pjsnmp.ctr" acct_enab = btrue; } break; case 4: { #line 2456 "pjsnmp.ctr" acct_achk = btrue; } break; case 5: { #line 2459 "pjsnmp.ctr" if (0 == set_string(&acct_name, value, printcap_entry_names[5])) { back = 0; } } break; case 6: { #line 2464 "pjsnmp.ctr" if (0 == set_string(&acct_host, value, printcap_entry_names[6])) { back = 0; } } break; case 7: { #line 2469 "pjsnmp.ctr" if (0 == set_unsigned_short(&acct_port, value, printcap_entry_names[7])) { back = 0; } } break; case 8: { #line 2474 "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 2484 "pjsnmp.ctr" if (0 == set_snmp_version(&snmp_version, value)) { back = 0; } } break; case 10: { #line 2489 "pjsnmp.ctr" if (0 == set_string(&snmp_comm, value, printcap_entry_names[10])) { back = 0; } } break; case 11: { #line 2494 "pjsnmp.ctr" check_trans = btrue; } break; case 12: { #line 2497 "pjsnmp.ctr" if (0 == set_string(&model_file, value, printcap_entry_names[12])) { back = 0; } } break; case 13: { #line 2502 "pjsnmp.ctr" if (0 == set_string(&model_name, value, printcap_entry_names[13])) { back = 0; } } break; case 14: { #line 2507 "pjsnmp.ctr" snmp_igfs = btrue; } break; case 15: { #line 2510 "pjsnmp.ctr" acct_apcf = btrue; } break; case 16: { #line 2513 "pjsnmp.ctr" pdes_always = btrue; } break; case 17: { #line 2516 "pjsnmp.ctr" unkn_busy = btrue; } break; case 18: { #line 2519 "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 2529 "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 2539 "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 2549 "pjsnmp.ctr" if (0 == set_unsigned_short(&local_port, value, printcap_entry_names[21])) { back = 0; #line 2552 "pjsnmp.ctr" } } break; case 22: { #line 2555 "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 2562 "pjsnmp.ctr" back = 0; } } } break; case 23: { #line 2567 "pjsnmp.ctr" read_responses = btrue; } break; case 24: { #line 2570 "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 2580 "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 2592 "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 2604 "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 2618 "pjsnmp.ctr" return back; } /** Check whether the line opens the model we are searching for. @param str Text to check. @return 1 on success, 0 on error. */ static int check_in_model(char *str, dk4_um_t lineno) { char *ptr; /* Closing square bracket */ int back = 0; #line 2634 "pjsnmp.ctr" str = dk4str8_start(str, NULL); if (NULL != str) { ptr = dk4str8_chr(str, ']'); if (NULL != ptr) { *ptr = '\0'; dk4str8_normalize(str, NULL); #line 2640 "pjsnmp.ctr" if (0 == strcmp(str, model_name)) { back = 1; #line 2642 "pjsnmp.ctr" } #if TRACE_DEBUG else { #line 2645 "pjsnmp.ctr" } #endif } else { #line 2648 "pjsnmp.ctr" /* ERROR: Syntax */ log_model_1(lineno, 87); } } else { #line 2652 "pjsnmp.ctr" /* ERROR: Syntax */ log_model_1(lineno, 88); } #line 2655 "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 2670 "pjsnmp.ctr" if ((0 < devst) && (6 > devst)) { if ((0 < prst) && (6 > prst)) { #line 2672 "pjsnmp.ctr" summary_states[5 * devst + prst - 6] = sumst; } #if TRACE_DEBUG else { #line 2676 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 2681 "pjsnmp.ctr" } #endif #line 2684 "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 2699 "pjsnmp.ctr" if ((0 < devst) && (6 > devst)) { if ((0 < prst) && (6 > prst)) { #line 2701 "pjsnmp.ctr" back = summary_states[5 * devst + prst - 6]; #line 2703 "pjsnmp.ctr" } #if TRACE_DEBUG else { #line 2706 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 2711 "pjsnmp.ctr" } #endif #line 2714 "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 2735 "pjsnmp.ctr" psummary = dk4str8_next(str, NULL); if (NULL != psummary) { #line 2737 "pjsnmp.ctr" ppr = dk4str8_chr(str, '/'); if (NULL != ppr) { #line 2739 "pjsnmp.ctr" *(ppr++) = '\0'; ppr = dk4str8_start(ppr, NULL); if (NULL != ppr) { #line 2742 "pjsnmp.ctr" back = 1; switch (dk4str8_abbr_index(summary_state_names, '$', psummary, 0)) { case 0: { #line 2745 "pjsnmp.ctr" stsum = PJSNMP_ST_UNKNOWN; } break; case 1: { #line 2748 "pjsnmp.ctr" stsum = PJSNMP_ST_ERROR; } break; case 2: { #line 2751 "pjsnmp.ctr" stsum = PJSNMP_ST_BUSY; } break; case 3: { #line 2754 "pjsnmp.ctr" stsum = PJSNMP_ST_IDLE; } break; case 4: { #line 2757 "pjsnmp.ctr" stsum = PJSNMP_ST_WARMUP; } break; case 5: { #line 2760 "pjsnmp.ctr" stsum = PJSNMP_ST_STANDBY; } break; default: { #line 2763 "pjsnmp.ctr" back = 0; /* ERROR: Illegal summary state */ log_model_3(lineno, 89, 90, psummary); } break; } if (0 != back) { #line 2769 "pjsnmp.ctr" if (0 == strcmp(str, pjsnmp_kw[3])) { if (0 == strcmp(ppr, pjsnmp_kw[3])) { #line 2771 "pjsnmp.ctr" for (stdev = 1; stdev < 6; stdev++) { for (stpri = 1; stpri < 6; stpri++) { set_state_mapping(stdev, stpri, stsum); } } } else { #line 2777 "pjsnmp.ctr" stpri = dk4str8_abbr_index(printer_status_names, '$', ppr, 0); if (-1 < stpri) { stpri++; #line 2780 "pjsnmp.ctr" for (stdev = 1; stdev < 6; stdev++) { set_state_mapping(stdev, stpri, stsum); } } else { #line 2784 "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 2793 "pjsnmp.ctr" if (0 == strcmp(ppr, pjsnmp_kw[3])) { #line 2794 "pjsnmp.ctr" for (stpri = 1; stpri < 6; stpri++) { set_state_mapping(stdev, stpri, stsum); } } else { #line 2798 "pjsnmp.ctr" stpri = dk4str8_abbr_index(printer_status_names, '$', ppr, 0); if (-1 < stpri) { stpri++; #line 2801 "pjsnmp.ctr" set_state_mapping(stdev, stpri, stsum); } else { #line 2803 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, illegal printer status name */ log_model_3(lineno, 91, 92, ppr); } } } else { #line 2809 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, illegal device status name */ log_model_3(lineno, 93, 94, ppr); } } } else { #line 2815 "pjsnmp.ctr" } } else { #line 2817 "pjsnmp.ctr" /* ERROR: Syntax, printer status missing */ log_model_1(lineno, 95); } } else { #line 2821 "pjsnmp.ctr" /* ERROR: Syntax, printer status missing */ log_model_1(lineno, 95); } } else { #line 2825 "pjsnmp.ctr" /* ERROR: Syntax, summary state missing */ log_model_1(lineno, 96); } #line 2828 "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 2847 "pjsnmp.ctr" if ((0 == addcond) && (0 == pdes_reset)) { pdes_error = 0UL; #line 2849 "pjsnmp.ctr" } pdes_reset = 1; dk4str8_normalize(str, NULL); i = dk4str8_array_index(condition_names, str, 0); #line 2853 "pjsnmp.ctr" if (-1 < i) { back = 1; cond = 0x80000000UL; while (0 < i--) { cond = cond / 2UL; } pdes_error |= cond; #line 2858 "pjsnmp.ctr" } else { #line 2859 "pjsnmp.ctr" /* ERROR: Syntax, illegal condition name */ log_model_3(lineno, 97, 98, str); } #line 2862 "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 2883 "pjsnmp.ctr" dk4str8_normalize(str, NULL); if ('.' == *str) { #line 2885 "pjsnmp.ctr" str++; } while ((NULL != str) && (1 == back)) { np = dk4str8_chr(str, '.'); if (NULL != np) { *(np++) = '\0'; } #line 2892 "pjsnmp.ctr" ep = NULL; res = dk4ma_input_c8_dec_dk4_um_t(&num, str, &ep, 1, NULL); if (0 != res) { #line 2895 "pjsnmp.ctr" if ((dk4_um_t)(MAX_SUBID) >= num) { #line 2896 "pjsnmp.ctr" if (used < DK4_SIZEOF(oid_st,oid)) { #line 2897 "pjsnmp.ctr" oid_st[used++] = (oid)num; } else { #line 2899 "pjsnmp.ctr" /* ERROR: Syntax, OID too long */ log_model_1(lineno, 99); } } else { #line 2903 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, overflow */ log_model_3(lineno, 100, 101, str); } } else { #line 2908 "pjsnmp.ctr" back = 0; /* ERROR: Syntax, not a number */ log_model_3(lineno, 102, 103, str); } str = np; } if (0 == used) { #line 2915 "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 2926 "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 2942 "pjsnmp.ctr" ptr = dk4str8_rchr(str, '"'); if (NULL != ptr) { #line 2944 "pjsnmp.ctr" *(ptr++) = '\0'; back = 1; while ('\0' != *ptr) { if (' ' != *ptr) { if ('\t' != *ptr) { if ('\r' != *ptr) { if ('\n' != *ptr) { back = 0; #line 2952 "pjsnmp.ctr" } } } } ptr++; } } #if TRACE_DEBUG else { #line 2961 "pjsnmp.ctr" } #endif #line 2964 "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 2989 "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 2999 "pjsnmp.ctr" if (NULL != str) { #line 3000 "pjsnmp.ctr" if ('"' == *str) { #line 3001 "pjsnmp.ctr" str++; if (0 != remove_final_double_quote(str)) { sl = strlen(str); if (0 < sl) { #line 3005 "pjsnmp.ctr" stptr = stt_new((unsigned char *)str, sl, state, start); if (NULL != stptr) { #line 3007 "pjsnmp.ctr" if (0 != dk4sto_add(s_stn, stptr, NULL)) { back = 1; #line 3009 "pjsnmp.ctr" } else { #line 3010 "pjsnmp.ctr" /* ERROR: Allocation failed */ log_model_1(lineno, 105); stt_delete(stptr); } } else { #line 3015 "pjsnmp.ctr" /* ERROR: Allocation failed */ log_model_1(lineno, 105); } } else { #line 3019 "pjsnmp.ctr" /* ERROR: Syntax, string empty */ log_model_1(lineno, 106); } } else { #line 3023 "pjsnmp.ctr" /* ERROR: Syntax, closing double quote missing or text after */ log_model_1(lineno, 107); } } else { #line 3027 "pjsnmp.ctr" sl = 0; cptr = str; back = 1; while ((NULL != cptr) && (0 != back)) { nptr = dk4str8_next(cptr, NULL); ep = NULL; #line 3033 "pjsnmp.ctr" res = dk4ma_input_c8_hex_uchar(&uc, cptr, &ep, 1, NULL); if (0 != res) { str[sl++] = (char)uc; #line 3036 "pjsnmp.ctr" } else { back = 0; #line 3038 "pjsnmp.ctr" /* ERROR: Syntax, not a hexadecimal byte */ log_model_3(lineno, 108, 109, cptr); } cptr = nptr; } if (0 != back) { if (0 < sl) { #line 3045 "pjsnmp.ctr" stptr = stt_new((unsigned char *)str, sl, state, start); if (NULL != stptr) { #line 3047 "pjsnmp.ctr" if (0 == dk4sto_add(s_stn, stptr, NULL)) { back = 0; #line 3049 "pjsnmp.ctr" stt_delete(stptr); /* ERROR: Allocation failed */ log_model_1(lineno, 105); } #if TRACE_DEBUG else { #line 3055 "pjsnmp.ctr" } #endif } else { #line 3058 "pjsnmp.ctr" back = 0; /* ERROR: Memory allocation failed */ log_model_1(lineno, 105); } } else { #line 3063 "pjsnmp.ctr" /* ERROR: Syntax, empty string */ log_model_1(lineno, 106); } } } } else { #line 3069 "pjsnmp.ctr" /* ERROR: Value required */ log_model_1(lineno, 110); } } else { #line 3073 "pjsnmp.ctr" /* ERROR: Memory allocation failed */ log_model_1(lineno, 105); } #line 3076 "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 3093 "pjsnmp.ctr" valptr = dk4str8_chr(str, '='); if (NULL != valptr) { #line 3095 "pjsnmp.ctr" *(valptr++) = '\0'; dk4str8_normalize(str, NULL); valptr = dk4str8_start(valptr, NULL); if (NULL != valptr) { #line 3099 "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 3169 "pjsnmp.ctr" /* ERROR: Syntax, unknown key */ log_model_3(lineno, 113, 114, str); } break; } } else { #line 3174 "pjsnmp.ctr" /* ERROR: Syntax, missing value */ log_model_1(lineno, 110); } } else { #line 3178 "pjsnmp.ctr" /* ERROR: Syntax, missing value */ log_model_1(lineno, 110); } #line 3181 "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 3199 "pjsnmp.ctr" infile = fopen(((NULL != model_file) ? model_file : def_model_file), "r"); if (NULL != infile) { #line 3201 "pjsnmp.ctr" back = 1; while (NULL != fgets(pjsnmp_buf, sizeof(pjsnmp_buf), infile)) { lineno++; #if TRACE_DEBUG dk4str8_delnl(pjsnmp_buf); #line 3206 "pjsnmp.ctr" #endif p1 = dk4str8_start(pjsnmp_buf, NULL); if (NULL != p1) { if ('[' == *p1) { in_model = check_in_model(++p1, 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 3230 "pjsnmp.ctr" back = 0; /* ERROR: Model not found */ log_model_3((dk4_um_t)0UL, 115, 116, model_name); } } else { #line 3235 "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 3241 "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 3264 "pjsnmp.ctr" ptr = getenv(pjsnmp_kw[2]); if (NULL != ptr) { #line 3267 "pjsnmp.ctr" printcap_entry = dk4str8_dup(ptr, NULL); if (NULL != printcap_entry) { #line 3269 "pjsnmp.ctr" back = 1; #line 3270 "pjsnmp.ctr" cl = printcap_entry; while (NULL != cl) { nl = dk4str8_chr(cl, '\n'); if (NULL != nl) { *(nl++) = '\0'; nl = dk4str8_start(nl, NULL); } #line 3277 "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 3289 "pjsnmp.ctr" ci = dk4str8_start(ci, NULL); if (NULL != ci) { if (0 != found) { if (0 == process_one_config_item(ci)) { back = 0; #line 3294 "pjsnmp.ctr" } } found = 1; } ci = ni; } } } cl = nl; } if (NULL == host_name) { back = 0; #line 3306 "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 3312 "pjsnmp.ctr" } } if (0 != back) { if (0 != acct_achk) { #line 3316 "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 3328 "pjsnmp.ctr" /* ERROR: Memory allocation failed */ log_1_with_header(2, 105); } } else { #line 3332 "pjsnmp.ctr" /* ERROR: Missing printcap entry environment variable */ log_1_with_header(2, 120); } #line 3336 "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 3350 "pjsnmp.ctr" do { if (0 != can_continue(0)) { if (0 == have_eof) { #line 3353 "pjsnmp.ctr" rdb = fread(pjsnmp_buf, 1, sizeof(pjsnmp_buf), stdin); if (0 == rdb) { #line 3355 "pjsnmp.ctr" cc = 0; have_eof = 1; } #if TRACE_DEBUG else { #line 3360 "pjsnmp.ctr" } #endif } else { #line 3363 "pjsnmp.ctr" cc = 0; } } else { #line 3366 "pjsnmp.ctr" cc = -1; } } while (1 == cc); #line 3370 "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 3382 "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 3388 "pjsnmp.ctr" stt_delete(ptr); } } while(NULL != ptr); dk4sto_it_close(i_stn); i_stn = NULL; } dk4sto_close(s_stn); s_stn = NULL; } #line 3396 "pjsnmp.ctr" } /** Attempt to open an SNMP session. @return 1 on success, 0 on error. */ static int attempt_snmp_session(void) { struct snmp_session sesstemp; /* Template for the session */ int back = 0; #line 3410 "pjsnmp.ctr" init_snmp(pjsnmp_kw[4]); DK4_MEMRES(&sesstemp, sizeof(sesstemp)); snmp_sess_init(&sesstemp); sesstemp.version = snmp_version; sesstemp.peername = host_name; sesstemp.community = (unsigned char *)snmp_comm; if (NULL == snmp_comm) { sesstemp.community = (unsigned char *)(pjsnmp_kw[5]); } sesstemp.community_len = strlen((char *)(sesstemp.community)); snmp_sess = snmp_open(&sesstemp); if (NULL != snmp_sess) { #line 3422 "pjsnmp.ctr" back = 1; } else { #line 3424 "pjsnmp.ctr" /* ERROR: Failed to open SNMP session */ log_1_no_header(121); if (0 != snmp_igfs) { #line 3427 "pjsnmp.ctr" back = 1; } } #line 3430 "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 3452 "pjsnmp.ctr" cutted = 0; if (0 != can_continue(0)) { #line 3454 "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 3458 "pjsnmp.ctr" if (by == sl) { #line 3459 "pjsnmp.ctr" back = 1; #line 3460 "pjsnmp.ctr" } else { #line 3461 "pjsnmp.ctr" /* ERROR: Partial send */ log_1_no_header(123); } } else { #line 3465 "pjsnmp.ctr" /* ERROR: Failed to send data */ log_1_no_header(122); } pjsnmp_buf[0] = '\0'; res = dk4socket_shutdown(sock, DK4_SOCKET_SHUT_WRITE, NULL); if (DK4_SOCKET_RESULT_SUCCESS == res) { #line 3471 "pjsnmp.ctr" cc = 1; do { if (0 != can_continue(0)) { #line 3474 "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 3477 "pjsnmp.ctr" if (0 < by) { #line 3478 "pjsnmp.ctr" stat_text[by] = '\0'; res = dk4str8_cat_s(pjsnmp_buf,sizeof(pjsnmp_buf),stat_text,NULL); if (0 == res) { cutted = 1; #line 3482 "pjsnmp.ctr" back = 0; } } else { #line 3485 "pjsnmp.ctr" cc = 0; } } else { #line 3488 "pjsnmp.ctr" cc = -1; } } else { #line 3491 "pjsnmp.ctr" cc = -1; back = 0; } } while(1 == cc); } else { #line 3496 "pjsnmp.ctr" back = 0; /* ERROR: Socket shutdown failed */ log_1_no_header(124); } if (0 != expect_response) { #line 3501 "pjsnmp.ctr" if (0 == strlen(pjsnmp_buf)) { #line 3502 "pjsnmp.ctr" back = 0; } if (0 != cutted) { #line 3505 "pjsnmp.ctr" back = 0; } } } else { #line 3509 "pjsnmp.ctr" pjsnmp_buf[0] = '\0'; } dk4socket_close(sock, NULL); #line 3513 "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 3529 "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 3539 "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 3555 "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 3565 "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 3581 "pjsnmp.ctr" if (EOF != fputs(pjsnmp_buf, fipo)) { #line 3582 "pjsnmp.ctr" if (EOF != fflush(fipo)) { #line 3583 "pjsnmp.ctr" back = 1; } #if TRACE_DEBUG else { #line 3587 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 3592 "pjsnmp.ctr" } #endif pjsnmp_buf[0] = '\0'; if (0 != expect_response) { #line 3596 "pjsnmp.ctr" back = 0; } #line 3598 "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 3616 "pjsnmp.ctr" prgn = dk4str8_start(&(acct_name[1]), NULL); if (NULL != prgn) { #line 3618 "pjsnmp.ctr" fipo = popen(prgn, "w"); if (NULL != fipo) { #line 3620 "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; } break; default : { decision = 1; } break; } log_3_no_header(166, 167, accounting_responses[decision - 1]); } } else { #line 3638 "pjsnmp.ctr" /* ERROR: Failed to start program for pipe */ log_1_no_header(126); pjsnmp_buf[0] = '\0'; } } else { #line 3643 "pjsnmp.ctr" /* ERROR: Not command name found */ log_1_with_header(2, 127); pjsnmp_buf[0] = '\0'; } #line 3647 "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 3666 "pjsnmp.ctr" if (0 != dk4isadmin()) { #line 3667 "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 3672 "pjsnmp.ctr" back = accounting_ex_file(fipo, expect_response); if(EOF == fclose(fipo)) { #line 3674 "pjsnmp.ctr" back = 0; } } else { #line 3677 "pjsnmp.ctr" /* ERROR: Failed to open accounting file name */ log_1_no_header(128); pjsnmp_buf[0] = '\0'; } #line 3681 "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 3706 "pjsnmp.ctr" sl = strlen(pjsnmp_buf); bwr = write(3, pjsnmp_buf, sl); pjsnmp_buf[0] = '\0'; if (0 < bwr) { #line 3710 "pjsnmp.ctr" if (sl == (size_t)bwr) { #line 3711 "pjsnmp.ctr" back = 1; } else { #line 3713 "pjsnmp.ctr" /* ERROR: Incomplete write operation */ log_1_no_header(122); } if (0 != expect_response) { #line 3717 "pjsnmp.ctr" bwr = read(3, pjsnmp_buf, sizeof(pjsnmp_buf)); if (0 < bwr) { #line 3719 "pjsnmp.ctr" pjsnmp_buf[bwr] = '\0'; } else { #line 3721 "pjsnmp.ctr" pjsnmp_buf[0] = '\0'; back = 0; } } } else { #line 3726 "pjsnmp.ctr" /* ERROR: Write failed */ log_1_no_header(122); } #line 3729 "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 3753 "pjsnmp.ctr" if ((NULL != acct_host) && (0 < acct_port)) { #line 3754 "pjsnmp.ctr" log_1_no_header(154); back = accounting_ex_network(expect_response); log_1_no_header((0 != back) ? 159 : 160); } else { #line 3758 "pjsnmp.ctr" if (NULL != acct_name) { #line 3759 "pjsnmp.ctr" if ('|' == *acct_name) { #line 3760 "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 3770 "pjsnmp.ctr" if (0 != dk4stat_c8(&stb, acct_name, NULL)) { if (0 != dk4stat_is_unix_domain_socket(&stb, NULL)) { issock = 1; #line 3773 "pjsnmp.ctr" } } else { crf = 1; #line 3776 "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 3792 "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 3801 "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 3817 "pjsnmp.ctr" if ((0 != acct_enab) && (0 != acct_achk)) { #line 3818 "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 3827 "pjsnmp.ctr" if (0 != accounting_exchange(1)) { #line 3828 "pjsnmp.ctr" dk4str8_normalize(pjsnmp_buf, NULL); #line 3829 "pjsnmp.ctr" if (0 < strlen(pjsnmp_buf)) { #line 3830 "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 3839 "pjsnmp.ctr" } break; case 1: { #line 3841 "pjsnmp.ctr" exval = LPRNG_EXIT_HOLD; } break; } log_3_no_header(166, 167, pjsnmp_buf); } else { #line 3846 "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 3855 "pjsnmp.ctr" if (0 != acct_apcf) { back = 1; } else { decision = 3; } } } } } } } } /* LOG: Test result */ log_1_no_header((0 != back) ? 134 : 135); } #line 3867 "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 3887 "pjsnmp.ctr" switch (var->type) { case ASN_OCTET_STR : { #line 3889 "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 3902 "pjsnmp.ctr" l = *((var->val).integer); *iptr = (int)l; back = 1; } break; } #line 3908 "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 3926 "pjsnmp.ctr" switch (var->type) { case ASN_OCTET_STR : { #line 3928 "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 3953 "pjsnmp.ctr" l = *((var->val).integer); if (0L <= l) { *ulptr = (unsigned long)l; back = 1; } } break; } #line 3961 "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 3977 "pjsnmp.ctr" while ((0 == back) && (0 < i)) { if (0x7F < (unsigned char)(*(ptr++))) { back = 1; } i--; } #line 3983 "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 4055 "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 4068 "pjsnmp.ctr" if (0 != oids_equal(p, sz, oid_st, sz_oid_st)) { back = 4; } } #if TRACE_DEBUG else { #line 4074 "pjsnmp.ctr" } #endif } } } } #line 4080 "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(void) { unsigned long tcond = 0x80000000UL; /* Bit for one condition */ int must_report = 0; /* Flag: Must report change */ int i; #line 4128 "pjsnmp.ctr" /* Check whether or not to report. */ if (stsum != ostsum) { #line 4131 "pjsnmp.ctr" must_report = 1; } else { if (devst != odevst) { #line 4134 "pjsnmp.ctr" must_report = 1; } else { if (prist != oprist) { #line 4137 "pjsnmp.ctr" must_report = 1; } else { if (pdes_cond != opdes_cond) { #line 4140 "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 4155 "pjsnmp.ctr" } else { if (0 != dk4mem_cmp(stat_text,ostat_text,sz_stat_text,NULL)) { must_report = 1; #line 4158 "pjsnmp.ctr" } } } } } } } } } /* Report if necessary. */ if (0 != must_report) { #line 4171 "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); (void)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 4234 "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 4255 "pjsnmp.ctr" if (0 != can_continue(0)) { #line 4256 "pjsnmp.ctr" if (NULL != snmp_sess) { #line 4257 "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 4266 "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 4272 "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 4276 "pjsnmp.ctr" if (NULL != rs) { #line 4277 "pjsnmp.ctr" if (SNMP_ERR_NOERROR == rs->errstat) { #line 4278 "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 4286 "pjsnmp.ctr" if (0 != get_int(&devst, vars)) { #line 4287 "pjsnmp.ctr" found |= 1; } } break; case 1: { #line 4291 "pjsnmp.ctr" if (0 != get_int(&prist, vars)) { #line 4292 "pjsnmp.ctr" found |= 2; } } break; case 2: { #line 4296 "pjsnmp.ctr" if (0 != get_ul(&pcnt, vars)) { #line 4297 "pjsnmp.ctr" found |= 4; #line 4298 "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 4319 "pjsnmp.ctr" if (0 != get_ul(&pdes_cond, vars)) { found |= 8; } } break; case 4: { #line 4322 "pjsnmp.ctr" if (0 < vars->val_len) { if (sizeof(stat_text) > vars->val_len) { #line 4324 "pjsnmp.ctr" dk4mem_cpy( stat_text, (vars->val).string, vars->val_len, NULL ); sz_stat_text = vars->val_len; } else { #line 4330 "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 4348 "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 4356 "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 4374 "pjsnmp.ctr" } } } } /* Build summary (4): Map unknown to busy if configured */ if ((0 != unkn_busy) && (PJSNMP_ST_UNKNOWN == stsum)) { stsum = PJSNMP_ST_BUSY; #line 4383 "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 4391 "pjsnmp.ctr" if ((0 < passno) && (0UL < pcnt)) { pc_error = pcnt; #line 4393 "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 4401 "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(); /* 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 4433 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 4438 "pjsnmp.ctr" } #endif } #if TRACE_DEBUG else { #line 4443 "pjsnmp.ctr" } #endif if (NULL != rs) { snmp_free_pdu(rs); } } #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 #line 4464 "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 4484 "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 4505 "pjsnmp.ctr" (void)accounting_exchange(0); } } } } } } } } } } } } } #line 4519 "pjsnmp.ctr" } /** Report used pages to accounting system. */ static void report_used_pages(void) { #line 4529 "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 4536 "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 4560 "pjsnmp.ctr" if (NULL != snmp_sess) { #line 4561 "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 4567 "pjsnmp.ctr" if (0 != one_snmp_request((0 == passno) ? 0 : 2)) { #line 4569 "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 4577 "pjsnmp.ctr" cto = 0; if (1 == passno) { if ((0 == seen_printing) && (0 < print_timeout)) { cto = 1; #line 4581 "pjsnmp.ctr" } else { if ((0UL != pc_error) && (1 == have_pce)) { if ((pc_end == pc_error)&&((dk4_um_t)0UL < print_timeout)) { cto = 1; #line 4585 "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 4593 "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 4630 "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_time_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 4688 "pjsnmp.ctr" cc = -1; } } else { #line 4691 "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 4697 "pjsnmp.ctr" res = dk4ma_write_c8_decimal_unsigned(buf, sizeof(buf), pcnt, 0, NULL); if (0 != res) { #line 4700 "pjsnmp.ctr" log_3_no_header((147+passno), 0, buf); #line 4702 "pjsnmp.ctr" } #line 4704 "pjsnmp.ctr" } else { #line 4706 "pjsnmp.ctr" log_1_no_header(149); #line 4708 "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 4722 "pjsnmp.ctr" if ((0 != have_pcs) && (0 != have_pce)) { #line 4723 "pjsnmp.ctr" if (pc_end > pc_start) { #line 4724 "pjsnmp.ctr" /* Report number of used pages to accounting system */ report_used_pages(); } } } } else { #line 4730 "pjsnmp.ctr" if (0 != snmp_igfs) { #line 4731 "pjsnmp.ctr" back = 1; } } #line 4734 "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 4763 "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); (void)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 4937 "pjsnmp.ctr" /* ERROR: Failed to connect */ log_1_no_header(140); } } else { #line 4941 "pjsnmp.ctr" } #line 4943 "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 5170 "pjsnmp.ctr" #line 5171 "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 5324 "pjsnmp.ctr" #line 5325 "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(). */