1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
3a9de470cSBruce Richardson */
4a9de470cSBruce Richardson
5a9de470cSBruce Richardson #ifndef _PROCESS_H_
6a9de470cSBruce Richardson #define _PROCESS_H_
7a9de470cSBruce Richardson
8b8d5e544SAnatoly Burakov #include <errno.h> /* errno */
9a9de470cSBruce Richardson #include <limits.h> /* PATH_MAX */
10*987d40a0SJie Zhou #ifndef RTE_EXEC_ENV_WINDOWS
11a9de470cSBruce Richardson #include <libgen.h> /* basename et al */
12*987d40a0SJie Zhou #include <sys/wait.h>
13*987d40a0SJie Zhou #endif
14a9de470cSBruce Richardson #include <stdlib.h> /* NULL */
15b8d5e544SAnatoly Burakov #include <string.h> /* strerror */
16a9de470cSBruce Richardson #include <unistd.h> /* readlink */
1718562261SKrzysztof Kanas #include <dirent.h>
18a9de470cSBruce Richardson
19b8d5e544SAnatoly Burakov #include <rte_string_fns.h> /* strlcpy */
20b8d5e544SAnatoly Burakov
215fbc1d49SBruce Richardson #ifdef RTE_EXEC_ENV_FREEBSD
22a9de470cSBruce Richardson #define self "curproc"
23a9de470cSBruce Richardson #define exe "file"
24a9de470cSBruce Richardson #else
25a9de470cSBruce Richardson #define self "self"
26a9de470cSBruce Richardson #define exe "exe"
27a9de470cSBruce Richardson #endif
28a9de470cSBruce Richardson
29a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
30a8d0d473SBruce Richardson #ifdef RTE_NET_RING
31a9de470cSBruce Richardson #include <pthread.h>
32a9de470cSBruce Richardson extern void *send_pkts(void *empty);
33a9de470cSBruce Richardson extern uint16_t flag_for_send_pkts;
346d27d8c0SReshma Pattan #endif
35207b1c81SReshma Pattan #endif
36a9de470cSBruce Richardson
37a9de470cSBruce Richardson /*
38a9de470cSBruce Richardson * launches a second copy of the test process using the given argv parameters,
39a9de470cSBruce Richardson * which should include argv[0] as the process name. To identify in the
40a9de470cSBruce Richardson * subprocess the source of the call, the env_value parameter is set in the
41a9de470cSBruce Richardson * environment as $RTE_TEST
42a9de470cSBruce Richardson */
43a9de470cSBruce Richardson static inline int
process_dup(const char * const argv[],int numargs,const char * env_value)44a9de470cSBruce Richardson process_dup(const char *const argv[], int numargs, const char *env_value)
45a9de470cSBruce Richardson {
46a9de470cSBruce Richardson int num;
47a9de470cSBruce Richardson char *argv_cpy[numargs + 1];
4818562261SKrzysztof Kanas int i, status;
49a9de470cSBruce Richardson char path[32];
50a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
51a8d0d473SBruce Richardson #ifdef RTE_NET_RING
52a9de470cSBruce Richardson pthread_t thread;
53a20cb9d0SChengwen Feng int rc;
546d27d8c0SReshma Pattan #endif
55207b1c81SReshma Pattan #endif
56a9de470cSBruce Richardson
57a9de470cSBruce Richardson pid_t pid = fork();
58a9de470cSBruce Richardson if (pid < 0)
59a9de470cSBruce Richardson return -1;
60a9de470cSBruce Richardson else if (pid == 0) {
61a9de470cSBruce Richardson /* make a copy of the arguments to be passed to exec */
62a9de470cSBruce Richardson for (i = 0; i < numargs; i++)
63a9de470cSBruce Richardson argv_cpy[i] = strdup(argv[i]);
64a9de470cSBruce Richardson argv_cpy[i] = NULL;
65a9de470cSBruce Richardson num = numargs;
66a9de470cSBruce Richardson
6718562261SKrzysztof Kanas #ifdef RTE_EXEC_ENV_LINUX
6818562261SKrzysztof Kanas {
6918562261SKrzysztof Kanas const char *procdir = "/proc/" self "/fd/";
7018562261SKrzysztof Kanas struct dirent *dirent;
7118562261SKrzysztof Kanas char *endptr;
7218562261SKrzysztof Kanas int fd, fdir;
7318562261SKrzysztof Kanas DIR *dir;
7418562261SKrzysztof Kanas
7518562261SKrzysztof Kanas /* close all open file descriptors, check /proc/self/fd
7618562261SKrzysztof Kanas * to only call close on open fds. Exclude fds 0, 1 and
7718562261SKrzysztof Kanas * 2
7818562261SKrzysztof Kanas */
7918562261SKrzysztof Kanas dir = opendir(procdir);
8018562261SKrzysztof Kanas if (dir == NULL) {
8118562261SKrzysztof Kanas rte_panic("Error opening %s: %s\n", procdir,
8218562261SKrzysztof Kanas strerror(errno));
8318562261SKrzysztof Kanas }
8418562261SKrzysztof Kanas
8518562261SKrzysztof Kanas fdir = dirfd(dir);
8618562261SKrzysztof Kanas if (fdir < 0) {
8718562261SKrzysztof Kanas status = errno;
8818562261SKrzysztof Kanas closedir(dir);
8918562261SKrzysztof Kanas rte_panic("Error %d obtaining fd for dir %s: %s\n",
9018562261SKrzysztof Kanas fdir, procdir,
9118562261SKrzysztof Kanas strerror(status));
9218562261SKrzysztof Kanas }
9318562261SKrzysztof Kanas
9418562261SKrzysztof Kanas while ((dirent = readdir(dir)) != NULL) {
95b13da15eSJohn Levon
96b13da15eSJohn Levon if (strcmp(dirent->d_name, ".") == 0 ||
97b13da15eSJohn Levon strcmp(dirent->d_name, "..") == 0)
98b13da15eSJohn Levon continue;
99b13da15eSJohn Levon
10018562261SKrzysztof Kanas errno = 0;
10118562261SKrzysztof Kanas fd = strtol(dirent->d_name, &endptr, 10);
10218562261SKrzysztof Kanas if (errno != 0 || endptr[0] != '\0') {
10318562261SKrzysztof Kanas printf("Error converting name fd %d %s:\n",
10418562261SKrzysztof Kanas fd, dirent->d_name);
10518562261SKrzysztof Kanas continue;
10618562261SKrzysztof Kanas }
10718562261SKrzysztof Kanas
10818562261SKrzysztof Kanas if (fd == fdir || fd <= 2)
10918562261SKrzysztof Kanas continue;
11018562261SKrzysztof Kanas
111a9de470cSBruce Richardson close(fd);
112a9de470cSBruce Richardson }
11318562261SKrzysztof Kanas closedir(dir);
11418562261SKrzysztof Kanas }
11518562261SKrzysztof Kanas #endif
116a9de470cSBruce Richardson printf("Running binary with argv[]:");
117a9de470cSBruce Richardson for (i = 0; i < num; i++)
118a9de470cSBruce Richardson printf("'%s' ", argv_cpy[i]);
119a9de470cSBruce Richardson printf("\n");
120b73c8edeSJohn Levon fflush(stdout);
121a9de470cSBruce Richardson
122a9de470cSBruce Richardson /* set the environment variable */
123a9de470cSBruce Richardson if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0)
124a9de470cSBruce Richardson rte_panic("Cannot export environment variable\n");
125b8d5e544SAnatoly Burakov
126b8d5e544SAnatoly Burakov strlcpy(path, "/proc/" self "/" exe, sizeof(path));
127b8d5e544SAnatoly Burakov if (execv(path, argv_cpy) < 0) {
128b8d5e544SAnatoly Burakov if (errno == ENOENT) {
129b8d5e544SAnatoly Burakov printf("Could not find '%s', is procfs mounted?\n",
130b8d5e544SAnatoly Burakov path);
131b8d5e544SAnatoly Burakov }
132b8d5e544SAnatoly Burakov rte_panic("Cannot exec: %s\n", strerror(errno));
133b8d5e544SAnatoly Burakov }
134a9de470cSBruce Richardson }
135a9de470cSBruce Richardson /* parent process does a wait */
136a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
137a8d0d473SBruce Richardson #ifdef RTE_NET_RING
138a20cb9d0SChengwen Feng if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
139a20cb9d0SChengwen Feng rc = pthread_create(&thread, NULL, &send_pkts, NULL);
140a20cb9d0SChengwen Feng if (rc != 0) {
141a20cb9d0SChengwen Feng rte_panic("Cannot start send pkts thread: %s\n",
142a20cb9d0SChengwen Feng strerror(rc));
143a20cb9d0SChengwen Feng }
144a20cb9d0SChengwen Feng }
1456d27d8c0SReshma Pattan #endif
146207b1c81SReshma Pattan #endif
147a9de470cSBruce Richardson
148a9de470cSBruce Richardson while (wait(&status) != pid)
149a9de470cSBruce Richardson ;
150a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
151a8d0d473SBruce Richardson #ifdef RTE_NET_RING
152a9de470cSBruce Richardson if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
153a9de470cSBruce Richardson flag_for_send_pkts = 0;
154a9de470cSBruce Richardson pthread_join(thread, NULL);
155a9de470cSBruce Richardson }
1566d27d8c0SReshma Pattan #endif
157207b1c81SReshma Pattan #endif
158a9de470cSBruce Richardson return status;
159a9de470cSBruce Richardson }
160a9de470cSBruce Richardson
161a9de470cSBruce Richardson /* FreeBSD doesn't support file prefixes, so force compile failures for any
162a9de470cSBruce Richardson * tests attempting to use this function on FreeBSD.
163a9de470cSBruce Richardson */
164742bde12SBruce Richardson #ifdef RTE_EXEC_ENV_LINUX
165a9de470cSBruce Richardson static char *
get_current_prefix(char * prefix,int size)166a9de470cSBruce Richardson get_current_prefix(char *prefix, int size)
167a9de470cSBruce Richardson {
168a9de470cSBruce Richardson char path[PATH_MAX] = {0};
169a9de470cSBruce Richardson char buf[PATH_MAX] = {0};
170a9de470cSBruce Richardson
171a9de470cSBruce Richardson /* get file for config (fd is always 3) */
172a9de470cSBruce Richardson snprintf(path, sizeof(path), "/proc/self/fd/%d", 3);
173a9de470cSBruce Richardson
174a9de470cSBruce Richardson /* return NULL on error */
175a9de470cSBruce Richardson if (readlink(path, buf, sizeof(buf)) == -1)
176a9de470cSBruce Richardson return NULL;
177a9de470cSBruce Richardson
178a9de470cSBruce Richardson /* get the prefix */
179a9de470cSBruce Richardson snprintf(prefix, size, "%s", basename(dirname(buf)));
180a9de470cSBruce Richardson
181a9de470cSBruce Richardson return prefix;
182a9de470cSBruce Richardson }
183a9de470cSBruce Richardson #endif
184a9de470cSBruce Richardson
185a9de470cSBruce Richardson #endif /* _PROCESS_H_ */
186