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/param.h>
25 #include <sys/types.h>
26 #include <dirent.h>
27 #include <sys/ioctl.h>
28 #include <sys/prnio.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 
33 #include <libhal.h>
34 #include <logger.h>
35 
36 #include "printer.h"
37 
38 static int
prnio_printer_info(char * device_file,char ** manufacturer,char ** model,char ** description,char ** serial_number,char *** command_set)39 prnio_printer_info(char *device_file, char **manufacturer, char **model,
40 		char **description, char **serial_number, char ***command_set)
41 {
42 	struct prn_1284_device_id id;
43 	char buf[BUFSIZ];
44 	int fd = -1, rc = -1;
45 
46 	memset(&id, 0, sizeof (id));
47 	memset(&buf, 0, sizeof (buf));
48 	id.id_data = buf;
49 	id.id_len = sizeof (buf);
50 
51 	if ((fd = open (device_file, O_RDONLY | O_NONBLOCK)) < 0) {
52 		goto prnio_out;
53 	}
54 
55 	if (ioctl(fd, PRNIOC_GET_1284_DEVID, &id) < 0) {
56 		goto prnio_out;
57 	}
58 
59 	HAL_DEBUG(("IEEE-1284 DeviceId = %s", buf));
60 
61 	rc = ieee1284_devid_to_printer_info(buf, manufacturer, model,
62 			description, NULL, serial_number, command_set);
63 
64 prnio_out:
65 	if (fd != -1)
66 		close(fd);
67 
68 	return (rc);
69 }
70 
71 /*
72  * It is assumed that all devices that support prnio(7i), also have a link
73  * in /dev/printers.
74  */
75 static char *
prnio_device_name(void)76 prnio_device_name(void)
77 {
78 	char *result = NULL;
79 	char *devfs_path;
80 	DIR *dp;
81 
82 	if (((devfs_path = getenv("HAL_PROP_SOLARIS_DEVFS_PATH")) != NULL) &&
83 	    ((dp = opendir("/dev/printers")) != NULL)) {
84 		struct dirent *ep;
85 
86 		while ((ep = readdir(dp)) != NULL) {
87 			char path[MAXPATHLEN], lpath[MAXPATHLEN];
88 
89 			snprintf(path, sizeof (path), "/dev/printers/%s",
90 					ep->d_name);
91 			memset(lpath, 0, sizeof (lpath));
92 			if ((readlink(path, lpath, sizeof (lpath)) > 0) &&
93 			    (strstr(lpath, devfs_path) != NULL)) {
94 				result = strdup(path);
95 				break;
96 			}
97 		}
98 		closedir(dp);
99 	}
100 
101 	return (result);
102 }
103 
104 int
main(int argc,char * argv[])105 main(int argc, char *argv[])
106 {
107 	int ret = 1;
108 	char *udi;
109 	char *device_file;
110 	char *manufacturer = NULL,
111 	     *model = NULL,
112 	     *serial_number = NULL,
113 	     *description = NULL,
114 	     **command_set = NULL;
115 	DBusError error;
116 	LibHalContext *ctx = NULL;
117 	LibHalChangeSet *cs = NULL;
118 
119 	if ((udi = getenv("UDI")) == NULL)
120 		goto out;
121 	if ((device_file = getenv("HAL_PROP_PRINTER_DEVICE")) == NULL)
122 		device_file = prnio_device_name();
123 
124 	if (device_file == NULL)
125 		goto out;
126 
127 	setup_logger();
128 
129 	dbus_error_init(&error);
130 	if ((ctx = libhal_ctx_init_direct(&error)) == NULL)
131 		goto out;
132 
133 	if ((cs = libhal_device_new_changeset(udi)) == NULL) {
134 		HAL_DEBUG(("Cannot allocate changeset"));
135 		goto out;
136 	}
137 
138 	/* Probe the printer for characteristics via prnio(7i) */
139 	ret = prnio_printer_info(device_file, &manufacturer, &model,
140 			&description, &serial_number, &command_set);
141 	if (ret < 0) {
142 		HAL_DEBUG(("Cannot get prnio data for %s: %s",
143 				device_file, strerror(errno)));
144 		goto out;
145 	}
146 
147 	/* Add printer characteristics to the HAL device tree */
148 	ret = add_printer_info(cs, udi, manufacturer, model, description,
149 			serial_number, command_set, device_file);
150 	if (ret < 0) {
151 		HAL_DEBUG(("Cannot add printer data for %s to %s: %s",
152 				device_file, udi, strerror(errno)));
153 		goto out;
154 	}
155 
156 	libhal_device_commit_changeset(ctx, cs, &error);
157 
158 	ret = 0;
159 
160 out:
161 	if (cs != NULL) {
162 		libhal_device_free_changeset(cs);
163 	}
164 
165 	if (ctx != NULL) {
166 		if (dbus_error_is_set(&error)) {
167 			dbus_error_free(&error);
168 		}
169 		libhal_ctx_shutdown(ctx, &error);
170 		libhal_ctx_free(ctx);
171 	}
172 
173 	return (ret);
174 }
175