07f8be7a58aea02e76126416d6aa9a2983dcca52
[tpg/acess2.git] / Tools / NetTest_Runner / stack.c
1 /*
2  */
3 #define _POSIX_C_SOURCE 200809L
4 #include "stack.h"
5 #include <unistd.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <errno.h>
10 #include <assert.h>
11 #include <stdarg.h>
12
13 #include <fcntl.h>
14 #include <spawn.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17
18 #define MAX_ARGS        16
19
20 extern char **environ;
21
22 // === GLOBALS ===
23 pid_t   giStack_PID;
24  int    giStack_InFD = -1;
25  int    giNumStackArgs = 1;
26 char    *gasStackArgs[MAX_ARGS] = {"nettest",NULL};
27
28 // === CODE ===
29 void Stack_AddDevice(const char *Ident, const void *MacAddr)
30 {
31         Stack_AddArg("-dev");
32         Stack_AddArg("%02x%02x%02x%02x%02x%02x:unix:%s",
33                 ((uint8_t*)MacAddr)[0],
34                 ((uint8_t*)MacAddr)[1],
35                 ((uint8_t*)MacAddr)[2],
36                 ((uint8_t*)MacAddr)[3],
37                 ((uint8_t*)MacAddr)[4],
38                 ((uint8_t*)MacAddr)[5],
39                 Ident);
40 }
41
42 void Stack_AddInterface(const char *Name, int AddrType, const void *Addr, int MaskBits)
43 {
44         Stack_AddArg("-ip");
45         switch(AddrType)
46         {
47         case 4:
48                 Stack_AddArg("%s,%i.%i.%i.%i/%i", Name,
49                         ((uint8_t*)Addr)[0],
50                         ((uint8_t*)Addr)[1],
51                         ((uint8_t*)Addr)[2],
52                         ((uint8_t*)Addr)[3],
53                         MaskBits
54                         );
55                 break;
56         default:
57                 assert(AddrType == 4);
58                 fprintf(stderr, "Stack_AddInterface: Bad address type %i\n", AddrType);
59                 exit(1);
60         }
61 }
62
63 void Stack_AddRoute(int Type, const void *Network, int MaskBits, const void *NextHop)
64 {
65 }
66
67 void Stack_AddArg(const char *Fmt, ...)
68 {
69         if( giNumStackArgs == MAX_ARGS ) {
70                 fprintf(stderr, "ERROR: Too many arguments to stack, %i max\n", MAX_ARGS);
71                 return ;
72         }
73         va_list args;
74         
75         va_start(args, Fmt);
76         size_t len = vsnprintf(NULL, 0, Fmt, args);
77         va_end(args);
78
79         char *arg = malloc(len+1);
80         assert(arg);
81
82         va_start(args, Fmt);
83         vsnprintf(arg, len+1, Fmt, args);
84         va_end(args);
85         
86         assert( arg[len] == '\0' );
87         gasStackArgs[giNumStackArgs++] = arg;
88 }
89
90 void sigchld_handler(int signum)
91 {
92          int status;
93         wait(&status);
94         fprintf(stderr, "FAILURE: Child exited (%i)\n", status);
95 }
96
97 int Stack_Start(const char *RunName, const char *Subcommand)
98 {
99         Stack_AddArg(Subcommand);
100         
101         for( int i = 3; i < 16; i ++ )
102                 fcntl(i, F_SETFD, FD_CLOEXEC);
103
104         //signal(SIGCHLD, sigchld_handler);
105
106          int    fds_in[2];
107         pipe(fds_in);
108         giStack_InFD = fds_in[1];
109         fcntl(giStack_InFD, F_SETFD, FD_CLOEXEC);
110
111         FILE    *fp;
112         fp = fopen("stdout.txt", "a"); fprintf(fp, "--- TEST: %s\n", RunName); fclose(fp);
113         fp = fopen("stderr.txt", "a"); fprintf(fp, "--- TEST: %s\n", RunName); fclose(fp);
114
115         posix_spawn_file_actions_t      fa;
116         posix_spawn_file_actions_init(&fa);
117         posix_spawn_file_actions_adddup2(&fa, fds_in[0], 0);
118         posix_spawn_file_actions_addopen(&fa, 1, "stdout.txt", O_CREAT|O_APPEND|O_WRONLY, 0644);
119         posix_spawn_file_actions_addopen(&fa, 2, "stderr.txt", O_CREAT|O_APPEND|O_WRONLY, 0644);
120
121         int rv = posix_spawn(&giStack_PID, "./nettest", &fa, NULL, gasStackArgs, environ);
122         if(rv) {
123                 giStack_PID = 0;
124                 fprintf(stderr, "posix_spawn failed: %s", strerror(rv));
125                 return 1;
126         }
127         
128         posix_spawn_file_actions_destroy(&fa);
129
130         return 0;
131 }
132 void Stack_Kill(void)
133 {
134         if( giStack_PID )
135         {
136                 kill(giStack_PID, SIGTERM);
137                 giStack_PID = 0;
138         }
139         
140         for( int i = 1; i < giNumStackArgs; i ++ )
141                 free(gasStackArgs[i]);
142         giNumStackArgs = 1;
143 }
144
145 int Stack_SendCommand(const char *Fmt, ...)
146 {
147         va_list args;
148         va_start(args, Fmt);
149         size_t len = vsnprintf(NULL, 0, Fmt, args);
150         va_end(args);
151         char command[len+1];
152         va_start(args, Fmt);
153         vsnprintf(command, len+1, Fmt, args);
154         va_end(args);
155         
156         write(giStack_InFD, command, len);
157         write(giStack_InFD, "\n", 1);
158         return 0;
159 }
160

UCC git Repository :: git.ucc.asn.au