1139969Simp/*-
262813Speter * Copyright (c) 2000  Peter Wemm <peter@freebsd.org>
362813Speter *
462813Speter * Redistribution and use in source and binary forms, with or without
562813Speter * modification, are permitted provided that the following conditions
662813Speter * are met:
762813Speter * 1. Redistributions of source code must retain the above copyright
862813Speter *    notice, this list of conditions and the following disclaimer.
962813Speter * 2. Redistributions in binary form must reproduce the above copyright
1062813Speter *    notice, this list of conditions and the following disclaimer in the
1162813Speter *    documentation and/or other materials provided with the distribution.
1262813Speter *
1362813Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1462813Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1562813Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1662813Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
1762813Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1862813Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1962813Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2062813Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2162813Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2262813Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2362813Speter * SUCH DAMAGE.
2462813Speter */
2599112Sobrien
2699112Sobrien#include <sys/cdefs.h>
2799112Sobrien__FBSDID("$FreeBSD$");
2899112Sobrien
2962813Speter#include <sys/types.h>
3062813Speter#include <sys/sysctl.h>
31128698Sdas#include <err.h>
32128698Sdas#include <kenv.h>
33128698Sdas#include <stdio.h>
3462813Speter#include <stdlib.h>
3562813Speter#include <string.h>
3662813Speter#include <unistd.h>
3762813Speter
3894937Smuxstatic void	usage(void);
3994937Smuxstatic int	kdumpenv(void);
40251156Sdelphijstatic int	kgetenv(const char *);
41251156Sdelphijstatic int	ksetenv(const char *, char *);
42251156Sdelphijstatic int	kunsetenv(const char *);
4362813Speter
4494937Smuxstatic int hflag = 0;
45236118Smdfstatic int Nflag = 0;
46150101Srwatsonstatic int qflag = 0;
4794937Smuxstatic int uflag = 0;
48236118Smdfstatic int vflag = 0;
4994937Smux
5062813Speterstatic void
5162813Speterusage(void)
5262813Speter{
5394937Smux	(void)fprintf(stderr, "%s\n%s\n%s\n",
54236118Smdf	    "usage: kenv [-hNq]",
55236118Smdf	    "       kenv [-qv] variable[=value]",
56150101Srwatson	    "       kenv [-q] -u variable");
5786404Sdd	exit(1);
5862813Speter}
5962813Speter
6062813Speterint
6162813Spetermain(int argc, char **argv)
6262813Speter{
6394937Smux	char *env, *eq, *val;
6494937Smux	int ch, error;
6562813Speter
6694937Smux	error = 0;
6794937Smux	val = NULL;
6862813Speter	env = NULL;
69236118Smdf	while ((ch = getopt(argc, argv, "hNquv")) != -1) {
7062813Speter		switch (ch) {
7162813Speter		case 'h':
7262813Speter			hflag++;
7362813Speter			break;
74236118Smdf		case 'N':
75236118Smdf			Nflag++;
76236118Smdf			break;
77150101Srwatson		case 'q':
78150101Srwatson			qflag++;
79150101Srwatson			break;
8094937Smux		case 'u':
8194937Smux			uflag++;
8294937Smux			break;
83236118Smdf		case 'v':
84236118Smdf			vflag++;
85236118Smdf			break;
8662813Speter		default:
8762813Speter			usage();
8862813Speter		}
8962813Speter	}
9062813Speter	argc -= optind;
9162813Speter	argv += optind;
9262813Speter	if (argc > 0) {
9362813Speter		env = argv[0];
9494937Smux		eq = strchr(env, '=');
9594937Smux		if (eq != NULL) {
9694937Smux			*eq++ = '\0';
9794937Smux			val = eq;
9894937Smux		}
9962813Speter		argv++;
10062813Speter		argc--;
10162813Speter	}
102236118Smdf	if ((hflag || Nflag) && env != NULL)
10362813Speter		usage();
104236118Smdf	if (argc > 0 || ((uflag || vflag) && env == NULL))
10594937Smux		usage();
106128698Sdas	if (env == NULL) {
107128698Sdas		error = kdumpenv();
108150101Srwatson		if (error && !qflag)
109128698Sdas			warn("kdumpenv");
110128698Sdas	} else if (val == NULL) {
11194937Smux		if (uflag) {
11294937Smux			error = kunsetenv(env);
113150101Srwatson			if (error && !qflag)
11494937Smux				warnx("unable to unset %s", env);
11594937Smux		} else {
11694937Smux			error = kgetenv(env);
117150101Srwatson			if (error && !qflag)
11894937Smux				warnx("unable to get %s", env);
11962813Speter		}
12094937Smux	} else {
12194937Smux		error = ksetenv(env, val);
122150101Srwatson		if (error && !qflag)
12394937Smux			warnx("unable to set %s to %s", env, val);
12494937Smux	}
12594937Smux	return (error);
12694937Smux}
12794937Smux
12894937Smuxstatic int
129201177Sedkdumpenv(void)
13094937Smux{
13194937Smux	char *buf, *cp;
132128698Sdas	int buflen, envlen;
13394937Smux
134128698Sdas	envlen = kenv(KENV_DUMP, NULL, NULL, 0);
135128698Sdas	if (envlen < 0)
13694937Smux		return (-1);
137128698Sdas	for (;;) {
138128698Sdas		buflen = envlen * 120 / 100;
139128698Sdas		buf = malloc(buflen + 1);
140128698Sdas		if (buf == NULL)
141128698Sdas			return (-1);
142128698Sdas		memset(buf, 0, buflen + 1);	/* Be defensive */
143128698Sdas		envlen = kenv(KENV_DUMP, NULL, buf, buflen);
144128698Sdas		if (envlen < 0) {
145128698Sdas			free(buf);
146128698Sdas			return (-1);
147128698Sdas		}
148128698Sdas		if (envlen > buflen)
149128698Sdas			free(buf);
150128698Sdas		else
151128698Sdas			break;
152128698Sdas	}
153128698Sdas
15494937Smux	for (; *buf != '\0'; buf += strlen(buf) + 1) {
15562813Speter		if (hflag) {
15694937Smux			if (strncmp(buf, "hint.", 5) != 0)
15762813Speter				continue;
15862813Speter		}
15994937Smux		cp = strchr(buf, '=');
16094937Smux		if (cp == NULL)
16194937Smux			continue;
16294937Smux		*cp++ = '\0';
163236118Smdf		if (Nflag)
164236118Smdf			printf("%s\n", buf);
165236118Smdf		else
166236118Smdf			printf("%s=\"%s\"\n", buf, cp);
16794937Smux		buf = cp;
16862813Speter	}
16994937Smux	return (0);
17062813Speter}
17194937Smux
17294937Smuxstatic int
173251156Sdelphijkgetenv(const char *env)
17494937Smux{
17594937Smux	char buf[1024];
17694937Smux	int ret;
17794937Smux
17894937Smux	ret = kenv(KENV_GET, env, buf, sizeof(buf));
17994937Smux	if (ret == -1)
18094937Smux		return (ret);
181236118Smdf	if (vflag)
182236118Smdf		printf("%s=\"%s\"\n", env, buf);
183236118Smdf	else
184236118Smdf		printf("%s\n", buf);
18594937Smux	return (0);
18694937Smux}
18794937Smux
18894937Smuxstatic int
189251156Sdelphijksetenv(const char *env, char *val)
19094937Smux{
19194937Smux	int ret;
19294937Smux
19394937Smux	ret = kenv(KENV_SET, env, val, strlen(val)+1);
19494937Smux	if (ret == 0)
19594937Smux		printf("%s=\"%s\"\n", env, val);
19694937Smux	return (ret);
19794937Smux}
19894937Smux
19994937Smuxstatic int
200251156Sdelphijkunsetenv(const char *env)
20194937Smux{
20294937Smux	int ret;
20394937Smux
20494937Smux	ret = kenv(KENV_UNSET, env, NULL, 0);
20594937Smux	return (ret);
20694937Smux}
207