xref: /illumos-gate/usr/src/cmd/lp/lib/users/loadpri.c (revision f928ce67ef743c33ea27c573c9c7e2d4a4833cbd)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 # include	<errno.h>
33 # include	<stdio.h>
34 # include	<stdlib.h>
35 
36 # include	"lp.h"
37 # include	"users.h"
38 
39 static long pri;
40 
41 /*
42   Input:  Path name of the user priority file.  It has the following
43 		format:
44 	1 line with a number representing the default priority level.
45 		This must be the first line of the file, and no extra
46 		white space is allowed between the priority value and
47 		the newline.
48 	1 line anywhere in the file with a number representing
49 		the default priority limit.  This number is followed
50 		by a ':', and no extra white space is allowed.
51 	any number of lines with a number followed by a ':', followed
52 		by a white space (blank, tab or newline) separated
53 		list of user names.  No white space is allowed
54 		between the priority value and the colon (:), but any
55 		amount is ok in the UID list.
56 
57   Note:  If the default priority level is missing, a value of 20 will
58 	be used.  If the default limit is missing, zero will be used.
59 	Also, the st_priority_file writes out the priority file in the
60 	same order as the fields occur in the user_priority structure,
61 	but the only order restriction is that the default level is
62 	the first this.  A priority level may occur more than once, and
63 	this function will group them together (but the defaults may
64 	only occur once, however the defaults may occur only once each.
65 
66   Output:  This function returns a pointer to a statically stored
67 	structure containing the priority information.
68 
69    Effect:  The user priority file is read and parsed.  Storage for
70 	the priorities are allocated and loaded.  In case of an error,
71 	it prints out an error message, and returns 0 (NULL).
72 */
73 
74 struct user_priority * ld_priority_file ( char * path )
75 {
76     char				line[BUFSIZ],
77 					*p,
78 					*user,
79 					*next_user();
80     static struct user_priority		pri_tbl;
81     int					line_no	= 1,
82     					opri;
83     int fd;
84 
85     if ((fd = open_locked(path, "r", 0)) < 0) {
86 	if (errno == ENOENT) {
87 empty:
88 	    pri_tbl.deflt = LEVEL_DFLT;
89 	    pri_tbl.deflt_limit = LIMIT_DFLT;
90 	    memset ((char *)pri_tbl.users, 0, sizeof(pri_tbl.users));
91 	    return (&pri_tbl);
92 	}
93 	return(0);
94     }
95 
96     /* initialize table to empty */
97     pri_tbl.deflt = -1;
98     pri_tbl.deflt_limit = -1;
99     memset ((char *)pri_tbl.users, 0, sizeof(pri_tbl.users));
100 
101     /* this loop reads the line containing the default priority,
102        if any, and the first priority limit.  p is left pointing
103        to the colon (:) in the line with the first limit. */
104 
105     while (1)
106     {
107 	if (!(p = fdgets(line, BUFSIZ, fd)))
108 	    goto empty;
109 	p = line;
110 	pri = strtol(line, &p, 10);
111 	if (p == line)
112 	    goto Error;
113 	if (pri < PRI_MIN || pri > PRI_MAX)
114 	    goto Error;
115 	if (line_no == 1 && *p == '\n' && !p[1])
116 	    pri_tbl.deflt = pri;
117 	else
118 	    if (*p == ':')
119 	    {
120 		p++;
121 		break;
122 	    }
123 	    else
124 		goto Error;
125 	line_no++;
126     }
127 
128     do
129     {
130 	/* search list for this priority */
131 	opri = pri;
132 	if (!(user = next_user(fd, line, &p)))
133 	{
134 	    if (pri_tbl.deflt_limit == -1)
135 	    {
136 		pri_tbl.deflt_limit = opri;
137 		if (pri == -1) break;
138 		if (!(user = next_user(fd, line, &p))) goto Error;
139 	    }
140 	    else
141 	    {
142 Error:
143 	        errno = EBADF;
144 		close(fd);
145 		return(0);
146 	    }
147 	}
148 
149 	do
150 	{
151 	    add_user (&pri_tbl, user, pri);
152 	}
153 	while ((user = next_user(fd, line, &p)));
154     }
155     while (pri != -1);
156 
157     if (pri_tbl.deflt == -1)
158 	pri_tbl.deflt = LEVEL_DFLT;
159 
160     if (pri_tbl.deflt_limit == -1)
161 	pri_tbl.deflt_limit = LIMIT_DFLT;
162 
163     close(fd);
164     return (&pri_tbl);
165 }
166 
167 /*
168 Inputs:  A pointer to a limit structure, and a user.
169 Ouputs:  The limit structure is modified.
170 Effects: Adds <user> to the list of users, if it is not already
171 	 there.
172 */
173 
174 int add_user ( struct user_priority * ppri_tbl, char * user, int limit )
175 {
176     if (limit < PRI_MIN || PRI_MAX < limit)
177 	return 1;
178     addlist (&(ppri_tbl->users[limit - PRI_MIN]), user);
179     return 0;
180 }
181 
182 /*
183 Inputs:   The input file to read additional lines, a pointer to
184 	  a buffer containing the current line, and to read additional
185 	  lines into, and a pointer to the location pointer (a pointer
186 	  into buf).
187 Outputs:  The routine returns the next user-id read or 0 if all the
188 	  users for this priority are read.  The buffer, the location
189 	  pointer, and the variable pri are modified as a side effect.
190 Effects:  The input buffer is scanned starting at *pp for the next
191 	  user-id, if the end of the line is reached, the next line is
192 	  read from the file.  If it scans the next priority value, the
193 	  variable pri (static to this file), is set to that priority.
194 	  EOF is indicated by setting this variable to -1, and also
195 	  returning 0.
196 */
197 char * next_user (int fd, char * buf, char ** pp )
198 {
199     long	temp;
200     char	*p;
201     static	int beg_line = 0; /* assumes a partial line is in buf to start */
202 
203     do
204     {
205 	while (**pp == ' ' || **pp == '\n' || **pp == '\t')
206 	    (*pp)++;
207 	p = *pp;
208 	if (*p)
209 	{
210 	    if (*p >= '0' && *p <= '9')
211 	    {
212 		temp = strtol(p, pp, 10);
213 		if (beg_line && **pp == ':')
214 		{
215 		    (*pp)++;
216 		    pri = temp;
217 		    beg_line = 0;
218 		    return (0);
219 		}
220 	    }
221 
222 	    for (; **pp && **pp != ' ' && **pp != '\n' && **pp != '\t'; (*pp)++)
223 		;
224 	    if (**pp)
225 		*(*pp)++ = 0;
226 	    beg_line = 0;
227 	    return (p);
228 	}
229 	beg_line = 1;
230     }
231     while (*pp = fdgets(buf, BUFSIZ, fd));
232 
233     pri = -1;
234     return (0);
235 }
236 
237 /*
238 Inputs:  A pointer to a priority table and a user.
239 Outputs: Zero if user found, else 1, and priority table is modified.
240 Effects: All occurences of <user> in the priority table will be removed.
241 	 (There should only be one at most.)
242 */
243 int del_user ( struct user_priority * ppri_tbl, char * user )
244 {
245     int		limit;
246 
247     for (limit = PRI_MIN; limit <= PRI_MAX; limit++)
248 	if (searchlist(user, ppri_tbl->users[limit - PRI_MIN]))
249 	{
250 	    dellist (&(ppri_tbl->users[limit - PRI_MIN]), user);
251 	    return (0);
252 	}
253     return (1);
254 }
255