and added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / host / hr_print.c
1 /*
2  *  Host Resources MIB - printer device group implementation - hr_print.c
3  *
4  */
5
6 #include <net-snmp/net-snmp-config.h>
7 #if HAVE_STRING_H
8 #include <string.h>
9 #else
10 #include <strings.h>
11 #endif
12 #if HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15 #include "host_res.h"
16 #include "hr_print.h"
17 #include "struct.h"
18 #include "util_funcs.h"
19
20 #define HRPRINT_MONOTONICALLY_INCREASING
21
22         /*********************
23          *
24          *  Kernel & interface information,
25          *   and internal forward declarations
26          *
27          *********************/
28
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 *);
39
40
41         /*********************
42          *
43          *  Initialisation & common implementation functions
44          *
45          *********************/
46
47 #define HRPRINT_STATUS          1
48 #define HRPRINT_ERROR           2
49
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}}
53 };
54 oid             hrprint_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 5 };
55
56
57 void
58 init_hr_print(void)
59 {
60     init_device[HRDEV_PRINTER] = Init_HR_Print;
61     next_device[HRDEV_PRINTER] = Get_Next_HR_Print;
62     /*
63      * save_device[ HRDEV_PRINTER ] = Save_HR_Print;        
64      */
65 #ifdef HRPRINT_MONOTONICALLY_INCREASING
66     dev_idx_inc[HRDEV_PRINTER] = 1;
67 #endif
68
69     device_descr[HRDEV_PRINTER] = describe_printer;
70     device_status[HRDEV_PRINTER] = printer_status;
71     device_errors[HRDEV_PRINTER] = printer_errors;
72
73     REGISTER_MIB("host/hr_print", hrprint_variables, variable4,
74                  hrprint_variables_oid);
75 }
76
77 /*
78  * header_hrprint(...
79  * Arguments:
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
85  * write_method
86  * 
87  */
88 int
89 header_hrprint(struct variable *vp,
90                oid * name,
91                size_t * length,
92                int exact, size_t * var_len, WriteMethod ** write_method)
93 {
94 #define HRPRINT_ENTRY_NAME_LENGTH       11
95     oid             newname[MAX_OID_LEN];
96     int             print_idx, LowIndex = -1;
97     int             result;
98
99     DEBUGMSGTL(("host/hr_print", "var_hrprint: "));
100     DEBUGMSGOID(("host/hr_print", name, *length));
101     DEBUGMSG(("host/hr_print", " %d\n", exact));
102
103     memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
104     /*
105      * Find "next" print entry 
106      */
107
108     Init_HR_Print();
109     for (;;) {
110         print_idx = Get_Next_HR_Print();
111         if (print_idx == -1)
112             break;
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;
117             /*
118              * Save printer status information 
119              */
120             break;
121         }
122         if ((!exact && (result < 0)) &&
123             (LowIndex == -1 || print_idx < LowIndex)) {
124             LowIndex = print_idx;
125             /*
126              * Save printer status information 
127              */
128 #ifdef HRPRINT_MONOTONICALLY_INCREASING
129             break;
130 #endif
131         }
132     }
133
134     if (LowIndex == -1) {
135         DEBUGMSGTL(("host/hr_print", "... index out of range\n"));
136         return (MATCH_FAILED);
137     }
138
139     memcpy((char *) name, (char *) newname,
140            (vp->namelen + 1) * sizeof(oid));
141     *length = vp->namelen + 1;
142     *write_method = 0;
143     *var_len = sizeof(long);    /* default to 'long' results */
144
145     DEBUGMSGTL(("host/hr_print", "... get print stats "));
146     DEBUGMSGOID(("host/hr_print", name, *length));
147     DEBUGMSG(("host/hr_print", "\n"));
148     return LowIndex;
149 }
150
151
152         /*********************
153          *
154          *  System specific implementation functions
155          *
156          *********************/
157
158
159 u_char         *
160 var_hrprint(struct variable * vp,
161             oid * name,
162             size_t * length,
163             int exact, size_t * var_len, WriteMethod ** write_method)
164 {
165     int             print_idx;
166
167     print_idx =
168         header_hrprint(vp, name, length, exact, var_len, write_method);
169     if (print_idx == MATCH_FAILED)
170         return NULL;
171
172
173     switch (vp->magic) {
174     case HRPRINT_STATUS:
175         long_return = printer_detail_status(print_idx);
176         return (u_char *) & long_return;
177     case HRPRINT_ERROR:
178 #if NO_DUMMY_VALUES
179         return NULL;
180 #endif
181         long_return = 0;        /* Null string */
182         return (u_char *) & long_return;
183     default:
184         DEBUGMSGTL(("host/hr_print", "unknown sub-id %d in var_hrprint\n",
185                     vp->magic));
186     }
187     return NULL;
188 }
189
190
191         /*********************
192          *
193          *  Internal implementation functions
194          *
195          *********************/
196
197 static int      HRP_index;
198 static char   **HRP_name;
199 static int      HRP_names, HRP_maxnames;
200
201 void
202 Init_HR_Print(void)
203 {
204 #if HAVE_LPSTAT || HAVE_CGETNEXT || HAVE_PRINTCAP
205     int             i, fd;
206 #if HAVE_LPSTAT
207     FILE           *p;
208 #elif HAVE_CGETNEXT
209     const char     *caps[] = { "/etc/printcap", NULL };
210 #elif HAVE_PRINTCAP
211     FILE           *p;
212 #endif
213
214     if (HRP_name) {
215         for (i = 0; i < HRP_names; i++)
216             free(HRP_name[i]);
217         HRP_names = 0;
218     } else {
219         HRP_maxnames = 5;
220         HRP_name = (char **) calloc(HRP_maxnames, sizeof(char *));
221         if (!HRP_name)
222             return;
223     }
224
225 #if HAVE_LPSTAT
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);
230 #elif HAVE_CGETNEXT
231     {
232         char           *buf = NULL, *ptr;
233         while (cgetnext(&buf, caps)) {
234             if ((ptr = strchr(buf, ':')))
235                 *ptr = 0;
236             if ((ptr = strchr(buf, '|')))
237                 *ptr = 0;
238             ptr = buf;
239 #elif HAVE_PRINTCAP
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] == ' '
245                 || buf[0] == '\t')
246                 continue;
247             if ((ptr = strchr(buf, '\\')))
248                 *ptr = 0;
249             if ((ptr = strchr(buf, ':')))
250                 *ptr = 0;
251             if ((ptr = strchr(buf, '|')))
252                 *ptr = 0;
253             ptr = buf;
254 #endif
255             if (HRP_names == HRP_maxnames) {
256                 char          **tmp;
257                 HRP_maxnames += 5;
258                 tmp = (char **) calloc(HRP_maxnames, sizeof(char *));
259                 if (!tmp)
260                     goto finish;
261                 memcpy(tmp, HRP_name, HRP_names * sizeof(char *));
262                 HRP_name = tmp;
263             }
264             HRP_name[HRP_names++] = strdup(ptr);
265 #if HAVE_CGETNEXT
266             if (buf)
267                 free(buf);
268 #endif
269         }
270 finish:
271 #if HAVE_LPSTAT
272         fclose(p);
273         close(fd);
274 #elif HAVE_CGETNEXT
275         cgetclose();
276 #elif HAVE_PRINTCAP
277         fclose(p);
278 #endif
279     }
280 #endif                          /* HAVE_anything */
281
282     HRP_index = 0;
283 }
284
285 int
286 Get_Next_HR_Print(void)
287 {
288     /*
289      * The initial implementation system
290      *   has no printers attached, and I've
291      *   no real idea how to detect them,
292      *   so don't bother.
293      */
294     if (HRP_index < HRP_names)  /* No printer */
295         return (HRDEV_PRINTER << HRDEV_TYPE_SHIFT) + HRP_index++;
296     else
297         return -1;
298 }
299
300 const char     *
301 describe_printer(int idx)
302 {
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];
306 }
307
308 int
309 printer_status(int idx)
310 {
311     /*
312      * hrDeviceStatus OBJECT-TYPE
313      * SYNTAX     INTEGER {
314      * unknown(1), running(2), warning(3), testing(4), down(5)
315      * }
316      */
317
318     return 1;                   /* unknown */
319 }
320
321 int
322 printer_detail_status(int idx)
323 {
324     /*
325      * hrPrinterStatus OBJECT-TYPE
326      * SYNTAX     INTEGER {
327      * other(1), unknown(2), idle(3), printing(4), warmup(5)
328      * }
329      */
330
331     return 2;                   /* unknown */
332 }
333
334 int
335 printer_errors(int idx)
336 {
337     return 0;
338 }
339
340 #ifdef        HAVE_LPSTAT
341 /*
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
345  * due to timeouts).
346  */
347 FILE           *
348 run_lpstat(int *fd)
349 {
350     struct extensible ex;
351
352     memset(&ex, 0, sizeof(ex));
353     strcpy(ex.command, LPSTAT_PATH " -v");
354     if ((*fd = get_exec_output(&ex)) < 0)
355         return NULL;
356
357     return fdopen(*fd, "r");
358 }
359 #endif