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 *)¬e + 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