1 /***************************************************************************
2  *
3  * probe-printer.c : Probe for prnio(7i) printer device information
4  *
5  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
6  * Use is subject to license terms.
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  **************************************************************************/
11 
12 #pragma ident	"%Z%%M%	%I%	%E% SMI"
13 
14 #ifdef HAVE_CONFIG_H
15 #  include <config.h>
16 #endif
17 
18 #include <errno.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <sys/ioctl.h>
25 #include <sys/prnio.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <ctype.h>
29 
30 #include <libhal.h>
31 #include <logger.h>
32 
33 #define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
34 
35 static char *
36 strip_ws(char *s)
37 {
38 	if (s != NULL) {
39 		char *p;
40 
41 		/* skip the leading whitespace */
42 		for (; ((*s != NULL) && (isspace(*s) != 0)); s++) ;
43 
44 		/* drop the trailing whitespace */
45 		for (p = s + strlen(s) - 1; ((p > s) && (isspace(*p) != 0));
46 		     p--) ;
47 		*(++p) = '\0';
48 	}
49 
50 	return (s);
51 }
52 
53 static int
54 get_prnio_data(int fd, LibHalChangeSet *cs)
55 {
56 	struct prn_1284_device_id id;
57 	char buf[BUFSIZ];
58 	char *s, *iter = NULL;
59 
60 	memset(&id, 0, sizeof (id));
61 	memset(&buf, 0, sizeof (buf));
62 	id.id_data = buf;
63 	id.id_len = sizeof (buf);
64 
65 	if (ioctl(fd, PRNIOC_GET_1284_DEVID, &id) < 0) {
66 		return (-1);
67 	}
68 
69 	HAL_DEBUG (("IEEE-1284 DeviceId = %s", buf));
70 
71 	for (s = strtok_r(buf, ";\n", &iter); s != NULL;
72 	     s = strtok_r(NULL, ";\n", &iter)) {
73 		char *t, *u, *iter2 = NULL;
74 
75 		if ((t = strtok_r(s, ":\n", &iter2)) == NULL) {
76 			continue;
77 		}
78 
79 		if ((u = strtok_r(NULL, ":\n", &iter2)) == NULL) {
80 			continue;
81 		}
82 
83 		if ((strcasecmp(t, "MFG") == 0) ||
84 		    (strcasecmp(t, "MANUFACTURER") == 0)) {
85 			libhal_changeset_set_property_string (cs,
86 					"printer.vendor", strip_ws(u));
87 		} else if ((strcasecmp(t, "MDL") == 0) ||
88 		    (strcasecmp(t, "MODEL") == 0)) {
89 			libhal_changeset_set_property_string (cs,
90 					"printer.product", strip_ws(u));
91 		} else if ((strcasecmp(t, "SN") == 0) ||
92 		    (strcasecmp(t, "SERN") == 0) ||
93 		    (strcasecmp(t, "SERIALNUMBER") == 0)) {
94 			libhal_changeset_set_property_string (cs,
95 					"printer.serial", strip_ws(u));
96 		} else if ((strcasecmp(t, "DES") == 0) ||
97 		    (strcasecmp(t, "DESCRIPTION") == 0)) {
98 			libhal_changeset_set_property_string (cs,
99 					"printer.description", strip_ws(u));
100 		} else if ((strcasecmp(t, "CMD") == 0) ||
101 		    (strcasecmp(t, "COMMAND SET") == 0) ||
102 		    (strcasecmp(t, "COMMANDSET") == 0)) {
103 			char *v, *iter3 = NULL;
104 			const char *cmds[32];
105 			int i = 0;
106 
107 			memset(&cmds, 0, sizeof (cmds));
108 			for (v = strtok_r(u, ",\n", &iter3);
109 			     ((v != NULL) && (i < NELEM(cmds)));
110 			     v = strtok_r(NULL, ",\n", &iter3)) {
111 				cmds[i++] = strip_ws(v);
112 			}
113 
114 			libhal_changeset_set_property_strlist(cs,
115 					"printer.commandset", cmds);
116 		}
117 	}
118 
119 	return (0);
120 }
121 
122 int
123 main (int argc, char *argv[])
124 {
125 	int ret = 1;
126 	int fd = -1;
127 	char *udi;
128 	char *device_file;
129 	DBusError error;
130 	LibHalContext *ctx = NULL;
131 	LibHalChangeSet *cs = NULL;
132 
133 	if ((udi = getenv ("UDI")) == NULL)
134 		goto out;
135 	if ((device_file = getenv ("HAL_PROP_PRINTER_DEVICE")) == NULL)
136 		goto out;
137 
138 	setup_logger ();
139 
140 	dbus_error_init (&error);
141 	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
142 		goto out;
143 
144 	if ((cs = libhal_device_new_changeset (udi)) == NULL) {
145 		HAL_DEBUG (("Cannot allocate changeset"));
146 		goto out;
147 	}
148 
149 	HAL_DEBUG (("Doing probe-printer for %s (udi=%s)",
150 	     device_file, udi));
151 
152 	if ((fd = open (device_file, O_RDONLY | O_NONBLOCK)) < 0) {
153 		HAL_DEBUG (("Cannot open %s: %s", device_file, strerror (errno)));
154 		goto out;
155 	}
156 
157 	if (get_prnio_data(fd, cs) < 0) {
158 		HAL_DEBUG (("Cannot get prnio data %s: %s", device_file, strerror (errno)));
159 		goto out;
160 	}
161 
162 	libhal_device_commit_changeset (ctx, cs, &error);
163 
164 	ret = 0;
165 
166 out:
167 	if (cs != NULL) {
168 		libhal_device_free_changeset (cs);
169 	}
170 
171 	if (fd >= 0) {
172 		close (fd);
173 	}
174 
175 	if (ctx != NULL) {
176 		if (dbus_error_is_set(&error)) {
177 			dbus_error_free (&error);
178 		}
179 		libhal_ctx_shutdown (ctx, &error);
180 		libhal_ctx_free (ctx);
181 	}
182 
183 	return ret;
184 }
185