1/*
2 * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like.  Any license provided herein, whether implied or
15 * otherwise, applies only to this software file.  Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA  94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33#include <sys/types.h>
34#include <sys/param.h>
35#include <sys/stat.h>
36#include <stdio.h>
37#include <fcntl.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <errno.h>
41#include <string.h>
42#include <locale.h>
43
44#include <attr/attributes.h>
45#include "config.h"
46
47#define	SETOP		1		/* do a SET operation */
48#define	GETOP		2		/* do a GET operation */
49#define	REMOVEOP	3		/* do a REMOVE operation */
50
51static char *progname;
52
53void
54usage(void)
55{
56	fprintf(stderr, _(
57"Usage: %s [-LRq] -s attrname [-V attrvalue] pathname  # set value\n"
58"       %s [-LRq] -g attrname pathname                 # get value\n"
59"       %s [-LRq] -r attrname pathname                 # remove attr\n"
60"      -s reads a value from stdin and -g writes a value to stdout\n"),
61		progname, progname, progname);
62	exit(1);
63}
64
65int
66main(int argc, char **argv)
67{
68	char *attrname, *attrvalue, *filename;
69	int attrlength;
70	int opflag, ch, error, follow, verbose, rootflag;
71
72	progname = basename(argv[0]);
73
74	setlocale(LC_CTYPE, "");
75	setlocale(LC_MESSAGES, "");
76	bindtextdomain(PACKAGE, LOCALEDIR);
77	textdomain(PACKAGE);
78
79	/*
80	 * Pick up and validate the arguments.
81	 */
82	verbose = 1;
83	follow = opflag = rootflag = 0;
84	attrname = attrvalue = NULL;
85	while ((ch = getopt(argc, argv, "s:V:g:r:qLR")) != EOF) {
86		switch (ch) {
87		case 's':
88			if ((opflag != 0) && (opflag != SETOP)) {
89				fprintf(stderr,
90				    _("Only one of -s, -g, or -r allowed\n"));
91				usage();
92			}
93			opflag = SETOP;
94			attrname = optarg;
95			break;
96		case 'V':
97			if ((opflag != 0) && (opflag != SETOP)) {
98				fprintf(stderr,
99				    _("-V only allowed with -s\n"));
100				usage();
101			}
102			opflag = SETOP;
103			attrvalue = optarg;
104			break;
105		case 'g':
106			if (opflag) {
107				fprintf(stderr,
108				    _("Only one of -s, -g, or -r allowed\n"));
109				usage();
110			}
111			opflag = GETOP;
112			attrname = optarg;
113			break;
114		case 'r':
115			if (opflag) {
116				fprintf(stderr,
117				    _("Only one of -s, -g, or -r allowed\n"));
118				usage();
119			}
120			opflag = REMOVEOP;
121			attrname = optarg;
122			break;
123		case 'L':
124			follow++;
125			break;
126		case 'R':
127			rootflag++;
128			break;
129		case 'q':
130			verbose = 0;
131			break;
132		default:
133			fprintf(stderr,
134			    _("Unrecognized option: %c\n"), (char)ch);
135			usage();
136			break;
137		}
138	}
139	if (optind != argc-1) {
140		fprintf(stderr, _("A filename to operate on is required\n"));
141		usage();
142	}
143	filename = argv[optind];
144
145	/*
146	 * Break out into option-specific processing.
147	 */
148	switch (opflag) {
149	case SETOP:
150		if (attrvalue == NULL) {
151			attrvalue = malloc(ATTR_MAX_VALUELEN);
152			if (attrvalue == NULL) {
153				perror("malloc");
154				exit(1);
155			}
156			attrlength =
157				fread(attrvalue, 1, ATTR_MAX_VALUELEN, stdin);
158		} else {
159			attrlength = strlen(attrvalue);
160		}
161		error = attr_set(filename, attrname, attrvalue,
162					   attrlength,
163					   (!follow ? ATTR_DONTFOLLOW : 0) |
164					   (rootflag ? ATTR_ROOT : 0));
165		if (error) {
166			perror("attr_set");
167			fprintf(stderr, _("Could not set \"%s\" for %s\n"),
168					attrname, filename);
169			exit(1);
170		}
171		if (verbose) {
172			printf(_("Attribute \"%s\" set to a %d byte value "
173			       "for %s:\n"), attrname, attrlength, filename);
174			fwrite(attrvalue, 1, attrlength, stdout);
175			printf("\n");
176		}
177		break;
178
179	case GETOP:
180		attrvalue = malloc(ATTR_MAX_VALUELEN);
181		if (attrvalue == NULL) {
182			perror("malloc");
183			exit(1);
184		}
185		attrlength = ATTR_MAX_VALUELEN;
186		error = attr_get(filename, attrname, attrvalue,
187					   &attrlength,
188					   (!follow ? ATTR_DONTFOLLOW : 0) |
189					   (rootflag ? ATTR_ROOT : 0));
190		if (error) {
191			perror("attr_get");
192			fprintf(stderr, _("Could not get \"%s\" for %s\n"),
193					attrname, filename);
194			exit(1);
195		}
196		if (verbose) {
197			printf(_("Attribute \"%s\" had a %d byte value "
198				"for %s:\n"), attrname, attrlength, filename);
199		}
200		fwrite(attrvalue, 1, attrlength, stdout);
201		if (verbose) {
202			printf("\n");
203		}
204		break;
205
206	case REMOVEOP:
207		error = attr_remove(filename, attrname,
208					      (!follow ? ATTR_DONTFOLLOW : 0) |
209					      (rootflag ? ATTR_ROOT : 0));
210		if (error) {
211			perror("attr_remove");
212			fprintf(stderr, _("Could not remove \"%s\" for %s\n"),
213					attrname, filename);
214			exit(1);
215		}
216		break;
217
218	default:
219		fprintf(stderr,
220			_("At least one of -s, -g, or -r is required\n"));
221		usage();
222		break;
223	}
224
225	return(0);
226}
227