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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include "time.h" 33 #include "dispatch.h" 34 #include <syslog.h> 35 36 37 /** 38 ** s_accept_dest() 39 **/ 40 41 void 42 s_accept_dest(char *m, MESG *md) 43 { 44 char *destination; 45 ushort status; 46 register PSTATUS *pps; 47 register CSTATUS *pcs; 48 49 getmessage (m, S_ACCEPT_DEST, &destination); 50 syslog(LOG_DEBUG, "s_accept_dest(%s)", 51 (destination ? destination : "NULL")); 52 53 /* 54 * Have we seen this destination as a printer? 55 */ 56 if ((pps = search_pstatus(destination))) 57 if ((pps->status & PS_REJECTED) == 0) 58 status = MERRDEST; 59 else { 60 pps->status &= ~PS_REJECTED; 61 (void) time (&pps->rej_date); 62 dump_pstatus (); 63 status = MOK; 64 } 65 66 /* 67 * Have we seen this destination as a class? 68 */ 69 else if ((pcs = search_cstatus(destination))) 70 if ((pcs->status & CS_REJECTED) == 0) 71 status = MERRDEST; 72 else { 73 pcs->status &= ~CS_REJECTED; 74 (void) time (&pcs->rej_date); 75 dump_cstatus (); 76 status = MOK; 77 } 78 79 else 80 status = MNODEST; 81 82 mputm (md, R_ACCEPT_DEST, status); 83 return; 84 } 85 86 /** 87 ** s_reject_dest() 88 **/ 89 90 void 91 s_reject_dest(char *m, MESG *md) 92 { 93 char *destination, 94 *reason; 95 ushort status; 96 register PSTATUS *pps; 97 register CSTATUS *pcs; 98 99 100 getmessage (m, S_REJECT_DEST, &destination, &reason); 101 syslog(LOG_DEBUG, "s_reject_dest(%s, %s)", 102 (destination ? destination : "NULL"), 103 (reason ? reason : "NULL")); 104 105 /* 106 * Have we seen this destination as a printer? 107 */ 108 if ((pps = search_pstatus(destination))) 109 if (pps->status & PS_REJECTED) 110 status = MERRDEST; 111 else { 112 pps->status |= PS_REJECTED; 113 (void) time (&pps->rej_date); 114 load_str (&pps->rej_reason, reason); 115 dump_pstatus (); 116 status = MOK; 117 } 118 119 /* 120 * Have we seen this destination as a class? 121 */ 122 else if ((pcs = search_cstatus(destination))) 123 if (pcs->status & CS_REJECTED) 124 status = MERRDEST; 125 else { 126 pcs->status |= CS_REJECTED; 127 (void) time (&pcs->rej_date); 128 load_str (&pcs->rej_reason, reason); 129 dump_cstatus (); 130 status = MOK; 131 } 132 133 else 134 status = MNODEST; 135 136 mputm (md, R_REJECT_DEST, status); 137 return; 138 } 139 140 /** 141 ** s_enable_dest() 142 **/ 143 144 void 145 s_enable_dest(char *m, MESG *md) 146 { 147 char *printer; 148 ushort status; 149 register PSTATUS *pps; 150 151 152 getmessage (m, S_ENABLE_DEST, &printer); 153 syslog(LOG_DEBUG, "s_enable_dest(%s)", (printer ? printer : "NULL")); 154 155 /* 156 * Have we seen this printer before? 157 */ 158 if ((pps = search_pstatus(printer))) 159 if (enable(pps) == -1) 160 status = MERRDEST; 161 else 162 status = MOK; 163 else 164 status = MNODEST; 165 166 mputm (md, R_ENABLE_DEST, status); 167 return; 168 } 169 170 /** 171 ** s_disable_dest() 172 **/ 173 174 void 175 s_disable_dest(char *m, MESG *md) 176 { 177 char *destination, 178 *reason, 179 *req_id = 0; 180 ushort when, 181 status; 182 register PSTATUS *pps; 183 184 getmessage (m, S_DISABLE_DEST, &destination, &reason, &when); 185 syslog(LOG_DEBUG, "s_disable_dest(%s, %s, %d)", 186 (destination ? destination : "NULL"), 187 (reason ? reason : "NULL"), when); 188 189 190 /* 191 * Have we seen this printer before? 192 */ 193 if ((pps = search_pstatus(destination))) { 194 195 /* 196 * If we are to cancel a currently printing request, 197 * we will send back the request's ID. 198 * Save a copy of the ID before calling "disable()", 199 * in case the disabling loses it (e.g. the request 200 * might get attached to another printer). (Actually, 201 * the current implementation won't DETACH the request 202 * from this printer until the child process responds, 203 * but a future implementation might.) 204 */ 205 if (pps->request && when == 2) 206 req_id = Strdup(pps->request->secure->req_id); 207 208 if (disable(pps, reason, (int)when) == -1) { 209 if (req_id) { 210 Free (req_id); 211 req_id = 0; 212 } 213 status = MERRDEST; 214 } else 215 status = MOK; 216 217 } else 218 status = MNODEST; 219 220 mputm (md, R_DISABLE_DEST, status, NB(req_id)); 221 if (req_id) 222 Free (req_id); 223 224 return; 225 } 226 227 /** 228 ** s_load_filter_table() 229 **/ 230 231 void 232 s_load_filter_table(char *m, MESG *md) 233 { 234 ushort status; 235 236 syslog(LOG_DEBUG, "s_load_filter_table()"); 237 238 trash_filters (); 239 if (Loadfilters((char *)0) == -1) 240 status = MNOOPEN; 241 else { 242 /* 243 * This is what makes changing filters expensive! 244 */ 245 queue_check (qchk_filter); 246 247 status = MOK; 248 } 249 250 mputm (md, R_LOAD_FILTER_TABLE, status); 251 return; 252 } 253 254 /** 255 ** s_unload_filter_table() 256 **/ 257 258 void 259 s_unload_filter_table(char *m, MESG *md) 260 { 261 syslog(LOG_DEBUG, "s_unload_filter_table()"); 262 263 trash_filters (); 264 265 /* 266 * This is what makes changing filters expensive! 267 */ 268 queue_check (qchk_filter); 269 270 mputm (md, R_UNLOAD_FILTER_TABLE, MOK); 271 return; 272 } 273 274 /** 275 ** s_load_user_file() 276 **/ 277 278 void 279 s_load_user_file(char *m, MESG *md) 280 { 281 /* 282 * The first call to "getuser()" will load the whole file. 283 */ 284 syslog(LOG_DEBUG, "s_load_user_file()"); 285 286 trashusers (); 287 288 mputm (md, R_LOAD_USER_FILE, MOK); 289 return; 290 } 291 292 /** 293 ** s_unload_user_file() 294 **/ 295 296 void 297 s_unload_user_file(char *m, MESG *md) 298 { 299 syslog(LOG_DEBUG, "s_unload_user_file()"); 300 301 trashusers (); /* THIS WON'T DO TRUE UNLOAD, SORRY! */ 302 303 mputm (md, R_UNLOAD_USER_FILE, MOK); 304 return; 305 } 306 /** 307 ** s_shutdown() 308 **/ 309 310 void 311 s_shutdown(char *m, MESG *md) 312 { 313 ushort immediate; 314 315 (void)getmessage (m, S_SHUTDOWN, &immediate); 316 syslog(LOG_DEBUG, "s_shutdown(%d)", immediate); 317 318 switch (md->type) { 319 case MD_STREAM: 320 case MD_SYS_FIFO: 321 case MD_USR_FIFO: 322 mputm (md, R_SHUTDOWN, MOK); 323 lpshut (immediate); 324 /*NOTREACHED*/ 325 default: 326 syslog(LOG_DEBUG, 327 "Received S_SHUTDOWN on a type %d connection\n", 328 md->type); 329 } 330 331 return; 332 } 333 334 /** 335 ** s_quiet_alert() 336 **/ 337 338 void 339 s_quiet_alert(char *m, MESG *md) 340 { 341 char *name; 342 ushort type, 343 status; 344 register FSTATUS *pfs; 345 register PSTATUS *pps; 346 register PWSTATUS *ppws; 347 348 349 /* 350 * We quiet an alert by cancelling it with "cancel_alert()" 351 * and then resetting the active flag. This effectively just 352 * terminates the process running the alert but tricks the 353 * rest of the Spooler into thinking it is still active. 354 * The alert will be reactivated only AFTER "cancel_alert()" 355 * has been called (to clear the active flag) and then "alert()" 356 * is called again. Thus: 357 * 358 * For printer faults the alert will be reactivated when: 359 * - a fault is found after the current fault has been 360 * cleared (i.e. after successful print or after manually 361 * enabled). 362 * 363 * For forms/print-wheels the alert will be reactivated when: 364 * - the form/print-wheel becomes mounted and then unmounted 365 * again, with too many requests still pending; 366 * - the number of requests falls below the threshold and 367 * then rises above it again. 368 */ 369 370 (void)getmessage (m, S_QUIET_ALERT, &name, &type); 371 syslog(LOG_DEBUG, "s_quiet_alert(%s, %d)", (name ? name : "NULL"), 372 type); 373 374 if (!*name) 375 status = MNODEST; 376 377 else switch (type) { 378 case QA_FORM: 379 if (!(pfs = search_fstatus(name))) 380 status = MNODEST; 381 382 else if (!pfs->alert->active) 383 status = MERRDEST; 384 385 else { 386 cancel_alert (A_FORM, pfs); 387 pfs->alert->active = 1; 388 status = MOK; 389 } 390 break; 391 392 case QA_PRINTER: 393 if (!(pps = search_pstatus(name))) 394 status = MNODEST; 395 396 else if (!pps->alert->active) 397 status = MERRDEST; 398 399 else { 400 cancel_alert (A_PRINTER, pps); 401 pps->alert->active = 1; 402 status = MOK; 403 } 404 break; 405 406 case QA_PRINTWHEEL: 407 if (!(ppws = search_pwstatus(name))) 408 status = MNODEST; 409 410 else if (!ppws->alert->active) 411 status = MERRDEST; 412 413 else { 414 cancel_alert (A_PWHEEL, ppws); 415 ppws->alert->active = 1; 416 status = MOK; 417 } 418 break; 419 } 420 421 mputm (md, R_QUIET_ALERT, status); 422 return; 423 } 424 425 /** 426 ** s_send_fault() 427 **/ 428 429 void 430 s_send_fault(char *m, MESG *md) 431 { 432 long key; 433 char *printerOrForm, *alert_text; 434 ushort status; 435 register PSTATUS *pps; 436 437 getmessage (m, S_SEND_FAULT, &printerOrForm, &key, &alert_text); 438 syslog(LOG_DEBUG, "s_send_fault(%s, %x, %s)", 439 (printerOrForm ? printerOrForm : "NULL"), key, 440 (alert_text ? alert_text : "NULL")); 441 442 if (!(pps = search_pstatus(printerOrForm)) || (!pps->exec) || 443 pps->exec->key != key || !pps->request) { 444 status = MERRDEST; 445 } else { 446 printer_fault(pps, pps->request, alert_text, 0); 447 status = MOK; 448 } 449 450 mputm (md, R_SEND_FAULT, status); 451 } 452 453 /* 454 * s_clear_fault() 455 */ 456 void 457 s_clear_fault(char *m, MESG *md) 458 { 459 long key; 460 char *printerOrForm, *alert_text; 461 ushort status; 462 register PSTATUS *pps; 463 464 getmessage(m, S_CLEAR_FAULT, &printerOrForm, &key, &alert_text); 465 syslog(LOG_DEBUG, "s_clear_fault(%s, %x, %s)", 466 (printerOrForm ? printerOrForm : "NULL"), key, 467 (alert_text ? alert_text : "NULL")); 468 469 470 if (! (pps = search_pstatus(printerOrForm)) || ((key > 0) && 471 ((!pps->exec) || pps->exec->key != key || !pps->request ))) { 472 status = MERRDEST; 473 } else { 474 clear_printer_fault(pps, alert_text); 475 status = MOK; 476 } 477 478 mputm (md, R_CLEAR_FAULT, status); 479 } 480 481 482 /* 483 * s_paper_changed() 484 */ 485 void 486 s_paper_changed(char *m, MESG *md) 487 { 488 short trayNum, mode, pagesPrinted; 489 char *printer, *paper; 490 ushort status; 491 short chgd = 0; 492 register PSTATUS *pps; 493 register FSTATUS *pfs,*pfsWas; 494 495 getmessage(m, S_PAPER_CHANGED, &printer, &trayNum, &paper, &mode, 496 &pagesPrinted); 497 syslog(LOG_DEBUG, "s_paper_changed(%s, %d, %s, %d, %d)", 498 (printer ? printer : "NULL"), trayNum, (paper ? paper : "NULL"), 499 mode, pagesPrinted); 500 501 if (!(pps = search_pstatus(printer))) 502 status = MNODEST; 503 else if ((trayNum <=0) || (trayNum > pps->numForms)) 504 status = MNOTRAY; 505 else { 506 status = MOK; 507 if (*paper && (pfsWas = pps->forms[trayNum-1].form) && 508 (!STREQU(pfsWas->form->paper,paper))) { 509 pfs = search_fptable(paper); 510 if (pfs) { 511 remount_form(pps, pfs, trayNum); 512 chgd = 1; 513 } else 514 status = MNOMEDIA; 515 } 516 if ( status == MOK ) { 517 pps->forms[trayNum].isAvailable = mode; 518 if ((chgd || !mode) && (!pagesPrinted) && pps->exec) { 519 if (pps->request) 520 pps->request->request->outcome |= 521 RS_STOPPED; 522 terminate(pps->exec); 523 schedule(EV_LATER, 1, EV_INTERF, pps); 524 } 525 } 526 } 527 mputm(md, R_PAPER_CHANGED, status); 528 } 529 530