Print this page
2837 - remove print/lp* from gate and use CUPS from userland
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/print/libipp-listener/common/ipp-listener.c
+++ new/usr/src/lib/print/libipp-listener/common/ipp-listener.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 *
26 26 */
27 27
28 28 /* $Id: ipp-listener.c 146 2006-03-24 00:26:54Z njacobs $ */
29 29
30 -#pragma ident "%Z%%M% %I% %E% SMI"
31 -
32 30 #include <stdio.h>
33 31 #include <stdlib.h>
34 32 #include <string.h>
35 33 #include <netinet/in.h>
36 34 #include <assert.h>
37 35 #include <errno.h>
38 36 #include <syslog.h>
39 37 #include <sys/types.h>
40 38 #include <sys/stat.h>
41 39 #include <fcntl.h>
42 40 #include <unistd.h>
43 41 #include <sys/systeminfo.h>
44 42
45 43 #include <papi.h>
46 44 #include <ipp-listener.h>
47 45 #include <uri.h>
48 46
49 47 typedef papi_status_t (ipp_handler_t)(papi_service_t svc,
50 48 papi_attribute_t **request,
51 49 papi_attribute_t ***response,
52 50 ipp_reader_t iread, void *fd);
53 51
54 52 /*
55 53 * protocol request handlers are inserted below. The handler must be
56 54 * declared extern immediately below this comment and then an entry
57 55 * must be inserted in the "handlers" table a little further down.
58 56 */
59 57 extern ipp_handler_t ipp_print_job;
60 58 extern ipp_handler_t ipp_validate_job;
61 59 extern ipp_handler_t ipp_create_job;
62 60 extern ipp_handler_t ipp_get_printer_attributes;
63 61 extern ipp_handler_t ipp_get_jobs;
64 62 extern ipp_handler_t ipp_pause_printer;
65 63 extern ipp_handler_t ipp_resume_printer;
66 64 extern ipp_handler_t ipp_disable_printer;
67 65 extern ipp_handler_t ipp_enable_printer;
68 66 extern ipp_handler_t ipp_purge_jobs;
69 67 extern ipp_handler_t ipp_send_document;
70 68 extern ipp_handler_t ipp_cancel_job;
71 69 extern ipp_handler_t ipp_get_job_attributes;
72 70 extern ipp_handler_t ipp_release_job;
73 71 extern ipp_handler_t ipp_hold_job;
74 72 extern ipp_handler_t ipp_restart_job;
75 73 extern ipp_handler_t ipp_set_job_attributes;
76 74 extern ipp_handler_t ipp_set_printer_attributes;
77 75 extern ipp_handler_t cups_get_default;
78 76 extern ipp_handler_t cups_get_printers;
79 77 extern ipp_handler_t cups_get_classes;
80 78 extern ipp_handler_t cups_accept_jobs;
81 79 extern ipp_handler_t cups_reject_jobs;
82 80 extern ipp_handler_t cups_move_job;
83 81
84 82 /* ARGSUSED0 */
85 83 static papi_status_t
86 84 default_handler(papi_service_t svc, papi_attribute_t **request,
87 85 papi_attribute_t ***response, ipp_reader_t iread, void *fd)
88 86 {
89 87 int result = (int)PAPI_INTERNAL_ERROR;
90 88
91 89 if (response != NULL)
92 90 (void) papiAttributeListGetInteger(*response, NULL,
93 91 "status-code", &result);
94 92
95 93 return ((papi_status_t)result);
96 94 }
97 95
98 96 static struct {
99 97 int16_t id;
100 98 char *name;
101 99 ipp_handler_t *function;
102 100 enum { OP_REQUIRED, OP_OPTIONAL, OP_VENDOR } type;
103 101 } handlers[] = {
104 102 /* Printer Operations */
105 103 { 0x0002, "print-job", ipp_print_job, OP_REQUIRED },
106 104 { 0x0003, "print-uri", NULL, OP_OPTIONAL },
107 105 { 0x0004, "validate-job", ipp_validate_job,
108 106 OP_REQUIRED },
109 107 { 0x0005, "create-job", ipp_create_job, OP_OPTIONAL },
110 108 { 0x000a, "get-jobs", ipp_get_jobs, OP_REQUIRED },
111 109 { 0x000b, "get-printer-attributes", ipp_get_printer_attributes,
112 110 OP_REQUIRED },
113 111 { 0x0010, "pause-printer", ipp_pause_printer,
114 112 OP_OPTIONAL },
115 113 { 0x0011, "resume-printer", ipp_resume_printer,
116 114 OP_OPTIONAL },
117 115 { 0x0012, "purge-jobs", ipp_purge_jobs, OP_OPTIONAL },
118 116 { 0x0013, "set-printer-attributes", ipp_set_printer_attributes,
119 117 OP_OPTIONAL },
120 118 { 0x0014, "set-job-attributes", ipp_set_job_attributes,
121 119 OP_OPTIONAL },
122 120 { 0x0022, "enable-printer", ipp_enable_printer,
123 121 OP_OPTIONAL },
124 122 { 0x0023, "disable-printer", ipp_disable_printer,
125 123 OP_OPTIONAL },
126 124 /* Job Operations */
127 125 { 0x0006, "send-document", ipp_send_document,
128 126 OP_OPTIONAL },
129 127 { 0x0007, "send-uri", NULL, OP_OPTIONAL },
130 128 { 0x0008, "cancel-job", ipp_cancel_job, OP_REQUIRED },
131 129 { 0x0009, "get-job-attributes", ipp_get_job_attributes,
132 130 OP_REQUIRED },
133 131 { 0x000c, "hold-job", ipp_hold_job, OP_OPTIONAL },
134 132 { 0x000d, "release-job", ipp_release_job,
135 133 OP_OPTIONAL },
136 134 { 0x000e, "restart-job", ipp_restart_job,
137 135 OP_OPTIONAL },
138 136 /* Other Operations */
139 137 { 0x4001, "cups-get-default", cups_get_default,
140 138 OP_VENDOR },
141 139 { 0x4002, "cups-get-printers", cups_get_printers,
142 140 OP_VENDOR },
143 141 { 0x4005, "cups-get-classes", cups_get_classes,
↓ open down ↓ |
102 lines elided |
↑ open up ↑ |
144 142 OP_VENDOR },
145 143 { 0x4008, "cups-accept-jobs", cups_accept_jobs,
146 144 OP_VENDOR },
147 145 { 0x4009, "cups-reject-jobs", cups_reject_jobs,
148 146 OP_VENDOR },
149 147 { 0x400D, "cups-move-job", cups_move_job, OP_VENDOR },
150 148 { 0, NULL, NULL, OP_VENDOR }
151 149 };
152 150
153 151 static int
154 -ipp_operation_name_to_index(char *name)
152 +ipp_operation_name_to_index(const char *name)
155 153 {
156 154 int i;
157 155
158 156 for (i = 0; handlers[i].name != NULL; i++)
159 157 if (strcasecmp(name, handlers[i].name) == 0)
160 158 return (i);
161 159
162 160 return (-1);
163 161 }
164 162
165 163 static int
166 164 ipp_operation_id_to_index(int16_t id)
167 165 {
168 166 int i;
169 167
170 168 for (i = 0; handlers[i].name != NULL; i++)
171 169 if (id == handlers[i].id)
172 170 return (i);
173 171
174 172 return (-1);
175 173 }
176 174
177 175 static ipp_handler_t *
178 176 ipp_operation_handler(papi_attribute_t **request, papi_attribute_t ***response)
179 177 {
180 178 int id = 0;
181 179 int index;
182 180 papi_attribute_t **ops = NULL;
183 181 papi_status_t status;
184 182 char configured = PAPI_FALSE;
185 183
186 184 /* get the operation from the request */
187 185 status = papiAttributeListGetInteger(request, NULL,
188 186 "operation-id", &id);
189 187 if (status != PAPI_OK) {
190 188 ipp_set_status(response, PAPI_BAD_ARGUMENT,
191 189 "no operation specified in request");
192 190 return (default_handler);
193 191 }
194 192
195 193 /* find the operation in the handler table */
196 194 index = ipp_operation_id_to_index(id);
197 195 #ifdef DEBUG
198 196 if (index == -1)
199 197 fprintf(stderr, "Operation: 0x%4.4x\n", id);
200 198 else
201 199 fprintf(stderr, "Operation: 0x%4.4x(%s)\n", id,
202 200 handlers[index].name);
203 201 fflush(stderr);
204 202 #endif
205 203
206 204 if ((index == -1) || (handlers[index].function == NULL)) {
207 205 ipp_set_status(response, PAPI_OPERATION_NOT_SUPPORTED,
208 206 "operation (0x%4.4x) not implemented by server",
209 207 id);
210 208 return (default_handler);
211 209 }
212 210
213 211 /* find the configured operations */
214 212 status = papiAttributeListGetCollection(request, NULL,
215 213 "operations", &ops);
216 214 if (status != PAPI_OK) { /* this should not be possible */
217 215 ipp_set_status(response, PAPI_INTERNAL_ERROR,
218 216 "sofware error, no operations configured");
219 217 return (default_handler);
220 218 }
221 219
222 220 /* check if the requested operation is configured */
223 221 status = papiAttributeListGetBoolean(ops, NULL,
224 222 handlers[index].name, &configured);
225 223 if ((status != PAPI_OK) || (configured != PAPI_TRUE)) {
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
226 224 ipp_set_status(response, PAPI_OPERATION_NOT_SUPPORTED,
227 225 "operation (%s 0x%4.4x) not enabled on server",
228 226 handlers[index].name, id);
229 227 return (default_handler);
230 228 }
231 229
232 230 return (handlers[index].function);
233 231 }
234 232
235 233 static char
236 -type_to_boolean(char *type)
234 +type_to_boolean(const char *type)
237 235 {
238 236 char result = PAPI_FALSE;
239 237
240 238 if ((strcasecmp(type, "true") == 0) ||
241 239 (strcasecmp(type, "yes") == 0) ||
242 240 (strcasecmp(type, "on") == 0) ||
243 241 (strcasecmp(type, "enable") == 0))
244 242 result = PAPI_TRUE;
245 243
246 244 return (result);
247 245 }
248 246
249 247 static papi_status_t
250 248 ipp_configure_required_operations(papi_attribute_t ***list, char boolean)
251 249 {
252 250 papi_status_t result = PAPI_OK;
253 251 int i;
254 252
255 253 for (i = 0; ((result == PAPI_OK) && (handlers[i].name != NULL)); i++)
256 254 if (handlers[i].type == OP_REQUIRED)
257 255 result = papiAttributeListAddBoolean(list,
258 256 PAPI_ATTR_REPLACE, handlers[i].name,
259 257 boolean);
260 258
261 259 return (result);
262 260
263 261 }
264 262
265 263 static papi_status_t
266 264 ipp_configure_all_operations(papi_attribute_t ***list, char boolean)
267 265 {
268 266 papi_status_t result = PAPI_OK;
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
269 267 int i;
270 268
271 269 for (i = 0; ((result == PAPI_OK) && (handlers[i].name != NULL)); i++)
272 270 result = papiAttributeListAddBoolean(list, PAPI_ATTR_REPLACE,
273 271 handlers[i].name, boolean);
274 272
275 273 return (result);
276 274 }
277 275
278 276 papi_status_t
279 -ipp_configure_operation(papi_attribute_t ***list, char *operation, char *type)
277 +ipp_configure_operation(papi_attribute_t ***list, const char *operation, const char *type)
280 278 {
281 279 papi_status_t result = PAPI_OPERATION_NOT_SUPPORTED;
282 280 char boolean = PAPI_FALSE;
283 281
284 282 if ((list == NULL) || (operation == NULL) || (type == NULL))
285 283 return (PAPI_BAD_ARGUMENT);
286 284
287 285 boolean = type_to_boolean(type);
288 286
289 287 if (strcasecmp(operation, "all") == 0) {
290 288 result = ipp_configure_all_operations(list, boolean);
291 289 } else if (strcasecmp(operation, "required") == 0) {
292 290 result = ipp_configure_required_operations(list, boolean);
293 291 } else if (ipp_operation_name_to_index(operation) != -1) {
294 292 result = papiAttributeListAddBoolean(list, PAPI_ATTR_REPLACE,
295 293 operation, boolean);
296 294 }
297 295
298 296 return (result);
299 297 }
300 298
301 299 void
302 300 ipp_operations_supported(papi_attribute_t ***list, papi_attribute_t **request)
303 301 {
304 302 papi_attribute_t **group = NULL;
305 303
306 304 (void) papiAttributeListGetCollection(request, NULL,
307 305 "operations", &group);
308 306 if (group != NULL) {
309 307 int i;
310 308
311 309 for (i = 0; handlers[i].name != NULL; i++) {
312 310 char boolean = PAPI_FALSE;
313 311 (void) papiAttributeListGetBoolean(group, NULL,
314 312 handlers[i].name, &boolean);
315 313
316 314 if (boolean == PAPI_TRUE)
317 315 (void) papiAttributeListAddInteger(list,
318 316 PAPI_ATTR_APPEND,
319 317 "operations-supported",
320 318 handlers[i].id);
321 319 }
322 320 }
323 321 }
324 322
325 323 static papi_status_t
326 324 ipp_initialize_response(papi_attribute_t **request,
327 325 papi_attribute_t ***response)
328 326 {
329 327 papi_attribute_t **operational = NULL;
330 328 int i;
331 329
332 330 if ((request == NULL) || (response == NULL))
333 331 return (PAPI_BAD_ARGUMENT);
334 332
335 333 /* If the response was initialized, start over */
336 334 if (*response != NULL) {
337 335 papiAttributeListFree(*response);
338 336 *response = NULL;
339 337 }
340 338
341 339 /* Add the basic ipp header information to the response */
342 340 (void) papiAttributeListGetInteger(request, NULL, "version-major", &i);
343 341 (void) papiAttributeListAddInteger(response, PAPI_ATTR_REPLACE,
344 342 "version-major", i);
345 343 (void) papiAttributeListGetInteger(request, NULL, "version-minor", &i);
346 344 (void) papiAttributeListAddInteger(response, PAPI_ATTR_REPLACE,
347 345 "version-minor", i);
348 346
349 347 (void) papiAttributeListGetInteger(request, NULL, "request-id", &i);
350 348 (void) papiAttributeListAddInteger(response, PAPI_ATTR_REPLACE,
351 349 "request-id", i);
352 350
353 351 /* Add a default operational attributes group to the response */
354 352 (void) papiAttributeListAddString(&operational, PAPI_ATTR_EXCL,
355 353 "attributes-charset", "utf-8");
356 354 (void) papiAttributeListAddString(&operational, PAPI_ATTR_EXCL,
357 355 "attributes-natural-language", "en-us");
358 356
359 357 (void) papiAttributeListAddCollection(response, PAPI_ATTR_REPLACE,
360 358 "operational-attributes-group", operational);
361 359 papiAttributeListFree(operational);
362 360
363 361 return (PAPI_OK);
364 362 }
365 363
366 364 /* simplistic check for cyclical service references */
367 365 static int
368 366 cyclical_service_check(char *svc_name, int port)
369 367 {
370 368 papi_attribute_t **list;
371 369 char buf[BUFSIZ];
372 370 uri_t *uri = NULL;
373 371 char *s = NULL;
374 372
375 373 /* was there a service_uri? */
376 374 if (svc_name == NULL)
377 375 return (0);
378 376
379 377 if ((list = getprinterbyname(svc_name, NULL)) == NULL)
380 378 return (0); /* if it doesnt' resolve, we will fail later */
381 379
382 380 papiAttributeListGetString(list, NULL, "printer-uri-supported", &s);
383 381 if ((s == NULL) || (strcasecmp(svc_name, s) != 0))
384 382 return (0); /* they don't match */
385 383
386 384 /* is it in uri form? */
387 385 if (uri_from_string(s, &uri) < 0)
388 386 return (0);
389 387
390 388 if ((uri == NULL) || (uri->scheme == NULL) || (uri->host == NULL)) {
391 389 uri_free(uri);
392 390 return (0);
393 391 }
394 392
395 393 /* is it ipp form */
396 394 if (strcasecmp(uri->scheme, "ipp") != 0) {
397 395 uri_free(uri);
398 396 return (0);
399 397 }
400 398
401 399 /* does the host match up */
402 400 if (is_localhost(uri->host) != 0) {
403 401 uri_free(uri);
404 402 return (0);
405 403 }
406 404
407 405 /* does the port match our own */
408 406 if (((uri->port == NULL) && (port != 631)) ||
409 407 ((uri->port != NULL) && (atoi(uri->port) != port))) {
410 408 uri_free(uri);
411 409 return (0);
412 410 }
413 411
414 412 uri_free(uri);
415 413
416 414 return (1);
417 415 }
418 416
419 417 static papi_status_t
420 418 print_service_connect(papi_service_t *svc, papi_attribute_t **request,
421 419 papi_attribute_t ***response)
422 420 {
423 421 papi_status_t status;
424 422 papi_attribute_t **operational = NULL;
425 423 char *printer_uri = NULL;
426 424 char *svc_name = NULL;
427 425 char *user = NULL;
428 426 int port = 631;
429 427
430 428 /* Get the operational attributes group from the request */
431 429 (void) papiAttributeListGetCollection(request, NULL,
432 430 "operational-attributes-group", &operational);
433 431
434 432 /* get the user name */
435 433 (void) papiAttributeListGetString(request, NULL, "default-user", &user);
436 434 (void) papiAttributeListGetString(operational, NULL,
437 435 "requesting-user-name", &user);
438 436
439 437 /* get the printer or service name */
440 438 (void) papiAttributeListGetString(request, NULL,
441 439 "default-service", &svc_name);
442 440 get_printer_id(operational, &svc_name, NULL);
443 441
444 442 /* get the port that we are listening on */
445 443 (void) papiAttributeListGetInteger(request, NULL, "uri-port", &port);
446 444
447 445 if (cyclical_service_check(svc_name, port) != 0) {
448 446 status = PAPI_NOT_POSSIBLE;
449 447 ipp_set_status(response, status, "printer-uri is cyclical");
450 448 return (status);
451 449 }
452 450
453 451 status = papiServiceCreate(svc, svc_name, user, NULL, NULL,
454 452 PAPI_ENCRYPT_NEVER, NULL);
455 453 if (status != PAPI_OK) {
456 454 ipp_set_status(response, status, "print service: %s",
457 455 papiStatusString(status));
458 456 return (status);
459 457 }
460 458
461 459 /*
462 460 * Trusted Solaris can't be trusting of intermediaries. Pass
463 461 * the socket connection to the print service to retrieve the
464 462 * sensativity label off of a multi-level port.
465 463 */
466 464 {
467 465 int fd = -1;
468 466
469 467 (void) papiAttributeListGetInteger(request, NULL,
470 468 "peer-socket", &fd);
471 469 if (fd != -1)
472 470 papiServiceSetPeer(*svc, fd);
473 471 }
474 472
475 473 return (status);
476 474 }
477 475
478 476 papi_status_t
479 477 ipp_process_request(papi_attribute_t **request, papi_attribute_t ***response,
480 478 ipp_reader_t iread, void *fd)
481 479 {
482 480 papi_status_t result = PAPI_OK;
483 481
484 482 ipp_initialize_response(request, response);
485 483
486 484 #ifdef DEBUG
487 485 fprintf(stderr, "REQUEST:");
488 486 papiAttributeListPrint(stderr, request, " %d ", getpid());
489 487 fprintf(stderr, "\n");
490 488 #endif
491 489
492 490 /* verify that the request is "well-formed" */
493 491 if ((result = ipp_validate_request(request, response)) == PAPI_OK) {
494 492 papi_service_t svc = NULL;
495 493 ipp_handler_t *handler;
496 494
497 495 result = print_service_connect(&svc, request, response);
498 496 handler = ipp_operation_handler(request, response);
499 497
500 498 /* process the request */
501 499 if ((result == PAPI_OK) && (handler != NULL))
502 500 result = (handler)(svc, request, response, iread, fd);
503 501 #ifdef DEBUG
504 502 fprintf(stderr, "RESULT: %s\n", papiStatusString(result));
505 503 #endif
506 504 papiServiceDestroy(svc);
507 505 }
508 506
509 507 (void) papiAttributeListAddInteger(response, PAPI_ATTR_EXCL,
510 508 "status-code", result);
511 509 massage_response(request, *response);
512 510
513 511 #ifdef DEBUG
514 512 fprintf(stderr, "RESPONSE:");
515 513 papiAttributeListPrint(stderr, *response, " %d ", getpid());
516 514 fprintf(stderr, "\n");
517 515 #endif
518 516
519 517 return (result);
520 518 }
↓ open down ↓ |
231 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX