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