xref: /titanic_52/usr/src/cmd/setfacl/setfacl.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate #ifndef lint
25*7c478bd9Sstevel@tonic-gate static char sccsid[] = "%Z%%M%	%I%	%E% SMI";
26*7c478bd9Sstevel@tonic-gate #endif
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1993, by Sun Microsystems, Inc.
30*7c478bd9Sstevel@tonic-gate  */
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  * setfacl [-r] -f aclfile file ...
34*7c478bd9Sstevel@tonic-gate  * setfacl [-r] -d acl_entries file ...
35*7c478bd9Sstevel@tonic-gate  * setfacl [-r] -m acl_entries file ...
36*7c478bd9Sstevel@tonic-gate  * setfacl [-r] -s acl_entries file ...
37*7c478bd9Sstevel@tonic-gate  * This command deletes/adds/modifies/sets discretionary information for a file
38*7c478bd9Sstevel@tonic-gate  * or files.
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
42*7c478bd9Sstevel@tonic-gate #include <stdio.h>
43*7c478bd9Sstevel@tonic-gate #include <pwd.h>
44*7c478bd9Sstevel@tonic-gate #include <grp.h>
45*7c478bd9Sstevel@tonic-gate #include <string.h>
46*7c478bd9Sstevel@tonic-gate #include <locale.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/acl.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
49*7c478bd9Sstevel@tonic-gate #include <unistd.h>
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #define	ADD	1
53*7c478bd9Sstevel@tonic-gate #define	MODIFY	2
54*7c478bd9Sstevel@tonic-gate #define	DELETE	3
55*7c478bd9Sstevel@tonic-gate #define	SET	4
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static int get_acl_info(char *filep, aclent_t **aclpp);
58*7c478bd9Sstevel@tonic-gate static int mod_entries(aclent_t *, int, char *, char *, char *, int);
59*7c478bd9Sstevel@tonic-gate static int set_file_entries(char *, char *, int);
60*7c478bd9Sstevel@tonic-gate static int set_online_entries(char *, char *, int);
61*7c478bd9Sstevel@tonic-gate static void usage();
62*7c478bd9Sstevel@tonic-gate static int parse_entry_list(aclent_t **, int *, char *, int);
63*7c478bd9Sstevel@tonic-gate static int convert_to_aclent_t(char *, int *, aclent_t **, int);
64*7c478bd9Sstevel@tonic-gate static int parse_entry(char *, aclent_t *, int);
65*7c478bd9Sstevel@tonic-gate static void err_handle(int, aclent_t *);
66*7c478bd9Sstevel@tonic-gate static int conv_id(char *);
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate 	int		c;
71*7c478bd9Sstevel@tonic-gate 	int		dflag = 0;
72*7c478bd9Sstevel@tonic-gate 	int		mflag = 0;
73*7c478bd9Sstevel@tonic-gate 	int		rflag = 0;
74*7c478bd9Sstevel@tonic-gate 	int		sflag = 0;
75*7c478bd9Sstevel@tonic-gate 	int		fflag = 0;
76*7c478bd9Sstevel@tonic-gate 	int		errflag = 0;
77*7c478bd9Sstevel@tonic-gate 	int		aclcnt;			/* used by -m -d */
78*7c478bd9Sstevel@tonic-gate 	aclent_t	*aclp;			/* used by -m -d */
79*7c478bd9Sstevel@tonic-gate 	char		*aclfilep;		/* acl file argument */
80*7c478bd9Sstevel@tonic-gate 	char		*d_entryp = NULL;	/* ptr to del entry list */
81*7c478bd9Sstevel@tonic-gate 	char		*m_entryp = NULL;	/* ptr to mod entry list */
82*7c478bd9Sstevel@tonic-gate 	char		*s_entryp = NULL;	/* ptr to set entry list */
83*7c478bd9Sstevel@tonic-gate 	char		*work_dp = NULL;	/* working ptrs for the above */
84*7c478bd9Sstevel@tonic-gate 	char		*work_mp = NULL;
85*7c478bd9Sstevel@tonic-gate 	char		*work_sp = NULL;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
88*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	if (argc < 3)
91*7c478bd9Sstevel@tonic-gate 		usage();
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "rm:d:s:f:")) != EOF) {
94*7c478bd9Sstevel@tonic-gate 		switch (c) {
95*7c478bd9Sstevel@tonic-gate 		case 'r':
96*7c478bd9Sstevel@tonic-gate 			rflag++;
97*7c478bd9Sstevel@tonic-gate 			break;
98*7c478bd9Sstevel@tonic-gate 		case 'd':
99*7c478bd9Sstevel@tonic-gate 			if (dflag || fflag || sflag)
100*7c478bd9Sstevel@tonic-gate 				usage();
101*7c478bd9Sstevel@tonic-gate 			dflag++;
102*7c478bd9Sstevel@tonic-gate 			d_entryp = optarg;
103*7c478bd9Sstevel@tonic-gate 			break;
104*7c478bd9Sstevel@tonic-gate 		case 'm':
105*7c478bd9Sstevel@tonic-gate 			if (mflag || fflag || sflag)
106*7c478bd9Sstevel@tonic-gate 				usage();
107*7c478bd9Sstevel@tonic-gate 			mflag++;
108*7c478bd9Sstevel@tonic-gate 			m_entryp = optarg;
109*7c478bd9Sstevel@tonic-gate 			break;
110*7c478bd9Sstevel@tonic-gate 		case 's':
111*7c478bd9Sstevel@tonic-gate 			if (fflag || sflag || mflag || dflag)
112*7c478bd9Sstevel@tonic-gate 				usage();
113*7c478bd9Sstevel@tonic-gate 			sflag++;
114*7c478bd9Sstevel@tonic-gate 			s_entryp = optarg;
115*7c478bd9Sstevel@tonic-gate 			break;
116*7c478bd9Sstevel@tonic-gate 		case 'f':
117*7c478bd9Sstevel@tonic-gate 			if (fflag || sflag || mflag || dflag)
118*7c478bd9Sstevel@tonic-gate 				usage();
119*7c478bd9Sstevel@tonic-gate 			fflag++;
120*7c478bd9Sstevel@tonic-gate 			aclfilep = optarg;
121*7c478bd9Sstevel@tonic-gate 			break;
122*7c478bd9Sstevel@tonic-gate 		case '?':
123*7c478bd9Sstevel@tonic-gate 			errflag++;
124*7c478bd9Sstevel@tonic-gate 			break;
125*7c478bd9Sstevel@tonic-gate 		}
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	if (errflag)
128*7c478bd9Sstevel@tonic-gate 		usage();
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	/* one of these flags should be set */
131*7c478bd9Sstevel@tonic-gate 	if (!fflag && !sflag && !mflag && !dflag)
132*7c478bd9Sstevel@tonic-gate 		usage();
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	/* no file arguments */
135*7c478bd9Sstevel@tonic-gate 	if (optind >= argc)
136*7c478bd9Sstevel@tonic-gate 		usage();
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	for (; optind < argc; optind++) {
139*7c478bd9Sstevel@tonic-gate 		register char *filep;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 		filep = argv[optind];
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 		/* modify and delete: we need to get the ACL first */
144*7c478bd9Sstevel@tonic-gate 		if (mflag || dflag) {
145*7c478bd9Sstevel@tonic-gate 			if (m_entryp != NULL) {
146*7c478bd9Sstevel@tonic-gate 				free(work_mp);
147*7c478bd9Sstevel@tonic-gate 				work_mp = strdup(m_entryp);
148*7c478bd9Sstevel@tonic-gate 				if (work_mp == NULL) {
149*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
150*7c478bd9Sstevel@tonic-gate 					    gettext("out of memory %s\n"),
151*7c478bd9Sstevel@tonic-gate 					    m_entryp);
152*7c478bd9Sstevel@tonic-gate 					exit(1);
153*7c478bd9Sstevel@tonic-gate 				}
154*7c478bd9Sstevel@tonic-gate 			}
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 			if (d_entryp != NULL) {
157*7c478bd9Sstevel@tonic-gate 				free(work_dp);
158*7c478bd9Sstevel@tonic-gate 				work_dp = strdup(d_entryp);
159*7c478bd9Sstevel@tonic-gate 				if (work_dp == NULL) {
160*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
161*7c478bd9Sstevel@tonic-gate 					    gettext("out of memory %s\n"),
162*7c478bd9Sstevel@tonic-gate 					    d_entryp);
163*7c478bd9Sstevel@tonic-gate 					exit(1);
164*7c478bd9Sstevel@tonic-gate 				}
165*7c478bd9Sstevel@tonic-gate 			}
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 			aclcnt = get_acl_info(filep, &aclp);
168*7c478bd9Sstevel@tonic-gate 			if (aclcnt == -1)
169*7c478bd9Sstevel@tonic-gate 				exit(2);
170*7c478bd9Sstevel@tonic-gate 			if (mod_entries(aclp, aclcnt, work_mp,
171*7c478bd9Sstevel@tonic-gate 			    work_dp, filep, rflag) == -1)
172*7c478bd9Sstevel@tonic-gate 				exit(2);
173*7c478bd9Sstevel@tonic-gate 		} else if (fflag) {
174*7c478bd9Sstevel@tonic-gate 			if (set_file_entries(aclfilep, filep, rflag) == -1)
175*7c478bd9Sstevel@tonic-gate 				exit(2);
176*7c478bd9Sstevel@tonic-gate 		} else if (sflag) {
177*7c478bd9Sstevel@tonic-gate 			if (s_entryp != NULL) {
178*7c478bd9Sstevel@tonic-gate 				free(work_sp);
179*7c478bd9Sstevel@tonic-gate 				work_sp = strdup(s_entryp);
180*7c478bd9Sstevel@tonic-gate 				if (work_sp == NULL) {
181*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
182*7c478bd9Sstevel@tonic-gate 					    gettext("out of memory %s\n"),
183*7c478bd9Sstevel@tonic-gate 					    s_entryp);
184*7c478bd9Sstevel@tonic-gate 					exit(1);
185*7c478bd9Sstevel@tonic-gate 				}
186*7c478bd9Sstevel@tonic-gate 			}
187*7c478bd9Sstevel@tonic-gate 			if (set_online_entries(work_sp, filep, rflag) == -1)
188*7c478bd9Sstevel@tonic-gate 				exit(2);
189*7c478bd9Sstevel@tonic-gate 		}
190*7c478bd9Sstevel@tonic-gate 	}
191*7c478bd9Sstevel@tonic-gate 	exit(0);
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate /*
195*7c478bd9Sstevel@tonic-gate  * For add, modify, and delete, we need to get the ACL of the file first.
196*7c478bd9Sstevel@tonic-gate  */
197*7c478bd9Sstevel@tonic-gate static int
198*7c478bd9Sstevel@tonic-gate get_acl_info(char *filep, aclent_t **aclpp)
199*7c478bd9Sstevel@tonic-gate {
200*7c478bd9Sstevel@tonic-gate 	int	aclcnt;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if ((aclcnt = acl(filep, GETACLCNT, 0, NULL)) < 0) {
203*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
204*7c478bd9Sstevel@tonic-gate 		    gettext("%s: failed to get acl count\n"), filep);
205*7c478bd9Sstevel@tonic-gate 		perror("get acl count error");
206*7c478bd9Sstevel@tonic-gate 		return (-1);
207*7c478bd9Sstevel@tonic-gate 	}
208*7c478bd9Sstevel@tonic-gate 	if (aclcnt < MIN_ACL_ENTRIES) {
209*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
210*7c478bd9Sstevel@tonic-gate 		    gettext("%d: acl count is too small from %s\n"),
211*7c478bd9Sstevel@tonic-gate 		    aclcnt, filep);
212*7c478bd9Sstevel@tonic-gate 		return (-1);
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate 	if ((*aclpp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt)) == NULL) {
216*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("out of memory\n"));
217*7c478bd9Sstevel@tonic-gate 		return (-1);
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 	if (acl(filep, GETACL, aclcnt, *aclpp) < 0) {
220*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
221*7c478bd9Sstevel@tonic-gate 		    gettext("%s: failed to get acl entries\n"), filep);
222*7c478bd9Sstevel@tonic-gate 		perror("getacl error");
223*7c478bd9Sstevel@tonic-gate 		return (-1);
224*7c478bd9Sstevel@tonic-gate 	}
225*7c478bd9Sstevel@tonic-gate 	return (aclcnt);
226*7c478bd9Sstevel@tonic-gate }
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate /*
229*7c478bd9Sstevel@tonic-gate  * mod_entries() handles add, delete, and modify ACL entries of a file.
230*7c478bd9Sstevel@tonic-gate  * The real action is in convert_to_aclent_t() called by parse_entry_list().
231*7c478bd9Sstevel@tonic-gate  * aclp: points ACL of a file and may be changed by lower level routine.
232*7c478bd9Sstevel@tonic-gate  * modp: modify entry list in ascii format
233*7c478bd9Sstevel@tonic-gate  * delp: delete entry list in ascii format
234*7c478bd9Sstevel@tonic-gate  * fnamep: file of interest
235*7c478bd9Sstevel@tonic-gate  */
236*7c478bd9Sstevel@tonic-gate static int
237*7c478bd9Sstevel@tonic-gate mod_entries(aclent_t *aclp, int cnt, char *modp, char *delp,
238*7c478bd9Sstevel@tonic-gate 	char *fnamep, int rfg)
239*7c478bd9Sstevel@tonic-gate {
240*7c478bd9Sstevel@tonic-gate 	int	rc;		/* return code */
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	/* modify and add: from -m option */
243*7c478bd9Sstevel@tonic-gate 	if (parse_entry_list(&aclp, &cnt, modp, MODIFY) == -1)
244*7c478bd9Sstevel@tonic-gate 		return (-1);
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	/* deletion: from -d option */
247*7c478bd9Sstevel@tonic-gate 	if (parse_entry_list(&aclp, &cnt, delp, DELETE) == -1)
248*7c478bd9Sstevel@tonic-gate 		return (-1);
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	if (aclsort(cnt, rfg, aclp) == -1) {
251*7c478bd9Sstevel@tonic-gate 		(void) err_handle(cnt, aclp);
252*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
253*7c478bd9Sstevel@tonic-gate 		    gettext("aclcnt %d, file %s\n"), cnt, fnamep);
254*7c478bd9Sstevel@tonic-gate 		return (-1);
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	if (acl(fnamep, SETACL, cnt, aclp) < 0) {
258*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
259*7c478bd9Sstevel@tonic-gate 		    gettext("%s: failed to set acl entries\n"), fnamep);
260*7c478bd9Sstevel@tonic-gate 		perror("setacl error");
261*7c478bd9Sstevel@tonic-gate 		return (-1);
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 	return (0);
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate /*
267*7c478bd9Sstevel@tonic-gate  * set_file_entries() creates ACL entries from ACL file (acl_fnamep).
268*7c478bd9Sstevel@tonic-gate  * It opens the file and converts every line (one line per acl entry)
269*7c478bd9Sstevel@tonic-gate  * into aclent_t format. It then recalculates the mask according to rflag.
270*7c478bd9Sstevel@tonic-gate  * Finally it sets ACL to the file (fnamep).
271*7c478bd9Sstevel@tonic-gate  */
272*7c478bd9Sstevel@tonic-gate static int
273*7c478bd9Sstevel@tonic-gate set_file_entries(char *acl_fnamep, char *fnamep, int rflag)
274*7c478bd9Sstevel@tonic-gate {
275*7c478bd9Sstevel@tonic-gate 	int		aclcnt = 0;
276*7c478bd9Sstevel@tonic-gate 	FILE		*acl_fp;
277*7c478bd9Sstevel@tonic-gate 	aclent_t	*aclp;
278*7c478bd9Sstevel@tonic-gate 	char		buf[BUFSIZ];
279*7c478bd9Sstevel@tonic-gate 	char		*tp;
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	if (strcmp(acl_fnamep, "-") == 0)
282*7c478bd9Sstevel@tonic-gate 		acl_fp = stdin;
283*7c478bd9Sstevel@tonic-gate 	else {
284*7c478bd9Sstevel@tonic-gate 		if ((acl_fp = fopen(acl_fnamep, "r")) == NULL) {
285*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("Can't open acl file %s\n"),
286*7c478bd9Sstevel@tonic-gate 			    acl_fnamep);
287*7c478bd9Sstevel@tonic-gate 			return (-1);
288*7c478bd9Sstevel@tonic-gate 		}
289*7c478bd9Sstevel@tonic-gate 	}
290*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, acl_fp) != NULL) {
291*7c478bd9Sstevel@tonic-gate 		if (buf[0] == '#' || buf[0] == '\n')
292*7c478bd9Sstevel@tonic-gate 			continue;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		/* check effective permission: add a null after real perm */
295*7c478bd9Sstevel@tonic-gate 		if ((tp = (char *)strchr(buf, '#')) != NULL) {
296*7c478bd9Sstevel@tonic-gate 			tp--;
297*7c478bd9Sstevel@tonic-gate 			while (*tp == ' ' || *tp == '\t') {
298*7c478bd9Sstevel@tonic-gate 				if (tp != buf)
299*7c478bd9Sstevel@tonic-gate 					tp--;
300*7c478bd9Sstevel@tonic-gate 				else {
301*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
302*7c478bd9Sstevel@tonic-gate 					    gettext("entry format error %s\n"),
303*7c478bd9Sstevel@tonic-gate 					    buf);
304*7c478bd9Sstevel@tonic-gate 					exit(1);
305*7c478bd9Sstevel@tonic-gate 				}
306*7c478bd9Sstevel@tonic-gate 			}
307*7c478bd9Sstevel@tonic-gate 			*(tp+1) = '\0';
308*7c478bd9Sstevel@tonic-gate 		}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 		/* remove <nl> at the end if there is one */
311*7c478bd9Sstevel@tonic-gate 		if ((tp = (char *)strchr(buf, '\n')) != NULL)
312*7c478bd9Sstevel@tonic-gate 			*tp = '\0';
313*7c478bd9Sstevel@tonic-gate 		aclcnt++;
314*7c478bd9Sstevel@tonic-gate 		if (convert_to_aclent_t(buf, &aclcnt, &aclp, SET) == -1)
315*7c478bd9Sstevel@tonic-gate 			return (-1);
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	if (aclsort(aclcnt, rflag, aclp) == -1) {
319*7c478bd9Sstevel@tonic-gate 		(void) err_handle(aclcnt, aclp);
320*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("aclcnt %d, aclfile %s\n"),
321*7c478bd9Sstevel@tonic-gate 		    aclcnt, acl_fnamep);
322*7c478bd9Sstevel@tonic-gate 		return (-1);
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	if (acl(fnamep, SETACL, aclcnt, aclp) < 0) {
326*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
327*7c478bd9Sstevel@tonic-gate 		    gettext("%s: failed to set acl entries\n"), fnamep);
328*7c478bd9Sstevel@tonic-gate 		perror("setacl error");
329*7c478bd9Sstevel@tonic-gate 		return (-1);
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate 	return (0);
332*7c478bd9Sstevel@tonic-gate }
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate /*
335*7c478bd9Sstevel@tonic-gate  * set_online_entries() parses the acl entries from command line (setp).
336*7c478bd9Sstevel@tonic-gate  * It converts the comma separated acl entries into aclent_t format.
337*7c478bd9Sstevel@tonic-gate  * It then recalculates the mask according to rflag.
338*7c478bd9Sstevel@tonic-gate  * Finally it sets ACL to the file (fnamep).
339*7c478bd9Sstevel@tonic-gate  */
340*7c478bd9Sstevel@tonic-gate static int
341*7c478bd9Sstevel@tonic-gate set_online_entries(char *setp, char *fnamep, int rflag)
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate 	char		*commap;
344*7c478bd9Sstevel@tonic-gate 	aclent_t	*aclp;
345*7c478bd9Sstevel@tonic-gate 	int		aclcnt = 0;
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	if (parse_entry_list(&aclp, &aclcnt, setp, SET) == -1)
348*7c478bd9Sstevel@tonic-gate 		return (-1);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	if (aclsort(aclcnt, rflag, aclp) == -1) {
351*7c478bd9Sstevel@tonic-gate 		(void) err_handle(aclcnt, aclp);
352*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
353*7c478bd9Sstevel@tonic-gate 		    gettext("aclcnt %d, file %s\n"), aclcnt, fnamep);
354*7c478bd9Sstevel@tonic-gate 		return (-1);
355*7c478bd9Sstevel@tonic-gate 	}
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	if (acl(fnamep, SETACL, aclcnt, aclp) < 0) {
358*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
359*7c478bd9Sstevel@tonic-gate 		    gettext("%s: failed to set acl entries\n"), fnamep);
360*7c478bd9Sstevel@tonic-gate 		perror("setacl error");
361*7c478bd9Sstevel@tonic-gate 		return (-1);
362*7c478bd9Sstevel@tonic-gate 	}
363*7c478bd9Sstevel@tonic-gate 	return (0);
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate /*
367*7c478bd9Sstevel@tonic-gate  * parse_entry_list() parses entry list (listp) separated by commas.
368*7c478bd9Sstevel@tonic-gate  * Once it gets an ACL entry, it calls convert_to_aclent_t() to convert
369*7c478bd9Sstevel@tonic-gate  * to internal format.
370*7c478bd9Sstevel@tonic-gate  */
371*7c478bd9Sstevel@tonic-gate static int
372*7c478bd9Sstevel@tonic-gate parse_entry_list(aclent_t **aclpp, int *aclcntp, char *listp, int mode)
373*7c478bd9Sstevel@tonic-gate {
374*7c478bd9Sstevel@tonic-gate 	char	*commap;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	if (listp == NULL)
377*7c478bd9Sstevel@tonic-gate 		return (0);
378*7c478bd9Sstevel@tonic-gate 	while ((commap = (char *)strchr(listp, ',')) != NULL) {
379*7c478bd9Sstevel@tonic-gate 		*commap = '\0';
380*7c478bd9Sstevel@tonic-gate 		*aclcntp += 1;
381*7c478bd9Sstevel@tonic-gate 		/* aclcnt may be updated after the call: add or modify */
382*7c478bd9Sstevel@tonic-gate 		if (convert_to_aclent_t(listp, aclcntp, aclpp, mode) == -1)
383*7c478bd9Sstevel@tonic-gate 			return (-1);
384*7c478bd9Sstevel@tonic-gate 		listp = ++commap;
385*7c478bd9Sstevel@tonic-gate 	}
386*7c478bd9Sstevel@tonic-gate 	/* this is for only one entry or last entry */
387*7c478bd9Sstevel@tonic-gate 	if (*listp != '\0') {
388*7c478bd9Sstevel@tonic-gate 		*aclcntp += 1;
389*7c478bd9Sstevel@tonic-gate 		if (convert_to_aclent_t(listp, aclcntp, aclpp, mode) == -1)
390*7c478bd9Sstevel@tonic-gate 			return (-1);
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate }
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate /*
395*7c478bd9Sstevel@tonic-gate  * convert_to_aclent_t() converts an acl entry in ascii format (fields separated
396*7c478bd9Sstevel@tonic-gate  * by colon) into aclent_t and appends it to the current ACL. It also handles
397*7c478bd9Sstevel@tonic-gate  * memory allocation/deallocation for acl entries in aclent_t format.
398*7c478bd9Sstevel@tonic-gate  * aclpp that contains acl entries in acl format will be returned.
399*7c478bd9Sstevel@tonic-gate  * We don't check duplicates.
400*7c478bd9Sstevel@tonic-gate  */
401*7c478bd9Sstevel@tonic-gate static int
402*7c478bd9Sstevel@tonic-gate convert_to_aclent_t(char *entryp, int *cntp, aclent_t **aclpp, int mode)
403*7c478bd9Sstevel@tonic-gate {
404*7c478bd9Sstevel@tonic-gate 	aclent_t	*new_aclp;
405*7c478bd9Sstevel@tonic-gate 	aclent_t	tmpacl;
406*7c478bd9Sstevel@tonic-gate 	aclent_t	*taclp;
407*7c478bd9Sstevel@tonic-gate 	int		cur_cnt;
408*7c478bd9Sstevel@tonic-gate 	int		found = 0;
409*7c478bd9Sstevel@tonic-gate 	int		is_obj;
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	if (entryp == NULL)
412*7c478bd9Sstevel@tonic-gate 		return (0);
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 	if (*cntp > 1)
415*7c478bd9Sstevel@tonic-gate 		new_aclp = (aclent_t *)realloc(*aclpp,
416*7c478bd9Sstevel@tonic-gate 		    sizeof (aclent_t) * (*cntp));
417*7c478bd9Sstevel@tonic-gate 	else
418*7c478bd9Sstevel@tonic-gate 		new_aclp = (aclent_t *) malloc(sizeof (aclent_t) * (*cntp));
419*7c478bd9Sstevel@tonic-gate 	if (new_aclp == NULL) {
420*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
421*7c478bd9Sstevel@tonic-gate 		    gettext("Insufficient memory for acl %d\n"), *cntp);
422*7c478bd9Sstevel@tonic-gate 		return (-1);
423*7c478bd9Sstevel@tonic-gate 	}
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 	tmpacl.a_id = 0;	/* id field needs to be initialized */
426*7c478bd9Sstevel@tonic-gate 	if (entryp[0] == 'u')
427*7c478bd9Sstevel@tonic-gate 		tmpacl.a_id = getuid();	/* id field for user */
428*7c478bd9Sstevel@tonic-gate 	if (entryp[0] == 'g')
429*7c478bd9Sstevel@tonic-gate 		tmpacl.a_id = getgid();	/* id field for group */
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	tmpacl.a_type = 0;
432*7c478bd9Sstevel@tonic-gate 	if (parse_entry(entryp, &tmpacl, mode) == -1)
433*7c478bd9Sstevel@tonic-gate 		return (-1);
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	is_obj = ((tmpacl.a_type == USER_OBJ) ||
436*7c478bd9Sstevel@tonic-gate 		    (tmpacl.a_type == GROUP_OBJ) ||
437*7c478bd9Sstevel@tonic-gate 		    (tmpacl.a_type == DEF_USER_OBJ) ||
438*7c478bd9Sstevel@tonic-gate 		    (tmpacl.a_type == DEF_GROUP_OBJ));
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	cur_cnt = *cntp - 1;
441*7c478bd9Sstevel@tonic-gate 	switch (mode) {
442*7c478bd9Sstevel@tonic-gate 	case MODIFY:	/* and add */
443*7c478bd9Sstevel@tonic-gate 		for (taclp = new_aclp; cur_cnt-- > 0; taclp++) {
444*7c478bd9Sstevel@tonic-gate 			if (taclp->a_type == tmpacl.a_type &&
445*7c478bd9Sstevel@tonic-gate 			    ((taclp->a_id == tmpacl.a_id) || is_obj)) {
446*7c478bd9Sstevel@tonic-gate 				found++;
447*7c478bd9Sstevel@tonic-gate 				/* cnt is added before it's called */
448*7c478bd9Sstevel@tonic-gate 				*cntp -= 1;
449*7c478bd9Sstevel@tonic-gate 				taclp->a_perm = tmpacl.a_perm;
450*7c478bd9Sstevel@tonic-gate 				break;
451*7c478bd9Sstevel@tonic-gate 			}
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 		if (!found)	/* Add it to the end: no need to change cntp */
454*7c478bd9Sstevel@tonic-gate 			memcpy(new_aclp + *cntp -1, &tmpacl, sizeof (aclent_t));
455*7c478bd9Sstevel@tonic-gate 		break;
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	case DELETE:
458*7c478bd9Sstevel@tonic-gate 		for (taclp = new_aclp; cur_cnt-- > 0; taclp++) {
459*7c478bd9Sstevel@tonic-gate 			if (taclp->a_type == tmpacl.a_type &&
460*7c478bd9Sstevel@tonic-gate 			    ((taclp->a_id == tmpacl.a_id) || is_obj)) {
461*7c478bd9Sstevel@tonic-gate 				found++;
462*7c478bd9Sstevel@tonic-gate 				/* move up the rest */
463*7c478bd9Sstevel@tonic-gate 				while (cur_cnt-- > 0) {
464*7c478bd9Sstevel@tonic-gate 					memcpy(taclp, taclp+1,
465*7c478bd9Sstevel@tonic-gate 					    sizeof (aclent_t));
466*7c478bd9Sstevel@tonic-gate 					taclp++;
467*7c478bd9Sstevel@tonic-gate 				}
468*7c478bd9Sstevel@tonic-gate 				*cntp = *cntp - 2;
469*7c478bd9Sstevel@tonic-gate 				break;
470*7c478bd9Sstevel@tonic-gate 			}
471*7c478bd9Sstevel@tonic-gate 		}
472*7c478bd9Sstevel@tonic-gate 		if (!found)
473*7c478bd9Sstevel@tonic-gate 			*cntp -= 1;
474*7c478bd9Sstevel@tonic-gate 		break;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	case SET:
477*7c478bd9Sstevel@tonic-gate 		/* we may check duplicate before copying over?? */
478*7c478bd9Sstevel@tonic-gate 		memcpy(new_aclp + *cntp -1, &tmpacl, sizeof (aclent_t));
479*7c478bd9Sstevel@tonic-gate 		break;
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	default:
482*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
483*7c478bd9Sstevel@tonic-gate 		    gettext("Unrecognized mode: internal error\n"));
484*7c478bd9Sstevel@tonic-gate 		break;
485*7c478bd9Sstevel@tonic-gate 	}
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	*aclpp = new_aclp; 	/* return new acl entries */
488*7c478bd9Sstevel@tonic-gate 	return (0);
489*7c478bd9Sstevel@tonic-gate }
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate static void
492*7c478bd9Sstevel@tonic-gate usage()
493*7c478bd9Sstevel@tonic-gate {
494*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("usage:\n"));
495*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
496*7c478bd9Sstevel@tonic-gate 	    gettext("\tsetfacl [-r] -f aclfile file ...\n"));
497*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
498*7c478bd9Sstevel@tonic-gate 	    gettext("\tsetfacl [-r] -d acl_entries file ...\n"));
499*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
500*7c478bd9Sstevel@tonic-gate 	    gettext("\tsetfacl [-r] -m acl_entries file ...\n"));
501*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
502*7c478bd9Sstevel@tonic-gate 	    gettext("\tsetfacl [-r] -s acl_entries file ...\n"));
503*7c478bd9Sstevel@tonic-gate 	exit(1);
504*7c478bd9Sstevel@tonic-gate }
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate static void
507*7c478bd9Sstevel@tonic-gate err_handle(int cnt, aclent_t *aclentp)
508*7c478bd9Sstevel@tonic-gate {
509*7c478bd9Sstevel@tonic-gate 	int	rc;
510*7c478bd9Sstevel@tonic-gate 	int	which;
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	rc = aclcheck(aclentp, cnt, &which);
513*7c478bd9Sstevel@tonic-gate 	switch (rc) {
514*7c478bd9Sstevel@tonic-gate 	case USER_ERROR:
515*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
516*7c478bd9Sstevel@tonic-gate 		    gettext("There is more than one user owner entry"));
517*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
518*7c478bd9Sstevel@tonic-gate 		    gettext(" -- error found at entry index %d\n"), which);
519*7c478bd9Sstevel@tonic-gate 		break;
520*7c478bd9Sstevel@tonic-gate 	case GRP_ERROR:
521*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
522*7c478bd9Sstevel@tonic-gate 		    gettext("There is more than one group owner entry"));
523*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
524*7c478bd9Sstevel@tonic-gate 		    gettext(" -- error found at entry index %d\n"), which);
525*7c478bd9Sstevel@tonic-gate 		break;
526*7c478bd9Sstevel@tonic-gate 	case CLASS_ERROR:
527*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
528*7c478bd9Sstevel@tonic-gate 		    gettext("There is more than one mask entry"));
529*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
530*7c478bd9Sstevel@tonic-gate 		    gettext(" -- error found at entry index %d\n"), which);
531*7c478bd9Sstevel@tonic-gate 		break;
532*7c478bd9Sstevel@tonic-gate 	case OTHER_ERROR:
533*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
534*7c478bd9Sstevel@tonic-gate 		    gettext("There is more than one other entry"));
535*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
536*7c478bd9Sstevel@tonic-gate 		    gettext(" -- error found at entry index %d\n"), which);
537*7c478bd9Sstevel@tonic-gate 		break;
538*7c478bd9Sstevel@tonic-gate 	case DUPLICATE_ERROR:
539*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
540*7c478bd9Sstevel@tonic-gate 		    gettext("Duplicate user or group entries"));
541*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
542*7c478bd9Sstevel@tonic-gate 		    gettext(" -- error found at entry index %d\n"), which);
543*7c478bd9Sstevel@tonic-gate 		break;
544*7c478bd9Sstevel@tonic-gate 	case MISS_ERROR:
545*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
546*7c478bd9Sstevel@tonic-gate 		    gettext("Missing user/group owner, other, mask entry\n"));
547*7c478bd9Sstevel@tonic-gate 		break;
548*7c478bd9Sstevel@tonic-gate 	case MEM_ERROR:
549*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
550*7c478bd9Sstevel@tonic-gate 		    gettext("Insufficient memory\n"));
551*7c478bd9Sstevel@tonic-gate 		break;
552*7c478bd9Sstevel@tonic-gate 	case ENTRY_ERROR:
553*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
554*7c478bd9Sstevel@tonic-gate 		    gettext("Unrecognized entry type"));
555*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
556*7c478bd9Sstevel@tonic-gate 		    gettext(" -- error found at entry index %d\n"), which);
557*7c478bd9Sstevel@tonic-gate 		break;
558*7c478bd9Sstevel@tonic-gate 	default:
559*7c478bd9Sstevel@tonic-gate 		/* error is not from aclcheck */
560*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
561*7c478bd9Sstevel@tonic-gate 		    gettext("aclsort error\n"));
562*7c478bd9Sstevel@tonic-gate 		break;
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate static int
567*7c478bd9Sstevel@tonic-gate parse_entry(char *fieldp, aclent_t *aclentp, int mode)
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	char		*colonp;
570*7c478bd9Sstevel@tonic-gate 	int		def_flag = 0, mo_flag = 0;
571*7c478bd9Sstevel@tonic-gate 	int		id;
572*7c478bd9Sstevel@tonic-gate 	struct passwd	*pwp;
573*7c478bd9Sstevel@tonic-gate 	struct group	*grp;
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 	colonp = (char *)strchr(fieldp, ':');
576*7c478bd9Sstevel@tonic-gate 	if (colonp == NULL) {
577*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
578*7c478bd9Sstevel@tonic-gate 		    gettext("Can't find colon delimiter %s\n"), fieldp);
579*7c478bd9Sstevel@tonic-gate 		return (-1);
580*7c478bd9Sstevel@tonic-gate 	}
581*7c478bd9Sstevel@tonic-gate 	*colonp = '\0';
582*7c478bd9Sstevel@tonic-gate 	if ((strcmp(fieldp, "default") == 0) || (strcmp(fieldp, "d") == 0)) {
583*7c478bd9Sstevel@tonic-gate 		def_flag++;
584*7c478bd9Sstevel@tonic-gate 		fieldp = ++colonp;
585*7c478bd9Sstevel@tonic-gate 		colonp = (char *)strchr(fieldp, ':');
586*7c478bd9Sstevel@tonic-gate 		if (colonp == NULL) {
587*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
588*7c478bd9Sstevel@tonic-gate 			    gettext("Can't find colon delimiter %s\n"), fieldp);
589*7c478bd9Sstevel@tonic-gate 			return (-1);
590*7c478bd9Sstevel@tonic-gate 		}
591*7c478bd9Sstevel@tonic-gate 		*colonp = '\0';
592*7c478bd9Sstevel@tonic-gate 	}
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	/* process entry type */
595*7c478bd9Sstevel@tonic-gate 	if ((strcmp(fieldp, "user") == 0) || (strcmp(fieldp, "u") == 0)) {
596*7c478bd9Sstevel@tonic-gate 		if (def_flag)
597*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = DEF_USER;
598*7c478bd9Sstevel@tonic-gate 		else
599*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = USER;
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 	if ((strcmp(fieldp, "group") == 0) || (strcmp(fieldp, "g") == 0)) {
602*7c478bd9Sstevel@tonic-gate 		if (def_flag)
603*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = DEF_GROUP;
604*7c478bd9Sstevel@tonic-gate 		else
605*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = GROUP;
606*7c478bd9Sstevel@tonic-gate 	}
607*7c478bd9Sstevel@tonic-gate 	if ((strcmp(fieldp, "mask") == 0) || (strcmp(fieldp, "m") == 0)) {
608*7c478bd9Sstevel@tonic-gate 		if (def_flag)
609*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = DEF_CLASS_OBJ;
610*7c478bd9Sstevel@tonic-gate 		else
611*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = CLASS_OBJ;
612*7c478bd9Sstevel@tonic-gate 	}
613*7c478bd9Sstevel@tonic-gate 	if ((strcmp(fieldp, "other") == 0) || (strcmp(fieldp, "o") == 0)) {
614*7c478bd9Sstevel@tonic-gate 		if (def_flag)
615*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = DEF_OTHER_OBJ;
616*7c478bd9Sstevel@tonic-gate 		else
617*7c478bd9Sstevel@tonic-gate 			aclentp->a_type = OTHER_OBJ;
618*7c478bd9Sstevel@tonic-gate 	}
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	/* still can't determine entry type */
621*7c478bd9Sstevel@tonic-gate 	if (aclentp->a_type == 0) {
622*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
623*7c478bd9Sstevel@tonic-gate 		    gettext("Unrecognized entry type %s \n"), fieldp);
624*7c478bd9Sstevel@tonic-gate 		return (-1);
625*7c478bd9Sstevel@tonic-gate 	}
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 	/* mask and other entries dont have id field */
628*7c478bd9Sstevel@tonic-gate 	if (aclentp->a_type != CLASS_OBJ && aclentp->a_type != OTHER_OBJ &&
629*7c478bd9Sstevel@tonic-gate 	    aclentp->a_type != DEF_CLASS_OBJ &&
630*7c478bd9Sstevel@tonic-gate 	    aclentp->a_type != DEF_OTHER_OBJ) {
631*7c478bd9Sstevel@tonic-gate 		/* process id: */
632*7c478bd9Sstevel@tonic-gate 		fieldp = ++colonp;
633*7c478bd9Sstevel@tonic-gate 		colonp = (char *)strchr(fieldp, ':');
634*7c478bd9Sstevel@tonic-gate 		if (colonp == NULL) {
635*7c478bd9Sstevel@tonic-gate 			if (mode != DELETE) {
636*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
637*7c478bd9Sstevel@tonic-gate 				    gettext("Can't find colon delimiter %s\n"),
638*7c478bd9Sstevel@tonic-gate 				    fieldp);
639*7c478bd9Sstevel@tonic-gate 				return (-1);
640*7c478bd9Sstevel@tonic-gate 			}
641*7c478bd9Sstevel@tonic-gate 		} else
642*7c478bd9Sstevel@tonic-gate 			*colonp = '\0';
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 		if (*fieldp == '\0') {
645*7c478bd9Sstevel@tonic-gate 			/* empty uid */
646*7c478bd9Sstevel@tonic-gate 			if (aclentp->a_type == USER)
647*7c478bd9Sstevel@tonic-gate 				aclentp->a_type = USER_OBJ;
648*7c478bd9Sstevel@tonic-gate 			if (aclentp->a_type == DEF_USER)
649*7c478bd9Sstevel@tonic-gate 				aclentp->a_type = DEF_USER_OBJ;
650*7c478bd9Sstevel@tonic-gate 			if (aclentp->a_type == GROUP)
651*7c478bd9Sstevel@tonic-gate 				aclentp->a_type = GROUP_OBJ;
652*7c478bd9Sstevel@tonic-gate 			if (aclentp->a_type == DEF_GROUP)
653*7c478bd9Sstevel@tonic-gate 				aclentp->a_type = DEF_GROUP_OBJ;
654*7c478bd9Sstevel@tonic-gate 		} else {
655*7c478bd9Sstevel@tonic-gate 			/* see if it's a user/group name */
656*7c478bd9Sstevel@tonic-gate 			if (aclentp->a_type == USER ||
657*7c478bd9Sstevel@tonic-gate 			    aclentp->a_type == USER_OBJ ||
658*7c478bd9Sstevel@tonic-gate 			    aclentp->a_type == DEF_USER ||
659*7c478bd9Sstevel@tonic-gate 			    aclentp->a_type == DEF_USER_OBJ) {
660*7c478bd9Sstevel@tonic-gate 				if ((pwp = getpwnam(fieldp)) != NULL)
661*7c478bd9Sstevel@tonic-gate 					aclentp->a_id = pwp->pw_uid;
662*7c478bd9Sstevel@tonic-gate 				else {
663*7c478bd9Sstevel@tonic-gate 					/* treat it as numeric id */
664*7c478bd9Sstevel@tonic-gate 					id = conv_id(fieldp);
665*7c478bd9Sstevel@tonic-gate 					if (id == -1)
666*7c478bd9Sstevel@tonic-gate 						return (-1);
667*7c478bd9Sstevel@tonic-gate 					aclentp->a_id = id;
668*7c478bd9Sstevel@tonic-gate 				}
669*7c478bd9Sstevel@tonic-gate 			} else {
670*7c478bd9Sstevel@tonic-gate 				/* group name */
671*7c478bd9Sstevel@tonic-gate 				if ((grp = getgrnam(fieldp)) != NULL)
672*7c478bd9Sstevel@tonic-gate 					aclentp->a_id = grp->gr_gid;
673*7c478bd9Sstevel@tonic-gate 				else {
674*7c478bd9Sstevel@tonic-gate 					id = conv_id(fieldp);
675*7c478bd9Sstevel@tonic-gate 					if (id == -1)
676*7c478bd9Sstevel@tonic-gate 						return (-1);
677*7c478bd9Sstevel@tonic-gate 					aclentp->a_id = id;
678*7c478bd9Sstevel@tonic-gate 				}
679*7c478bd9Sstevel@tonic-gate 			}
680*7c478bd9Sstevel@tonic-gate 		}
681*7c478bd9Sstevel@tonic-gate 	} else {
682*7c478bd9Sstevel@tonic-gate 		/* it is mask/other entry */
683*7c478bd9Sstevel@tonic-gate 		mo_flag = 1;
684*7c478bd9Sstevel@tonic-gate 	}
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	/* process permission: rwx and [0]n  format */
687*7c478bd9Sstevel@tonic-gate 	if (mode == DELETE)
688*7c478bd9Sstevel@tonic-gate 		/* delete format: no permission field */
689*7c478bd9Sstevel@tonic-gate 		return (0);
690*7c478bd9Sstevel@tonic-gate 	fieldp = ++colonp;
691*7c478bd9Sstevel@tonic-gate 	colonp = (char *)strchr(fieldp, ':');
692*7c478bd9Sstevel@tonic-gate 	if (colonp != NULL) {
693*7c478bd9Sstevel@tonic-gate 		if (mo_flag == 1) {
694*7c478bd9Sstevel@tonic-gate 			/* Use only single : on mask/other entry */
695*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("use only 1 colon for "
696*7c478bd9Sstevel@tonic-gate 						"mask and other entries.\n"));
697*7c478bd9Sstevel@tonic-gate 			return (-1);
698*7c478bd9Sstevel@tonic-gate 		} else {
699*7c478bd9Sstevel@tonic-gate 			/* it's ok to have extra colon */
700*7c478bd9Sstevel@tonic-gate 			*colonp = '\0';
701*7c478bd9Sstevel@tonic-gate 		}
702*7c478bd9Sstevel@tonic-gate 	}
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	if ((int)strlen(fieldp) > 3) {
705*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
706*7c478bd9Sstevel@tonic-gate 		    gettext("only rwx or [0]n format is allowed\n"));
707*7c478bd9Sstevel@tonic-gate 		return (-1);
708*7c478bd9Sstevel@tonic-gate 	}
709*7c478bd9Sstevel@tonic-gate 	if (strlen(fieldp) == 3) {
710*7c478bd9Sstevel@tonic-gate 		aclentp->a_perm = 0;
711*7c478bd9Sstevel@tonic-gate 		/* treat it as rwx */
712*7c478bd9Sstevel@tonic-gate 		if (*fieldp == 'r')
713*7c478bd9Sstevel@tonic-gate 			aclentp->a_perm += 4;
714*7c478bd9Sstevel@tonic-gate 		else
715*7c478bd9Sstevel@tonic-gate 			if (*fieldp != '-') {
716*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
717*7c478bd9Sstevel@tonic-gate 				    gettext("Unrecognized character "));
718*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
719*7c478bd9Sstevel@tonic-gate 				    gettext("found in mode field\n"));
720*7c478bd9Sstevel@tonic-gate 				return (-1);
721*7c478bd9Sstevel@tonic-gate 			}
722*7c478bd9Sstevel@tonic-gate 		fieldp++;
723*7c478bd9Sstevel@tonic-gate 		if (*fieldp == 'w')
724*7c478bd9Sstevel@tonic-gate 			aclentp->a_perm += 2;
725*7c478bd9Sstevel@tonic-gate 		else
726*7c478bd9Sstevel@tonic-gate 			if (*fieldp != '-') {
727*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
728*7c478bd9Sstevel@tonic-gate 				    gettext("Unrecognized character "));
729*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
730*7c478bd9Sstevel@tonic-gate 				    gettext("found in mode field\n"));
731*7c478bd9Sstevel@tonic-gate 				return (-1);
732*7c478bd9Sstevel@tonic-gate 			}
733*7c478bd9Sstevel@tonic-gate 		fieldp++;
734*7c478bd9Sstevel@tonic-gate 		if (*fieldp == 'x')
735*7c478bd9Sstevel@tonic-gate 			aclentp->a_perm += 1;
736*7c478bd9Sstevel@tonic-gate 		else
737*7c478bd9Sstevel@tonic-gate 			if (*fieldp != '-') {
738*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
739*7c478bd9Sstevel@tonic-gate 				    gettext("Unrecognized character "));
740*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
741*7c478bd9Sstevel@tonic-gate 				    gettext("found in mode field\n"));
742*7c478bd9Sstevel@tonic-gate 				return (-1);
743*7c478bd9Sstevel@tonic-gate 			}
744*7c478bd9Sstevel@tonic-gate 		return (0);
745*7c478bd9Sstevel@tonic-gate 	}
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 	if (*fieldp == '\0')
748*7c478bd9Sstevel@tonic-gate 		return (0);
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	if (*fieldp >= '0' && *fieldp <= '7')
751*7c478bd9Sstevel@tonic-gate 		aclentp->a_perm = *fieldp - '0';
752*7c478bd9Sstevel@tonic-gate 	else {
753*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Unrecognized character "));
754*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("found in mode field\n"));
755*7c478bd9Sstevel@tonic-gate 		return (-1);
756*7c478bd9Sstevel@tonic-gate 	}
757*7c478bd9Sstevel@tonic-gate 	if (aclentp->a_perm == 0 && *++fieldp != '\0') {
758*7c478bd9Sstevel@tonic-gate 		/* look at next char */
759*7c478bd9Sstevel@tonic-gate 		if (*fieldp >= '0' && *fieldp <= '7')
760*7c478bd9Sstevel@tonic-gate 			aclentp->a_perm = *fieldp - '0';
761*7c478bd9Sstevel@tonic-gate 		else {
762*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("Unrecognized character "));
763*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("found in mode field\n"));
764*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
765*7c478bd9Sstevel@tonic-gate 			    gettext("Check also the number of fields "));
766*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
767*7c478bd9Sstevel@tonic-gate 			    gettext("(default) mask and other entries\n"));
768*7c478bd9Sstevel@tonic-gate 			return (-1);
769*7c478bd9Sstevel@tonic-gate 		}
770*7c478bd9Sstevel@tonic-gate 	}
771*7c478bd9Sstevel@tonic-gate 	/* check for junk at the end ??? */
772*7c478bd9Sstevel@tonic-gate 	return (0);
773*7c478bd9Sstevel@tonic-gate }
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate /*
776*7c478bd9Sstevel@tonic-gate  * This function is different from atoi() in that it checks for
777*7c478bd9Sstevel@tonic-gate  * valid digit in the id field whereas atoi() won't report any
778*7c478bd9Sstevel@tonic-gate  * error.
779*7c478bd9Sstevel@tonic-gate  */
780*7c478bd9Sstevel@tonic-gate static int
781*7c478bd9Sstevel@tonic-gate conv_id(char *fieldp)
782*7c478bd9Sstevel@tonic-gate {
783*7c478bd9Sstevel@tonic-gate 	int	a_id = 0;
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate 	for (; *fieldp != '\0'; fieldp++) {
786*7c478bd9Sstevel@tonic-gate 		if (!isdigit(*fieldp)) {
787*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("non-digit in id field\n"));
788*7c478bd9Sstevel@tonic-gate 			return (-1);
789*7c478bd9Sstevel@tonic-gate 		}
790*7c478bd9Sstevel@tonic-gate 		a_id = a_id * 10 + (*fieldp - '0');
791*7c478bd9Sstevel@tonic-gate 	}
792*7c478bd9Sstevel@tonic-gate 	return (a_id);
793*7c478bd9Sstevel@tonic-gate }
794