2 * Host Resources MIB - printer device group implementation - hr_print.c
6 #include <net-snmp/net-snmp-config.h>
18 #include "util_funcs.h"
20 #define HRPRINT_MONOTONICALLY_INCREASING
22 /*********************
24 * Kernel & interface information,
25 * and internal forward declarations
27 *********************/
29 void Init_HR_Print(void);
30 int Get_Next_HR_Print(void);
31 void Save_HR_Print(void);
32 const char *describe_printer(int);
33 int printer_status(int);
34 int printer_detail_status(int);
35 int printer_errors(int);
36 int header_hrprint(struct variable *, oid *, size_t *, int,
37 size_t *, WriteMethod **);
38 FILE *run_lpstat(int *);
41 /*********************
43 * Initialisation & common implementation functions
45 *********************/
47 #define HRPRINT_STATUS 1
48 #define HRPRINT_ERROR 2
50 struct variable4 hrprint_variables[] = {
51 {HRPRINT_STATUS, ASN_INTEGER, RONLY, var_hrprint, 2, {1, 1}},
52 {HRPRINT_ERROR, ASN_OCTET_STR, RONLY, var_hrprint, 2, {1, 2}}
54 oid hrprint_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 5 };
60 init_device[HRDEV_PRINTER] = Init_HR_Print;
61 next_device[HRDEV_PRINTER] = Get_Next_HR_Print;
63 * save_device[ HRDEV_PRINTER ] = Save_HR_Print;
65 #ifdef HRPRINT_MONOTONICALLY_INCREASING
66 dev_idx_inc[HRDEV_PRINTER] = 1;
69 device_descr[HRDEV_PRINTER] = describe_printer;
70 device_status[HRDEV_PRINTER] = printer_status;
71 device_errors[HRDEV_PRINTER] = printer_errors;
73 REGISTER_MIB("host/hr_print", hrprint_variables, variable4,
74 hrprint_variables_oid);
80 * vp IN - pointer to variable entry that points here
81 * name IN/OUT - IN/name requested, OUT/name found
82 * length IN/OUT - length of IN/OUT oid's
83 * exact IN - TRUE if an exact match was requested
84 * var_len OUT - length of variable or 0 if function returned
89 header_hrprint(struct variable *vp,
92 int exact, size_t * var_len, WriteMethod ** write_method)
94 #define HRPRINT_ENTRY_NAME_LENGTH 11
95 oid newname[MAX_OID_LEN];
96 int print_idx, LowIndex = -1;
99 DEBUGMSGTL(("host/hr_print", "var_hrprint: "));
100 DEBUGMSGOID(("host/hr_print", name, *length));
101 DEBUGMSG(("host/hr_print", " %d\n", exact));
103 memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
105 * Find "next" print entry
110 print_idx = Get_Next_HR_Print();
113 newname[HRPRINT_ENTRY_NAME_LENGTH] = print_idx;
114 result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
115 if (exact && (result == 0)) {
116 LowIndex = print_idx;
118 * Save printer status information
122 if ((!exact && (result < 0)) &&
123 (LowIndex == -1 || print_idx < LowIndex)) {
124 LowIndex = print_idx;
126 * Save printer status information
128 #ifdef HRPRINT_MONOTONICALLY_INCREASING
134 if (LowIndex == -1) {
135 DEBUGMSGTL(("host/hr_print", "... index out of range\n"));
136 return (MATCH_FAILED);
139 memcpy((char *) name, (char *) newname,
140 (vp->namelen + 1) * sizeof(oid));
141 *length = vp->namelen + 1;
143 *var_len = sizeof(long); /* default to 'long' results */
145 DEBUGMSGTL(("host/hr_print", "... get print stats "));
146 DEBUGMSGOID(("host/hr_print", name, *length));
147 DEBUGMSG(("host/hr_print", "\n"));
152 /*********************
154 * System specific implementation functions
156 *********************/
160 var_hrprint(struct variable * vp,
163 int exact, size_t * var_len, WriteMethod ** write_method)
168 header_hrprint(vp, name, length, exact, var_len, write_method);
169 if (print_idx == MATCH_FAILED)
175 long_return = printer_detail_status(print_idx);
176 return (u_char *) & long_return;
181 long_return = 0; /* Null string */
182 return (u_char *) & long_return;
184 DEBUGMSGTL(("host/hr_print", "unknown sub-id %d in var_hrprint\n",
191 /*********************
193 * Internal implementation functions
195 *********************/
197 static int HRP_index;
198 static char **HRP_name;
199 static int HRP_names, HRP_maxnames;
204 #if HAVE_LPSTAT || HAVE_CGETNEXT || HAVE_PRINTCAP
209 const char *caps[] = { "/etc/printcap", NULL };
215 for (i = 0; i < HRP_names; i++)
220 HRP_name = (char **) calloc(HRP_maxnames, sizeof(char *));
226 if ((p = run_lpstat(&fd)) != NULL) {
227 char buf[BUFSIZ], ptr[BUFSIZ];
228 while (fgets(buf, sizeof buf, p)) {
229 sscanf(buf, "%*s %*s %[^:]", ptr);
232 char *buf = NULL, *ptr;
233 while (cgetnext(&buf, caps)) {
234 if ((ptr = strchr(buf, ':')))
236 if ((ptr = strchr(buf, '|')))
240 if ((p = fopen("/etc/printcap", "r")) != NULL) {
241 char buf[BUFSIZ], *ptr;
242 while (fgets(buf, sizeof buf, p)) {
243 buf[strlen(buf) - 1] = 0;
244 if (buf[0] == '#' || buf[0] == 0 || buf[0] == ' '
247 if ((ptr = strchr(buf, '\\')))
249 if ((ptr = strchr(buf, ':')))
251 if ((ptr = strchr(buf, '|')))
255 if (HRP_names == HRP_maxnames) {
258 tmp = (char **) calloc(HRP_maxnames, sizeof(char *));
261 memcpy(tmp, HRP_name, HRP_names * sizeof(char *));
264 HRP_name[HRP_names++] = strdup(ptr);
280 #endif /* HAVE_anything */
286 Get_Next_HR_Print(void)
289 * The initial implementation system
290 * has no printers attached, and I've
291 * no real idea how to detect them,
294 if (HRP_index < HRP_names) /* No printer */
295 return (HRDEV_PRINTER << HRDEV_TYPE_SHIFT) + HRP_index++;
301 describe_printer(int idx)
303 DEBUGMSGTL(("host/hr_print", "describe p: %d/%d %s\n", HRP_index, idx,
304 HRP_name[HRP_index - 1]));
305 return HRP_name[HRP_index - 1];
309 printer_status(int idx)
312 * hrDeviceStatus OBJECT-TYPE
314 * unknown(1), running(2), warning(3), testing(4), down(5)
318 return 1; /* unknown */
322 printer_detail_status(int idx)
325 * hrPrinterStatus OBJECT-TYPE
327 * other(1), unknown(2), idle(3), printing(4), warmup(5)
331 return 2; /* unknown */
335 printer_errors(int idx)
342 * Run the lpstat command. If compiled with EXCACHE support, this
343 * will actually cache the output for a while which helps a lot
344 * with snmpbulkwalk (in fact, it keeps the client from exiting
350 struct extensible ex;
352 memset(&ex, 0, sizeof(ex));
353 strcpy(ex.command, LPSTAT_PATH " -v");
354 if ((*fd = get_exec_output(&ex)) < 0)
357 return fdopen(*fd, "r");