xref: /titanic_50/usr/src/cmd/print/printer-info/printer-info.c (revision 3eae19d9cf3390cf5b75e10c9c1945fd36ad856a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <sys/ioctl.h>
33 #include <sys/prnio.h>
34 #include <fcntl.h>
35 
36 #define	COMMAND_SET_MAX	16	/* more than 16 command sets is not likely */
37 #define	NP(x)	(x ? x : "")
38 
39 typedef struct {
40 	char *manufacturer;
41 	char *model;
42 	char *description;
43 	char *class;
44 	char *command_set[COMMAND_SET_MAX];
45 } printer_description_t;
46 
47 int
48 get_printer_description(char *path, printer_description_t *info)
49 {
50 	int fd, rc;
51 	struct prn_1284_device_id id;
52 	char buf[BUFSIZ];
53 	char *s, *iter = NULL;
54 
55 	/* open the device */
56 	if ((fd = open(path, O_RDWR)) < 0)
57 		return (fd);
58 
59 	/* get the 1284 device id */
60 	memset(&id, 0, sizeof (id));
61 	memset(&buf, 0, sizeof (buf));
62 	id.id_len = sizeof (buf);
63 	id.id_data = buf;
64 
65 	rc = ioctl(fd, PRNIOC_GET_1284_DEVID, &id);
66 	/* close(fd); */
67 	if (rc < 0)
68 		return (rc);
69 
70 	memset(info, 0, sizeof (*info));
71 
72 	/* parse the 1284 device id string */
73 	for (s = (char *)strtok_r(buf, ";\n", &iter); s != NULL;
74 			s = (char *)strtok_r(NULL, ";\n", &iter)) {
75 		char *t, *u, *iter2 = NULL;
76 
77 		if ((t = (char *)strtok_r(s, ":\n", &iter2)) == NULL)
78 			continue;
79 
80 		if ((u = (char *)strtok_r(NULL, ":\n", &iter2)) == NULL)
81 			continue;
82 
83 		if ((strcasecmp(t, "MFG") == 0) ||
84 		    (strcasecmp(t, "MANUFACTURER") == 0))
85 			info->manufacturer = strdup(u);
86 		else if ((strcasecmp(t, "MDL") == 0) ||
87 		    (strcasecmp(t, "MODEL") == 0))
88 			info->model = strdup(u);
89 		else if ((strcasecmp(t, "DES") == 0) ||
90 		    (strcasecmp(t, "DESCRIPTION") == 0))
91 			info->description = strdup(u);
92 		else if ((strcasecmp(t, "CLS") == 0) ||
93 		    (strcasecmp(t, "CLASS") == 0))
94 			info->class = strdup(u);
95 		else if ((strcasecmp(t, "CMD") == 0) ||
96 		    (strcasecmp(t, "COMMAND SET") == 0)) {
97 			/* this should be more dynamic, I got lazy */
98 			char *v, *iter3 = NULL;
99 			int i = 0;
100 
101 			for (v = (char *)strtok_r(u, ",\n", &iter3);
102 				((v != NULL) && (i < COMMAND_SET_MAX));
103 			v = (char *)strtok_r(NULL, ",\n", &iter3))
104 				info->command_set[i++] = strdup(v);
105 		}
106 	}
107 
108 	return (0);
109 }
110 
111 static void
112 usage(char *name)
113 {
114 	char *program;
115 
116 	if ((program = strrchr(name, '/')) == NULL)
117 		program = name;
118 	else
119 		program++;
120 
121 	printf("Usage: %s [-aMmdCc] (path) ...\n", program);
122 }
123 
124 int
125 main(int ac, char *av[])
126 {
127 	int rc;
128 	int manufacturer = 0, model = 0, description = 0, command_set = 0,
129 	    class = 0;
130 
131 	while ((rc = getopt(ac, av, "aMmdCc")) != EOF)
132 		switch (rc) {
133 		case 'a':
134 			manufacturer++;
135 			model++;
136 			description++;
137 			command_set++;
138 			class++;
139 			break;
140 		case 'M':
141 			manufacturer++;
142 			break;
143 		case 'm':
144 			model++;
145 			break;
146 		case 'd':
147 			description++;
148 			break;
149 		case 'C':
150 			command_set++;
151 			break;
152 		case 'c':
153 			class++;
154 			break;
155 		default:
156 			usage(av[0]);
157 			exit(1);
158 		}
159 
160 	if (optind >= ac) {
161 		usage(av[0]);
162 		exit(1);
163 	}
164 
165 	while (optind < ac) {
166 		char *path = av[optind++];
167 		printer_description_t info;
168 
169 		rc = get_printer_description(path, &info);
170 		if (rc == 0) {
171 			printf("%s:\n", path);
172 			if (manufacturer != 0)
173 				printf("\tManufacturer: %s\n",
174 						NP(info.manufacturer));
175 			if (model != 0)
176 				printf("\tModel:        %s\n",
177 						NP(info.model));
178 			if (description != 0)
179 				printf("\tDescription:  %s\n",
180 						NP(info.description));
181 			if (class != 0)
182 				printf("\tClass:        %s\n",
183 						NP(info.class));
184 			if (command_set != 0) {
185 				int i;
186 
187 				printf("\tCommand set:\n");
188 				for (i = 0; info.command_set[i] != NULL; i++)
189 					printf("\t\tcmd[%d]: %s\n", i,
190 						info.command_set[i]);
191 			}
192 		} else
193 			perror(path);
194 	}
195 	return (rc);
196 }
197