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 }