4343#endif /* VERSION */
4444
4545#define E (...) logger(__func__, __FILE__, __LINE__, __VA_ARGS__)
46+ #define E_RAW (...) logger_raw(__VA_ARGS__)
4647
48+ static FILE * g_logfp = NULL ;
4749static int g_sockfd = 0 ;
4850static int g_exit = 0 ;
4951static int g_repeat = 3 ;
@@ -67,6 +69,7 @@ static void print_usage(const char *name)
6769 " -r <repeat> duplicate generated packets for <repeat> "
6870 "times\n"
6971 " -t <ttl> TTL for generated packets\n"
72+ " -w <file> write log to <file> instead of stderr\n"
7073 " -x <mask> set the mask for fwmark\n"
7174 "\n"
7275 "FakeHTTP version " VERSION "\n" ,
@@ -77,23 +80,38 @@ static void print_usage(const char *name)
7780static void logger (const char * funcname , const char * filename ,
7881 unsigned long line , const char * fmt , ...)
7982{
83+ FILE * fp ;
8084 va_list args ;
8185 time_t t ;
8286 char * stime ;
8387
88+ fp = g_logfp ? g_logfp : stderr ;
8489 t = time (NULL );
8590 stime = ctime (& t );
8691 if (stime ) {
8792 stime [strlen (stime ) - 1 ] = '\0' ;
88- fprintf (stderr , "%s " , stime );
93+ fprintf (fp , "%s " , stime );
8994 }
9095
91- fprintf (stderr , "[%s() - %s:%lu] " , funcname , filename , line );
96+ fprintf (fp , "[%s() - %s:%lu] " , funcname , filename , line );
9297 va_start (args , fmt );
93- vfprintf (stderr , fmt , args );
98+ vfprintf (fp , fmt , args );
9499 va_end (args );
95- fputc ('\n' , stderr );
96- fflush (stderr );
100+ fputc ('\n' , fp );
101+ fflush (fp );
102+ }
103+
104+
105+ static void logger_raw (const char * fmt , ...)
106+ {
107+ FILE * fp ;
108+ va_list args ;
109+
110+ fp = g_logfp ? g_logfp : stderr ;
111+ va_start (args , fmt );
112+ vfprintf (fp , fmt , args );
113+ va_end (args );
114+ fflush (fp );
97115}
98116
99117
@@ -160,12 +178,23 @@ static int execute_command(char **argv, int silent)
160178 }
161179
162180 if (!pid ) {
181+ fd = -1 ;
182+
163183 if (silent ) {
164184 fd = open ("/dev/null" , O_WRONLY );
165185 if (fd < 0 ) {
166186 E ("ERROR: open(): %s" , strerror (errno ));
167187 _exit (EXIT_FAILURE );
168188 }
189+ } else if (g_logfp ) {
190+ fd = fileno (g_logfp );
191+ if (fd < 0 ) {
192+ E ("ERROR: fileno(): %s" , strerror (errno ));
193+ _exit (EXIT_FAILURE );
194+ }
195+ }
196+
197+ if (fd >= 0 ) {
169198 res = dup2 (fd , STDOUT_FILENO );
170199 if (res < 0 ) {
171200 E ("ERROR: dup2(): %s" , strerror (errno ));
@@ -197,11 +226,11 @@ static int execute_command(char **argv, int silent)
197226
198227child_failed :
199228 if (!silent ) {
200- fprintf ( stderr , " failed command is: %s" , argv [0 ]);
229+ E_RAW ( "[*] failed command is: %s" , argv [0 ]);
201230 for (i = 1 ; argv [i ]; i ++ ) {
202- fprintf ( stderr , " %s" , argv [i ]);
231+ E_RAW ( " %s" , argv [i ]);
203232 }
204- fputc ( '\n' , stderr );
233+ E_RAW ( "\n" );
205234 }
206235
207236 return -1 ;
@@ -676,7 +705,7 @@ int main(int argc, char *argv[])
676705 return EXIT_FAILURE ;
677706 }
678707
679- while ((opt = getopt (argc , argv , "h:i:m:n:r:t:x:" )) != -1 ) {
708+ while ((opt = getopt (argc , argv , "h:i:m:n:r:t:w: x:" )) != -1 ) {
680709 switch (opt ) {
681710 case 'h' :
682711 if (strlen (optarg ) > _POSIX_HOST_NAME_MAX ) {
@@ -731,6 +760,15 @@ int main(int argc, char *argv[])
731760 }
732761 g_ttl = tmp ;
733762 break ;
763+ case 'w' :
764+ g_logfp = fopen (optarg , "a" );
765+ if (!g_logfp ) {
766+ fprintf (stderr , "%s: invalid value for -w: %s\n" , argv [0 ],
767+ strerror (errno ));
768+ print_usage (argv [0 ]);
769+ return EXIT_FAILURE ;
770+ }
771+ break ;
734772 case 'x' :
735773 tmp = strtoull (optarg , NULL , 0 );
736774 if (!tmp || tmp > UINT32_MAX ) {
@@ -973,5 +1011,9 @@ int main(int argc, char *argv[])
9731011free_buff :
9741012 free (buff );
9751013
1014+ if (g_logfp ) {
1015+ fclose (g_logfp );
1016+ }
1017+
9761018 return exitcode ;
9771019}
0 commit comments