xref: /aosp_15_r20/external/ethtool/test-common.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
1*1b481fc3SMaciej Żenczykowski /****************************************************************************
2*1b481fc3SMaciej Żenczykowski  * Common test functions for ethtool
3*1b481fc3SMaciej Żenczykowski  * Copyright 2011 Solarflare Communications Inc.
4*1b481fc3SMaciej Żenczykowski  *
5*1b481fc3SMaciej Żenczykowski  * Partly derived from kernel <linux/list.h>.
6*1b481fc3SMaciej Żenczykowski  *
7*1b481fc3SMaciej Żenczykowski  * This program is free software; you can redistribute it and/or modify it
8*1b481fc3SMaciej Żenczykowski  * under the terms of the GNU General Public License version 2 as published
9*1b481fc3SMaciej Żenczykowski  * by the Free Software Foundation, incorporated herein by reference.
10*1b481fc3SMaciej Żenczykowski  */
11*1b481fc3SMaciej Żenczykowski 
12*1b481fc3SMaciej Żenczykowski #include <assert.h>
13*1b481fc3SMaciej Żenczykowski #include <errno.h>
14*1b481fc3SMaciej Żenczykowski #include <setjmp.h>
15*1b481fc3SMaciej Żenczykowski #include <stdarg.h>
16*1b481fc3SMaciej Żenczykowski #include <stdlib.h>
17*1b481fc3SMaciej Żenczykowski #include <string.h>
18*1b481fc3SMaciej Żenczykowski #include <sys/fcntl.h>
19*1b481fc3SMaciej Żenczykowski #include <unistd.h>
20*1b481fc3SMaciej Żenczykowski #define TEST_NO_WRAPPERS
21*1b481fc3SMaciej Żenczykowski #include "internal.h"
22*1b481fc3SMaciej Żenczykowski 
23*1b481fc3SMaciej Żenczykowski /* List utilities */
24*1b481fc3SMaciej Żenczykowski 
25*1b481fc3SMaciej Żenczykowski struct list_head {
26*1b481fc3SMaciej Żenczykowski 	struct list_head *next, *prev;
27*1b481fc3SMaciej Żenczykowski };
28*1b481fc3SMaciej Żenczykowski 
29*1b481fc3SMaciej Żenczykowski #define LIST_HEAD_INIT(name) { &(name), &(name) }
30*1b481fc3SMaciej Żenczykowski 
init_list_head(struct list_head * list)31*1b481fc3SMaciej Żenczykowski static void init_list_head(struct list_head *list)
32*1b481fc3SMaciej Żenczykowski {
33*1b481fc3SMaciej Żenczykowski 	list->next = list;
34*1b481fc3SMaciej Żenczykowski 	list->prev = list;
35*1b481fc3SMaciej Żenczykowski }
36*1b481fc3SMaciej Żenczykowski 
list_add(struct list_head * new,struct list_head * head)37*1b481fc3SMaciej Żenczykowski static void list_add(struct list_head *new, struct list_head *head)
38*1b481fc3SMaciej Żenczykowski {
39*1b481fc3SMaciej Żenczykowski 	head->next->prev = new;
40*1b481fc3SMaciej Żenczykowski 	new->next = head->next;
41*1b481fc3SMaciej Żenczykowski 	new->prev = head;
42*1b481fc3SMaciej Żenczykowski 	head->next = new;
43*1b481fc3SMaciej Żenczykowski }
44*1b481fc3SMaciej Żenczykowski 
list_del(struct list_head * entry)45*1b481fc3SMaciej Żenczykowski static void list_del(struct list_head *entry)
46*1b481fc3SMaciej Żenczykowski {
47*1b481fc3SMaciej Żenczykowski 	entry->next->prev = entry->prev;
48*1b481fc3SMaciej Żenczykowski 	entry->prev->next = entry->next;
49*1b481fc3SMaciej Żenczykowski 	entry->next = NULL;
50*1b481fc3SMaciej Żenczykowski 	entry->prev = NULL;
51*1b481fc3SMaciej Żenczykowski }
52*1b481fc3SMaciej Żenczykowski 
53*1b481fc3SMaciej Żenczykowski #define list_for_each_safe(pos, n, head) \
54*1b481fc3SMaciej Żenczykowski 	for (pos = (head)->next, n = pos->next; pos != (head); \
55*1b481fc3SMaciej Żenczykowski 		pos = n, n = pos->next)
56*1b481fc3SMaciej Żenczykowski 
57*1b481fc3SMaciej Żenczykowski /* Free memory at end of test */
58*1b481fc3SMaciej Żenczykowski 
59*1b481fc3SMaciej Żenczykowski static struct list_head malloc_list = LIST_HEAD_INIT(malloc_list);
60*1b481fc3SMaciej Żenczykowski 
test_malloc(size_t size)61*1b481fc3SMaciej Żenczykowski void *test_malloc(size_t size)
62*1b481fc3SMaciej Żenczykowski {
63*1b481fc3SMaciej Żenczykowski 	struct list_head *block = malloc(sizeof(*block) + size);
64*1b481fc3SMaciej Żenczykowski 
65*1b481fc3SMaciej Żenczykowski 	if (!block)
66*1b481fc3SMaciej Żenczykowski 		return NULL;
67*1b481fc3SMaciej Żenczykowski 	list_add(block, &malloc_list);
68*1b481fc3SMaciej Żenczykowski 	return block + 1;
69*1b481fc3SMaciej Żenczykowski }
70*1b481fc3SMaciej Żenczykowski 
test_calloc(size_t nmemb,size_t size)71*1b481fc3SMaciej Żenczykowski void *test_calloc(size_t nmemb, size_t size)
72*1b481fc3SMaciej Żenczykowski {
73*1b481fc3SMaciej Żenczykowski 	void *ptr = test_malloc(nmemb * size);
74*1b481fc3SMaciej Żenczykowski 
75*1b481fc3SMaciej Żenczykowski 	if (ptr)
76*1b481fc3SMaciej Żenczykowski 		memset(ptr, 0, nmemb * size);
77*1b481fc3SMaciej Żenczykowski 	return ptr;
78*1b481fc3SMaciej Żenczykowski }
79*1b481fc3SMaciej Żenczykowski 
test_strdup(const char * s)80*1b481fc3SMaciej Żenczykowski char *test_strdup(const char *s)
81*1b481fc3SMaciej Żenczykowski {
82*1b481fc3SMaciej Żenczykowski 	size_t size = strlen(s) + 1;
83*1b481fc3SMaciej Żenczykowski 	char *dup = test_malloc(size);
84*1b481fc3SMaciej Żenczykowski 
85*1b481fc3SMaciej Żenczykowski 	if (dup)
86*1b481fc3SMaciej Żenczykowski 		memcpy(dup, s, size);
87*1b481fc3SMaciej Żenczykowski 	return dup;
88*1b481fc3SMaciej Żenczykowski }
89*1b481fc3SMaciej Żenczykowski 
test_free(void * ptr)90*1b481fc3SMaciej Żenczykowski void test_free(void *ptr)
91*1b481fc3SMaciej Żenczykowski {
92*1b481fc3SMaciej Żenczykowski 	struct list_head *block;
93*1b481fc3SMaciej Żenczykowski 
94*1b481fc3SMaciej Żenczykowski 	if (!ptr)
95*1b481fc3SMaciej Żenczykowski 		return;
96*1b481fc3SMaciej Żenczykowski 	block = (struct list_head *)ptr - 1;
97*1b481fc3SMaciej Żenczykowski 	list_del(block);
98*1b481fc3SMaciej Żenczykowski 	free(block);
99*1b481fc3SMaciej Żenczykowski }
100*1b481fc3SMaciej Żenczykowski 
test_realloc(void * ptr,size_t size)101*1b481fc3SMaciej Żenczykowski void *test_realloc(void *ptr, size_t size)
102*1b481fc3SMaciej Żenczykowski {
103*1b481fc3SMaciej Żenczykowski 	struct list_head *block = NULL;
104*1b481fc3SMaciej Żenczykowski 
105*1b481fc3SMaciej Żenczykowski 	if (ptr) {
106*1b481fc3SMaciej Żenczykowski 		block = (struct list_head *)ptr - 1;
107*1b481fc3SMaciej Żenczykowski 		list_del(block);
108*1b481fc3SMaciej Żenczykowski 	}
109*1b481fc3SMaciej Żenczykowski 	block = realloc(block, sizeof(*block) + size);
110*1b481fc3SMaciej Żenczykowski 	if (!block)
111*1b481fc3SMaciej Żenczykowski 		return NULL;
112*1b481fc3SMaciej Żenczykowski 	list_add(block, &malloc_list);
113*1b481fc3SMaciej Żenczykowski 	return block + 1;
114*1b481fc3SMaciej Żenczykowski }
115*1b481fc3SMaciej Żenczykowski 
test_free_all(void)116*1b481fc3SMaciej Żenczykowski static void test_free_all(void)
117*1b481fc3SMaciej Żenczykowski {
118*1b481fc3SMaciej Żenczykowski 	struct list_head *block, *next;
119*1b481fc3SMaciej Żenczykowski 
120*1b481fc3SMaciej Żenczykowski 	list_for_each_safe(block, next, &malloc_list)
121*1b481fc3SMaciej Żenczykowski 		free(block);
122*1b481fc3SMaciej Żenczykowski 	init_list_head(&malloc_list);
123*1b481fc3SMaciej Żenczykowski }
124*1b481fc3SMaciej Żenczykowski 
125*1b481fc3SMaciej Żenczykowski /* Close files at end of test */
126*1b481fc3SMaciej Żenczykowski 
127*1b481fc3SMaciej Żenczykowski struct file_node {
128*1b481fc3SMaciej Żenczykowski 	struct list_head link;
129*1b481fc3SMaciej Żenczykowski 	FILE *fh;
130*1b481fc3SMaciej Żenczykowski 	int fd;
131*1b481fc3SMaciej Żenczykowski };
132*1b481fc3SMaciej Żenczykowski 
133*1b481fc3SMaciej Żenczykowski static struct list_head file_list = LIST_HEAD_INIT(file_list);
134*1b481fc3SMaciej Żenczykowski 
test_open(const char * pathname,int flag,...)135*1b481fc3SMaciej Żenczykowski int test_open(const char *pathname, int flag, ...)
136*1b481fc3SMaciej Żenczykowski {
137*1b481fc3SMaciej Żenczykowski 	struct file_node *node;
138*1b481fc3SMaciej Żenczykowski 	mode_t mode;
139*1b481fc3SMaciej Żenczykowski 
140*1b481fc3SMaciej Żenczykowski 	if (flag & O_CREAT) {
141*1b481fc3SMaciej Żenczykowski 		va_list ap;
142*1b481fc3SMaciej Żenczykowski 		va_start(ap, flag);
143*1b481fc3SMaciej Żenczykowski 		mode = va_arg(ap, mode_t);
144*1b481fc3SMaciej Żenczykowski 		va_end(ap);
145*1b481fc3SMaciej Żenczykowski 	} else {
146*1b481fc3SMaciej Żenczykowski 		mode = 0;
147*1b481fc3SMaciej Żenczykowski 	}
148*1b481fc3SMaciej Żenczykowski 
149*1b481fc3SMaciej Żenczykowski 	node = malloc(sizeof(*node));
150*1b481fc3SMaciej Żenczykowski 	if (!node)
151*1b481fc3SMaciej Żenczykowski 		return -1;
152*1b481fc3SMaciej Żenczykowski 
153*1b481fc3SMaciej Żenczykowski 	node->fd = open(pathname, flag, mode);
154*1b481fc3SMaciej Żenczykowski 	if (node->fd < 0) {
155*1b481fc3SMaciej Żenczykowski 		free(node);
156*1b481fc3SMaciej Żenczykowski 		return -1;
157*1b481fc3SMaciej Żenczykowski 	}
158*1b481fc3SMaciej Żenczykowski 
159*1b481fc3SMaciej Żenczykowski 	node->fh = NULL;
160*1b481fc3SMaciej Żenczykowski 	list_add(&node->link, &file_list);
161*1b481fc3SMaciej Żenczykowski 	return node->fd;
162*1b481fc3SMaciej Żenczykowski }
163*1b481fc3SMaciej Żenczykowski 
test_socket(int domain,int type,int protocol)164*1b481fc3SMaciej Żenczykowski int test_socket(int domain, int type, int protocol)
165*1b481fc3SMaciej Żenczykowski {
166*1b481fc3SMaciej Żenczykowski 	struct file_node *node;
167*1b481fc3SMaciej Żenczykowski 
168*1b481fc3SMaciej Żenczykowski 	node = malloc(sizeof(*node));
169*1b481fc3SMaciej Żenczykowski 	if (!node)
170*1b481fc3SMaciej Żenczykowski 		return -1;
171*1b481fc3SMaciej Żenczykowski 
172*1b481fc3SMaciej Żenczykowski 	node->fd = socket(domain, type, protocol);
173*1b481fc3SMaciej Żenczykowski 	if (node->fd < 0) {
174*1b481fc3SMaciej Żenczykowski 		free(node);
175*1b481fc3SMaciej Żenczykowski 		return -1;
176*1b481fc3SMaciej Żenczykowski 	}
177*1b481fc3SMaciej Żenczykowski 
178*1b481fc3SMaciej Żenczykowski 	node->fh = NULL;
179*1b481fc3SMaciej Żenczykowski 	list_add(&node->link, &file_list);
180*1b481fc3SMaciej Żenczykowski 	return node->fd;
181*1b481fc3SMaciej Żenczykowski }
182*1b481fc3SMaciej Żenczykowski 
test_close(int fd)183*1b481fc3SMaciej Żenczykowski int test_close(int fd)
184*1b481fc3SMaciej Żenczykowski {
185*1b481fc3SMaciej Żenczykowski 	struct list_head *head, *next;
186*1b481fc3SMaciej Żenczykowski 
187*1b481fc3SMaciej Żenczykowski 	if (fd >= 0) {
188*1b481fc3SMaciej Żenczykowski 		list_for_each_safe(head, next, &file_list) {
189*1b481fc3SMaciej Żenczykowski 			if (((struct file_node *)head)->fd == fd) {
190*1b481fc3SMaciej Żenczykowski 				list_del(head);
191*1b481fc3SMaciej Żenczykowski 				free(head);
192*1b481fc3SMaciej Żenczykowski 				break;
193*1b481fc3SMaciej Żenczykowski 			}
194*1b481fc3SMaciej Żenczykowski 		}
195*1b481fc3SMaciej Żenczykowski 	}
196*1b481fc3SMaciej Żenczykowski 
197*1b481fc3SMaciej Żenczykowski 	return close(fd);
198*1b481fc3SMaciej Żenczykowski }
199*1b481fc3SMaciej Żenczykowski 
test_fopen(const char * path,const char * mode)200*1b481fc3SMaciej Żenczykowski FILE *test_fopen(const char *path, const char *mode)
201*1b481fc3SMaciej Żenczykowski {
202*1b481fc3SMaciej Żenczykowski 	struct file_node *node;
203*1b481fc3SMaciej Żenczykowski 
204*1b481fc3SMaciej Żenczykowski 	node = malloc(sizeof(*node));
205*1b481fc3SMaciej Żenczykowski 	if (!node)
206*1b481fc3SMaciej Żenczykowski 		return NULL;
207*1b481fc3SMaciej Żenczykowski 
208*1b481fc3SMaciej Żenczykowski 	node->fh = fopen(path, mode);
209*1b481fc3SMaciej Żenczykowski 	if (!node->fh) {
210*1b481fc3SMaciej Żenczykowski 		free(node);
211*1b481fc3SMaciej Żenczykowski 		return NULL;
212*1b481fc3SMaciej Żenczykowski 	}
213*1b481fc3SMaciej Żenczykowski 
214*1b481fc3SMaciej Żenczykowski 	node->fd = -1;
215*1b481fc3SMaciej Żenczykowski 	list_add(&node->link, &file_list);
216*1b481fc3SMaciej Żenczykowski 	return node->fh;
217*1b481fc3SMaciej Żenczykowski }
218*1b481fc3SMaciej Żenczykowski 
test_fclose(FILE * fh)219*1b481fc3SMaciej Żenczykowski int test_fclose(FILE *fh)
220*1b481fc3SMaciej Żenczykowski {
221*1b481fc3SMaciej Żenczykowski 	struct list_head *head, *next;
222*1b481fc3SMaciej Żenczykowski 
223*1b481fc3SMaciej Żenczykowski 	assert(fh);
224*1b481fc3SMaciej Żenczykowski 
225*1b481fc3SMaciej Żenczykowski 	list_for_each_safe(head, next, &file_list) {
226*1b481fc3SMaciej Żenczykowski 		if (((struct file_node *)head)->fh == fh) {
227*1b481fc3SMaciej Żenczykowski 			list_del(head);
228*1b481fc3SMaciej Żenczykowski 			free(head);
229*1b481fc3SMaciej Żenczykowski 			break;
230*1b481fc3SMaciej Żenczykowski 		}
231*1b481fc3SMaciej Żenczykowski 	}
232*1b481fc3SMaciej Żenczykowski 
233*1b481fc3SMaciej Żenczykowski 	return fclose(fh);
234*1b481fc3SMaciej Żenczykowski }
235*1b481fc3SMaciej Żenczykowski 
test_close_all(void)236*1b481fc3SMaciej Żenczykowski static void test_close_all(void)
237*1b481fc3SMaciej Żenczykowski {
238*1b481fc3SMaciej Żenczykowski 	struct list_head *head, *next;
239*1b481fc3SMaciej Żenczykowski 	struct file_node *node;
240*1b481fc3SMaciej Żenczykowski 
241*1b481fc3SMaciej Żenczykowski 	list_for_each_safe(head, next, &file_list) {
242*1b481fc3SMaciej Żenczykowski 		node = (struct file_node *)head;
243*1b481fc3SMaciej Żenczykowski 		if (node->fh)
244*1b481fc3SMaciej Żenczykowski 			fclose(node->fh);
245*1b481fc3SMaciej Żenczykowski 		else
246*1b481fc3SMaciej Żenczykowski 			close(node->fd);
247*1b481fc3SMaciej Żenczykowski 		free(node);
248*1b481fc3SMaciej Żenczykowski 	}
249*1b481fc3SMaciej Żenczykowski 	init_list_head(&file_list);
250*1b481fc3SMaciej Żenczykowski }
251*1b481fc3SMaciej Żenczykowski 
252*1b481fc3SMaciej Żenczykowski /* Wrap test main function */
253*1b481fc3SMaciej Żenczykowski 
254*1b481fc3SMaciej Żenczykowski static jmp_buf test_return;
255*1b481fc3SMaciej Żenczykowski static FILE *orig_stderr;
256*1b481fc3SMaciej Żenczykowski 
test_exit(int rc)257*1b481fc3SMaciej Żenczykowski void test_exit(int rc)
258*1b481fc3SMaciej Żenczykowski {
259*1b481fc3SMaciej Żenczykowski 	longjmp(test_return, rc + 1);
260*1b481fc3SMaciej Żenczykowski }
261*1b481fc3SMaciej Żenczykowski 
test_ioctl(const struct cmd_expect * expect,void * cmd)262*1b481fc3SMaciej Żenczykowski int test_ioctl(const struct cmd_expect *expect, void *cmd)
263*1b481fc3SMaciej Żenczykowski {
264*1b481fc3SMaciej Żenczykowski 	int rc;
265*1b481fc3SMaciej Żenczykowski 
266*1b481fc3SMaciej Żenczykowski 	if (!expect->cmd || *(u32 *)cmd != *(const u32 *)expect->cmd) {
267*1b481fc3SMaciej Żenczykowski 		/* We have no idea how long this command structure is */
268*1b481fc3SMaciej Żenczykowski 		fprintf(orig_stderr, "Unexpected ioctl: cmd=%#10x\n",
269*1b481fc3SMaciej Żenczykowski 			*(u32 *)cmd);
270*1b481fc3SMaciej Żenczykowski 		return TEST_IOCTL_MISMATCH;
271*1b481fc3SMaciej Żenczykowski 	}
272*1b481fc3SMaciej Żenczykowski 
273*1b481fc3SMaciej Żenczykowski 	if (memcmp(cmd, expect->cmd, expect->cmd_len)) {
274*1b481fc3SMaciej Żenczykowski 		fprintf(orig_stderr, "Expected ioctl structure:\n");
275*1b481fc3SMaciej Żenczykowski 		dump_hex(orig_stderr, expect->cmd, expect->cmd_len, 0);
276*1b481fc3SMaciej Żenczykowski 		fprintf(orig_stderr, "Actual ioctl structure:\n");
277*1b481fc3SMaciej Żenczykowski 		dump_hex(orig_stderr, cmd, expect->cmd_len, 0);
278*1b481fc3SMaciej Żenczykowski 		return TEST_IOCTL_MISMATCH;
279*1b481fc3SMaciej Żenczykowski 	}
280*1b481fc3SMaciej Żenczykowski 
281*1b481fc3SMaciej Żenczykowski 	if (expect->resp)
282*1b481fc3SMaciej Żenczykowski 		memcpy(cmd, expect->resp, expect->resp_len);
283*1b481fc3SMaciej Żenczykowski 	rc = expect->rc;
284*1b481fc3SMaciej Żenczykowski 
285*1b481fc3SMaciej Żenczykowski 	/* Convert kernel return code according to libc convention */
286*1b481fc3SMaciej Żenczykowski 	if (rc >= 0) {
287*1b481fc3SMaciej Żenczykowski 		return rc;
288*1b481fc3SMaciej Żenczykowski 	} else {
289*1b481fc3SMaciej Żenczykowski 		errno = -rc;
290*1b481fc3SMaciej Żenczykowski 		return -1;
291*1b481fc3SMaciej Żenczykowski 	}
292*1b481fc3SMaciej Żenczykowski }
293*1b481fc3SMaciej Żenczykowski 
test_cmdline(const char * args)294*1b481fc3SMaciej Żenczykowski int test_cmdline(const char *args)
295*1b481fc3SMaciej Żenczykowski {
296*1b481fc3SMaciej Żenczykowski 	int volatile orig_stdout_fd = -1;
297*1b481fc3SMaciej Żenczykowski 	int volatile orig_stderr_fd = -1;
298*1b481fc3SMaciej Żenczykowski 	char **volatile argv;
299*1b481fc3SMaciej Żenczykowski 	int volatile argc;
300*1b481fc3SMaciej Żenczykowski 	int dev_null = -1;
301*1b481fc3SMaciej Żenczykowski 	const char *arg;
302*1b481fc3SMaciej Żenczykowski 	size_t len;
303*1b481fc3SMaciej Żenczykowski 	int rc, i;
304*1b481fc3SMaciej Żenczykowski 
305*1b481fc3SMaciej Żenczykowski 	/* Convert line to argv */
306*1b481fc3SMaciej Żenczykowski 	argc = 1;
307*1b481fc3SMaciej Żenczykowski 	arg = args;
308*1b481fc3SMaciej Żenczykowski 	for (;;) {
309*1b481fc3SMaciej Żenczykowski 		len = strcspn(arg, " ");
310*1b481fc3SMaciej Żenczykowski 		if (len == 0)
311*1b481fc3SMaciej Żenczykowski 			break;
312*1b481fc3SMaciej Żenczykowski 		argc++;
313*1b481fc3SMaciej Żenczykowski 		if (arg[len] == 0)
314*1b481fc3SMaciej Żenczykowski 			break;
315*1b481fc3SMaciej Żenczykowski 		arg += len + 1;
316*1b481fc3SMaciej Żenczykowski 	}
317*1b481fc3SMaciej Żenczykowski 	argv = test_calloc(argc + 1, sizeof(argv[0]));
318*1b481fc3SMaciej Żenczykowski 	argv[0] = test_strdup("ethtool");
319*1b481fc3SMaciej Żenczykowski 	arg = args;
320*1b481fc3SMaciej Żenczykowski 	for (i = 1; i < argc; i++) {
321*1b481fc3SMaciej Żenczykowski 		len = strcspn(arg, " ");
322*1b481fc3SMaciej Żenczykowski 		argv[i] = test_malloc(len + 1);
323*1b481fc3SMaciej Żenczykowski 		memcpy(argv[i], arg, len);
324*1b481fc3SMaciej Żenczykowski 		argv[i][len] = 0;
325*1b481fc3SMaciej Żenczykowski 		arg += len + 1;
326*1b481fc3SMaciej Żenczykowski 	}
327*1b481fc3SMaciej Żenczykowski 
328*1b481fc3SMaciej Żenczykowski 	dev_null = open("/dev/null", O_RDWR);
329*1b481fc3SMaciej Żenczykowski 	if (dev_null < 0) {
330*1b481fc3SMaciej Żenczykowski 		perror("open /dev/null");
331*1b481fc3SMaciej Żenczykowski 		rc = -1;
332*1b481fc3SMaciej Żenczykowski 		goto out;
333*1b481fc3SMaciej Żenczykowski 	}
334*1b481fc3SMaciej Żenczykowski 
335*1b481fc3SMaciej Żenczykowski 	fflush(NULL);
336*1b481fc3SMaciej Żenczykowski 	dup2(dev_null, STDIN_FILENO);
337*1b481fc3SMaciej Żenczykowski 	if (getenv("TEST_TEST_VERBOSE")) {
338*1b481fc3SMaciej Żenczykowski 		orig_stderr = stderr;
339*1b481fc3SMaciej Żenczykowski 	} else {
340*1b481fc3SMaciej Żenczykowski 		orig_stdout_fd = dup(STDOUT_FILENO);
341*1b481fc3SMaciej Żenczykowski 		if (orig_stdout_fd < 0) {
342*1b481fc3SMaciej Żenczykowski 			perror("dup stdout");
343*1b481fc3SMaciej Żenczykowski 			rc = -1;
344*1b481fc3SMaciej Żenczykowski 			goto out;
345*1b481fc3SMaciej Żenczykowski 		}
346*1b481fc3SMaciej Żenczykowski 		dup2(dev_null, STDOUT_FILENO);
347*1b481fc3SMaciej Żenczykowski 		orig_stderr_fd = dup(STDERR_FILENO);
348*1b481fc3SMaciej Żenczykowski 		if (orig_stderr_fd < 0) {
349*1b481fc3SMaciej Żenczykowski 			perror("dup stderr");
350*1b481fc3SMaciej Żenczykowski 			rc = -1;
351*1b481fc3SMaciej Żenczykowski 			goto out;
352*1b481fc3SMaciej Żenczykowski 		}
353*1b481fc3SMaciej Żenczykowski 		orig_stderr = fdopen(orig_stderr_fd, "w");
354*1b481fc3SMaciej Żenczykowski 		if (orig_stderr == NULL) {
355*1b481fc3SMaciej Żenczykowski 			perror("fdopen orig_stderr_fd");
356*1b481fc3SMaciej Żenczykowski 			rc = -1;
357*1b481fc3SMaciej Żenczykowski 			goto out;
358*1b481fc3SMaciej Żenczykowski 		}
359*1b481fc3SMaciej Żenczykowski 		dup2(dev_null, STDERR_FILENO);
360*1b481fc3SMaciej Żenczykowski 	}
361*1b481fc3SMaciej Żenczykowski 
362*1b481fc3SMaciej Żenczykowski 	rc = setjmp(test_return);
363*1b481fc3SMaciej Żenczykowski 	rc = rc ? rc - 1 : test_main(argc, argv);
364*1b481fc3SMaciej Żenczykowski 
365*1b481fc3SMaciej Żenczykowski out:
366*1b481fc3SMaciej Żenczykowski 	fflush(NULL);
367*1b481fc3SMaciej Żenczykowski 	if (orig_stderr_fd >= 0) {
368*1b481fc3SMaciej Żenczykowski 		dup2(orig_stderr_fd, STDERR_FILENO);
369*1b481fc3SMaciej Żenczykowski 		if (orig_stderr)
370*1b481fc3SMaciej Żenczykowski 			fclose(orig_stderr);
371*1b481fc3SMaciej Żenczykowski 		else
372*1b481fc3SMaciej Żenczykowski 			close(orig_stderr_fd);
373*1b481fc3SMaciej Żenczykowski 	}
374*1b481fc3SMaciej Żenczykowski 	orig_stderr = NULL;
375*1b481fc3SMaciej Żenczykowski 	if (orig_stdout_fd >= 0) {
376*1b481fc3SMaciej Żenczykowski 		dup2(orig_stdout_fd, STDOUT_FILENO);
377*1b481fc3SMaciej Żenczykowski 		close(orig_stdout_fd);
378*1b481fc3SMaciej Żenczykowski 	}
379*1b481fc3SMaciej Żenczykowski 	if (dev_null >= 0)
380*1b481fc3SMaciej Żenczykowski 		close(dev_null);
381*1b481fc3SMaciej Żenczykowski 
382*1b481fc3SMaciej Żenczykowski 	test_free_all();
383*1b481fc3SMaciej Żenczykowski 	test_close_all();
384*1b481fc3SMaciej Żenczykowski 	return rc;
385*1b481fc3SMaciej Żenczykowski }
386