fncs.c revision 19d32b9ab53d17ac6605971e14c45a5281f8d9bb
/*
* 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 == NULL || !strncmp(buf, SPOOLDIR, sizeof(SPOOLDIR)-1))
strcpy(buf, "<File name not available>");
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;
}