1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 3125 jacobs * Common Development and Distribution License (the "License"). 6 3125 jacobs * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 0 stevel /* All Rights Reserved */ 23 0 stevel 24 0 stevel 25 0 stevel /* 26 4599 wendyp * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 3125 jacobs * Use is subject to license terms. 28 0 stevel */ 29 0 stevel 30 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 31 0 stevel 32 0 stevel #include "lpsched.h" 33 4599 wendyp #include <syslog.h> 34 0 stevel 35 0 stevel static int max_requests_needing_form_mounted ( FSTATUS * ); 36 0 stevel static int max_requests_needing_pwheel_mounted ( char * ); 37 0 stevel 38 0 stevel /** 39 0 stevel ** queue_form() - ADD A REQUEST TO A FORM QUEUE 40 0 stevel **/ 41 0 stevel 42 0 stevel void 43 3125 jacobs queue_form(RSTATUS *prs, FSTATUS *pfs) 44 0 stevel { 45 0 stevel if ((prs->form = pfs) != NULL) { 46 0 stevel prs->form->requests++; 47 0 stevel if (prs->printer) 48 0 stevel check_form_alert (prs->form, (_FORM *)0); 49 0 stevel } 50 0 stevel return; 51 0 stevel } 52 0 stevel 53 0 stevel /** 54 0 stevel ** unqueue_form() - REMOVE A REQUEST FROM A FORM QUEUE 55 0 stevel **/ 56 0 stevel 57 0 stevel void 58 3125 jacobs unqueue_form(RSTATUS *prs) 59 0 stevel { 60 0 stevel FSTATUS * pfs = prs->form; 61 0 stevel 62 0 stevel prs->form = 0; 63 0 stevel if (pfs) { 64 0 stevel pfs->requests--; 65 0 stevel if (prs->printer) 66 0 stevel check_form_alert (pfs, (_FORM *)0); 67 0 stevel } 68 0 stevel return; 69 0 stevel } 70 0 stevel 71 0 stevel /** 72 0 stevel ** queue_pwheel() - ADD A REQUEST TO A PRINT WHEEL QUEUE 73 0 stevel **/ 74 0 stevel 75 0 stevel void 76 3125 jacobs queue_pwheel(RSTATUS *prs, char *name) 77 0 stevel { 78 0 stevel if (name) { 79 0 stevel prs->pwheel_name = Strdup(name); 80 0 stevel /* 81 0 stevel * Don't bother queueing the request for 82 0 stevel * a print wheel if this request is destined for 83 0 stevel * only this printer and the printer doesn't take 84 0 stevel * print wheels. 85 0 stevel */ 86 0 stevel if ( 87 0 stevel !one_printer_with_charsets(prs) 88 3125 jacobs && (prs->pwheel = search_pwstatus(name)) 89 0 stevel ) { 90 0 stevel prs->pwheel->requests++; 91 0 stevel check_pwheel_alert (prs->pwheel, (PWHEEL *)0); 92 0 stevel } 93 0 stevel } 94 0 stevel return; 95 0 stevel } 96 0 stevel 97 0 stevel /** 98 0 stevel ** unqueue_pwheel() - REMOVE A REQUEST FROM A PRINT WHEEL QUEUE 99 0 stevel **/ 100 0 stevel 101 0 stevel void 102 3125 jacobs unqueue_pwheel(RSTATUS *prs) 103 0 stevel { 104 0 stevel PWSTATUS * ppws = prs->pwheel; 105 0 stevel 106 0 stevel prs->pwheel = 0; 107 0 stevel unload_str (&(prs->pwheel_name)); 108 0 stevel if (ppws) { 109 0 stevel ppws->requests--; 110 0 stevel check_pwheel_alert (ppws, (PWHEEL *)0); 111 0 stevel } 112 0 stevel return; 113 0 stevel } 114 0 stevel 115 0 stevel /** 116 0 stevel ** check_form_alert() - CHECK CHANGES TO MOUNT FORM ALERT 117 0 stevel **/ 118 0 stevel 119 0 stevel void 120 3125 jacobs check_form_alert(FSTATUS *pfs, _FORM *pf) 121 0 stevel { 122 3125 jacobs short trigger, 123 0 stevel fire_off_alert = 0; 124 0 stevel 125 0 stevel int requests_waiting; 126 0 stevel 127 0 stevel 128 0 stevel /* 129 0 stevel * Call this routine whenever a requests has been queued 130 0 stevel * or dequeued for a form, and whenever the form changes. 131 0 stevel * If a pointer to a new _FORM is passed, the FSTATUS 132 0 stevel * structure is updated with the changes. Use a second 133 0 stevel * argument of 0 if no change. 134 0 stevel * 135 0 stevel * WARNING: It is valid to call this routine when adding 136 0 stevel * a NEW form (not just changing it). Thus the members of 137 0 stevel * the structure "pfs->form" may not be set. 138 0 stevel * In this case, though, "pf" MUST be set, and there can 139 0 stevel * be NO alert active. 140 0 stevel */ 141 0 stevel 142 4599 wendyp syslog(LOG_DEBUG, "check_form_alert:\n"); 143 4599 wendyp if (pfs) 144 4599 wendyp syslog(LOG_DEBUG, "check_form_alert: pfs->name <%s>\n", 145 4599 wendyp (pfs->form->name != NULL) ? pfs->form->name : "null"); 146 4599 wendyp if (pf) 147 4599 wendyp syslog(LOG_DEBUG, "check_form_alert: pf->name <%s>\n", 148 4599 wendyp (pf->name != NULL) ? pf->name : "null"); 149 4599 wendyp 150 4599 wendyp 151 0 stevel if (pf) { 152 0 stevel if ((trigger = pf->alert.Q) <= 0) 153 0 stevel trigger = 1; 154 0 stevel } else 155 0 stevel trigger = pfs->trigger; 156 0 stevel 157 0 stevel if (Starting) 158 0 stevel goto Return; 159 0 stevel 160 0 stevel #define OALERT pfs->form->alert 161 0 stevel #define NALERT pf->alert 162 0 stevel 163 0 stevel requests_waiting = max_requests_needing_form_mounted(pfs); 164 0 stevel 165 0 stevel /* 166 0 stevel * Cancel an active alert if the number of requests queued 167 0 stevel * has dropped below the threshold (or the threshold has been 168 0 stevel * raised), or if the alert command or period has changed. 169 0 stevel * In the latter case we'll reactive the alert later. 170 0 stevel */ 171 0 stevel if (pfs->alert->active) 172 0 stevel if (!requests_waiting || requests_waiting < trigger) 173 0 stevel cancel_alert (A_FORM, pfs); 174 0 stevel 175 0 stevel else if ( 176 0 stevel pf 177 0 stevel && ( 178 0 stevel !SAME(NALERT.shcmd, OALERT.shcmd) 179 0 stevel || NALERT.W != OALERT.W 180 0 stevel || NALERT.Q != OALERT.Q 181 0 stevel ) 182 0 stevel ) 183 0 stevel cancel_alert (A_FORM, pfs); 184 0 stevel 185 0 stevel /* 186 0 stevel * If we still have the condition for an alert, we'll fire 187 0 stevel * one off. It is possible the alert is still running, but 188 0 stevel * that's okay. First, we may want to change the alert message; 189 0 stevel * second, the "alert()" routine doesn't execute an alert 190 0 stevel * if it is already running. 191 0 stevel */ 192 0 stevel if (trigger > 0 && requests_waiting >= trigger) 193 0 stevel if ((pf && NALERT.shcmd) || OALERT.shcmd) 194 0 stevel fire_off_alert = 1; 195 0 stevel 196 0 stevel #undef OALERT 197 0 stevel #undef NALERT 198 0 stevel 199 0 stevel Return: if (pf) { 200 0 stevel 201 4599 wendyp pfs->form = pf; 202 4599 wendyp 203 0 stevel pfs->trigger = trigger; 204 0 stevel } 205 0 stevel 206 0 stevel /* 207 0 stevel * Have to do this after updating the changes. 208 0 stevel */ 209 0 stevel if (fire_off_alert) 210 0 stevel alert (A_FORM, pfs); 211 0 stevel 212 0 stevel return; 213 0 stevel } 214 0 stevel 215 0 stevel /** 216 0 stevel ** check_pwheel_alert() - CHECK CHANGES TO MOUNT PRINTWHEEL ALERT 217 0 stevel **/ 218 0 stevel 219 0 stevel void 220 3125 jacobs check_pwheel_alert(PWSTATUS *ppws, PWHEEL *ppw) 221 0 stevel { 222 3125 jacobs short trigger, 223 0 stevel fire_off_alert = 0; 224 0 stevel int requests_waiting; 225 0 stevel 226 0 stevel 227 0 stevel /* 228 0 stevel * Call this routine whenever a request has been queued 229 0 stevel * or dequeued for a print-wheel, and whenever the print-wheel 230 0 stevel * changes. If a pointer to a new PWHEEL is passed, the 231 0 stevel * PWSTATUS structure is updated with the changes. Use a 232 0 stevel * second argument of 0 if no change. 233 0 stevel * 234 0 stevel * WARNING: It is valid to call this routine when adding 235 0 stevel * a NEW print wheel (not just changing it). Thus the members 236 0 stevel * of the structure "ppws->pwheel" may not be set. 237 0 stevel * In this case, though, "ppw" MUST be set, and there can 238 0 stevel * be NO alert active. 239 0 stevel */ 240 0 stevel 241 0 stevel if (ppw) { 242 0 stevel if ((trigger = ppw->alert.Q) <= 0) 243 0 stevel trigger = 1; 244 0 stevel } else 245 0 stevel trigger = ppws->trigger; 246 0 stevel 247 0 stevel if (Starting) 248 0 stevel goto Return; 249 0 stevel 250 0 stevel #define OALERT ppws->pwheel->alert 251 0 stevel #define NALERT ppw->alert 252 0 stevel 253 0 stevel requests_waiting = max_requests_needing_pwheel_mounted(ppws->pwheel->name); 254 0 stevel 255 0 stevel /* 256 0 stevel * Cancel an active alert if the number of requests queued 257 0 stevel * has dropped below the threshold (or the threshold has been 258 0 stevel * raised), or if the alert command or period has changed. 259 0 stevel * In the latter case we'll reactive the alert later. 260 0 stevel */ 261 0 stevel if (ppws->alert->active) 262 0 stevel if (!requests_waiting || requests_waiting < trigger) 263 0 stevel cancel_alert (A_PWHEEL, ppws); 264 0 stevel 265 0 stevel else if ( 266 0 stevel ppw 267 0 stevel && ( 268 0 stevel !SAME(NALERT.shcmd, OALERT.shcmd) 269 0 stevel || NALERT.W != OALERT.W 270 0 stevel || NALERT.Q != OALERT.Q 271 0 stevel ) 272 0 stevel ) 273 0 stevel cancel_alert (A_PWHEEL, ppws); 274 0 stevel 275 0 stevel /* 276 0 stevel * If we still have the condition for an alert, we'll fire 277 0 stevel * one off. It is possible the alert is still running, but 278 0 stevel * that's okay. First, we may want to change the alert message; 279 0 stevel * second, the "alert()" routine doesn't execute an alert 280 0 stevel * if it is already running. 281 0 stevel */ 282 0 stevel if (trigger > 0 && requests_waiting >= trigger) 283 0 stevel if ((ppw && NALERT.shcmd) || OALERT.shcmd) 284 0 stevel fire_off_alert = 1; 285 0 stevel 286 0 stevel #undef OALERT 287 0 stevel #undef NALERT 288 0 stevel 289 0 stevel Return: if (ppw) { 290 0 stevel 291 4599 wendyp ppws->pwheel = ppw; 292 0 stevel ppws->trigger = trigger; 293 0 stevel } 294 0 stevel 295 0 stevel /* 296 0 stevel * Have to do this after updating the changes. 297 0 stevel */ 298 0 stevel if (fire_off_alert) 299 0 stevel alert (A_PWHEEL, ppws); 300 0 stevel 301 0 stevel return; 302 0 stevel } 303 0 stevel 304 0 stevel static int 305 0 stevel trayWithForm(PSTATUS *pps, FSTATUS *pfs, int startingTray, int checkAvail) 306 0 stevel { 307 0 stevel int i; 308 0 stevel PFSTATUS *ppfs; 309 0 stevel 310 0 stevel ppfs = pps->forms; 311 0 stevel if (startingTray < 0) 312 0 stevel startingTray = 0; 313 0 stevel 314 0 stevel if (ppfs) { 315 0 stevel for (i = startingTray; i < pps->numForms; i++) 316 0 stevel if ((!checkAvail || ppfs[i].isAvailable) && 317 0 stevel (ppfs[i].form == pfs)) 318 0 stevel return(i); 319 0 stevel } 320 0 stevel else if (!pfs) 321 0 stevel /* no form request matches no form mounted */ 322 0 stevel return(0); 323 0 stevel 324 0 stevel return(-1); 325 0 stevel } 326 0 stevel 327 0 stevel char * 328 0 stevel allTraysWithForm(PSTATUS *pps, FSTATUS *pfs) 329 0 stevel { 330 0 stevel 331 0 stevel int tray = 0; 332 0 stevel char *ptr, *p; 333 0 stevel char trayList[MAX_INPUT]; 334 0 stevel int n; 335 0 stevel 336 0 stevel ptr = trayList; 337 0 stevel if (pfs && pfs->form && pfs->form->paper) 338 0 stevel p = pfs->form->paper; 339 0 stevel else 340 0 stevel p = ""; 341 0 stevel 342 0 stevel n = sizeof (trayList); 343 0 stevel snprintf(ptr, n, "LP_TRAY_ARG=%s:", p); 344 0 stevel 345 0 stevel ptr += strlen(ptr); 346 0 stevel n -= strlen(ptr); 347 0 stevel 348 0 stevel while ((tray = trayWithForm(pps, pfs, tray, 1)) > 0) { 349 0 stevel tray++; 350 0 stevel snprintf(ptr, n, "%d,", tray); 351 0 stevel ptr += strlen(ptr); 352 0 stevel n -= strlen(ptr); 353 0 stevel } 354 0 stevel if (*(ptr-1) == ',') 355 0 stevel *(ptr-1) = 0; 356 0 stevel 357 0 stevel putenv(trayList); 358 0 stevel return(NULL); 359 0 stevel } 360 0 stevel 361 0 stevel int 362 0 stevel isFormUsableOnPrinter(PSTATUS *pps, FSTATUS *pfs) 363 0 stevel { 364 0 stevel return (trayWithForm(pps,pfs,0,1) >= 0 ); 365 0 stevel } 366 0 stevel int 367 0 stevel isFormMountedOnPrinter(PSTATUS *pps, FSTATUS *pfs) 368 0 stevel { 369 0 stevel return (trayWithForm(pps,pfs,0,0) >= 0 ); 370 0 stevel } 371 0 stevel 372 0 stevel /** 373 0 stevel ** max_requests_needing_form_mounted() 374 0 stevel ** max_requests_needing_pwheel_mounted() 375 0 stevel **/ 376 0 stevel 377 0 stevel static int 378 0 stevel max_requests_needing_form_mounted(FSTATUS *pfs) 379 0 stevel { 380 0 stevel PSTATUS * pps; 381 0 stevel RSTATUS * prs; 382 0 stevel int max = 0; 383 3125 jacobs int i; 384 0 stevel 385 0 stevel /* 386 0 stevel * For each printer that doesn't have this form mounted, 387 0 stevel * count the number of requests needing this form and 388 0 stevel * assigned to the printer. Find the maximum across all such 389 0 stevel * printers. Sorry, the code actually has a different loop 390 0 stevel * (it steps through the requests) but the description of what 391 0 stevel * happens below is easier to understand as given. (Looping 392 0 stevel * through the printers would result in #printers x #requests 393 0 stevel * steps, whereas this entails #requests steps.) 394 0 stevel */ 395 3125 jacobs for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) 396 3125 jacobs PStatus[i]->nrequests = 0; 397 3125 jacobs 398 3125 jacobs for (prs = Request_List; prs != NULL; prs = prs->next) 399 3125 jacobs if ((prs->form == pfs) && ((pps = prs->printer) != NULL) && 400 3125 jacobs (!isFormMountedOnPrinter(pps,pfs)) && 401 3125 jacobs (++pps->nrequests >= max)) 402 3125 jacobs max = pps->nrequests; 403 3125 jacobs 404 0 stevel if (NewRequest) 405 0 stevel if (((pps = NewRequest->printer) != NULL) && 406 0 stevel (!isFormMountedOnPrinter(pps,pfs))) 407 0 stevel if (++pps->nrequests >= max) 408 0 stevel max = pps->nrequests; 409 0 stevel return (max); 410 0 stevel } 411 0 stevel 412 0 stevel static int 413 0 stevel max_requests_needing_pwheel_mounted(char *pwheel_name) 414 0 stevel { 415 0 stevel PSTATUS * pps; 416 0 stevel RSTATUS * prs; 417 0 stevel int max = 0; 418 3125 jacobs int i; 419 0 stevel 420 0 stevel 421 0 stevel /* 422 0 stevel * For each printer that doesn't have this print-wheel mounted, 423 0 stevel * count the number of requests needing this print-wheel and 424 0 stevel * assigned to the printer. Find the maximum across all such 425 0 stevel * printers. Sorry, the code actually has a different loop 426 0 stevel * (it steps through the requests) but the description of what 427 0 stevel * happens below is easier to understand as given. (Looping 428 0 stevel * through the printers would result in #printers x #requests 429 0 stevel * steps, whereas this entails #requests steps.) 430 0 stevel */ 431 3125 jacobs for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) 432 3125 jacobs PStatus[i]->nrequests = 0; 433 3125 jacobs 434 3125 jacobs for (prs = Request_List; prs != NULL; prs = prs->next) 435 3125 jacobs if ((prs->pwheel_name != NULL) && 436 3125 jacobs (STREQU(prs->pwheel_name, pwheel_name)) && 437 3125 jacobs ((pps = prs->printer) != NULL) && pps->printer->daisy && 438 3125 jacobs (!SAME(pps->pwheel_name, pwheel_name))) 439 0 stevel if (++pps->nrequests >= max) 440 0 stevel max = pps->nrequests; 441 3125 jacobs 442 0 stevel if (NewRequest) 443 0 stevel if ( 444 0 stevel ((pps = NewRequest->printer) != NULL) 445 0 stevel && pps->printer->daisy 446 0 stevel && !SAME(pps->pwheel_name, pwheel_name) 447 0 stevel ) 448 0 stevel if (++pps->nrequests >= max) 449 0 stevel max = pps->nrequests; 450 0 stevel return (max); 451 0 stevel } 452 0 stevel 453 0 stevel /** 454 0 stevel ** one_printer_with_charsets() 455 0 stevel **/ 456 0 stevel 457 0 stevel int 458 3125 jacobs one_printer_with_charsets(RSTATUS *prs) 459 0 stevel { 460 0 stevel /* 461 0 stevel * This little function answers the question: Is a request 462 0 stevel * that needs a character set destined for a particular 463 0 stevel * printer that has selectable character sets instead of 464 0 stevel * mountable print wheels? 465 0 stevel */ 466 0 stevel return ( 467 0 stevel STREQU(prs->request->destination, prs->printer->printer->name) 468 0 stevel && !prs->printer->printer->daisy 469 0 stevel ); 470 0 stevel } 471