xref: /f-stack/tools/libutil/getlocalbase.c (revision 22ce4aff)
1*22ce4affSfengbojiang /*-
2*22ce4affSfengbojiang  * SPDX-License-Identifier: BSD-2-Clause
3*22ce4affSfengbojiang  *
4*22ce4affSfengbojiang  * Copyright 2020 Stefan Eßer <[email protected]>
5*22ce4affSfengbojiang  *
6*22ce4affSfengbojiang  * Redistribution and use in source and binary forms, with or without
7*22ce4affSfengbojiang  * modification, are permitted provided that the following conditions
8*22ce4affSfengbojiang  * are met:
9*22ce4affSfengbojiang  * 1. Redistributions of source code must retain the above copyright
10*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer.
11*22ce4affSfengbojiang  * 2. Redistributions in binary form must reproduce the above copyright
12*22ce4affSfengbojiang  *    notice, this list of conditions and the following disclaimer in the
13*22ce4affSfengbojiang  *    documentation and/or other materials provided with the distribution.
14*22ce4affSfengbojiang  *
15*22ce4affSfengbojiang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16*22ce4affSfengbojiang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*22ce4affSfengbojiang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*22ce4affSfengbojiang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19*22ce4affSfengbojiang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*22ce4affSfengbojiang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*22ce4affSfengbojiang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*22ce4affSfengbojiang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*22ce4affSfengbojiang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*22ce4affSfengbojiang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*22ce4affSfengbojiang  * SUCH DAMAGE.
26*22ce4affSfengbojiang  */
27*22ce4affSfengbojiang 
28*22ce4affSfengbojiang #include <sys/cdefs.h>
29*22ce4affSfengbojiang __FBSDID("$FreeBSD$");
30*22ce4affSfengbojiang 
31*22ce4affSfengbojiang #include <sys/param.h>
32*22ce4affSfengbojiang #include <sys/sysctl.h>
33*22ce4affSfengbojiang #include <sys/limits.h>
34*22ce4affSfengbojiang #include <errno.h>
35*22ce4affSfengbojiang #include <stdlib.h>
36*22ce4affSfengbojiang #include <paths.h>
37*22ce4affSfengbojiang #include <libutil.h>
38*22ce4affSfengbojiang #include <unistd.h>
39*22ce4affSfengbojiang 
40*22ce4affSfengbojiang #ifndef _PATH_LOCALBASE
41*22ce4affSfengbojiang #define _PATH_LOCALBASE "/usr/local"
42*22ce4affSfengbojiang #endif
43*22ce4affSfengbojiang 
44*22ce4affSfengbojiang #ifndef LOCALBASE_CTL_LEN
45*22ce4affSfengbojiang #define LOCALBASE_CTL_LEN MAXPATHLEN
46*22ce4affSfengbojiang #endif
47*22ce4affSfengbojiang 
48*22ce4affSfengbojiang /* Any prefix guaranteed to not be the start of a valid path name */
49*22ce4affSfengbojiang #define ILLEGAL_PREFIX "/dev/null/"
50*22ce4affSfengbojiang 
51*22ce4affSfengbojiang const char *
getlocalbase(void)52*22ce4affSfengbojiang getlocalbase(void)
53*22ce4affSfengbojiang {
54*22ce4affSfengbojiang #if LOCALBASE_CTL_LEN > 0
55*22ce4affSfengbojiang 	int localbase_oid[2] = {CTL_USER, USER_LOCALBASE};
56*22ce4affSfengbojiang 	static char localpath[LOCALBASE_CTL_LEN];
57*22ce4affSfengbojiang 	size_t localpathlen = LOCALBASE_CTL_LEN;
58*22ce4affSfengbojiang #endif
59*22ce4affSfengbojiang 	char *tmppath;
60*22ce4affSfengbojiang 	static const char *localbase = NULL;
61*22ce4affSfengbojiang 
62*22ce4affSfengbojiang 	if (localbase != NULL)
63*22ce4affSfengbojiang 		return (localbase);
64*22ce4affSfengbojiang 
65*22ce4affSfengbojiang 	if (issetugid() == 0) {
66*22ce4affSfengbojiang 		tmppath = getenv("LOCALBASE");
67*22ce4affSfengbojiang 		if (tmppath != NULL && tmppath[0] != '\0') {
68*22ce4affSfengbojiang 			localbase = tmppath;
69*22ce4affSfengbojiang 			return (localbase);
70*22ce4affSfengbojiang 		}
71*22ce4affSfengbojiang 	}
72*22ce4affSfengbojiang 
73*22ce4affSfengbojiang #if LOCALBASE_CTL_LEN > 0
74*22ce4affSfengbojiang 	if (sysctl(localbase_oid, 2, localpath, &localpathlen, NULL, 0) != 0) {
75*22ce4affSfengbojiang 		if (errno != ENOMEM)
76*22ce4affSfengbojiang 			localbase = _PATH_LOCALBASE;
77*22ce4affSfengbojiang 		else
78*22ce4affSfengbojiang 			localbase = ILLEGAL_PREFIX;
79*22ce4affSfengbojiang 	} else {
80*22ce4affSfengbojiang 		if (localpath[0] != '\0')
81*22ce4affSfengbojiang 			localbase = localpath;
82*22ce4affSfengbojiang 		else
83*22ce4affSfengbojiang 			localbase = _PATH_LOCALBASE;
84*22ce4affSfengbojiang 	}
85*22ce4affSfengbojiang #else
86*22ce4affSfengbojiang 	localbase = _PATH_LOCALBASE;
87*22ce4affSfengbojiang #endif
88*22ce4affSfengbojiang 
89*22ce4affSfengbojiang 	return (localbase);
90*22ce4affSfengbojiang }
91