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