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
ld_priority_file(char * path)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
add_user(struct user_priority * ppri_tbl,char * user,int limit)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 */
next_user(int fd,char * buf,char ** pp)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 */
del_user(struct user_priority * ppri_tbl,char * user)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