/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ #include "unistd.h" #include "sys/types.h" #include "sys/stat.h" #include "errno.h" #include "fcntl.h" #include "stdlib.h" #include "string.h" #include "lpsched.h" static int __list_increment = 16; int list_append(void ***list, void *item) { int count; if ((list == NULL) || (item == NULL)) { errno = EINVAL; return (-1); } if (item != NULL) { if (*list == NULL) *list = (void **)calloc(__list_increment, sizeof (void *)); if (*list == NULL) return (-1); for (count = 0; (*list)[count] != NULL; count++); if ((count + 1) % __list_increment == 0) { /* expand the list */ void **new_list = NULL; int new_size = (((count + 1) / __list_increment) + 1) * __list_increment; new_list = (void **)calloc(new_size, sizeof (void *)); if (new_list == NULL) return (-1); for (count = 0; (*list)[count] != NULL; count++) new_list[count] = (*list)[count]; free(*list); *list = new_list; } (*list)[count] = item; } return (0); } void list_remove(void ***list, void *item) { int i, count; void **tmp = NULL; if ((list == NULL) || (*list == NULL) || (item == NULL)) return; for (count = 0; (*list)[count] != NULL; count++) ; if (count > 0) { int new_size = (((count + 1) / __list_increment) + 1) * __list_increment; if ((tmp = (void **)calloc(new_size, sizeof (void *))) == NULL) tmp = *list; /* copy up to item */ for (i = 0; (((*list)[i] != NULL) && ((*list)[i] != item)); i++) tmp[i] = (*list)[i]; /* copy after item */ if ((*list)[i] == item) for (++i; ((*list)[i] != NULL); i++) tmp[i-1] = (*list)[i]; } /* replace the list */ if (tmp != *list) { free(*list); *list = tmp; } } void free_exec(EXEC *ep) { if (ep != NULL) { free(ep); list_remove((void ***)&Exec_Table, (void *)ep); } } EXEC * new_exec(int type, void *ex) { EXEC *result = calloc(1, sizeof (*result)); if (result != NULL) { result->type = type; switch (type) { case EX_ALERT: case EX_INTERF: case EX_FAULT_MESSAGE: result->ex.printer = ex; break; case EX_FALERT: result->ex.form = ex; break; case EX_PALERT: result->ex.pwheel = ex; break; case EX_SLOWF: case EX_NOTIFY: break; } list_append((void ***)&Exec_Table, (void *)result); } return (result); } void free_alert(ALERT *ap) { if (ap != NULL) { if (ap->msgfile != NULL) free(ap->msgfile); if (ap->exec != NULL) free_exec(ap->exec); free(ap); } } ALERT * new_alert(char *fmt, int i) { ALERT *result = calloc(1, sizeof (*result)); if (result != NULL) { char buf[15]; snprintf(buf, sizeof (buf), fmt, i); result->msgfile = makepath(Lp_Temp, buf, (char *)0); (void) Unlink(result->msgfile); } return (result); } void free_pstatus(PSTATUS *psp) { if (psp != NULL) { if (psp->alert != NULL) free_alert(psp->alert); if (psp->exec != NULL) free_exec(psp->exec); if (psp->fault_exec != NULL) free_exec(psp->fault_exec); if (psp->printer != NULL) freeprinter(psp->printer); if (psp->pwheel_name != NULL) free(psp->pwheel_name); if (psp->dis_reason != NULL) free(psp->dis_reason); if (psp->rej_reason != NULL) free(psp->rej_reason); if (psp->users_allowed != NULL) unload_list(&psp->users_allowed); if (psp->users_denied != NULL) unload_list(&psp->users_denied); if (psp->forms_allowed != NULL) unload_list(&psp->forms_allowed); if (psp->forms_denied != NULL) unload_list(&psp->forms_denied); if (psp->cpi != NULL) free(psp->cpi); if (psp->lpi != NULL) free(psp->lpi); if (psp->plen != NULL) free(psp->plen); if (psp->pwid != NULL) free(psp->pwid); if (psp->fault_reason != NULL) free(psp->fault_reason); if (psp->paper_allowed != NULL) unload_list(&psp->paper_allowed); free(psp); } } void pstatus_add_printer(PSTATUS *ps, PRINTER *p) { if ((ps != NULL) && (p != NULL)) { char **paperDenied = NULL; ps->printer = p; load_userprinter_access(p->name, &(ps->users_allowed), &(ps->users_denied)); load_formprinter_access(p->name, &(ps->forms_allowed), &(ps->forms_denied)); load_paperprinter_access(p->name, &ps->paper_allowed, &paperDenied); freelist(paperDenied); load_sdn(&(ps->cpi), p->cpi); load_sdn(&(ps->lpi), p->lpi); load_sdn(&(ps->plen), p->plen); load_sdn(&(ps->pwid), p->pwid); } } PSTATUS * new_pstatus(PRINTER *p) { PSTATUS *result = calloc(1, sizeof (*result)); if (result != NULL) { static int i = 0; char **paperDenied = NULL; result->alert = new_alert("A-%d", i++); result->alert->exec = new_exec(EX_ALERT, result); result->exec = new_exec(EX_INTERF, result); result->fault_exec = new_exec(EX_FAULT_MESSAGE, result); if (p != NULL) pstatus_add_printer(result, p); list_append((void ***)&PStatus, (void *)result); } return (result); } void free_cstatus(CLSTATUS *csp) { if (csp != NULL) { if (csp->rej_reason != NULL) free(csp->rej_reason); if (csp->class != NULL) freeclass(csp->class); free(csp); } } CLSTATUS * new_cstatus(CLASS *c) { CLSTATUS *result = calloc(1, sizeof (*result)); if (result != NULL) { if (c != NULL) result->class = c; else result->class = calloc(1, sizeof (CLASS)); list_append((void ***)&CStatus, result); } return (result); } void free_fstatus(FSTATUS *fsp) { if (fsp != NULL) { if (fsp->form != NULL) free_form(fsp->form); if (fsp->alert != NULL) free_alert(fsp->alert); if (fsp->users_allowed != NULL) unload_list(&fsp->users_allowed); if (fsp->users_denied != NULL) unload_list(&fsp->users_denied); if (fsp->cpi != NULL) free(fsp->cpi); if (fsp->lpi != NULL) free(fsp->lpi); if (fsp->plen != NULL) free(fsp->plen); if (fsp->pwid != NULL) free(fsp->pwid); free(fsp); } } FSTATUS * new_fstatus(_FORM *f) { FSTATUS *result = calloc(1, sizeof (*result)); if (result != NULL) { static int i = 0; if (f != NULL) result->form = f; else result->form = calloc(1, sizeof (_FORM)); result->alert = new_alert("F-%d", i++); result->alert->exec = new_exec(EX_FALERT, result); result->trigger = result->form->alert.Q; if (f != NULL) { load_userform_access(f->name, &(result->users_allowed), &(result->users_denied)); load_sdn (&(result->cpi), f->cpi); load_sdn (&(result->lpi), f->lpi); load_sdn (&(result->plen), f->plen); load_sdn (&(result->pwid), f->pwid); } list_append((void ***)&FStatus, (void *)result); } return (result); } void free_pwstatus(PWSTATUS *pwp) { if (pwp != NULL) { if (pwp->pwheel) freepwheel(pwp->pwheel); if (pwp->alert != NULL) free_alert(pwp->alert); free(pwp); } } PWSTATUS * new_pwstatus(PWHEEL *p) { PWSTATUS *result = calloc(1, sizeof (*result)); if (result != NULL) { static int i = 0; if (p != NULL) result->pwheel = p; else result->pwheel = calloc(1, sizeof (*result)); result->alert = new_alert("P-%d", i++); result->alert->exec = new_exec(EX_PALERT, result); result->trigger = result->pwheel->alert.Q; list_append((void ***)&PWStatus, (void *)result); } return (result); } void free_rstatus(RSTATUS *rsp) { if (rsp != NULL) { remover(rsp); if (rsp->request != NULL) freerequest(rsp->request); if (rsp->secure != NULL) freesecure(rsp->secure); if (rsp->req_file) Free (rsp->req_file); if (rsp->slow) Free (rsp->slow); if (rsp->fast) Free (rsp->fast); if (rsp->pwheel_name) Free (rsp->pwheel_name); if (rsp->printer_type) Free (rsp->printer_type); if (rsp->output_type) Free (rsp->output_type); if (rsp->cpi) Free (rsp->cpi); if (rsp->lpi) Free (rsp->lpi); if (rsp->plen) Free (rsp->plen); if (rsp->pwid) Free (rsp->pwid); free(rsp); } } RSTATUS * new_rstatus(REQUEST *r, SECURE *s) { RSTATUS *result = calloc(1, sizeof (*result)); if (result != NULL) { if ((result->request = r) == NULL) result->request = calloc(1, sizeof (REQUEST)); if ((result->secure = s) == NULL) result->secure = calloc(1, sizeof (SECURE)); } return (result); } /** ** search_pstatus() - SEARCH PRINTER TABLE ** search_fstatus() - SEARCH FORMS TABLE ** search_cstatus() - SEARCH CLASS TABLE ** search_pwstatus() - SEARCH PRINT WHEEL TABLE **/ PSTATUS * search_pstatus(register char *name) { PSTATUS *ps = NULL; if (name != NULL) { if (PStatus != NULL) { int i; for (i = 0; ((PStatus[i] != NULL) && (ps == NULL)); i++) if (SAME(PStatus[i]->printer->name, name)) ps = PStatus[i]; } } else ps = new_pstatus(NULL); return (ps); } FSTATUS * search_fstatus(register char *name) { FSTATUS *ps = NULL; if (name != NULL) { if (FStatus != NULL) { int i; for (i = 0; ((FStatus[i] != NULL) && (ps == NULL)); i++) if (SAME(FStatus[i]->form->name, name)) ps = FStatus[i]; } } else ps = new_fstatus(NULL); return (ps); } FSTATUS * search_fptable(register char *paper) { FSTATUS *ps = NULL; int i; if (FStatus != NULL) { for (i = 0; ((FStatus[i] != NULL) && (ps == NULL)); i++) if (SAME(FStatus[i]->form->paper, paper)) { if (ps->form->isDefault) ps = FStatus[i]; } } return (ps); } CLSTATUS * search_cstatus(register char *name) { CLSTATUS *ps = NULL; if (name != NULL) { if (CStatus != NULL) { int i; for (i = 0; ((CStatus[i] != NULL) && (ps == NULL)); i++) if (SAME(CStatus[i]->class->name, name)) ps = CStatus[i]; } } else ps = new_cstatus(NULL); return (ps); } PWSTATUS * search_pwstatus(register char *name) { PWSTATUS *ps = NULL; if (name != NULL) { if (PWStatus != NULL) { int i; for (i = 0; ((PWStatus[i] != NULL) && (ps == NULL)); i++) if (SAME(PWStatus[i]->pwheel->name, name)) ps = PWStatus[i]; } } else ps = new_pwstatus(NULL); return (ps); } /** ** load_str() - LOAD STRING WHERE ALLOC'D STRING MAY BE ** unload_str() - REMOVE POSSIBLE ALLOC'D STRING **/ void load_str(char **pdst, char *src) { if (*pdst) Free (*pdst); *pdst = Strdup(src); return; } void unload_str(char **pdst) { if (*pdst) Free (*pdst); *pdst = 0; return; } /** ** unload_list() - REMOVE POSSIBLE ALLOC'D LIST **/ void unload_list(char ***plist) { if (*plist) freelist (*plist); *plist = 0; return; } /** ** load_sdn() - LOAD STRING WITH ASCII VERSION OF SCALED DECIMAL NUMBER **/ void load_sdn(char **p, SCALED sdn) { if (!p) return; if (*p) Free (*p); *p = 0; if (sdn.val <= 0 || 999999 < sdn.val) return; *p = Malloc(sizeof("999999.999x")); sprintf ( *p, "%.3f%s", sdn.val, (sdn.sc == 'c'? "c" : (sdn.sc == 'i'? "i" : "")) ); return; } /** ** Getform() - EASIER INTERFACE TO "getform()" **/ _FORM * Getform(char *form) { _FORM *_form; FORM formbuf; FALERT alertbuf; int ret; while ( (ret = getform(form, &formbuf, &alertbuf, (FILE **)0)) == -1 && errno == EINTR ) ; if (ret == -1) return (0); _form = calloc(1, sizeof (*_form)); _form->plen = formbuf.plen; _form->pwid = formbuf.pwid; _form->lpi = formbuf.lpi; _form->cpi = formbuf.cpi; _form->np = formbuf.np; _form->chset = formbuf.chset; _form->mandatory = formbuf.mandatory; _form->rcolor = formbuf.rcolor; _form->comment = formbuf.comment; _form->conttype = formbuf.conttype; _form->name = formbuf.name; _form->paper = formbuf.paper; _form->isDefault = formbuf.isDefault; if ((_form->alert.shcmd = alertbuf.shcmd) != NULL) { _form->alert.Q = alertbuf.Q; _form->alert.W = alertbuf.W; } else { _form->alert.Q = 0; _form->alert.W = 0; } return (_form); } /** ** Getprinter() ** Getrequest() ** Getuser() ** Getclass() ** Getpwheel() ** Getsecure() ** Loadfilters() **/ PRINTER * Getprinter(char *name) { register PRINTER *ret; while (!(ret = getprinter(name)) && errno == EINTR) ; return (ret); } REQUEST * Getrequest(char *file) { register REQUEST *ret; while (!(ret = getrequest(file)) && errno == EINTR) ; return (ret); } USER * Getuser(char *name) { register USER *ret; while (!(ret = getuser(name)) && errno == EINTR) ; return (ret); } CLASS * Getclass(char *name) { register CLASS *ret; while (!(ret = getclass(name)) && errno == EINTR) ; return (ret); } PWHEEL * Getpwheel(char *name) { register PWHEEL *ret; while (!(ret = getpwheel(name)) && errno == EINTR) ; return (ret); } SECURE * Getsecure(char *file) { register SECURE *ret; while (!(ret = getsecure(file)) && errno == EINTR) ; return ((SECURE *) ret); } int Loadfilters(char *file) { register int ret; while ((ret = loadfilters(file)) == -1 && errno == EINTR) ; return (ret); } /** ** free_form() - FREE MEMORY ALLOCATED FOR _FORM STRUCTURE **/ void free_form(register _FORM *pf) { if (!pf) return; if (pf->chset) Free (pf->chset); if (pf->rcolor) Free (pf->rcolor); if (pf->comment) Free (pf->comment); if (pf->conttype) Free (pf->conttype); if (pf->name) Free (pf->name); if (pf->paper) Free (pf->paper); pf->name = 0; if (pf->alert.shcmd) Free (pf->alert.shcmd); return; } /** ** getreqno() - GET NUMBER PART OF REQUEST ID **/ char * getreqno(char *req_id) { register char *cp; if (!(cp = strrchr(req_id, '-'))) cp = req_id; else cp++; return (cp); } /* Putsecure(): Insurance for writing out the secure request file. * input: char ptr to name of the request file, * ptr to the SECURE structure to be written. * ouput: 0 if successful, -1 otherwise. * * Description: * The normal call to putsecure() is woefully lacking. * The bottom line here is that there * is no way to make sure that the file has been written out * as expected. This can cause rude behaviour later on. * * This routine calls putsecure(), and then does a getsecure(). * The results are compared to the original structure. If the * info obtained by getsecure() doesn't match, we retry a few * times before giving up (presumably something is very seriously * wrong at that point). */ int Putsecure(char *file, SECURE *secbufp) { SECURE *pls; int retries = 5; /* # of attempts */ int status; /* 0 = success, nonzero otherwise */ while (retries--) { status = 1; /* assume the worst, hope for the best */ if (putsecure(file, secbufp) == -1) { rmsecure(file); continue; } if ((pls = getsecure(file)) == (SECURE *) NULL) { rmsecure(file); status = 2; continue; } /* now compare each field */ /* * A comparison is only valid if secbufp and pls point to * different locations. In reality getsecure() will have * already been called, allocating the same STATIC memory * location to both structures making the following compare * meaningless. * Therefore test for this condition to prevent us from * calling freesecure which will destroy uid and * req_id fields in the strucure */ status = 0; if (secbufp != pls) { if (strcmp(pls->req_id, secbufp->req_id) != 0) { rmsecure(file); status = 3; continue; } if (pls->uid != secbufp->uid) { rmsecure(file); status = 4; continue; } if (strcmp(pls->user, secbufp->user) != 0) { rmsecure(file); status = 5; continue; } if (pls->gid != secbufp->gid) { rmsecure(file); status = 6; continue; } if (pls->size != secbufp->size) { rmsecure(file); status = 7; continue; } if (pls->date != secbufp->date) { rmsecure(file); status = 8; continue; } freesecure(pls); } break; } if (status != 0) { note("Putsecure failed, status=%d\n", status); return -1; } return 0; } void GetRequestFiles(REQUEST *req, char *buffer, int length) { char buf[BUFSIZ]; memset(buf, 0, sizeof(buf)); if (req->title) { char *r = req->title; char *ptr = buf; while ( *r && strncmp(r,"\\n",2)) { *ptr++ = *r++; } } else if (req->file_list) strlcpy(buf, *req->file_list, sizeof (buf)); if (*buf == '\0' || !strncmp(buf, SPOOLDIR, sizeof(SPOOLDIR)-1)) strcpy(buf, ""); if (strlen(buf) > (size_t) 24) { char *r; if (r = strrchr(buf, '/')) r++; else r = buf; snprintf(buffer, length, "%-.24s", r); } else strlcpy(buffer, buf, length); return; } /** ** _Malloc() ** _Realloc() ** _Calloc() ** _Strdup() ** _Free() **/ void (*lp_alloc_fail_handler)( void ) = 0; typedef void *alloc_type; alloc_type _Malloc(size_t size, const char *file, int line) { alloc_type ret; ret = malloc(size); if (!ret) { if (lp_alloc_fail_handler) (*lp_alloc_fail_handler)(); errno = ENOMEM; } return (ret); } alloc_type _Realloc(void *ptr, size_t size, const char *file, int line) { alloc_type ret = realloc(ptr, size); if (!ret) { if (lp_alloc_fail_handler) (*lp_alloc_fail_handler)(); errno = ENOMEM; } return (ret); } alloc_type _Calloc(size_t nelem, size_t elsize, const char *file, int line) { alloc_type ret = calloc(nelem, elsize); if (!ret) { if (lp_alloc_fail_handler) (*lp_alloc_fail_handler)(); errno = ENOMEM; } return (ret); } char * _Strdup(const char *s, const char *file, int line) { char * ret; if (!s) return( (char *) 0); ret = strdup(s); if (!ret) { if (lp_alloc_fail_handler) (*lp_alloc_fail_handler)(); errno = ENOMEM; } return (ret); } void _Free(void *ptr, const char *file, int line) { free (ptr); return; }