xref: /kvm-unit-tests/lib/argv.c (revision 63d5cbec1ed738787a9d9be7e1f8268beb7a31ef)
14b6da826SThomas Huth /*
24b6da826SThomas Huth  * Set up arguments for main() and prepare environment variables
34b6da826SThomas Huth  *
44b6da826SThomas Huth  * This code is free software; you can redistribute it and/or modify it
54b6da826SThomas Huth  * under the terms of the GNU Library General Public License version 2.
64b6da826SThomas Huth  */
74b6da826SThomas Huth 
8ea7d43d0SAvi Kivity #include "libcflat.h"
9*63d5cbecSThomas Huth #include "argv.h"
106b97d595SAndrew Jones #include "auxinfo.h"
11ea7d43d0SAvi Kivity 
12ea7d43d0SAvi Kivity int __argc;
13*63d5cbecSThomas Huth const char *__args;
1469205bf1SAndrew Jones char *__argv[100];
1569205bf1SAndrew Jones char *__environ[200];
1669205bf1SAndrew Jones 
1769205bf1SAndrew Jones char **environ = __environ;
186b97d595SAndrew Jones 
196b97d595SAndrew Jones static char args_copy[1000];
206b97d595SAndrew Jones static char *copy_ptr = args_copy;
21ea7d43d0SAvi Kivity 
224bc666caSAndrew Jones #define isblank(c) ((c) == ' ' || (c) == '\t')
2369205bf1SAndrew Jones #define isalpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') || (c) == '_')
2469205bf1SAndrew Jones #define isalnum(c) (isalpha(c) || ((c) >= '0' && (c) <= '9'))
25ea7d43d0SAvi Kivity 
26*63d5cbecSThomas Huth static const char *skip_blanks(const char *p)
27ea7d43d0SAvi Kivity {
28ea7d43d0SAvi Kivity 	while (isblank(*p))
29ea7d43d0SAvi Kivity 		++p;
30ea7d43d0SAvi Kivity 	return p;
31ea7d43d0SAvi Kivity }
32ea7d43d0SAvi Kivity 
33ea7d43d0SAvi Kivity void __setup_args(void)
34ea7d43d0SAvi Kivity {
35*63d5cbecSThomas Huth 	const char *args = __args;
366b97d595SAndrew Jones 	char **argv = __argv + __argc;
37ea7d43d0SAvi Kivity 
38ea7d43d0SAvi Kivity 	while (*(args = skip_blanks(args)) != '\0') {
396b97d595SAndrew Jones 		*argv++ = copy_ptr;
40ea7d43d0SAvi Kivity 		while (*args != '\0' && !isblank(*args))
416b97d595SAndrew Jones 			*copy_ptr++ = *args++;
426b97d595SAndrew Jones 		*copy_ptr++ = '\0';
43ea7d43d0SAvi Kivity 	}
44ea7d43d0SAvi Kivity 	__argc = argv - __argv;
45ea7d43d0SAvi Kivity }
465e61cba0SAndrew Jones 
47*63d5cbecSThomas Huth static void setup_args(const char *args)
485e61cba0SAndrew Jones {
495e61cba0SAndrew Jones 	if (!args)
505e61cba0SAndrew Jones 		return;
515e61cba0SAndrew Jones 
525e61cba0SAndrew Jones 	__args = args;
535e61cba0SAndrew Jones 	__setup_args();
545e61cba0SAndrew Jones }
556ffea954SAndrew Jones 
56*63d5cbecSThomas Huth void setup_args_progname(const char *args)
576ffea954SAndrew Jones {
586b97d595SAndrew Jones 	__argv[0] = copy_ptr;
59809ebcb3SAndrew Jones 	strcpy(__argv[0], auxinfo.progname);
60809ebcb3SAndrew Jones 	copy_ptr += strlen(auxinfo.progname) + 1;
616b97d595SAndrew Jones 	++__argc;
62*63d5cbecSThomas Huth 	setup_args(args);
636ffea954SAndrew Jones }
6469205bf1SAndrew Jones 
6569205bf1SAndrew Jones static char *env_eol(char *env)
6669205bf1SAndrew Jones {
6769205bf1SAndrew Jones 	while (*env && *env != '\n')
6869205bf1SAndrew Jones 		++env;
6969205bf1SAndrew Jones 	return env;
7069205bf1SAndrew Jones }
7169205bf1SAndrew Jones 
7269205bf1SAndrew Jones static char *env_invalid_eol(char *env)
7369205bf1SAndrew Jones {
7469205bf1SAndrew Jones 	char *eol = env_eol(env);
7569205bf1SAndrew Jones 	char eol_old = *eol;
7669205bf1SAndrew Jones 
7769205bf1SAndrew Jones 	*eol = '\0';
7869205bf1SAndrew Jones 	printf("Invalid environment variable: %s\n", env);
7969205bf1SAndrew Jones 	*eol = eol_old;
8069205bf1SAndrew Jones 	return eol;
8169205bf1SAndrew Jones }
8269205bf1SAndrew Jones 
8369205bf1SAndrew Jones static char *env_next(char *env)
8469205bf1SAndrew Jones {
8569205bf1SAndrew Jones 	char *p;
8669205bf1SAndrew Jones 
8769205bf1SAndrew Jones 	if (!*env)
8869205bf1SAndrew Jones 		return env;
8969205bf1SAndrew Jones 
9069205bf1SAndrew Jones 	if (isalpha(*env)) {
9169205bf1SAndrew Jones 		bool invalid = false;
9269205bf1SAndrew Jones 
9369205bf1SAndrew Jones 		p = env + 1;
9469205bf1SAndrew Jones 		while (*p && *p != '=' && *p != '\n') {
9569205bf1SAndrew Jones 			if (!isalnum(*p))
9669205bf1SAndrew Jones 				invalid = true;
9769205bf1SAndrew Jones 			++p;
9869205bf1SAndrew Jones 		}
9969205bf1SAndrew Jones 
10069205bf1SAndrew Jones 		if (*p != '=')
10169205bf1SAndrew Jones 			invalid = true;
10269205bf1SAndrew Jones 
10369205bf1SAndrew Jones 		if (invalid) {
10469205bf1SAndrew Jones 			env = env_invalid_eol(env);
10569205bf1SAndrew Jones 			return *env ? env_next(env + 1) : env;
10669205bf1SAndrew Jones 		}
10769205bf1SAndrew Jones 		return env;
10869205bf1SAndrew Jones 	}
10969205bf1SAndrew Jones 
11069205bf1SAndrew Jones 	p = env;
11169205bf1SAndrew Jones 	while (isblank(*p))
11269205bf1SAndrew Jones 		++p;
11369205bf1SAndrew Jones 
11469205bf1SAndrew Jones 	if (*p == '\n')
11569205bf1SAndrew Jones 		return env_next(p + 1);
11669205bf1SAndrew Jones 
11769205bf1SAndrew Jones 	if (*p == '#')
11869205bf1SAndrew Jones 		env = env_eol(env);
11969205bf1SAndrew Jones 	else
12069205bf1SAndrew Jones 		env = env_invalid_eol(env);
12169205bf1SAndrew Jones 
12269205bf1SAndrew Jones 	return *env ? env_next(env + 1) : env;
12369205bf1SAndrew Jones }
12469205bf1SAndrew Jones 
12569205bf1SAndrew Jones void setup_env(char *env, int size)
12669205bf1SAndrew Jones {
12769205bf1SAndrew Jones 	char *eof = env + size, *p = env;
12869205bf1SAndrew Jones 	bool newline = false;
12969205bf1SAndrew Jones 	int i = 0;
13069205bf1SAndrew Jones 
13169205bf1SAndrew Jones 	while (*p)
13269205bf1SAndrew Jones 		++p;
13369205bf1SAndrew Jones 	if (p == eof)
13469205bf1SAndrew Jones 		newline = true;
13569205bf1SAndrew Jones 
13669205bf1SAndrew Jones 	while (env < eof) {
13769205bf1SAndrew Jones 		if (newline)
13869205bf1SAndrew Jones 			env = env_next(env);
13969205bf1SAndrew Jones 		if (!*env || env >= eof)
14069205bf1SAndrew Jones 			break;
14169205bf1SAndrew Jones 		__environ[i++] = env;
14269205bf1SAndrew Jones 		while (env < eof && *env && !(newline && *env == '\n'))
14369205bf1SAndrew Jones 			++env;
14469205bf1SAndrew Jones 		*env++ = '\0';
14569205bf1SAndrew Jones 	}
14669205bf1SAndrew Jones }
147