xref: /illumos-gate/usr/src/cmd/lp/lib/access/bang.c (revision 2a8bcb4efb45d99ac41c94a75c396b362c414f7f)
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 1999 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright (c) 2016 by Delphix. All rights reserved.
26  */
27 
28 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
31 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
32 
33 #include "string.h"
34 #include "unistd.h"
35 #include "stdlib.h"
36 #include "sys/utsname.h"
37 
38 #include "lp.h"
39 
40 /*
41  * The rules:
42  *
43  *	Key:	A - some system
44  *		X - some user
45  *
46  *	X	a user named X on the local system
47  *	A!X	the user named X from the system A
48  *	all!X	all users named X from any system
49  *	all	all users from local system
50  *	A!all	all users from the system A
51  *	all!all	all users from any system
52  */
53 
54 
55 /**
56  ** bangequ() - LIKE STREQU, BUT HANDLES system!name CASES
57  **/
58 
59 int
bangequ(char * user1p,char * user2p)60 bangequ (char *user1p, char *user2p)
61 {
62 	int	sysname1_all	= 0,
63 		username1_all	= 0;
64 	int	sysname2_all	= 0,
65 		username2_all	= 0;
66 	char	sysname1[BUFSIZ],
67 		sysname2[BUFSIZ];
68 	char	username1[BUFSIZ],
69 		username2[BUFSIZ],
70 		*sp;
71 
72 	static	char *Nodenamep = (char *) 0;
73 
74 	if (! user1p || ! user2p)
75 		return	1;
76 
77 	if (! Nodenamep) {
78 		struct utsname	utsbuf;
79 
80 		(void)	uname (&utsbuf);
81 		Nodenamep = Strdup (utsbuf.nodename);
82 	}
83 
84 	/* pattern=all */
85 	if (STREQU (NAME_ALL, user2p) || STREQU(NAME_ALL, user1p))
86 		return	1;
87 
88 	if ((sp = strrchr(user1p, '@')) != NULL) {	 /* user@host */
89 		*sp++ = '\0';
90 		(void) snprintf(sysname1, sizeof (sysname1), "%s", sp);
91 		(void) snprintf(username1, sizeof (username1), "%s", user1p);
92 		*--sp = '@';
93 	} else if ((sp = strchr(user1p, '!')) != NULL) { /* host!user */
94 		*sp++ = '\0';
95 		(void) snprintf(sysname1, sizeof (sysname1), "%s", user1p);
96 		(void) snprintf(username1, sizeof (username1), "%s", sp);
97 		*--sp = '!';
98 	} else {					 /* user */
99 		(void) snprintf(sysname1, sizeof (sysname1), "%s", Nodenamep);
100 		(void) snprintf(username1, sizeof (username1), "%s", user1p);
101 	}
102 
103 	sysname1_all = STREQU (NAME_ALL, sysname1);
104 	username1_all = STREQU (NAME_ALL, username1);
105 
106 	/* user2p is simple user name */
107 	if (strpbrk (user2p, "!@") == NULL)
108 		return	(username1_all && sysname1_all) ||
109 			 STREQU (username1, user2p);
110 
111 	if ((sp = strrchr(user2p, '@')) != NULL) {	 /* user@host */
112 		*sp++ = '\0';
113 		(void) snprintf(sysname2, sizeof (sysname2), "%s", sp);
114 		(void) snprintf(username2, sizeof (username2), "%s", user2p);
115 		*--sp = '@';
116 	} else if ((sp = strchr(user2p, '!')) != NULL) { /* host!user */
117 		*sp++ = '\0';
118 		(void) snprintf(sysname2, sizeof (sysname2), "%s", user2p);
119 		(void) snprintf(username2, sizeof (username2), "%s", sp);
120 		*--sp = '!';
121 	} else {					 /* user */
122 		(void) snprintf(sysname2, sizeof (sysname2), "%s", Nodenamep);
123 		(void) snprintf(username2, sizeof (username2), "%s", user1p);
124 	}
125 
126 	sysname2_all = STREQU (NAME_ALL, sysname2);
127 	username2_all = STREQU (NAME_ALL, username2);
128 
129 	if ((sysname1_all && username1_all) ||
130 	    (sysname2_all && username2_all) ||
131 	    (sysname1_all && username2_all) ||
132 	    (sysname2_all && username1_all))
133 		return 1;
134 
135 	if (sysname1_all || sysname2_all)
136 		return	STREQU (username1, username2);
137 
138 	if (username1_all || username2_all)
139 		return STREQU (sysname1, sysname2);
140 
141 	if (STREQU (sysname1, sysname2) && STREQU (username1, username2))
142 		return 1;
143 
144 	return 0;
145 }
146 
147 /**
148  ** bang_searchlist() - SEARCH (char **) LIST FOR "system!user" ITEM
149  **/
150 int
bang_searchlist(char * item,char ** list)151 bang_searchlist(char *item, char **list)
152 {
153 	if (!list || !*list)
154 		return (0);
155 
156 	/*
157 	 * This is a linear search--we believe that the lists
158 	 * will be short.
159 	 */
160 	while (*list) {
161 		if (bangequ(item, *list))
162 			return (1);
163 		list++;
164 	}
165 	return (0);
166 }
167 
168 /**
169  ** bang_dellist() - REMOVE "system!name" ITEM FROM (char **) LIST
170  **/
171 
172 int
bang_dellist(char *** plist,char * item)173 bang_dellist(char ***plist, char *item)
174 {
175 	register char **	pl;
176 	register char **	ql;
177 
178 	register int		n;
179 
180 				/*
181 				 * "hole" is a pointer guaranteed not
182 				 * to point to anyplace malloc'd.
183 				 */
184 	char *			hole	= "";
185 
186 
187 	/*
188 	 * There are two ways this routine is different from the
189 	 * regular "dellist()" routine: First, the items are of the form
190 	 * ``system!name'', which means there is a two part matching
191 	 * for ``all'' cases (all systems and/or all names). Second,
192 	 * ALL matching items in the list are deleted.
193 	 *
194 	 * Now suppose the list contains just the word ``all'', and
195 	 * the item to be deleted is the name ``foo''. What will
196 	 * happen? The word ``all'' will be deleted, leaving the list
197 	 * empty (null)! This may sound odd at first, but keep in mind
198 	 * that this routine is paired with the regular "addlist()"
199 	 * routine; the item (``foo'') is ADDED to an opposite list
200 	 * (we are either deleting from a deny list and adding to an allow
201 	 * list or vice versa). So, to continue the example, if previously
202 	 * ``all'' were allowed, removing ``foo'' from the allow list
203 	 * does indeed empty that list, but then putting it in the deny
204 	 * list means only ``foo'' is denied, which is the effect we
205 	 * want.
206 	 */
207 
208 	if (*plist) {
209 
210 		for (pl = *plist; *pl; pl++)
211 			if (bangequ(item, *pl)) {
212 				Free (*pl);
213 				*pl = hole;
214 			}
215 
216 		for (n = 0, ql = pl = *plist; *pl; pl++)
217 			if (*pl != hole) {
218 				*ql++ = *pl;
219 				n++;
220 			}
221 
222 		if (n == 0) {
223 			Free ((char *)*plist);
224 			*plist = 0;
225 		} else {
226 			*plist = (char **)Realloc(
227 				(char *)*plist,
228 				(n + 1) * sizeof(char *)
229 			);
230 			if (!*plist)
231 				return (-1);
232 			(*plist)[n] = 0;
233 		}
234 	}
235 
236 	return (0);
237 }
238