xref: /netbsd-src/external/bsd/pkg_install/dist/add/parse_cross.c (revision 85cb9062851ecde89dc2430f308ca5b162471f71)
1*85cb9062Swiz /*	$NetBSD: parse_cross.c,v 1.1.1.1 2024/06/11 09:15:38 wiz Exp $	*/
2*85cb9062Swiz 
3*85cb9062Swiz #if HAVE_CONFIG_H
4*85cb9062Swiz #include "config.h"
5*85cb9062Swiz #endif
6*85cb9062Swiz #include <nbcompat.h>
7*85cb9062Swiz #if HAVE_SYS_CDEFS_H
8*85cb9062Swiz #include <sys/cdefs.h>
9*85cb9062Swiz #endif
10*85cb9062Swiz __RCSID("$NetBSD: parse_cross.c,v 1.1.1.1 2024/06/11 09:15:38 wiz Exp $");
11*85cb9062Swiz 
12*85cb9062Swiz #if HAVE_ERR_H
13*85cb9062Swiz #include <err.h>
14*85cb9062Swiz #endif
15*85cb9062Swiz #include "lib.h"
16*85cb9062Swiz #include "add.h"
17*85cb9062Swiz 
18*85cb9062Swiz /*
19*85cb9062Swiz  * ${OPSYS}/${MACHINE_ARCH} ${OS_VERSION}
20*85cb9062Swiz  *
21*85cb9062Swiz  * or just
22*85cb9062Swiz  *
23*85cb9062Swiz  * ${MACHINE_ARCH}
24*85cb9062Swiz  */
25*85cb9062Swiz void
parse_cross(const char * text,char ** machine_arch,char ** opsys,char ** os_version)26*85cb9062Swiz parse_cross(const char *text, char **machine_arch, char **opsys,
27*85cb9062Swiz     char **os_version)
28*85cb9062Swiz {
29*85cb9062Swiz 	static const char safeset[] = /* XXX */
30*85cb9062Swiz 	    "abcdefghijklmnopqrstuvwxyz"
31*85cb9062Swiz 	    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
32*85cb9062Swiz 	    "0123456789"
33*85cb9062Swiz 	    "-._";
34*85cb9062Swiz 	char *copy = xstrdup(text);
35*85cb9062Swiz 	char *p = copy, *q, *r;
36*85cb9062Swiz 
37*85cb9062Swiz 	/*
38*85cb9062Swiz 	 * If there's no /, treat it as a single MACHINE_ARCH.
39*85cb9062Swiz 	 */
40*85cb9062Swiz 	if ((q = strchr(p, '/')) == NULL) {
41*85cb9062Swiz 		*machine_arch = copy;
42*85cb9062Swiz 		*opsys = NULL;
43*85cb9062Swiz 		*os_version = NULL;
44*85cb9062Swiz 	} else {
45*85cb9062Swiz 		/*
46*85cb9062Swiz 		 * NUL-terminate at the slash so p := text[0..slash)
47*85cb9062Swiz 		 * is the OPSYS.
48*85cb9062Swiz 		 */
49*85cb9062Swiz 		*q++ = '\0';
50*85cb9062Swiz 
51*85cb9062Swiz 		/*
52*85cb9062Swiz 		 * If there's no SPC, fail.
53*85cb9062Swiz 		 */
54*85cb9062Swiz 		if (*(r = strchr(q, ' ')) == '\0') {
55*85cb9062Swiz 			goto fail;
56*85cb9062Swiz 		}
57*85cb9062Swiz 
58*85cb9062Swiz 		/*
59*85cb9062Swiz 		 * NUL-terminate at the space so
60*85cb9062Swiz 		 *
61*85cb9062Swiz 		 *	q := text(slash..space)
62*85cb9062Swiz 		 *
63*85cb9062Swiz 		 * is the MACHINE_ARCH.
64*85cb9062Swiz 		 */
65*85cb9062Swiz 		*r++ = '\0';
66*85cb9062Swiz 
67*85cb9062Swiz 		/*
68*85cb9062Swiz 		 * The rest is already NUL-terminated, so
69*85cb9062Swiz 		 *
70*85cb9062Swiz 		 *	r := text(space..NUL)
71*85cb9062Swiz 		 *
72*85cb9062Swiz 		 * is the OS_VERSION.
73*85cb9062Swiz 		 */
74*85cb9062Swiz 		*opsys = p;
75*85cb9062Swiz 		*machine_arch = q;
76*85cb9062Swiz 		*os_version = r;
77*85cb9062Swiz 	}
78*85cb9062Swiz 
79*85cb9062Swiz 	/*
80*85cb9062Swiz 	 * Verify that MACHINE_ARCH, and, if specified, OPSYS and
81*85cb9062Swiz 	 * OS_VERSION lie within the safe set, so we can reserve large
82*85cb9062Swiz 	 * amounts of the space of inputs for additional syntax.
83*85cb9062Swiz 	 * Ideally we would impose more constraints here with a
84*85cb9062Swiz 	 * regular expression to restrict the space even more, but
85*85cb9062Swiz 	 * this'll do for now.
86*85cb9062Swiz 	 */
87*85cb9062Swiz 	if ((*machine_arch)[strspn(*machine_arch, safeset)] != '\0') {
88*85cb9062Swiz 		goto fail;
89*85cb9062Swiz 	}
90*85cb9062Swiz 	if (*opsys != NULL && (*opsys)[strspn(*opsys, safeset)] != '\0') {
91*85cb9062Swiz 		goto fail;
92*85cb9062Swiz 	}
93*85cb9062Swiz 	if (*os_version != NULL &&
94*85cb9062Swiz 	    (*os_version)[strspn(*os_version, safeset)] != '\0') {
95*85cb9062Swiz 		goto fail;
96*85cb9062Swiz 	}
97*85cb9062Swiz 	return;
98*85cb9062Swiz 
99*85cb9062Swiz fail:	errx(1, "Invalid -m argument: ${OPSYS}/${MACHINE_ARCH} ${OS_VERSION}");
100*85cb9062Swiz }
101