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