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 2003 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 /*LINTLIBRARY*/ 30 31 #include <stdio.h> 32 #include <stdarg.h> 33 #include <libintl.h> 34 #include <string.h> 35 #include <stdlib.h> 36 37 38 /* lpsched include files */ 39 #include "lp.h" 40 #include "msgs.h" 41 #include "printers.h" 42 43 #include <papi_impl.h> 44 45 46 /* 47 * Format and send message to lpsched (die if any errors occur) 48 */ 49 /*VARARGS1*/ 50 int 51 snd_msg(service_t *svc, int type, ...) 52 { 53 int rc = -1; 54 va_list ap; 55 56 if (svc == NULL) 57 return (-1); 58 59 /* fill the message buffer */ 60 va_start(ap, type); 61 rc = _putmessage(svc->msgbuf, type, ap); 62 va_end(ap); 63 if (rc < 0) { 64 detailed_error(svc, 65 gettext("unable to build message for scheduler: %s"), 66 strerror(errno)); 67 return (rc); 68 } 69 70 /* write the message */ 71 while (((rc = mwrite(svc->md, svc->msgbuf)) < 0) && (errno == EINTR)); 72 73 if (rc < 0) 74 detailed_error(svc, 75 gettext("unable to send message to scheduler: %s"), 76 strerror(errno)); 77 return (rc); 78 } 79 80 /* 81 * Receive message from lpsched (die if any errors occur) 82 */ 83 int 84 rcv_msg(service_t *svc, int type, ...) 85 { 86 int rc = -1; 87 88 if (svc == NULL) 89 return (-1); 90 91 /* read the message */ 92 while (((rc = mread(svc->md, svc->msgbuf, svc->msgbuf_size)) < 0) && 93 (errno == EINTR)); 94 95 if (rc < 0) 96 detailed_error(svc, 97 gettext("unable to read message from scheduler: %s"), 98 strerror(errno)); 99 else { 100 va_list ap; 101 102 va_start(ap, type); 103 rc = _getmessage(svc->msgbuf, type, ap); 104 va_end(ap); 105 106 if (rc < 0) 107 detailed_error(svc, 108 gettext("unable to parse message from scheduler: %s"), 109 strerror(errno)); 110 } 111 112 return (rc); 113 } 114 115 papi_status_t 116 lpsched_status_to_papi_status(int status) 117 { 118 switch (status) { 119 case MNOMEM: 120 return (PAPI_TEMPORARY_ERROR); 121 case MNOFILTER: 122 return (PAPI_DOCUMENT_FORMAT_ERROR); 123 case MNOOPEN: 124 return (PAPI_DOCUMENT_ACCESS_ERROR); 125 case MERRDEST: 126 return (PAPI_DEVICE_ERROR); 127 case MDENYDEST: 128 return (PAPI_NOT_ACCEPTING); 129 case MNOMEDIA: 130 return (PAPI_PRINT_SUPPORT_FILE_NOT_FOUND); 131 case MDENYMEDIA: 132 case MNOPERM: 133 return (PAPI_NOT_AUTHORIZED); 134 case MUNKNOWN: 135 case MNODEST: 136 case MNOINFO: 137 return (PAPI_NOT_FOUND); 138 case MTRANSMITERR: 139 return (PAPI_SERVICE_UNAVAILABLE); 140 case M2LATE: 141 return (PAPI_GONE); 142 case MOK: 143 case MOKMORE: 144 return (PAPI_OK); 145 } 146 147 return (PAPI_INTERNAL_ERROR); 148 } 149 150 char * 151 lpsched_status_string(short status) 152 { 153 switch (status) { 154 case MNOMEM: 155 return (gettext("lpsched: out of memory")); 156 case MNOFILTER: 157 return (gettext("No filter available to convert job")); 158 case MNOOPEN: 159 return (gettext("lpsched: could not open request")); 160 case MERRDEST: 161 return (gettext("An error occured in submission")); 162 case MDENYDEST: 163 return (gettext("destination denied request")); 164 case MNOMEDIA: 165 return (gettext("unknown form specified in job")); 166 case MDENYMEDIA: 167 return (gettext("access denied to form specified in job")); 168 case MUNKNOWN: 169 return (gettext("no such resource")); 170 case MNODEST: 171 return (gettext("unknown destination")); 172 case MNOPERM: 173 return (gettext("permission denied")); 174 case MNOINFO: 175 return (gettext("no information available")); 176 case MTRANSMITERR: 177 return (gettext("failure to communicate with lpsched")); 178 default: { 179 static char result[16]; 180 181 snprintf(result, sizeof (result), gettext("status: %d"), 182 status); 183 return (result); 184 } 185 } 186 } 187 188 papi_status_t 189 lpsched_alloc_files(papi_service_t svc, int number, char **prefix) 190 { 191 papi_status_t result = PAPI_OK; 192 short status = MOK; 193 194 if ((svc == NULL) || (prefix == NULL)) 195 return (PAPI_BAD_ARGUMENT); 196 197 if ((snd_msg(svc, S_ALLOC_FILES, number) < 0) || 198 (rcv_msg(svc, R_ALLOC_FILES, &status, prefix) < 0)) 199 status = MTRANSMITERR; 200 201 if (status != MOK) { 202 detailed_error(svc, 203 gettext("failed to allocate %d file(s) for request: %s"), 204 number, lpsched_status_string(status)); 205 result = lpsched_status_to_papi_status(status); 206 } 207 208 return (result); 209 } 210 211 papi_status_t 212 lpsched_commit_job(papi_service_t svc, char *job, char **tmp) 213 /* job is host/req-id */ 214 { 215 papi_status_t result = PAPI_OK; 216 short status = MOK; 217 long bits; 218 219 if ((svc == NULL) || (job == NULL) || (tmp == NULL)) 220 return (PAPI_BAD_ARGUMENT); 221 222 if ((snd_msg(svc, S_PRINT_REQUEST, job) < 0) || 223 (rcv_msg(svc, R_PRINT_REQUEST, &status, tmp, &bits) < 0)) 224 status = MTRANSMITERR; 225 226 if (status != MOK) { 227 detailed_error(svc, gettext("failed to commit job (%s): %s"), 228 job, lpsched_status_string(status)); 229 result = lpsched_status_to_papi_status(status); 230 } 231 232 return (result); 233 } 234 235 papi_status_t 236 lpsched_start_change(papi_service_t svc, const char *printer, int32_t job_id, 237 char **tmp) 238 { 239 papi_status_t result = PAPI_OK; 240 short status = MOK; 241 char req[BUFSIZ]; 242 char *dest; 243 244 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 245 return (PAPI_BAD_ARGUMENT); 246 247 dest = printer_name_from_uri_id(printer, job_id); 248 snprintf(req, sizeof (req), "%s-%d", dest, job_id); 249 free(dest); 250 251 if ((snd_msg(svc, S_START_CHANGE_REQUEST, req) < 0) || 252 (rcv_msg(svc, R_START_CHANGE_REQUEST, &status, tmp) < 0)) 253 status = MTRANSMITERR; 254 255 if (status != MOK) { 256 detailed_error(svc, 257 gettext("failed to initiate change for job (%s-%d): %s"), 258 printer, 259 job_id, lpsched_status_string(status)); 260 result = lpsched_status_to_papi_status(status); 261 } 262 263 return (result); 264 } 265 266 papi_status_t 267 lpsched_end_change(papi_service_t svc, const char *printer, int32_t job_id) 268 { 269 papi_status_t result = PAPI_OK; 270 short status = MOK; 271 long bits; 272 char req[BUFSIZ]; 273 char *dest; 274 275 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 276 return (PAPI_BAD_ARGUMENT); 277 278 dest = printer_name_from_uri_id(printer, job_id); 279 snprintf(req, sizeof (req), "%s-%d", dest, job_id); 280 free(dest); 281 282 if ((snd_msg(svc, S_END_CHANGE_REQUEST, req) < 0) || 283 (rcv_msg(svc, R_END_CHANGE_REQUEST, &status, &bits) < 0)) 284 status = MTRANSMITERR; 285 286 if (status != MOK) { 287 detailed_error(svc, 288 gettext("failed to commit change for job (%s-%d): %s"), printer, 289 job_id, lpsched_status_string(status)); 290 result = lpsched_status_to_papi_status(status); 291 } 292 293 return (result); 294 } 295 296 papi_status_t 297 lpsched_enable_printer(papi_service_t svc, const char *printer) 298 { 299 papi_status_t result = PAPI_OK; 300 short status; 301 char *req_id; 302 char *dest; 303 304 if ((svc == NULL) || (printer == NULL)) 305 return (PAPI_BAD_ARGUMENT); 306 307 dest = printer_name_from_uri_id(printer, -1); 308 if ((snd_msg(svc, S_ENABLE_DEST, dest) < 0) || 309 (rcv_msg(svc, R_ENABLE_DEST, &status, &req_id) < 0)) 310 status = MTRANSMITERR; 311 free(dest); 312 313 if ((status != MOK) && (status != MERRDEST)) { 314 detailed_error(svc, "%s: %s", printer, 315 lpsched_status_string(status)); 316 result = lpsched_status_to_papi_status(status); 317 } 318 319 return (result); 320 } 321 322 papi_status_t 323 lpsched_disable_printer(papi_service_t svc, const char *printer, 324 const char *message) 325 { 326 papi_status_t result = PAPI_OK; 327 short status; 328 char *req_id; 329 char *dest; 330 331 if ((svc == NULL) || (printer == NULL)) 332 return (PAPI_BAD_ARGUMENT); 333 334 if (message == NULL) 335 message = "stopped by user"; 336 337 dest = printer_name_from_uri_id(printer, -1); 338 if ((snd_msg(svc, S_DISABLE_DEST, dest, message, 0) < 0) || 339 (rcv_msg(svc, R_DISABLE_DEST, &status, &req_id) < 0)) 340 status = MTRANSMITERR; 341 free(dest); 342 343 if ((status != MOK) && (status != MERRDEST)) { 344 detailed_error(svc, "%s: %s", printer, 345 lpsched_status_string(status)); 346 result = lpsched_status_to_papi_status(status); 347 } 348 349 return (result); 350 } 351