xref: /dflybsd-src/usr.bin/dsynth/config.c (revision a361ab312536a661d74caf5630c7ae20bcd8e3e4)
18e25f19bSMatthew Dillon /*
28e25f19bSMatthew Dillon  * Copyright (c) 2019 The DragonFly Project.  All rights reserved.
38e25f19bSMatthew Dillon  *
48e25f19bSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
58e25f19bSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
68e25f19bSMatthew Dillon  *
78e25f19bSMatthew Dillon  * This code uses concepts and configuration based on 'synth', by
88e25f19bSMatthew Dillon  * John R. Marino <draco@marino.st>, which was written in ada.
98e25f19bSMatthew Dillon  *
108e25f19bSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
118e25f19bSMatthew Dillon  * modification, are permitted provided that the following conditions
128e25f19bSMatthew Dillon  * are met:
138e25f19bSMatthew Dillon  *
148e25f19bSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
158e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
168e25f19bSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
178e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
188e25f19bSMatthew Dillon  *    the documentation and/or other materials provided with the
198e25f19bSMatthew Dillon  *    distribution.
208e25f19bSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
218e25f19bSMatthew Dillon  *    contributors may be used to endorse or promote products derived
228e25f19bSMatthew Dillon  *    from this software without specific, prior written permission.
238e25f19bSMatthew Dillon  *
248e25f19bSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
258e25f19bSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
268e25f19bSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
278e25f19bSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
288e25f19bSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
298e25f19bSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
308e25f19bSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
318e25f19bSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
328e25f19bSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
338e25f19bSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
348e25f19bSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
358e25f19bSMatthew Dillon  * SUCH DAMAGE.
368e25f19bSMatthew Dillon  */
378e25f19bSMatthew Dillon 
388e25f19bSMatthew Dillon #include "dsynth.h"
398e25f19bSMatthew Dillon 
408e25f19bSMatthew Dillon int UseCCache;
41f4094b20SMatthew Dillon int UseUsrSrc;
428e25f19bSMatthew Dillon int UseTmpfs;
438e25f19bSMatthew Dillon int NumCores = 1;
448e25f19bSMatthew Dillon int MaxBulk = 8;
458e25f19bSMatthew Dillon int MaxWorkers = 8;
468e25f19bSMatthew Dillon int MaxJobs = 8;
478e25f19bSMatthew Dillon int UseTmpfsWork = 1;
488e25f19bSMatthew Dillon int UseTmpfsBase = 1;
497f0eca56SMatthew Dillon int UseNCurses = -1;		/* indicates default operation (enabled) */
508e25f19bSMatthew Dillon int LeveragePrebuilt = 0;
516fd67931SMatthew Dillon int WorkerProcFlags = 0;
52dc46751bSMatthew Dillon int DeleteObsoletePkgs;
537f0eca56SMatthew Dillon long PhysMem;
540df5ec4eSMatthew Dillon const char *OperatingSystemName = "Unknown";	/* e.g. "DragonFly" */
550df5ec4eSMatthew Dillon const char *ArchitectureName = "unknown";	/* e.g. "x86_64" */
560df5ec4eSMatthew Dillon const char *MachineName = "unknown";		/* e.g. "x86_64" */
570df5ec4eSMatthew Dillon const char *VersionName = "unknown";		/* e.g. "DragonFly 5.7-SYNTH" */
580df5ec4eSMatthew Dillon const char *VersionOnlyName = "unknown";	/* e.g. "5.7-SYNTH" */
590df5ec4eSMatthew Dillon const char *VersionFromParamHeader = "unknown";	/* e.g. "500704" */
60e5066875SAntonio Huete Jimenez const char *VersionFromSysctl = "unknown";	/* e.g. "500704" */
610df5ec4eSMatthew Dillon const char *ReleaseName = "unknown";		/* e.g. "5.7" */
628e25f19bSMatthew Dillon const char *DPortsPath = "/usr/dports";
63f4094b20SMatthew Dillon const char *CCachePath = DISABLED_STR;
648e25f19bSMatthew Dillon const char *PackagesPath = "/build/synth/live_packages";
658e25f19bSMatthew Dillon const char *RepositoryPath = "/build/synth/live_packages/All";
668e25f19bSMatthew Dillon const char *OptionsPath = "/build/synth/options";
678e25f19bSMatthew Dillon const char *DistFilesPath = "/build/synth/distfiles";
688e25f19bSMatthew Dillon const char *BuildBase = "/build/synth/build";
698e25f19bSMatthew Dillon const char *LogsPath = "/build/synth/logs";
708e25f19bSMatthew Dillon const char *SystemPath = "/";
71483dbac9SMatthew Dillon const char *UsePkgSufx = USE_PKG_SUFX;
72aac7a6d9SMatthew Dillon char *StatsBase;
73aac7a6d9SMatthew Dillon char *StatsFilePath;
74aac7a6d9SMatthew Dillon char *StatsLockPath;
75d50f9ae3SSascha Wildner static const char *ProfileLabel = "[LiveSystem]"; /* with the brackets */
7668dc2eeaSMatthew Dillon const char *Profile = "LiveSystem";		/* without the brackets */
776a7ba689SMatthew Dillon int MetaVersion = 2;
788e25f19bSMatthew Dillon 
7968dc2eeaSMatthew Dillon /*
8068dc2eeaSMatthew Dillon  * Hooks are scripts in ConfigBase
8168dc2eeaSMatthew Dillon  */
8268dc2eeaSMatthew Dillon int UsingHooks;
8368dc2eeaSMatthew Dillon const char *HookRunStart;
8468dc2eeaSMatthew Dillon const char *HookRunEnd;
8568dc2eeaSMatthew Dillon const char *HookPkgSuccess;
8668dc2eeaSMatthew Dillon const char *HookPkgFailure;
8768dc2eeaSMatthew Dillon const char *HookPkgIgnored;
8868dc2eeaSMatthew Dillon const char *HookPkgSkipped;
8968dc2eeaSMatthew Dillon 
9068dc2eeaSMatthew Dillon const char *ConfigBase;				/* The config base we found */
9168dc2eeaSMatthew Dillon const char *ConfigBase1 = "/etc/dsynth";
9268dc2eeaSMatthew Dillon const char *ConfigBase2 = "/usr/local/etc/dsynth";
938ec23ca1SMatthew Dillon 
948e25f19bSMatthew Dillon static void parseConfigFile(const char *path);
958e25f19bSMatthew Dillon static void parseProfile(const char *cpath, const char *path);
968e25f19bSMatthew Dillon static char *stripwhite(char *str);
978e25f19bSMatthew Dillon static int truefalse(const char *str);
988e25f19bSMatthew Dillon static char *dokernsysctl(int m1, int m2);
99a574cbf0SMatthew Dillon static void getElfInfo(const char *path);
10068dc2eeaSMatthew Dillon static char *checkhook(const char *scriptname);
1018e25f19bSMatthew Dillon 
1028e25f19bSMatthew Dillon void
ParseConfiguration(int isworker)1038e25f19bSMatthew Dillon ParseConfiguration(int isworker)
1048e25f19bSMatthew Dillon {
1051645cafeSMatthew Dillon 	struct stat st;
1068e25f19bSMatthew Dillon 	size_t len;
107294990e5SMatthew Dillon 	int reln;
1088ec23ca1SMatthew Dillon 	char *synth_config;
109294990e5SMatthew Dillon 	char *buf;
110e5066875SAntonio Huete Jimenez 	char *osreldate;
1118ec23ca1SMatthew Dillon 
1128ec23ca1SMatthew Dillon 	/*
113a574cbf0SMatthew Dillon 	 * Get the default OperatingSystemName, ArchitectureName, and
114a574cbf0SMatthew Dillon 	 * ReleaseName.
1158e25f19bSMatthew Dillon 	 */
1168e25f19bSMatthew Dillon 	OperatingSystemName = dokernsysctl(CTL_KERN, KERN_OSTYPE);
1178e25f19bSMatthew Dillon 	ArchitectureName = dokernsysctl(CTL_HW, HW_MACHINE_ARCH);
1188e25f19bSMatthew Dillon 	MachineName = dokernsysctl(CTL_HW, HW_MACHINE);
1198e25f19bSMatthew Dillon 	ReleaseName = dokernsysctl(CTL_KERN, KERN_OSRELEASE);
120e5066875SAntonio Huete Jimenez 	asprintf(&osreldate, "%d", getosreldate());
121e5066875SAntonio Huete Jimenez 	VersionFromSysctl = osreldate;
122294990e5SMatthew Dillon 
1238e25f19bSMatthew Dillon 	/*
124fef2fc63SMatthew Dillon 	 * Retrieve resource information from the system.  Note that
125fef2fc63SMatthew Dillon 	 * NumCores and PhysMem will also be used for dynamic load
126fef2fc63SMatthew Dillon 	 * management.
1278e25f19bSMatthew Dillon 	 */
1288e25f19bSMatthew Dillon 	NumCores = 1;
1298e25f19bSMatthew Dillon 	len = sizeof(NumCores);
1308e25f19bSMatthew Dillon 	if (sysctlbyname("hw.ncpu", &NumCores, &len, NULL, 0) < 0)
1318e25f19bSMatthew Dillon 		dfatal_errno("Cannot get hw.ncpu");
132fef2fc63SMatthew Dillon 
133fef2fc63SMatthew Dillon 	len = sizeof(PhysMem);
134fef2fc63SMatthew Dillon 	if (sysctlbyname("hw.physmem", &PhysMem, &len, NULL, 0) < 0)
135fef2fc63SMatthew Dillon 		dfatal_errno("Cannot get hw.physmem");
136fef2fc63SMatthew Dillon 
137fef2fc63SMatthew Dillon 	/*
138a574cbf0SMatthew Dillon 	 * Calculate nominal defaults.
139fef2fc63SMatthew Dillon 	 */
1408e25f19bSMatthew Dillon 	MaxBulk = NumCores;
1418e25f19bSMatthew Dillon 	MaxWorkers = MaxBulk / 2;
1427f0eca56SMatthew Dillon 	if (MaxWorkers > (int)((PhysMem + (ONEGB/2)) / ONEGB))
1437f0eca56SMatthew Dillon 		MaxWorkers = (PhysMem + (ONEGB/2)) / ONEGB;
144fef2fc63SMatthew Dillon 
1458e25f19bSMatthew Dillon 	if (MaxBulk < 1)
1468e25f19bSMatthew Dillon 		MaxBulk = 1;
1478e25f19bSMatthew Dillon 	if (MaxWorkers < 1)
1488e25f19bSMatthew Dillon 		MaxWorkers = 1;
1498e25f19bSMatthew Dillon 	if (MaxJobs < 1)
1508e25f19bSMatthew Dillon 		MaxJobs = 1;
1518e25f19bSMatthew Dillon 
1528e25f19bSMatthew Dillon 	/*
153a574cbf0SMatthew Dillon 	 * Configuration file must exist.  Look for it in
154a574cbf0SMatthew Dillon 	 * "/etc/dsynth" and "/usr/local/etc/dsynth".
1551645cafeSMatthew Dillon 	 */
15668dc2eeaSMatthew Dillon 	ConfigBase = ConfigBase1;
15768dc2eeaSMatthew Dillon 	asprintf(&synth_config, "%s/dsynth.ini", ConfigBase1);
158*a361ab31SMatthew Dillon 	if (stat(synth_config, &st) < 0 && ConfigBase2) {
15968dc2eeaSMatthew Dillon 		ConfigBase = ConfigBase2;
16068dc2eeaSMatthew Dillon 		asprintf(&synth_config, "%s/dsynth.ini", ConfigBase2);
16168dc2eeaSMatthew Dillon 	}
162a574cbf0SMatthew Dillon 
1638ec23ca1SMatthew Dillon 	if (stat(synth_config, &st) < 0) {
1648ec23ca1SMatthew Dillon 		dfatal("Configuration file missing, "
165*a361ab31SMatthew Dillon 		       "could not find %s/dsynth.ini%s%s/dsynth.ini\n",
16668dc2eeaSMatthew Dillon 		       ConfigBase1,
167*a361ab31SMatthew Dillon 		       (ConfigBase2 ? " or " : ""),
168*a361ab31SMatthew Dillon 		       (ConfigBase2 ? ConfigBase2 : ""));
1698ec23ca1SMatthew Dillon 	}
1701645cafeSMatthew Dillon 
1711645cafeSMatthew Dillon 	/*
17268dc2eeaSMatthew Dillon 	 * Check to see what hooks we have
17368dc2eeaSMatthew Dillon 	 */
17468dc2eeaSMatthew Dillon 	HookRunStart = checkhook("hook_run_start");
17568dc2eeaSMatthew Dillon 	HookRunEnd = checkhook("hook_run_end");
17668dc2eeaSMatthew Dillon 	HookPkgSuccess = checkhook("hook_pkg_success");
17768dc2eeaSMatthew Dillon 	HookPkgFailure = checkhook("hook_pkg_failure");
17868dc2eeaSMatthew Dillon 	HookPkgIgnored = checkhook("hook_pkg_ignored");
17968dc2eeaSMatthew Dillon 	HookPkgSkipped = checkhook("hook_pkg_skipped");
18068dc2eeaSMatthew Dillon 
18168dc2eeaSMatthew Dillon 	/*
182a574cbf0SMatthew Dillon 	 * Parse the configuration file(s).  This may override some of
183a574cbf0SMatthew Dillon 	 * the above defaults.
1848e25f19bSMatthew Dillon 	 */
1858ec23ca1SMatthew Dillon 	parseConfigFile(synth_config);
1868ec23ca1SMatthew Dillon 	parseProfile(synth_config, ProfileLabel);
1878e25f19bSMatthew Dillon 
1888e25f19bSMatthew Dillon 	/*
189f4094b20SMatthew Dillon 	 * Figure out whether CCache is configured.  Also set UseUsrSrc
190f4094b20SMatthew Dillon 	 * if it exists under the system path.
191f4094b20SMatthew Dillon 	 *
192f4094b20SMatthew Dillon 	 * Not supported for the moment
193f4094b20SMatthew Dillon 	 */
194f4094b20SMatthew Dillon 	if (strcmp(CCachePath, "disabled") != 0) {
19533c3dcc3SMatthew Dillon 		/* dfatal("Directory_ccache is not supported, please\n"
19633c3dcc3SMatthew Dillon 		       " set to 'disabled'\n"); */
197f4094b20SMatthew Dillon 		UseCCache = 1;
198f4094b20SMatthew Dillon 	}
199f4094b20SMatthew Dillon 	asprintf(&buf, "%s/usr/src/sys/Makefile", SystemPath);
200f4094b20SMatthew Dillon 	if (stat(buf, &st) == 0)
201f4094b20SMatthew Dillon 		UseUsrSrc = 1;
202f4094b20SMatthew Dillon 	free(buf);
203f4094b20SMatthew Dillon 
204f4094b20SMatthew Dillon 	/*
205c029abb0SMatthew Dillon 	 * Default pkg dependency memory target.  This is a heuristical
206c029abb0SMatthew Dillon 	 * calculation for how much memory we are willing to put towards
207c029abb0SMatthew Dillon 	 * pkg install dependencies.  The builder count is reduced as needed.
208c029abb0SMatthew Dillon 	 *
209c029abb0SMatthew Dillon 	 * Reduce the target even further when CCache is enabled due to
210c029abb0SMatthew Dillon 	 * its added overhead (even though it doesn't use tmpfs).
21198d51b4fSMatthew Dillon 	 * (NOT CURRENTLY IMPLEMENTED, LEAVE THE SAME)
212c029abb0SMatthew Dillon 	 */
213c029abb0SMatthew Dillon 	if (PkgDepMemoryTarget == 0) {
214c029abb0SMatthew Dillon 		if (UseCCache)
21598d51b4fSMatthew Dillon 			PkgDepMemoryTarget = PhysMem / 3;
216c029abb0SMatthew Dillon 		else
21798d51b4fSMatthew Dillon 			PkgDepMemoryTarget = PhysMem / 3;
218c029abb0SMatthew Dillon 	}
219c029abb0SMatthew Dillon 
220c029abb0SMatthew Dillon 	/*
2218e25f19bSMatthew Dillon 	 * If this is a dsynth WORKER exec it handles a single slot,
2228e25f19bSMatthew Dillon 	 * just set MaxWorkers to 1.
2238e25f19bSMatthew Dillon 	 */
2248e25f19bSMatthew Dillon 	if (isworker)
2258e25f19bSMatthew Dillon 		MaxWorkers = 1;
2261645cafeSMatthew Dillon 
227f4094b20SMatthew Dillon 	/*
228f4094b20SMatthew Dillon 	 * Final check
229f4094b20SMatthew Dillon 	 */
2301645cafeSMatthew Dillon 	if (stat(DPortsPath, &st) < 0)
2311645cafeSMatthew Dillon 		dfatal("Directory missing: %s", DPortsPath);
2321645cafeSMatthew Dillon 	if (stat(PackagesPath, &st) < 0)
2331645cafeSMatthew Dillon 		dfatal("Directory missing: %s", PackagesPath);
2341645cafeSMatthew Dillon 	if (stat(OptionsPath, &st) < 0)
2351645cafeSMatthew Dillon 		dfatal("Directory missing: %s", OptionsPath);
2361645cafeSMatthew Dillon 	if (stat(DistFilesPath, &st) < 0)
2371645cafeSMatthew Dillon 		dfatal("Directory missing: %s", DistFilesPath);
2381645cafeSMatthew Dillon 	if (stat(BuildBase, &st) < 0)
2391645cafeSMatthew Dillon 		dfatal("Directory missing: %s", BuildBase);
2401645cafeSMatthew Dillon 	if (stat(LogsPath, &st) < 0)
2411645cafeSMatthew Dillon 		dfatal("Directory missing: %s", LogsPath);
2421645cafeSMatthew Dillon 	if (stat(SystemPath, &st) < 0)
2431645cafeSMatthew Dillon 		dfatal("Directory missing: %s", SystemPath);
244f4094b20SMatthew Dillon 	if (UseCCache && stat(CCachePath, &st) < 0)
245f4094b20SMatthew Dillon 		dfatal("Directory missing: %s", CCachePath);
2461645cafeSMatthew Dillon 
2471645cafeSMatthew Dillon 	/*
248a574cbf0SMatthew Dillon 	 * Now use the SystemPath to retrieve file information from /bin/sh,
249a574cbf0SMatthew Dillon 	 * and use this to set OperatingSystemName, ArchitectureName,
250a574cbf0SMatthew Dillon 	 * MachineName, and ReleaseName.
251a574cbf0SMatthew Dillon 	 *
252a574cbf0SMatthew Dillon 	 * Since this method is used to build for specific releases, require
253a574cbf0SMatthew Dillon 	 * that it succeed.
254a574cbf0SMatthew Dillon 	 */
255a574cbf0SMatthew Dillon 	asprintf(&buf, "%s/bin/sh", SystemPath);
256a574cbf0SMatthew Dillon 	getElfInfo(buf);
257a574cbf0SMatthew Dillon 	free(buf);
258a574cbf0SMatthew Dillon 
259a574cbf0SMatthew Dillon 	/*
260a574cbf0SMatthew Dillon 	 * Calculate VersionName from OperatingSystemName and ReleaseName.
261a574cbf0SMatthew Dillon 	 */
262a574cbf0SMatthew Dillon 	if (strchr(ReleaseName, '-')) {
263a574cbf0SMatthew Dillon 		reln = strchr(ReleaseName, '-') - ReleaseName;
264a574cbf0SMatthew Dillon 		asprintf(&buf, "%s %*.*s-SYNTH",
265a574cbf0SMatthew Dillon 			 OperatingSystemName,
266a574cbf0SMatthew Dillon 			 reln, reln, ReleaseName);
2670df5ec4eSMatthew Dillon 		VersionName = buf;
2680df5ec4eSMatthew Dillon 		asprintf(&buf, "%*.*s-SYNTH", reln, reln, ReleaseName);
2690df5ec4eSMatthew Dillon 		VersionOnlyName = buf;
270a574cbf0SMatthew Dillon 	} else {
271a574cbf0SMatthew Dillon 		asprintf(&buf, "%s %s-SYNTH",
272a574cbf0SMatthew Dillon 			 OperatingSystemName,
273a574cbf0SMatthew Dillon 			 ReleaseName);
2740df5ec4eSMatthew Dillon 		asprintf(&buf, "%s-SYNTH", ReleaseName);
2750df5ec4eSMatthew Dillon 		VersionOnlyName = buf;
276a574cbf0SMatthew Dillon 	}
2770df5ec4eSMatthew Dillon 
2780df5ec4eSMatthew Dillon 	/*
2790df5ec4eSMatthew Dillon 	 * Get __DragonFly_version from the system header via SystemPath
2800df5ec4eSMatthew Dillon 	 */
2810df5ec4eSMatthew Dillon 	{
2820df5ec4eSMatthew Dillon 		char *ptr;
2830df5ec4eSMatthew Dillon 		FILE *fp;
2840df5ec4eSMatthew Dillon 
2850df5ec4eSMatthew Dillon 		asprintf(&buf, "%s/usr/include/sys/param.h", SystemPath);
2860df5ec4eSMatthew Dillon 		fp = fopen(buf, "r");
2870df5ec4eSMatthew Dillon 		if (fp == NULL)
2880df5ec4eSMatthew Dillon 			dpanic_errno("Cannot open %s", buf);
2890df5ec4eSMatthew Dillon 		while ((ptr = fgetln(fp, &len)) != NULL) {
2900df5ec4eSMatthew Dillon 			if (len == 0 || ptr[len-1] != '\n')
2910df5ec4eSMatthew Dillon 				continue;
2920df5ec4eSMatthew Dillon 			ptr[len-1] = 0;
2930df5ec4eSMatthew Dillon 			if (strncmp(ptr, "#define __DragonFly_version", 27))
2940df5ec4eSMatthew Dillon 				continue;
2950df5ec4eSMatthew Dillon 			ptr += 27;
2960df5ec4eSMatthew Dillon 			ptr = strtok(ptr, " \t\r\n");
2970df5ec4eSMatthew Dillon 			VersionFromParamHeader = strdup(ptr);
2980df5ec4eSMatthew Dillon 			break;
2990df5ec4eSMatthew Dillon 		}
3000df5ec4eSMatthew Dillon 		fclose(fp);
301e5066875SAntonio Huete Jimenez 
302e5066875SAntonio Huete Jimenez 		/* Warn the user that World/kernel are out of sync */
303a5b3c0e8SAntonio Huete Jimenez 		if (strcmp(VersionFromSysctl, VersionFromParamHeader)) {
304e5066875SAntonio Huete Jimenez 			dlog(DLOG_ALL, "Kernel (%s) out of sync with world (%s) on %s\n",
305a5b3c0e8SAntonio Huete Jimenez 			    VersionFromSysctl, VersionFromParamHeader, SystemPath);
306e5066875SAntonio Huete Jimenez 		}
3070df5ec4eSMatthew Dillon 	}
308a574cbf0SMatthew Dillon 
309a574cbf0SMatthew Dillon 	/*
3101645cafeSMatthew Dillon 	 * If RepositoryPath is under PackagesPath, make sure it
3111645cafeSMatthew Dillon 	 * is created.
3121645cafeSMatthew Dillon 	 */
3131645cafeSMatthew Dillon 	if (strncmp(RepositoryPath, PackagesPath, strlen(PackagesPath)) == 0) {
3141645cafeSMatthew Dillon 		if (stat(RepositoryPath, &st) < 0) {
3151645cafeSMatthew Dillon 			if (mkdir(RepositoryPath, 0755) < 0)
3161645cafeSMatthew Dillon 				dfatal_errno("Cannot mkdir '%s'",
3171645cafeSMatthew Dillon 					     RepositoryPath);
3181645cafeSMatthew Dillon 		}
3191645cafeSMatthew Dillon 	}
3201645cafeSMatthew Dillon 
3211645cafeSMatthew Dillon 	if (stat(RepositoryPath, &st) < 0)
3221645cafeSMatthew Dillon 		dfatal("Directory missing: %s", RepositoryPath);
323aac7a6d9SMatthew Dillon 
324aac7a6d9SMatthew Dillon 	/*
325aac7a6d9SMatthew Dillon 	 * StatsBase, StatsFilePath, StatsLockPath
326aac7a6d9SMatthew Dillon 	 */
327aac7a6d9SMatthew Dillon 	asprintf(&StatsBase, "%s/stats", LogsPath);
328aac7a6d9SMatthew Dillon 	asprintf(&StatsFilePath, "%s/monitor.dat", StatsBase);
329aac7a6d9SMatthew Dillon 	asprintf(&StatsLockPath, "%s/monitor.lk", StatsBase);
3308e25f19bSMatthew Dillon }
3318e25f19bSMatthew Dillon 
3328e25f19bSMatthew Dillon void
DoConfigure(void)3338e25f19bSMatthew Dillon DoConfigure(void)
3348e25f19bSMatthew Dillon {
3358e25f19bSMatthew Dillon 	dfatal("Not Implemented");
3368e25f19bSMatthew Dillon }
3378e25f19bSMatthew Dillon 
3388e25f19bSMatthew Dillon static void
parseConfigFile(const char * path)3398e25f19bSMatthew Dillon parseConfigFile(const char *path)
3408e25f19bSMatthew Dillon {
3418e25f19bSMatthew Dillon 	char buf[1024];
3428e25f19bSMatthew Dillon 	char copy[1024];
3438e25f19bSMatthew Dillon 	FILE *fp;
3448e25f19bSMatthew Dillon 	char *l1;
3458e25f19bSMatthew Dillon 	char *l2;
3468e25f19bSMatthew Dillon 	size_t len;
3478e25f19bSMatthew Dillon 	int mode = -1;
3488e25f19bSMatthew Dillon 	int lineno = 0;
3498e25f19bSMatthew Dillon 
3508e25f19bSMatthew Dillon 	fp = fopen(path, "r");
3518e25f19bSMatthew Dillon 	if (fp == NULL) {
3528e25f19bSMatthew Dillon 		ddprintf(0, "Warning: Config file %s does not exist\n", path);
3538e25f19bSMatthew Dillon 		return;
3548e25f19bSMatthew Dillon 	}
35554f2fefcSMatthew Dillon 	if (DebugOpt >= 2)
3568e25f19bSMatthew Dillon 		ddprintf(0, "ParseConfig %s\n", path);
3578e25f19bSMatthew Dillon 
3589e1d0b12SMatthew Dillon 	if (ProfileOverrideOpt) {
3599e1d0b12SMatthew Dillon 		Profile = strdup(ProfileOverrideOpt);
3609e1d0b12SMatthew Dillon 		asprintf(&l2, "[%s]", Profile);
3619e1d0b12SMatthew Dillon 		ProfileLabel = l2;
3629e1d0b12SMatthew Dillon 	}
3639e1d0b12SMatthew Dillon 
3648e25f19bSMatthew Dillon 	while (fgets(buf, sizeof(buf), fp) != NULL) {
3658e25f19bSMatthew Dillon 		++lineno;
3668e25f19bSMatthew Dillon 		len = strlen(buf);
3678e25f19bSMatthew Dillon 		if (len == 0 || buf[len-1] != '\n')
3688e25f19bSMatthew Dillon 			continue;
3698e25f19bSMatthew Dillon 		buf[--len] = 0;
3708e25f19bSMatthew Dillon 
3718e25f19bSMatthew Dillon 		/*
3728e25f19bSMatthew Dillon 		 * Remove any trailing whitespace, ignore empty lines.
3738e25f19bSMatthew Dillon 		 */
3748e25f19bSMatthew Dillon 		while (len > 0 && isspace(buf[len-1]))
3758e25f19bSMatthew Dillon 			--len;
3768e25f19bSMatthew Dillon 		if (len == 0)
3778e25f19bSMatthew Dillon 			continue;
3788e25f19bSMatthew Dillon 		buf[len] = 0;
3798e25f19bSMatthew Dillon 
3808e25f19bSMatthew Dillon 		/*
3818e25f19bSMatthew Dillon 		 * ignore comments
3828e25f19bSMatthew Dillon 		 */
3838e25f19bSMatthew Dillon 		if (buf[0] == ';' || buf[0] == '#')
3848e25f19bSMatthew Dillon 			continue;
3858e25f19bSMatthew Dillon 		if (buf[0] == '[') {
3868e25f19bSMatthew Dillon 			if (strcmp(buf, "[Global Configuration]") == 0)
3878e25f19bSMatthew Dillon 				mode = 0;	/* parse global config */
3888e25f19bSMatthew Dillon 			else if (strcmp(buf, ProfileLabel) == 0)
3898e25f19bSMatthew Dillon 				mode = 1;	/* use profile */
3908e25f19bSMatthew Dillon 			else
3918e25f19bSMatthew Dillon 				mode = -1;	/* ignore profile */
3928e25f19bSMatthew Dillon 			continue;
3938e25f19bSMatthew Dillon 		}
3948e25f19bSMatthew Dillon 
3958e25f19bSMatthew Dillon 		bcopy(buf, copy, len + 1);
3968e25f19bSMatthew Dillon 
3978e25f19bSMatthew Dillon 		l1 = strtok(copy, "=");
3988e25f19bSMatthew Dillon 		if (l1 == NULL) {
3998e25f19bSMatthew Dillon 			dfatal("Syntax error in config line %d: %s\n",
4008e25f19bSMatthew Dillon 			       lineno, buf);
4018e25f19bSMatthew Dillon 		}
4028e25f19bSMatthew Dillon 		l2 = strtok(NULL, " \t\n");
40368dc2eeaSMatthew Dillon 		if (l2 == NULL) {
40468dc2eeaSMatthew Dillon 			dfatal("Syntax error in config line %d: %s\n",
40568dc2eeaSMatthew Dillon 			       lineno, buf);
40668dc2eeaSMatthew Dillon 		}
4078e25f19bSMatthew Dillon 		l1 = stripwhite(l1);
4088e25f19bSMatthew Dillon 		l2 = stripwhite(l2);
4098e25f19bSMatthew Dillon 
4108e25f19bSMatthew Dillon 		switch(mode) {
4118e25f19bSMatthew Dillon 		case 0:
4128e25f19bSMatthew Dillon 			/*
4138e25f19bSMatthew Dillon 			 * Global Configuration
4148e25f19bSMatthew Dillon 			 */
4158e25f19bSMatthew Dillon 			if (strcmp(l1, "profile_selected") == 0) {
4169e1d0b12SMatthew Dillon 				if (ProfileOverrideOpt == NULL) {
41768dc2eeaSMatthew Dillon 					Profile = strdup(l2);
4188e25f19bSMatthew Dillon 					asprintf(&l2, "[%s]", l2);
4198e25f19bSMatthew Dillon 					ProfileLabel = l2;
4209e1d0b12SMatthew Dillon 				}
4218e25f19bSMatthew Dillon 			} else {
4228e25f19bSMatthew Dillon 				dfatal("Unknown directive in config "
4238e25f19bSMatthew Dillon 				       "line %d: %s\n", lineno, buf);
4248e25f19bSMatthew Dillon 			}
4258e25f19bSMatthew Dillon 			break;
4268e25f19bSMatthew Dillon 		case 1:
4278e25f19bSMatthew Dillon 			/*
4288e25f19bSMatthew Dillon 			 * Selected Profile
4298e25f19bSMatthew Dillon 			 */
4308e25f19bSMatthew Dillon 			l2 = strdup(l2);
4318e25f19bSMatthew Dillon 			if (strcmp(l1, "Operating_system") == 0) {
4328e25f19bSMatthew Dillon 				OperatingSystemName = l2;
4338e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_packages") == 0) {
4348e25f19bSMatthew Dillon 				PackagesPath = l2;
4358e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_repository") == 0) {
4368e25f19bSMatthew Dillon 				RepositoryPath = l2;
4378e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_portsdir") == 0) {
4388e25f19bSMatthew Dillon 				DPortsPath = l2;
4398e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_options") == 0) {
4408e25f19bSMatthew Dillon 				OptionsPath = l2;
4418e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_distfiles") == 0) {
4428e25f19bSMatthew Dillon 				DistFilesPath = l2;
4438e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_buildbase") == 0) {
4448e25f19bSMatthew Dillon 				BuildBase = l2;
4458e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_logs") == 0) {
4468e25f19bSMatthew Dillon 				LogsPath = l2;
4478e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_ccache") == 0) {
4488e25f19bSMatthew Dillon 				CCachePath = l2;
4498e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Directory_system") == 0) {
4508e25f19bSMatthew Dillon 				SystemPath = l2;
451483dbac9SMatthew Dillon 			} else if (strcmp(l1, "Package_suffix") == 0) {
452483dbac9SMatthew Dillon 				UsePkgSufx = l2;
453483dbac9SMatthew Dillon 				dassert(strcmp(l2, ".tgz") == 0 ||
454483dbac9SMatthew Dillon 					strcmp(l2, ".tar") == 0 ||
455483dbac9SMatthew Dillon 					strcmp(l2, ".txz") == 0 ||
456ef0c0bf5SKrzysztof Piecuch 					strcmp(l2, ".tzst") == 0 ||
457483dbac9SMatthew Dillon 					strcmp(l2, ".tbz") == 0,
458483dbac9SMatthew Dillon 					"Config: Unknown Package_suffix,"
459ef0c0bf5SKrzysztof Piecuch 					"specify .tgz .tar .txz .tbz or .tzst");
4606a7ba689SMatthew Dillon 			} else if (strcmp(l1, "Meta_version") == 0) {
4616a7ba689SMatthew Dillon 				MetaVersion = strtol(l2, NULL, 0);
4628e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Number_of_builders") == 0) {
4638e25f19bSMatthew Dillon 				MaxWorkers = strtol(l2, NULL, 0);
4648ec23ca1SMatthew Dillon 				if (MaxWorkers == 0)
4658ec23ca1SMatthew Dillon 					MaxWorkers = NumCores / 2 + 1;
4668ec23ca1SMatthew Dillon 				else
4678ec23ca1SMatthew Dillon 				if (MaxWorkers < 0 || MaxWorkers > MAXWORKERS) {
4688e25f19bSMatthew Dillon 					dfatal("Config: Number_of_builders "
4698ec23ca1SMatthew Dillon 					       "must range %d..%d",
4708e25f19bSMatthew Dillon 					       1, MAXWORKERS);
4718e25f19bSMatthew Dillon 				}
4728e25f19bSMatthew Dillon 				free(l2);
4738e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Max_jobs_per_builder") == 0) {
4748e25f19bSMatthew Dillon 				MaxJobs = strtol(l2, NULL, 0);
4758ec23ca1SMatthew Dillon 				if (MaxJobs == 0) {
4768ec23ca1SMatthew Dillon 					MaxJobs = NumCores;
4778ec23ca1SMatthew Dillon 				} else
4788ec23ca1SMatthew Dillon 				if (MaxJobs < 0 || MaxJobs > MAXJOBS) {
4798e25f19bSMatthew Dillon 					dfatal("Config: Max_jobs_per_builder "
4808ec23ca1SMatthew Dillon 					       "must range %d..%d",
4818e25f19bSMatthew Dillon 					       1, MAXJOBS);
4828e25f19bSMatthew Dillon 				}
4838e25f19bSMatthew Dillon 				free(l2);
4848e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Tmpfs_workdir") == 0) {
4858e25f19bSMatthew Dillon 				UseTmpfsWork = truefalse(l2);
4868e25f19bSMatthew Dillon 				dassert(UseTmpfsWork == 1,
4878e25f19bSMatthew Dillon 					"Config: Tmpfs_workdir must be "
4888e25f19bSMatthew Dillon 					"set to true, 'false' not supported");
4898e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Tmpfs_localbase") == 0) {
4908e25f19bSMatthew Dillon 				UseTmpfsBase = truefalse(l2);
4918e25f19bSMatthew Dillon 				dassert(UseTmpfsBase == 1,
4928e25f19bSMatthew Dillon 					"Config: Tmpfs_localbase must be "
4938e25f19bSMatthew Dillon 					"set to true, 'false' not supported");
4948e25f19bSMatthew Dillon 			} else if (strcmp(l1, "Display_with_ncurses") == 0) {
4957f0eca56SMatthew Dillon 				if (UseNCurses == -1)
4968e25f19bSMatthew Dillon 					UseNCurses = truefalse(l2);
4978e25f19bSMatthew Dillon 			} else if (strcmp(l1, "leverage_prebuilt") == 0) {
4988e25f19bSMatthew Dillon 				LeveragePrebuilt = truefalse(l2);
4998e25f19bSMatthew Dillon 				dassert(LeveragePrebuilt == 0,
5008e25f19bSMatthew Dillon 					"Config: leverage_prebuilt not "
5018e25f19bSMatthew Dillon 					"supported and must be set to false");
5029cb4fab1SMatthew Dillon 			} else if (strcmp(l1, "Check_plist") == 0) {
5039cb4fab1SMatthew Dillon 				if (truefalse(l2)) {
5049cb4fab1SMatthew Dillon 					WorkerProcFlags |=
5059cb4fab1SMatthew Dillon 						WORKER_PROC_CHECK_PLIST;
5069cb4fab1SMatthew Dillon 				}
5073bd7e0a7SMatthew Dillon 			} else if (strcmp(l1, "Numa_setsize") == 0) {
5083bd7e0a7SMatthew Dillon 				NumaSetSize = strtol(l2, NULL, 0);
5093bd7e0a7SMatthew Dillon 				free(l2);
5108e25f19bSMatthew Dillon 			} else {
5118e25f19bSMatthew Dillon 				dfatal("Unknown directive in profile section "
5128e25f19bSMatthew Dillon 				       "line %d: %s\n", lineno, buf);
5138e25f19bSMatthew Dillon 			}
5148e25f19bSMatthew Dillon 			break;
5158e25f19bSMatthew Dillon 		default:
5168e25f19bSMatthew Dillon 			/*
5178e25f19bSMatthew Dillon 			 * Ignore unselected profile
5188e25f19bSMatthew Dillon 			 */
5198e25f19bSMatthew Dillon 			break;
5208e25f19bSMatthew Dillon 		}
5218e25f19bSMatthew Dillon 	}
5228e25f19bSMatthew Dillon 	fclose(fp);
5238e25f19bSMatthew Dillon }
5248e25f19bSMatthew Dillon 
5258e25f19bSMatthew Dillon /*
5268e25f19bSMatthew Dillon  * NOTE: profile has brackets, e.g. "[LiveSystem]".
5278e25f19bSMatthew Dillon  */
5288e25f19bSMatthew Dillon static void
parseProfile(const char * cpath,const char * profile)5298e25f19bSMatthew Dillon parseProfile(const char *cpath, const char *profile)
5308e25f19bSMatthew Dillon {
5318e25f19bSMatthew Dillon 	char buf[1024];
5328e25f19bSMatthew Dillon 	char copy[1024];
5338e25f19bSMatthew Dillon 	char *ppath;
5348e25f19bSMatthew Dillon 	FILE *fp;
5358e25f19bSMatthew Dillon 	char *l1;
5368e25f19bSMatthew Dillon 	char *l2;
5378e25f19bSMatthew Dillon 	int len;
5388e25f19bSMatthew Dillon 	int plen;
5398e25f19bSMatthew Dillon 	int lineno = 0;
5408e25f19bSMatthew Dillon 
5418e25f19bSMatthew Dillon 	len = strlen(cpath);
5428e25f19bSMatthew Dillon 	while (len && cpath[len-1] != '/')
5438e25f19bSMatthew Dillon 		--len;
5448e25f19bSMatthew Dillon 	if (len == 0)
5458e25f19bSMatthew Dillon 		++len;
5468e25f19bSMatthew Dillon 	plen = strlen(profile);
5478e25f19bSMatthew Dillon 	ddassert(plen > 2 && profile[0] == '[' && profile[plen-1] == ']');
5488e25f19bSMatthew Dillon 
5498e25f19bSMatthew Dillon 	asprintf(&ppath, "%*.*s%*.*s-make.conf",
5508e25f19bSMatthew Dillon 		 len, len, cpath, plen - 2, plen - 2, profile + 1);
5518e25f19bSMatthew Dillon 	fp = fopen(ppath, "r");
5528e25f19bSMatthew Dillon 	if (fp == NULL) {
5538e25f19bSMatthew Dillon 		ddprintf(0, "Warning: Profile %s does not exist\n", ppath);
5548e25f19bSMatthew Dillon 		return;
5558e25f19bSMatthew Dillon 	}
55654f2fefcSMatthew Dillon 	if (DebugOpt >= 2)
5578e25f19bSMatthew Dillon 		ddprintf(0, "ParseProfile %s\n", ppath);
558a574cbf0SMatthew Dillon 	free(ppath);
5598e25f19bSMatthew Dillon 
5608e25f19bSMatthew Dillon 	while (fgets(buf, sizeof(buf), fp) != NULL) {
5618e25f19bSMatthew Dillon 		++lineno;
5628e25f19bSMatthew Dillon 		len = strlen(buf);
5638e25f19bSMatthew Dillon 		if (len == 0 || buf[len-1] != '\n')
5648e25f19bSMatthew Dillon 			continue;
5658e25f19bSMatthew Dillon 		buf[--len] = 0;
5668e25f19bSMatthew Dillon 
5678e25f19bSMatthew Dillon 		/*
5688e25f19bSMatthew Dillon 		 * Remove any trailing whitespace, ignore empty lines.
5698e25f19bSMatthew Dillon 		 */
5708e25f19bSMatthew Dillon 		while (len > 0 && isspace(buf[len-1]))
5718e25f19bSMatthew Dillon 			--len;
5728e25f19bSMatthew Dillon 		buf[len] = 0;
5738e25f19bSMatthew Dillon 		stripwhite(buf);
5749ed7494eSMatthew Dillon 
5759ed7494eSMatthew Dillon 		/*
5769ed7494eSMatthew Dillon 		 * Allow empty lines, ignore comments.
5779ed7494eSMatthew Dillon 		 */
5788e25f19bSMatthew Dillon 		len = strlen(buf);
5798e25f19bSMatthew Dillon 		if (len == 0)
5808e25f19bSMatthew Dillon 			continue;
5818e25f19bSMatthew Dillon 		if (buf[0] == ';' || buf[0] == '#')
5828e25f19bSMatthew Dillon 			continue;
5838e25f19bSMatthew Dillon 
5849ed7494eSMatthew Dillon 		/*
5859ed7494eSMatthew Dillon 		 * Require env variable name
5869ed7494eSMatthew Dillon 		 */
5878e25f19bSMatthew Dillon 		bcopy(buf, copy, len + 1);
5888e25f19bSMatthew Dillon 		l1 = strtok(copy, "=");
5898e25f19bSMatthew Dillon 		if (l1 == NULL) {
5908e25f19bSMatthew Dillon 			dfatal("Syntax error in profile line %d: %s\n",
5918e25f19bSMatthew Dillon 			       lineno, buf);
5928e25f19bSMatthew Dillon 		}
5939ed7494eSMatthew Dillon 
5949ed7494eSMatthew Dillon 		/*
5959ed7494eSMatthew Dillon 		 * Allow empty assignment
5969ed7494eSMatthew Dillon 		 */
5978e25f19bSMatthew Dillon 		l2 = strtok(NULL, " \t\n");
5989ed7494eSMatthew Dillon 		if (l2 == NULL)
5999ed7494eSMatthew Dillon 			l2 = l1 + strlen(l1);
6009ed7494eSMatthew Dillon 
6018e25f19bSMatthew Dillon 		l1 = stripwhite(l1);
6028e25f19bSMatthew Dillon 		l2 = stripwhite(l2);
6038e25f19bSMatthew Dillon 
6048e25f19bSMatthew Dillon 		/*
6058e25f19bSMatthew Dillon 		 * Add to builder environment
6068e25f19bSMatthew Dillon 		 */
6076fd67931SMatthew Dillon 		addbuildenv(l1, l2, BENV_MAKECONF);
60854f2fefcSMatthew Dillon 		if (DebugOpt >= 2)
6098e25f19bSMatthew Dillon 			ddprintf(4, "%s=%s\n", l1, l2);
6108e25f19bSMatthew Dillon 	}
6118e25f19bSMatthew Dillon 	fclose(fp);
61254f2fefcSMatthew Dillon 	if (DebugOpt >= 2)
6138e25f19bSMatthew Dillon 		ddprintf(0, "ParseProfile finished\n");
6148e25f19bSMatthew Dillon }
6158e25f19bSMatthew Dillon 
6168e25f19bSMatthew Dillon static char *
stripwhite(char * str)6178e25f19bSMatthew Dillon stripwhite(char *str)
6188e25f19bSMatthew Dillon {
6198e25f19bSMatthew Dillon 	size_t len;
6208e25f19bSMatthew Dillon 
6218e25f19bSMatthew Dillon 	len = strlen(str);
6228e25f19bSMatthew Dillon 	while (len > 0 && isspace(str[len-1]))
6238e25f19bSMatthew Dillon 		--len;
6248e25f19bSMatthew Dillon 	str[len] =0;
6258e25f19bSMatthew Dillon 
6268e25f19bSMatthew Dillon 	while (*str && isspace(*str))
6278e25f19bSMatthew Dillon 		++str;
6288e25f19bSMatthew Dillon 	return str;
6298e25f19bSMatthew Dillon }
6308e25f19bSMatthew Dillon 
6318e25f19bSMatthew Dillon static int
truefalse(const char * str)6328e25f19bSMatthew Dillon truefalse(const char *str)
6338e25f19bSMatthew Dillon {
6348e25f19bSMatthew Dillon 	if (strcmp(str, "0") == 0)
6358e25f19bSMatthew Dillon 		return 0;
6368e25f19bSMatthew Dillon 	if (strcmp(str, "1") == 0)
6378e25f19bSMatthew Dillon 		return 1;
6388e25f19bSMatthew Dillon 	if (strcasecmp(str, "false") == 0)
6398e25f19bSMatthew Dillon 		return 0;
6408e25f19bSMatthew Dillon 	if (strcasecmp(str, "true") == 0)
6418e25f19bSMatthew Dillon 		return 1;
6428e25f19bSMatthew Dillon 	dfatal("syntax error for boolean '%s': "
6438e25f19bSMatthew Dillon 	       "must be '0', '1', 'false', or 'true'", str);
6448e25f19bSMatthew Dillon 	return 0;
6458e25f19bSMatthew Dillon }
6468e25f19bSMatthew Dillon 
6478e25f19bSMatthew Dillon static char *
dokernsysctl(int m1,int m2)6488e25f19bSMatthew Dillon dokernsysctl(int m1, int m2)
6498e25f19bSMatthew Dillon {
6508e25f19bSMatthew Dillon 	int mib[] = { m1, m2 };
6518e25f19bSMatthew Dillon 	char buf[1024];
6528e25f19bSMatthew Dillon 	size_t len;
6538e25f19bSMatthew Dillon 
6548e25f19bSMatthew Dillon 	len = sizeof(buf) - 1;
6558e25f19bSMatthew Dillon 	if (sysctl(mib, 2, buf, &len, NULL, 0) < 0)
6568e25f19bSMatthew Dillon 		dfatal_errno("sysctl for system/architecture");
6578e25f19bSMatthew Dillon 	buf[len] = 0;
6588e25f19bSMatthew Dillon 	return(strdup(buf));
6598e25f19bSMatthew Dillon }
660a574cbf0SMatthew Dillon 
661a574cbf0SMatthew Dillon struct NoteTag {
662a574cbf0SMatthew Dillon 	Elf_Note note;
663a574cbf0SMatthew Dillon 	char osname1[12];
664a574cbf0SMatthew Dillon 	int version;		/* e.g. 500702 -> 5.7 */
665a574cbf0SMatthew Dillon 	int x1;
666a574cbf0SMatthew Dillon 	int x2;
667a574cbf0SMatthew Dillon 	int x3;
668a574cbf0SMatthew Dillon 	char osname2[12];
669a574cbf0SMatthew Dillon 	int zero;
670a574cbf0SMatthew Dillon };
671a574cbf0SMatthew Dillon 
672a574cbf0SMatthew Dillon static void
getElfInfo(const char * path)673a574cbf0SMatthew Dillon getElfInfo(const char *path)
674a574cbf0SMatthew Dillon {
675a574cbf0SMatthew Dillon 	struct NoteTag note;
676a574cbf0SMatthew Dillon 	char *cmd;
677a574cbf0SMatthew Dillon 	char *base;
678a574cbf0SMatthew Dillon 	FILE *fp;
679a574cbf0SMatthew Dillon 	size_t size;
680a574cbf0SMatthew Dillon 	size_t n;
681a574cbf0SMatthew Dillon 	int r;
682a574cbf0SMatthew Dillon 	uint32_t addr;
683a574cbf0SMatthew Dillon 	uint32_t v[4];
684a574cbf0SMatthew Dillon 
685a574cbf0SMatthew Dillon 	asprintf(&cmd, "readelf -x .note.tag %s", path);
686a574cbf0SMatthew Dillon 	fp = popen(cmd, "r");
687a574cbf0SMatthew Dillon 	dassert_errno(fp, "Cannot run: %s", cmd);
688a574cbf0SMatthew Dillon 	n = 0;
689a574cbf0SMatthew Dillon 
690a574cbf0SMatthew Dillon 	while (n != sizeof(note) &&
691a574cbf0SMatthew Dillon 	       (base = fgetln(fp, &size)) != NULL && size) {
692a574cbf0SMatthew Dillon 		base[--size] = 0;
693a574cbf0SMatthew Dillon 		if (strncmp(base, "  0x", 3) != 0)
694a574cbf0SMatthew Dillon 			continue;
695a574cbf0SMatthew Dillon 		r = sscanf(base, "%x %x %x %x %x",
696a574cbf0SMatthew Dillon 			   &addr, &v[0], &v[1], &v[2], &v[3]);
697a574cbf0SMatthew Dillon 		v[0] = ntohl(v[0]);
698a574cbf0SMatthew Dillon 		v[1] = ntohl(v[1]);
699a574cbf0SMatthew Dillon 		v[2] = ntohl(v[2]);
700a574cbf0SMatthew Dillon 		v[3] = ntohl(v[3]);
701a574cbf0SMatthew Dillon 		if (r < 2)
702a574cbf0SMatthew Dillon 			continue;
703a574cbf0SMatthew Dillon 		r = (r - 1) * sizeof(v[0]);
704a574cbf0SMatthew Dillon 		if (n + r > sizeof(note))
705a574cbf0SMatthew Dillon 			r = sizeof(note) - n;
706a574cbf0SMatthew Dillon 		bcopy((char *)v, (char *)&note + n, r);
707a574cbf0SMatthew Dillon 		n += r;
708a574cbf0SMatthew Dillon 	}
709a574cbf0SMatthew Dillon 	pclose(fp);
710a574cbf0SMatthew Dillon 
711a574cbf0SMatthew Dillon 	if (n != sizeof(note))
712a574cbf0SMatthew Dillon 		dfatal("Unable to parse output from: %s", cmd);
713a574cbf0SMatthew Dillon 	if (strncmp(OperatingSystemName, note.osname1, sizeof(note.osname1))) {
714a574cbf0SMatthew Dillon 		dfatal("%s ELF, mismatch OS name %.*s vs %s",
715a574cbf0SMatthew Dillon 		       path, (int)sizeof(note.osname1),
716a574cbf0SMatthew Dillon 		       note.osname1, OperatingSystemName);
717a574cbf0SMatthew Dillon 	}
718a574cbf0SMatthew Dillon 	free(cmd);
71963d3b33aSMatthew Dillon 	if (note.version) {
720a574cbf0SMatthew Dillon 		asprintf(&cmd, "%d.%d",
721a574cbf0SMatthew Dillon 			note.version / 100000,
722a574cbf0SMatthew Dillon 			(note.version % 100000) / 100);
72363d3b33aSMatthew Dillon 	} else if (note.zero) {
72463d3b33aSMatthew Dillon 		asprintf(&cmd, "%d.%d",
72563d3b33aSMatthew Dillon 			note.zero / 100000,
72663d3b33aSMatthew Dillon 			(note.zero % 100000) / 100);
72763d3b33aSMatthew Dillon 	} else {
72863d3b33aSMatthew Dillon 		dfatal("%s ELF, cannot extract version info", path);
72963d3b33aSMatthew Dillon 	}
730a574cbf0SMatthew Dillon 	ReleaseName = cmd;
731a574cbf0SMatthew Dillon }
73268dc2eeaSMatthew Dillon 
73368dc2eeaSMatthew Dillon static char *
checkhook(const char * scriptname)73468dc2eeaSMatthew Dillon checkhook(const char *scriptname)
73568dc2eeaSMatthew Dillon {
73668dc2eeaSMatthew Dillon 	struct stat st;
73768dc2eeaSMatthew Dillon 	char *path;
73868dc2eeaSMatthew Dillon 
73968dc2eeaSMatthew Dillon 	asprintf(&path, "%s/%s", ConfigBase, scriptname);
74068dc2eeaSMatthew Dillon 	if (stat(path, &st) < 0 || (st.st_mode & 0111) == 0) {
74168dc2eeaSMatthew Dillon 		free(path);
74268dc2eeaSMatthew Dillon 		return NULL;
74368dc2eeaSMatthew Dillon 	}
74468dc2eeaSMatthew Dillon 	UsingHooks = 1;
74568dc2eeaSMatthew Dillon 
74668dc2eeaSMatthew Dillon 	return path;
74768dc2eeaSMatthew Dillon }
748