27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
23f928ce6ceastha * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
277c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bdstevel@tonic-gate/*	  All Rights Reserved  	*/
30f928ce6ceastha#pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bdstevel@tonic-gate# include	<errno.h>
337c478bdstevel@tonic-gate# include	<stdio.h>
347c478bdstevel@tonic-gate# include	<stdlib.h>
367c478bdstevel@tonic-gate# include	"lp.h"
377c478bdstevel@tonic-gate# include	"users.h"
397c478bdstevel@tonic-gatestatic long pri;
427c478bdstevel@tonic-gate  Input:  Path name of the user priority file.  It has the following
437c478bdstevel@tonic-gate		format:
447c478bdstevel@tonic-gate	1 line with a number representing the default priority level.
457c478bdstevel@tonic-gate		This must be the first line of the file, and no extra
467c478bdstevel@tonic-gate		white space is allowed between the priority value and
477c478bdstevel@tonic-gate		the newline.
487c478bdstevel@tonic-gate	1 line anywhere in the file with a number representing
497c478bdstevel@tonic-gate		the default priority limit.  This number is followed
507c478bdstevel@tonic-gate		by a ':', and no extra white space is allowed.
517c478bdstevel@tonic-gate	any number of lines with a number followed by a ':', followed
527c478bdstevel@tonic-gate		by a white space (blank, tab or newline) separated
537c478bdstevel@tonic-gate		list of user names.  No white space is allowed
547c478bdstevel@tonic-gate		between the priority value and the colon (:), but any
557c478bdstevel@tonic-gate		amount is ok in the UID list.
577c478bdstevel@tonic-gate  Note:  If the default priority level is missing, a value of 20 will
587c478bdstevel@tonic-gate	be used.  If the default limit is missing, zero will be used.
597c478bdstevel@tonic-gate	Also, the st_priority_file writes out the priority file in the
607c478bdstevel@tonic-gate	same order as the fields occur in the user_priority structure,
617c478bdstevel@tonic-gate	but the only order restriction is that the default level is
627c478bdstevel@tonic-gate	the first this.  A priority level may occur more than once, and
637c478bdstevel@tonic-gate	this function will group them together (but the defaults may
647c478bdstevel@tonic-gate	only occur once, however the defaults may occur only once each.
667c478bdstevel@tonic-gate  Output:  This function returns a pointer to a statically stored
677c478bdstevel@tonic-gate	structure containing the priority information.
697c478bdstevel@tonic-gate   Effect:  The user priority file is read and parsed.  Storage for
707c478bdstevel@tonic-gate	the priorities are allocated and loaded.  In case of an error,
717c478bdstevel@tonic-gate	it prints out an error message, and returns 0 (NULL).
747c478bdstevel@tonic-gatestruct user_priority * ld_priority_file ( char * path )
767c478bdstevel@tonic-gate    char				line[BUFSIZ],
777c478bdstevel@tonic-gate					*p,
787c478bdstevel@tonic-gate					*user,
797c478bdstevel@tonic-gate					*next_user();
807c478bdstevel@tonic-gate    static struct user_priority		pri_tbl;
817c478bdstevel@tonic-gate    int					line_no	= 1,
827c478bdstevel@tonic-gate    					opri;
837c478bdstevel@tonic-gate    int fd;
857c478bdstevel@tonic-gate    if ((fd = open_locked(path, "r", 0)) < 0) {
867c478bdstevel@tonic-gate	if (errno == ENOENT) {
887c478bdstevel@tonic-gate	    pri_tbl.deflt = LEVEL_DFLT;
897c478bdstevel@tonic-gate	    pri_tbl.deflt_limit = LIMIT_DFLT;
907c478bdstevel@tonic-gate	    memset ((char *)pri_tbl.users, 0, sizeof(pri_tbl.users));
917c478bdstevel@tonic-gate	    return (&pri_tbl);
927c478bdstevel@tonic-gate	}
937c478bdstevel@tonic-gate	return(0);
947c478bdstevel@tonic-gate    }
967c478bdstevel@tonic-gate    /* initialize table to empty */
977c478bdstevel@tonic-gate    pri_tbl.deflt = -1;
987c478bdstevel@tonic-gate    pri_tbl.deflt_limit = -1;
997c478bdstevel@tonic-gate    memset ((char *)pri_tbl.users, 0, sizeof(pri_tbl.users));
1017c478bdstevel@tonic-gate    /* this loop reads the line containing the default priority,
1027c478bdstevel@tonic-gate       if any, and the first priority limit.  p is left pointing
1037c478bdstevel@tonic-gate       to the colon (:) in the line with the first limit. */
1057c478bdstevel@tonic-gate    while (1)
1067c478bdstevel@tonic-gate    {
1077c478bdstevel@tonic-gate	if (!(p = fdgets(line, BUFSIZ, fd)))
1087c478bdstevel@tonic-gate	    goto empty;
1097c478bdstevel@tonic-gate	p = line;
1107c478bdstevel@tonic-gate	pri = strtol(line, &p, 10);
1117c478bdstevel@tonic-gate	if (p == line)
1127c478bdstevel@tonic-gate	    goto Error;
1137c478bdstevel@tonic-gate	if (pri < PRI_MIN || pri > PRI_MAX)
1147c478bdstevel@tonic-gate	    goto Error;
1157c478bdstevel@tonic-gate	if (line_no == 1 && *p == '\n' && !p[1])
1167c478bdstevel@tonic-gate	    pri_tbl.deflt = pri;
1177c478bdstevel@tonic-gate	else
1187c478bdstevel@tonic-gate	    if (*p == ':')
1197c478bdstevel@tonic-gate	    {
1207c478bdstevel@tonic-gate		p++;
1217c478bdstevel@tonic-gate		break;
1227c478bdstevel@tonic-gate	    }
1237c478bdstevel@tonic-gate	    else
1247c478bdstevel@tonic-gate		goto Error;
1257c478bdstevel@tonic-gate	line_no++;
1267c478bdstevel@tonic-gate    }
1287c478bdstevel@tonic-gate    do
1297c478bdstevel@tonic-gate    {
1307c478bdstevel@tonic-gate	/* search list for this priority */
1317c478bdstevel@tonic-gate	opri = pri;
1327c478bdstevel@tonic-gate	if (!(user = next_user(fd, line, &p)))
1337c478bdstevel@tonic-gate	{
1347c478bdstevel@tonic-gate	    if (pri_tbl.deflt_limit == -1)
1357c478bdstevel@tonic-gate	    {
1367c478bdstevel@tonic-gate		pri_tbl.deflt_limit = opri;
1377c478bdstevel@tonic-gate		if (pri == -1) break;
1387c478bdstevel@tonic-gate		if (!(user = next_user(fd, line, &p))) goto Error;
1397c478bdstevel@tonic-gate	    }
1407c478bdstevel@tonic-gate	    else
1417c478bdstevel@tonic-gate	    {
1437c478bdstevel@tonic-gate	        errno = EBADF;
1447c478bdstevel@tonic-gate		close(fd);
1457c478bdstevel@tonic-gate		return(0);
1467c478bdstevel@tonic-gate	    }
1477c478bdstevel@tonic-gate	}
1497c478bdstevel@tonic-gate	do
1507c478bdstevel@tonic-gate	{
1517c478bdstevel@tonic-gate	    add_user (&pri_tbl, user, pri);
1527c478bdstevel@tonic-gate	}
1537c478bdstevel@tonic-gate	while ((user = next_user(fd, line, &p)));
1547c478bdstevel@tonic-gate    }
1557c478bdstevel@tonic-gate    while (pri != -1);
1577c478bdstevel@tonic-gate    if (pri_tbl.deflt == -1)
1587c478bdstevel@tonic-gate	pri_tbl.deflt = LEVEL_DFLT;
1607c478bdstevel@tonic-gate    if (pri_tbl.deflt_limit == -1)
1617c478bdstevel@tonic-gate	pri_tbl.deflt_limit = LIMIT_DFLT;
1637c478bdstevel@tonic-gate    close(fd);
1647c478bdstevel@tonic-gate    return (&pri_tbl);
1687c478bdstevel@tonic-gateInputs:  A pointer to a limit structure, and a user.
1697c478bdstevel@tonic-gateOuputs:  The limit structure is modified.
1707c478bdstevel@tonic-gateEffects: Adds <user> to the list of users, if it is not already
1717c478bdstevel@tonic-gate	 there.
1747c478bdstevel@tonic-gateint add_user ( struct user_priority * ppri_tbl, char * user, int limit )
1767c478bdstevel@tonic-gate    if (limit < PRI_MIN || PRI_MAX < limit)
1777c478bdstevel@tonic-gate	return 1;
1787c478bdstevel@tonic-gate    addlist (&(ppri_tbl->users[limit - PRI_MIN]), user);
1797c478bdstevel@tonic-gate    return 0;
1837c478bdstevel@tonic-gateInputs:   The input file to read additional lines, a pointer to
1847c478bdstevel@tonic-gate	  a buffer containing the current line, and to read additional
1857c478bdstevel@tonic-gate	  lines into, and a pointer to the location pointer (a pointer
1867c478bdstevel@tonic-gate	  into buf).
1877c478bdstevel@tonic-gateOutputs:  The routine returns the next user-id read or 0 if all the
1887c478bdstevel@tonic-gate	  users for this priority are read.  The buffer, the location
1897c478bdstevel@tonic-gate	  pointer, and the variable pri are modified as a side effect.
1907c478bdstevel@tonic-gateEffects:  The input buffer is scanned starting at *pp for the next
1917c478bdstevel@tonic-gate	  user-id, if the end of the line is reached, the next line is
1927c478bdstevel@tonic-gate	  read from the file.  If it scans the next priority value, the
1937c478bdstevel@tonic-gate	  variable pri (static to this file), is set to that priority.
1947c478bdstevel@tonic-gate	  EOF is indicated by setting this variable to -1, and also
1957c478bdstevel@tonic-gate	  returning 0.
1977c478bdstevel@tonic-gatechar * next_user (int fd, char * buf, char ** pp )
1997c478bdstevel@tonic-gate    long	temp;
2007c478bdstevel@tonic-gate    char	*p;
201f928ce6ceastha    static	int beg_line = 0; /* assumes a partial line is in buf to start */
2037c478bdstevel@tonic-gate    do
2047c478bdstevel@tonic-gate    {
2057c478bdstevel@tonic-gate	while (**pp == ' ' || **pp == '\n' || **pp == '\t')
2067c478bdstevel@tonic-gate	    (*pp)++;
2077c478bdstevel@tonic-gate	p = *pp;
2087c478bdstevel@tonic-gate	if (*p)
2097c478bdstevel@tonic-gate	{
2107c478bdstevel@tonic-gate	    if (*p >= '0' && *p <= '9')
2117c478bdstevel@tonic-gate	    {
2127c478bdstevel@tonic-gate		temp = strtol(p, pp, 10);
2137c478bdstevel@tonic-gate		if (beg_line && **pp == ':')
2147c478bdstevel@tonic-gate		{
2157c478bdstevel@tonic-gate		    (*pp)++;
2167c478bdstevel@tonic-gate		    pri = temp;
2177c478bdstevel@tonic-gate		    beg_line = 0;
2187c478bdstevel@tonic-gate		    return (0);
2197c478bdstevel@tonic-gate		}
2207c478bdstevel@tonic-gate	    }
2227c478bdstevel@tonic-gate	    for (; **pp && **pp != ' ' && **pp != '\n' && **pp != '\t'; (*pp)++)
2237c478bdstevel@tonic-gate		;
2247c478bdstevel@tonic-gate	    if (**pp)
2257c478bdstevel@tonic-gate		*(*pp)++ = 0;
2267c478bdstevel@tonic-gate	    beg_line = 0;
2277c478bdstevel@tonic-gate	    return (p);
2287c478bdstevel@tonic-gate	}
2297c478bdstevel@tonic-gate	beg_line = 1;
2307c478bdstevel@tonic-gate    }
2317c478bdstevel@tonic-gate    while (*pp = fdgets(buf, BUFSIZ, fd));
2337c478bdstevel@tonic-gate    pri = -1;
2347c478bdstevel@tonic-gate    return (0);
2387c478bdstevel@tonic-gateInputs:  A pointer to a priority table and a user.
2397c478bdstevel@tonic-gateOutputs: Zero if user found, else 1, and priority table is modified.
2407c478bdstevel@tonic-gateEffects: All occurences of <user> in the priority table will be removed.
2417c478bdstevel@tonic-gate	 (There should only be one at most.)
2437c478bdstevel@tonic-gateint del_user ( struct user_priority * ppri_tbl, char * user )
2457c478bdstevel@tonic-gate    int		limit;
2477c478bdstevel@tonic-gate    for (limit = PRI_MIN; limit <= PRI_MAX; limit++)
2487c478bdstevel@tonic-gate	if (searchlist(user, ppri_tbl->users[limit - PRI_MIN]))
2497c478bdstevel@tonic-gate	{
2507c478bdstevel@tonic-gate	    dellist (&(ppri_tbl->users[limit - PRI_MIN]), user);
2517c478bdstevel@tonic-gate	    return (0);
2527c478bdstevel@tonic-gate	}
2537c478bdstevel@tonic-gate    return (1);