1d76947f3SHartmut Brandt /*-
2d76947f3SHartmut Brandt * Copyright (c) 2005-2006 The FreeBSD Project
3d76947f3SHartmut Brandt * All rights reserved.
4d76947f3SHartmut Brandt *
5d76947f3SHartmut Brandt * Author: Victor Cruceru <soc-victor@freebsd.org>
6d76947f3SHartmut Brandt *
7d76947f3SHartmut Brandt * Redistribution of this software and documentation and use in source and
8d76947f3SHartmut Brandt * binary forms, with or without modification, are permitted provided that
9d76947f3SHartmut Brandt * the following conditions are met:
10d76947f3SHartmut Brandt *
11d76947f3SHartmut Brandt * 1. Redistributions of source code or documentation must retain the above
12d76947f3SHartmut Brandt * copyright notice, this list of conditions and the following disclaimer.
13d76947f3SHartmut Brandt * 2. Redistributions in binary form must reproduce the above copyright
14d76947f3SHartmut Brandt * notice, this list of conditions and the following disclaimer in the
15d76947f3SHartmut Brandt * documentation and/or other materials provided with the distribution.
16d76947f3SHartmut Brandt *
17d76947f3SHartmut Brandt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18d76947f3SHartmut Brandt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19d76947f3SHartmut Brandt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20d76947f3SHartmut Brandt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21d76947f3SHartmut Brandt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22d76947f3SHartmut Brandt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23d76947f3SHartmut Brandt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24d76947f3SHartmut Brandt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25d76947f3SHartmut Brandt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26d76947f3SHartmut Brandt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27d76947f3SHartmut Brandt * SUCH DAMAGE.
28d76947f3SHartmut Brandt */
29d76947f3SHartmut Brandt
30d76947f3SHartmut Brandt /*
31d76947f3SHartmut Brandt * Host Resources MIB implementation for SNMPd: instrumentation for
32d76947f3SHartmut Brandt * hrPrinterTable
33d76947f3SHartmut Brandt */
34d76947f3SHartmut Brandt
35d76947f3SHartmut Brandt #include <sys/param.h>
36d76947f3SHartmut Brandt #include <sys/stat.h>
37d76947f3SHartmut Brandt
38d76947f3SHartmut Brandt #include <assert.h>
39d76947f3SHartmut Brandt #include <err.h>
40d76947f3SHartmut Brandt #include <errno.h>
41d76947f3SHartmut Brandt #include <paths.h>
42d76947f3SHartmut Brandt #include <stdlib.h>
43d76947f3SHartmut Brandt #include <string.h>
44d76947f3SHartmut Brandt #include <syslog.h>
45d76947f3SHartmut Brandt #include <unistd.h>
46d76947f3SHartmut Brandt
47d76947f3SHartmut Brandt #include "hostres_snmp.h"
48d76947f3SHartmut Brandt #include "hostres_oid.h"
49d76947f3SHartmut Brandt #include "hostres_tree.h"
50d76947f3SHartmut Brandt
51d76947f3SHartmut Brandt #include <sys/dirent.h>
52d76947f3SHartmut Brandt #include "lp.h"
53d76947f3SHartmut Brandt
54d76947f3SHartmut Brandt /* Constants */
55d76947f3SHartmut Brandt static const struct asn_oid OIDX_hrDevicePrinter_c = OIDX_hrDevicePrinter;
56d76947f3SHartmut Brandt
57d76947f3SHartmut Brandt enum PrinterStatus {
58d76947f3SHartmut Brandt PS_OTHER = 1,
59d76947f3SHartmut Brandt PS_UNKNOWN = 2,
60d76947f3SHartmut Brandt PS_IDLE = 3,
61d76947f3SHartmut Brandt PS_PRINTING = 4,
62d76947f3SHartmut Brandt PS_WARMUP = 5
63d76947f3SHartmut Brandt };
64d76947f3SHartmut Brandt
65d76947f3SHartmut Brandt /*
66d76947f3SHartmut Brandt * This structure is used to hold a SNMP table entry
67d76947f3SHartmut Brandt * for HOST-RESOURCES-MIB's hrPrinterTable.
68d76947f3SHartmut Brandt */
69d76947f3SHartmut Brandt struct printer_entry {
70d76947f3SHartmut Brandt int32_t index;
71d76947f3SHartmut Brandt int32_t status; /* values from PrinterStatus enum above */
72d76947f3SHartmut Brandt u_char detectedErrorState[2];
73d76947f3SHartmut Brandt TAILQ_ENTRY(printer_entry) link;
74d76947f3SHartmut Brandt #define HR_PRINTER_FOUND 0x001
75d76947f3SHartmut Brandt uint32_t flags;
76d76947f3SHartmut Brandt
77d76947f3SHartmut Brandt };
78d76947f3SHartmut Brandt TAILQ_HEAD(printer_tbl, printer_entry);
79d76947f3SHartmut Brandt
80d76947f3SHartmut Brandt /* the hrPrinterTable */
81d76947f3SHartmut Brandt static struct printer_tbl printer_tbl = TAILQ_HEAD_INITIALIZER(printer_tbl);
82d76947f3SHartmut Brandt
83d76947f3SHartmut Brandt /* last (agent) tick when hrPrinterTable was updated */
84d76947f3SHartmut Brandt static uint64_t printer_tick;
85d76947f3SHartmut Brandt
86d76947f3SHartmut Brandt /**
87d76947f3SHartmut Brandt * Create entry into the printer table.
88d76947f3SHartmut Brandt */
89d76947f3SHartmut Brandt static struct printer_entry *
printer_entry_create(const struct device_entry * devEntry)90d76947f3SHartmut Brandt printer_entry_create(const struct device_entry *devEntry)
91d76947f3SHartmut Brandt {
92d76947f3SHartmut Brandt struct printer_entry *entry = NULL;
93d76947f3SHartmut Brandt
94d76947f3SHartmut Brandt assert(devEntry != NULL);
95d76947f3SHartmut Brandt if (devEntry == NULL)
96d76947f3SHartmut Brandt return (NULL);
97d76947f3SHartmut Brandt
98d76947f3SHartmut Brandt if ((entry = malloc(sizeof(*entry))) == NULL) {
99d76947f3SHartmut Brandt syslog(LOG_WARNING, "hrPrinterTable: %s: %m", __func__);
100d76947f3SHartmut Brandt return (NULL);
101d76947f3SHartmut Brandt }
102d76947f3SHartmut Brandt memset(entry, 0, sizeof(*entry));
103d76947f3SHartmut Brandt entry->index = devEntry->index;
104d76947f3SHartmut Brandt INSERT_OBJECT_INT(entry, &printer_tbl);
105d76947f3SHartmut Brandt return (entry);
106d76947f3SHartmut Brandt }
107d76947f3SHartmut Brandt
108d76947f3SHartmut Brandt /**
109d76947f3SHartmut Brandt * Delete entry from the printer table.
110d76947f3SHartmut Brandt */
111d76947f3SHartmut Brandt static void
printer_entry_delete(struct printer_entry * entry)112d76947f3SHartmut Brandt printer_entry_delete(struct printer_entry *entry)
113d76947f3SHartmut Brandt {
114d76947f3SHartmut Brandt
115d76947f3SHartmut Brandt assert(entry != NULL);
116d76947f3SHartmut Brandt if (entry == NULL)
117d76947f3SHartmut Brandt return;
118d76947f3SHartmut Brandt
119d76947f3SHartmut Brandt TAILQ_REMOVE(&printer_tbl, entry, link);
120d76947f3SHartmut Brandt free(entry);
121d76947f3SHartmut Brandt }
122d76947f3SHartmut Brandt
123d76947f3SHartmut Brandt /**
124d76947f3SHartmut Brandt * Find a printer by its index
125d76947f3SHartmut Brandt */
126d76947f3SHartmut Brandt static struct printer_entry *
printer_find_by_index(int32_t idx)127d76947f3SHartmut Brandt printer_find_by_index(int32_t idx)
128d76947f3SHartmut Brandt {
129d76947f3SHartmut Brandt struct printer_entry *entry;
130d76947f3SHartmut Brandt
131d76947f3SHartmut Brandt TAILQ_FOREACH(entry, &printer_tbl, link)
132d76947f3SHartmut Brandt if (entry->index == idx)
133d76947f3SHartmut Brandt return (entry);
134d76947f3SHartmut Brandt
135d76947f3SHartmut Brandt return (NULL);
136d76947f3SHartmut Brandt }
137d76947f3SHartmut Brandt
138d76947f3SHartmut Brandt /**
139d76947f3SHartmut Brandt * Get the status of a printer
140d76947f3SHartmut Brandt */
141d76947f3SHartmut Brandt static enum PrinterStatus
get_printer_status(const struct printer * pp)142d76947f3SHartmut Brandt get_printer_status(const struct printer *pp)
143d76947f3SHartmut Brandt {
144d76947f3SHartmut Brandt char statfile[MAXPATHLEN];
145d76947f3SHartmut Brandt char lockfile[MAXPATHLEN];
146d76947f3SHartmut Brandt char fline[128];
147d76947f3SHartmut Brandt int fd;
148d76947f3SHartmut Brandt FILE *f = NULL;
149d76947f3SHartmut Brandt enum PrinterStatus ps = PS_UNKNOWN;
150d76947f3SHartmut Brandt
151d76947f3SHartmut Brandt if (pp->lock_file[0] == '/')
152d76947f3SHartmut Brandt strlcpy(lockfile, pp->lock_file, sizeof(lockfile));
153d76947f3SHartmut Brandt else
154d76947f3SHartmut Brandt snprintf(lockfile, sizeof(lockfile), "%s/%s",
155d76947f3SHartmut Brandt pp->spool_dir, pp->lock_file);
156d76947f3SHartmut Brandt
157d76947f3SHartmut Brandt fd = open(lockfile, O_RDONLY);
158d76947f3SHartmut Brandt if (fd < 0 || flock(fd, LOCK_SH | LOCK_NB) == 0) {
159d76947f3SHartmut Brandt ps = PS_IDLE;
160d76947f3SHartmut Brandt goto LABEL_DONE;
161d76947f3SHartmut Brandt }
162d76947f3SHartmut Brandt
163d76947f3SHartmut Brandt if (pp->status_file[0] == '/')
164d76947f3SHartmut Brandt strlcpy(statfile, pp->status_file, sizeof(statfile));
165d76947f3SHartmut Brandt else
166d76947f3SHartmut Brandt snprintf(statfile, sizeof(statfile), "%s/%s",
167d76947f3SHartmut Brandt pp->spool_dir, pp->status_file);
168d76947f3SHartmut Brandt
169d76947f3SHartmut Brandt f = fopen(statfile, "r");
170d76947f3SHartmut Brandt if (f == NULL) {
171d76947f3SHartmut Brandt syslog(LOG_ERR, "cannot open status file: %s", strerror(errno));
172d76947f3SHartmut Brandt ps = PS_UNKNOWN;
173d76947f3SHartmut Brandt goto LABEL_DONE;
174d76947f3SHartmut Brandt }
175d76947f3SHartmut Brandt
176d37cb73cSPedro F. Giffuni memset(&fline[0], '\0', sizeof(fline));
177d76947f3SHartmut Brandt if (fgets(fline, sizeof(fline) -1, f) == NULL) {
178d76947f3SHartmut Brandt ps = PS_UNKNOWN;
179d76947f3SHartmut Brandt goto LABEL_DONE;
180d76947f3SHartmut Brandt }
181d76947f3SHartmut Brandt
182d76947f3SHartmut Brandt if (strstr(fline, "is ready and printing") != NULL) {
183d76947f3SHartmut Brandt ps = PS_PRINTING;
184d76947f3SHartmut Brandt goto LABEL_DONE;
185d76947f3SHartmut Brandt }
186d76947f3SHartmut Brandt
187d76947f3SHartmut Brandt if (strstr(fline, "to become ready (offline?)") != NULL) {
188d76947f3SHartmut Brandt ps = PS_OTHER;
189d76947f3SHartmut Brandt goto LABEL_DONE;
190d76947f3SHartmut Brandt }
191d76947f3SHartmut Brandt
192d76947f3SHartmut Brandt LABEL_DONE:
193d76947f3SHartmut Brandt if (fd >= 0)
194d76947f3SHartmut Brandt (void)close(fd); /* unlocks as well */
195d76947f3SHartmut Brandt
196d76947f3SHartmut Brandt if (f != NULL)
197d76947f3SHartmut Brandt (void)fclose(f);
198d76947f3SHartmut Brandt
199d76947f3SHartmut Brandt return (ps);
200d76947f3SHartmut Brandt }
201d76947f3SHartmut Brandt
202d76947f3SHartmut Brandt /**
203d76947f3SHartmut Brandt * Called for each printer found in /etc/printcap.
204d76947f3SHartmut Brandt */
205d76947f3SHartmut Brandt static void
handle_printer(struct printer * pp)206d76947f3SHartmut Brandt handle_printer(struct printer *pp)
207d76947f3SHartmut Brandt {
208d76947f3SHartmut Brandt struct device_entry *dev_entry;
209d76947f3SHartmut Brandt struct printer_entry *printer_entry;
210d76947f3SHartmut Brandt char dev_only[128];
211d76947f3SHartmut Brandt struct stat sb;
212d76947f3SHartmut Brandt
213d76947f3SHartmut Brandt if (pp->remote_host != NULL) {
214d76947f3SHartmut Brandt HRDBG("skipped %s -- remote", pp->printer);
215d76947f3SHartmut Brandt return;
216d76947f3SHartmut Brandt }
217d76947f3SHartmut Brandt
218d76947f3SHartmut Brandt if (strncmp(pp->lp, _PATH_DEV, strlen(_PATH_DEV)) != 0) {
219d76947f3SHartmut Brandt HRDBG("skipped %s [device %s] -- remote", pp->printer, pp->lp);
220d76947f3SHartmut Brandt return;
221d76947f3SHartmut Brandt }
222d76947f3SHartmut Brandt
223d76947f3SHartmut Brandt memset(dev_only, '\0', sizeof(dev_only));
224d76947f3SHartmut Brandt snprintf(dev_only, sizeof(dev_only), "%s", pp->lp + strlen(_PATH_DEV));
225d76947f3SHartmut Brandt
226d76947f3SHartmut Brandt HRDBG("printer %s has device %s", pp->printer, dev_only);
227d76947f3SHartmut Brandt
228d76947f3SHartmut Brandt if (stat(pp->lp, &sb) < 0) {
229d76947f3SHartmut Brandt if (errno == ENOENT) {
230d76947f3SHartmut Brandt HRDBG("skipped %s -- device %s missing",
231d76947f3SHartmut Brandt pp->printer, pp->lp);
232d76947f3SHartmut Brandt return;
233d76947f3SHartmut Brandt }
234d76947f3SHartmut Brandt }
235d76947f3SHartmut Brandt
236d76947f3SHartmut Brandt if ((dev_entry = device_find_by_name(dev_only)) == NULL) {
237d76947f3SHartmut Brandt HRDBG("%s not in hrDeviceTable", pp->lp);
238d76947f3SHartmut Brandt return;
239d76947f3SHartmut Brandt }
240d76947f3SHartmut Brandt HRDBG("%s found in hrDeviceTable", pp->lp);
241e55adffcSHartmut Brandt dev_entry->type = &OIDX_hrDevicePrinter_c;
242d76947f3SHartmut Brandt
243d76947f3SHartmut Brandt dev_entry->flags |= HR_DEVICE_IMMUTABLE;
244d76947f3SHartmut Brandt
245d76947f3SHartmut Brandt /* Then check hrPrinterTable for this device */
246d76947f3SHartmut Brandt if ((printer_entry = printer_find_by_index(dev_entry->index)) == NULL &&
247d76947f3SHartmut Brandt (printer_entry = printer_entry_create(dev_entry)) == NULL)
248d76947f3SHartmut Brandt return;
249d76947f3SHartmut Brandt
250d76947f3SHartmut Brandt printer_entry->flags |= HR_PRINTER_FOUND;
251d76947f3SHartmut Brandt printer_entry->status = get_printer_status(pp);
252d76947f3SHartmut Brandt memset(printer_entry->detectedErrorState, 0,
253d76947f3SHartmut Brandt sizeof(printer_entry->detectedErrorState));
254d76947f3SHartmut Brandt }
255d76947f3SHartmut Brandt
256d76947f3SHartmut Brandt static void
hrPrinter_get_OS_entries(void)257d76947f3SHartmut Brandt hrPrinter_get_OS_entries(void)
258d76947f3SHartmut Brandt {
259d76947f3SHartmut Brandt int status, more;
260d76947f3SHartmut Brandt struct printer myprinter, *pp = &myprinter;
261d76947f3SHartmut Brandt
262d76947f3SHartmut Brandt init_printer(pp);
263d76947f3SHartmut Brandt HRDBG("---->Getting printers .....");
264d76947f3SHartmut Brandt more = firstprinter(pp, &status);
265d76947f3SHartmut Brandt if (status)
266d76947f3SHartmut Brandt goto errloop;
267d76947f3SHartmut Brandt
268d76947f3SHartmut Brandt while (more) {
269d76947f3SHartmut Brandt do {
270d76947f3SHartmut Brandt HRDBG("---->Got printer %s", pp->printer);
271d76947f3SHartmut Brandt
272d76947f3SHartmut Brandt handle_printer(pp);
273d76947f3SHartmut Brandt more = nextprinter(pp, &status);
274d76947f3SHartmut Brandt errloop:
275d76947f3SHartmut Brandt if (status)
276d76947f3SHartmut Brandt syslog(LOG_WARNING,
277d76947f3SHartmut Brandt "hrPrinterTable: printcap entry for %s "
278d76947f3SHartmut Brandt "has errors, skipping",
279d76947f3SHartmut Brandt pp->printer ? pp->printer : "<noname?>");
280d76947f3SHartmut Brandt } while (more && status);
281d76947f3SHartmut Brandt }
282d76947f3SHartmut Brandt
283d76947f3SHartmut Brandt lastprinter();
284d76947f3SHartmut Brandt printer_tick = this_tick;
285d76947f3SHartmut Brandt }
286d76947f3SHartmut Brandt
287d76947f3SHartmut Brandt /**
288d76947f3SHartmut Brandt * Init the things for hrPrinterTable
289d76947f3SHartmut Brandt */
290d76947f3SHartmut Brandt void
init_printer_tbl(void)291d76947f3SHartmut Brandt init_printer_tbl(void)
292d76947f3SHartmut Brandt {
293d76947f3SHartmut Brandt
294d76947f3SHartmut Brandt hrPrinter_get_OS_entries();
295d76947f3SHartmut Brandt }
296d76947f3SHartmut Brandt
297d76947f3SHartmut Brandt /**
298d76947f3SHartmut Brandt * Finalization routine for hrPrinterTable
299d76947f3SHartmut Brandt * It destroys the lists and frees any allocated heap memory
300d76947f3SHartmut Brandt */
301d76947f3SHartmut Brandt void
fini_printer_tbl(void)302d76947f3SHartmut Brandt fini_printer_tbl(void)
303d76947f3SHartmut Brandt {
304d76947f3SHartmut Brandt struct printer_entry *n1;
305d76947f3SHartmut Brandt
306d76947f3SHartmut Brandt while ((n1 = TAILQ_FIRST(&printer_tbl)) != NULL) {
307d76947f3SHartmut Brandt TAILQ_REMOVE(&printer_tbl, n1, link);
308d76947f3SHartmut Brandt free(n1);
309d76947f3SHartmut Brandt }
310d76947f3SHartmut Brandt }
311d76947f3SHartmut Brandt
312d76947f3SHartmut Brandt /**
313d76947f3SHartmut Brandt * Refresh the printer table if needed.
314d76947f3SHartmut Brandt */
315d76947f3SHartmut Brandt void
refresh_printer_tbl(void)316d76947f3SHartmut Brandt refresh_printer_tbl(void)
317d76947f3SHartmut Brandt {
318d76947f3SHartmut Brandt struct printer_entry *entry;
319d76947f3SHartmut Brandt struct printer_entry *entry_tmp;
320d76947f3SHartmut Brandt
321d76947f3SHartmut Brandt if (this_tick <= printer_tick) {
322d76947f3SHartmut Brandt HRDBG("no refresh needed");
323d76947f3SHartmut Brandt return;
324d76947f3SHartmut Brandt }
325d76947f3SHartmut Brandt
326d76947f3SHartmut Brandt /* mark each entry as missing */
327d76947f3SHartmut Brandt TAILQ_FOREACH(entry, &printer_tbl, link)
328d76947f3SHartmut Brandt entry->flags &= ~HR_PRINTER_FOUND;
329d76947f3SHartmut Brandt
330d76947f3SHartmut Brandt hrPrinter_get_OS_entries();
331d76947f3SHartmut Brandt
332d76947f3SHartmut Brandt /*
333d76947f3SHartmut Brandt * Purge items that disappeared
334d76947f3SHartmut Brandt */
335d76947f3SHartmut Brandt entry = TAILQ_FIRST(&printer_tbl);
336d76947f3SHartmut Brandt while (entry != NULL) {
337d76947f3SHartmut Brandt entry_tmp = TAILQ_NEXT(entry, link);
338d76947f3SHartmut Brandt if (!(entry->flags & HR_PRINTER_FOUND))
339d76947f3SHartmut Brandt printer_entry_delete(entry);
340d76947f3SHartmut Brandt entry = entry_tmp;
341d76947f3SHartmut Brandt }
342d76947f3SHartmut Brandt
343d76947f3SHartmut Brandt printer_tick = this_tick;
344d76947f3SHartmut Brandt
345d76947f3SHartmut Brandt HRDBG("refresh DONE ");
346d76947f3SHartmut Brandt }
347d76947f3SHartmut Brandt
348d76947f3SHartmut Brandt int
op_hrPrinterTable(struct snmp_context * ctx __unused,struct snmp_value * value,u_int sub,u_int iidx __unused,enum snmp_op curr_op)349d76947f3SHartmut Brandt op_hrPrinterTable(struct snmp_context *ctx __unused, struct snmp_value *value,
350d76947f3SHartmut Brandt u_int sub, u_int iidx __unused, enum snmp_op curr_op)
351d76947f3SHartmut Brandt {
352d76947f3SHartmut Brandt struct printer_entry *entry;
353d76947f3SHartmut Brandt
354d76947f3SHartmut Brandt refresh_printer_tbl();
355d76947f3SHartmut Brandt
356d76947f3SHartmut Brandt switch (curr_op) {
357d76947f3SHartmut Brandt
358d76947f3SHartmut Brandt case SNMP_OP_GETNEXT:
359d76947f3SHartmut Brandt if ((entry = NEXT_OBJECT_INT(&printer_tbl, &value->var,
360d76947f3SHartmut Brandt sub)) == NULL)
361d76947f3SHartmut Brandt return (SNMP_ERR_NOSUCHNAME);
362d76947f3SHartmut Brandt value->var.len = sub + 1;
363d76947f3SHartmut Brandt value->var.subs[sub] = entry->index;
364d76947f3SHartmut Brandt goto get;
365d76947f3SHartmut Brandt
366d76947f3SHartmut Brandt case SNMP_OP_GET:
367d76947f3SHartmut Brandt if ((entry = FIND_OBJECT_INT(&printer_tbl, &value->var,
368d76947f3SHartmut Brandt sub)) == NULL)
369d76947f3SHartmut Brandt return (SNMP_ERR_NOSUCHNAME);
370d76947f3SHartmut Brandt goto get;
371d76947f3SHartmut Brandt
372d76947f3SHartmut Brandt case SNMP_OP_SET:
373d76947f3SHartmut Brandt if ((entry = FIND_OBJECT_INT(&printer_tbl, &value->var,
374d76947f3SHartmut Brandt sub)) == NULL)
375d76947f3SHartmut Brandt return (SNMP_ERR_NO_CREATION);
376d76947f3SHartmut Brandt return (SNMP_ERR_NOT_WRITEABLE);
377d76947f3SHartmut Brandt
378d76947f3SHartmut Brandt case SNMP_OP_ROLLBACK:
379d76947f3SHartmut Brandt case SNMP_OP_COMMIT:
380d76947f3SHartmut Brandt abort();
381d76947f3SHartmut Brandt }
382d76947f3SHartmut Brandt abort();
383d76947f3SHartmut Brandt
384d76947f3SHartmut Brandt get:
385d76947f3SHartmut Brandt switch (value->var.subs[sub - 1]) {
386d76947f3SHartmut Brandt
387d76947f3SHartmut Brandt case LEAF_hrPrinterStatus:
388d76947f3SHartmut Brandt value->v.integer = entry->status;
389d76947f3SHartmut Brandt return (SNMP_ERR_NOERROR);
390d76947f3SHartmut Brandt
391d76947f3SHartmut Brandt case LEAF_hrPrinterDetectedErrorState:
392d76947f3SHartmut Brandt return (string_get(value, entry->detectedErrorState,
393d76947f3SHartmut Brandt sizeof(entry->detectedErrorState)));
394d76947f3SHartmut Brandt }
395d76947f3SHartmut Brandt abort();
396d76947f3SHartmut Brandt }
397