xref: /kvm-unit-tests/lib/argv.c (revision e526bc786e9878c3880ae4b09b01a4572756e492)
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"
95927d1c2SAndrew Jones #include "ctype.h"
1063d5cbecSThomas Huth #include "argv.h"
116b97d595SAndrew Jones #include "auxinfo.h"
12ea7d43d0SAvi Kivity 
13ea7d43d0SAvi Kivity int __argc;
1463d5cbecSThomas Huth const char *__args;
1569205bf1SAndrew Jones char *__argv[100];
1669205bf1SAndrew Jones char *__environ[200];
1769205bf1SAndrew Jones 
1869205bf1SAndrew Jones char **environ = __environ;
196b97d595SAndrew Jones 
206b97d595SAndrew Jones static char args_copy[1000];
216b97d595SAndrew Jones static char *copy_ptr = args_copy;
22ea7d43d0SAvi Kivity 
skip_blanks(const char * p)2363d5cbecSThomas Huth static const char *skip_blanks(const char *p)
24ea7d43d0SAvi Kivity {
25ea7d43d0SAvi Kivity 	while (isblank(*p))
26ea7d43d0SAvi Kivity 		++p;
27ea7d43d0SAvi Kivity 	return p;
28ea7d43d0SAvi Kivity }
29ea7d43d0SAvi Kivity 
__setup_args(void)30ea7d43d0SAvi Kivity void __setup_args(void)
31ea7d43d0SAvi Kivity {
3263d5cbecSThomas Huth 	const char *args = __args;
336b97d595SAndrew Jones 	char **argv = __argv + __argc;
34ea7d43d0SAvi Kivity 
35ea7d43d0SAvi Kivity 	while (*(args = skip_blanks(args)) != '\0') {
366b97d595SAndrew Jones 		*argv++ = copy_ptr;
37ea7d43d0SAvi Kivity 		while (*args != '\0' && !isblank(*args))
386b97d595SAndrew Jones 			*copy_ptr++ = *args++;
396b97d595SAndrew Jones 		*copy_ptr++ = '\0';
40ea7d43d0SAvi Kivity 	}
41ea7d43d0SAvi Kivity 	__argc = argv - __argv;
42ea7d43d0SAvi Kivity }
435e61cba0SAndrew Jones 
setup_args(const char * args)44*85c3c524SNikos Nikoleris void setup_args(const char *args)
455e61cba0SAndrew Jones {
465e61cba0SAndrew Jones 	if (!args)
475e61cba0SAndrew Jones 		return;
485e61cba0SAndrew Jones 
495e61cba0SAndrew Jones 	__args = args;
505e61cba0SAndrew Jones 	__setup_args();
515e61cba0SAndrew Jones }
526ffea954SAndrew Jones 
add_setup_arg(const char * arg)5303b1e457SNadav Amit void add_setup_arg(const char *arg)
5403b1e457SNadav Amit {
5503b1e457SNadav Amit 	__argv[__argc] = copy_ptr;
5603b1e457SNadav Amit 	strcpy(__argv[__argc], arg);
5703b1e457SNadav Amit 	copy_ptr += strlen(arg) + 1;
5803b1e457SNadav Amit 	++__argc;
5903b1e457SNadav Amit }
6003b1e457SNadav Amit 
setup_args_progname(const char * args)6163d5cbecSThomas Huth void setup_args_progname(const char *args)
626ffea954SAndrew Jones {
6303b1e457SNadav Amit 	add_setup_arg(auxinfo.progname);
6463d5cbecSThomas Huth 	setup_args(args);
656ffea954SAndrew Jones }
6669205bf1SAndrew Jones 
env_eol(char * env)6769205bf1SAndrew Jones static char *env_eol(char *env)
6869205bf1SAndrew Jones {
6969205bf1SAndrew Jones 	while (*env && *env != '\n')
7069205bf1SAndrew Jones 		++env;
7169205bf1SAndrew Jones 	return env;
7269205bf1SAndrew Jones }
7369205bf1SAndrew Jones 
env_invalid_eol(char * env)7469205bf1SAndrew Jones static char *env_invalid_eol(char *env)
7569205bf1SAndrew Jones {
7669205bf1SAndrew Jones 	char *eol = env_eol(env);
7769205bf1SAndrew Jones 	char eol_old = *eol;
7869205bf1SAndrew Jones 
7969205bf1SAndrew Jones 	*eol = '\0';
8069205bf1SAndrew Jones 	printf("Invalid environment variable: %s\n", env);
8169205bf1SAndrew Jones 	*eol = eol_old;
8269205bf1SAndrew Jones 	return eol;
8369205bf1SAndrew Jones }
8469205bf1SAndrew Jones 
env_next(char * env)8569205bf1SAndrew Jones static char *env_next(char *env)
8669205bf1SAndrew Jones {
8769205bf1SAndrew Jones 	char *p;
8869205bf1SAndrew Jones 
8969205bf1SAndrew Jones 	if (!*env)
9069205bf1SAndrew Jones 		return env;
9169205bf1SAndrew Jones 
925927d1c2SAndrew Jones 	if (isalpha(*env) || *env == '_') {
9369205bf1SAndrew Jones 		bool invalid = false;
9469205bf1SAndrew Jones 
9569205bf1SAndrew Jones 		p = env + 1;
9669205bf1SAndrew Jones 		while (*p && *p != '=' && *p != '\n') {
975927d1c2SAndrew Jones 			if (!(isalnum(*p) || *p == '_'))
9869205bf1SAndrew Jones 				invalid = true;
9969205bf1SAndrew Jones 			++p;
10069205bf1SAndrew Jones 		}
10169205bf1SAndrew Jones 
10269205bf1SAndrew Jones 		if (*p != '=')
10369205bf1SAndrew Jones 			invalid = true;
10469205bf1SAndrew Jones 
10569205bf1SAndrew Jones 		if (invalid) {
10669205bf1SAndrew Jones 			env = env_invalid_eol(env);
10769205bf1SAndrew Jones 			return *env ? env_next(env + 1) : env;
10869205bf1SAndrew Jones 		}
10969205bf1SAndrew Jones 		return env;
11069205bf1SAndrew Jones 	}
11169205bf1SAndrew Jones 
11269205bf1SAndrew Jones 	p = env;
11369205bf1SAndrew Jones 	while (isblank(*p))
11469205bf1SAndrew Jones 		++p;
11569205bf1SAndrew Jones 
11669205bf1SAndrew Jones 	if (*p == '\n')
11769205bf1SAndrew Jones 		return env_next(p + 1);
11869205bf1SAndrew Jones 
11969205bf1SAndrew Jones 	if (*p == '#')
12069205bf1SAndrew Jones 		env = env_eol(env);
12169205bf1SAndrew Jones 	else
12269205bf1SAndrew Jones 		env = env_invalid_eol(env);
12369205bf1SAndrew Jones 
12469205bf1SAndrew Jones 	return *env ? env_next(env + 1) : env;
12569205bf1SAndrew Jones }
12669205bf1SAndrew Jones 
setup_env(char * env,int size)12769205bf1SAndrew Jones void setup_env(char *env, int size)
12869205bf1SAndrew Jones {
12969205bf1SAndrew Jones 	char *eof = env + size, *p = env;
13069205bf1SAndrew Jones 	bool newline = false;
13169205bf1SAndrew Jones 	int i = 0;
13269205bf1SAndrew Jones 
13369205bf1SAndrew Jones 	while (*p)
13469205bf1SAndrew Jones 		++p;
13569205bf1SAndrew Jones 	if (p == eof)
13669205bf1SAndrew Jones 		newline = true;
13769205bf1SAndrew Jones 
13869205bf1SAndrew Jones 	while (env < eof) {
13969205bf1SAndrew Jones 		if (newline)
14069205bf1SAndrew Jones 			env = env_next(env);
14169205bf1SAndrew Jones 		if (!*env || env >= eof)
14269205bf1SAndrew Jones 			break;
14369205bf1SAndrew Jones 		__environ[i++] = env;
14469205bf1SAndrew Jones 		while (env < eof && *env && !(newline && *env == '\n'))
14569205bf1SAndrew Jones 			++env;
14669205bf1SAndrew Jones 		*env++ = '\0';
14769205bf1SAndrew Jones 	}
14869205bf1SAndrew Jones }
149