2010-05-25 15:14:06 +04:00
/*
* commandhelper . c : Auxiliary program for commandtest
*
2014-03-18 12:13:43 +04:00
* Copyright ( C ) 2010 - 2014 Red Hat , Inc .
2010-05-25 15:14:06 +04:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2012-09-21 02:30:55 +04:00
* License along with this library . If not , see
2012-07-21 14:06:23 +04:00
* < http : //www.gnu.org/licenses/>.
2010-05-25 15:14:06 +04:00
*/
# include <config.h>
# include <unistd.h>
# include <fcntl.h>
2014-09-03 19:13:21 +04:00
# include <sys/stat.h>
2010-05-25 15:14:06 +04:00
2020-01-27 15:52:23 +03:00
# define VIR_NO_GLIB_STDIO /* This file intentionally does not link to libvirt/glib */
2017-09-21 10:55:07 +03:00
# include "testutils.h"
2012-03-29 13:50:00 +04:00
# ifndef WIN32
2020-01-17 14:19:13 +03:00
# include <poll.h>
2010-05-25 15:14:06 +04:00
2020-01-07 19:16:19 +03:00
/* Some UNIX lack it in headers & it doesn't hurt to redeclare */
extern char * * environ ;
2013-06-07 12:37:25 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
2010-05-25 15:14:06 +04:00
2014-03-18 12:13:43 +04:00
static int envsort ( const void * a , const void * b )
{
2010-05-25 15:14:06 +04:00
const char * const * astrptr = a ;
const char * const * bstrptr = b ;
const char * astr = * astrptr ;
const char * bstr = * bstrptr ;
char * aeq = strchr ( astr , ' = ' ) ;
char * beq = strchr ( bstr , ' = ' ) ;
2013-05-03 16:52:21 +04:00
char * akey ;
char * bkey ;
int ret ;
2017-09-20 14:03:47 +03:00
if ( ! ( akey = strndup ( astr , aeq - astr ) ) )
abort ( ) ;
if ( ! ( bkey = strndup ( bstr , beq - bstr ) ) )
abort ( ) ;
2013-05-03 16:52:21 +04:00
ret = strcmp ( akey , bkey ) ;
2017-09-20 14:03:47 +03:00
free ( akey ) ;
free ( bkey ) ;
2010-05-25 15:14:06 +04:00
return ret ;
}
int main ( int argc , char * * argv ) {
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i , n ;
2013-07-11 15:22:20 +04:00
int open_max ;
2010-05-25 15:14:06 +04:00
char * * origenv ;
2014-09-03 22:59:31 +04:00
char * * newenv = NULL ;
2011-04-29 21:14:23 +04:00
char * cwd ;
2010-05-25 15:14:06 +04:00
FILE * log = fopen ( abs_builddir " /commandhelper.log " , " w " ) ;
2014-09-03 22:59:31 +04:00
int ret = EXIT_FAILURE ;
2019-07-25 21:22:10 +03:00
int readfds [ 3 ] = { STDIN_FILENO , } ;
int numreadfds = 1 ;
struct pollfd fds [ 3 ] ;
int numpollfds = 0 ;
char * buffers [ 3 ] = { NULL , NULL , NULL } ;
size_t buflen [ 3 ] = { 0 , 0 , 0 } ;
char c ;
2020-07-21 13:32:10 +03:00
bool daemonize_check = false ;
size_t daemonize_retries = 3 ;
2020-08-03 18:27:58 +03:00
char buf [ 1024 ] ;
ssize_t got ;
2010-05-25 15:14:06 +04:00
if ( ! log )
2018-04-02 14:13:33 +03:00
return ret ;
2010-05-25 15:14:06 +04:00
2019-07-25 21:22:10 +03:00
for ( i = 1 ; i < argc ; i + + ) {
2010-05-25 15:14:06 +04:00
fprintf ( log , " ARG:%s \n " , argv [ i ] ) ;
2019-07-25 21:22:10 +03:00
if ( STREQ ( argv [ i - 1 ] , " --readfd " ) & &
sscanf ( argv [ i ] , " %u%c " , & readfds [ numreadfds + + ] , & c ) ! = 1 ) {
printf ( " Could not parse fd %s \n " , argv [ i ] ) ;
goto cleanup ;
2020-07-21 13:32:10 +03:00
} else if ( STREQ ( argv [ i ] , " --check-daemonize " ) ) {
daemonize_check = true ;
2019-07-25 21:22:10 +03:00
}
}
2010-05-25 15:14:06 +04:00
origenv = environ ;
n = 0 ;
while ( * origenv ! = NULL ) {
n + + ;
origenv + + ;
}
2017-09-20 14:03:47 +03:00
if ( ! ( newenv = malloc ( sizeof ( * newenv ) * n ) ) )
abort ( ) ;
2010-05-25 15:14:06 +04:00
origenv = environ ;
n = i = 0 ;
while ( * origenv ! = NULL ) {
newenv [ i + + ] = * origenv ;
n + + ;
origenv + + ;
}
qsort ( newenv , n , sizeof ( newenv [ 0 ] ) , envsort ) ;
2013-05-21 11:53:48 +04:00
for ( i = 0 ; i < n ; i + + ) {
2011-01-06 23:23:36 +03:00
/* Ignore the variables used to instruct the loader into
* behaving differently , as they could throw the tests off . */
if ( ! STRPREFIX ( newenv [ i ] , " LD_ " ) )
fprintf ( log , " ENV:%s \n " , newenv [ i ] ) ;
2010-05-25 15:14:06 +04:00
}
2013-07-11 15:22:20 +04:00
open_max = sysconf ( _SC_OPEN_MAX ) ;
if ( open_max < 0 )
2014-09-03 22:59:31 +04:00
goto cleanup ;
2013-07-11 15:22:20 +04:00
for ( i = 0 ; i < open_max ; i + + ) {
2010-05-25 15:14:06 +04:00
int f ;
int closed ;
if ( i = = fileno ( log ) )
continue ;
closed = fcntl ( i , F_GETFD , & f ) = = - 1 & &
errno = = EBADF ;
if ( ! closed )
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
fprintf ( log , " FD:%zu \n " , i ) ;
2010-05-25 15:14:06 +04:00
}
2020-07-21 13:32:10 +03:00
while ( true ) {
bool daemonized = getpgrp ( ) ! = getppid ( ) ;
if ( daemonize_check & & ! daemonized & & daemonize_retries - - > 0 ) {
usleep ( 100 * 1000 ) ;
continue ;
}
fprintf ( log , " DAEMON:%s \n " , daemonized ? " yes " : " no " ) ;
break ;
}
2011-04-29 21:14:23 +04:00
if ( ! ( cwd = getcwd ( NULL , 0 ) ) )
2014-09-03 22:59:31 +04:00
goto cleanup ;
2011-04-29 21:14:23 +04:00
if ( strlen ( cwd ) > strlen ( " .../commanddata " ) & &
2010-05-25 15:14:06 +04:00
STREQ ( cwd + strlen ( cwd ) - strlen ( " /commanddata " ) , " /commanddata " ) )
strcpy ( cwd , " .../commanddata " ) ;
2019-08-21 19:13:18 +03:00
# ifdef __APPLE__
char * noprivateprefix = NULL ;
if ( strstr ( cwd , " /private " ) )
noprivateprefix = cwd + strlen ( " /private " ) ;
else
noprivateprefix = cwd ;
fprintf ( log , " CWD:%s \n " , noprivateprefix ) ;
# else
2010-05-25 15:14:06 +04:00
fprintf ( log , " CWD:%s \n " , cwd ) ;
2019-08-21 19:13:18 +03:00
# endif
2017-09-20 14:03:47 +03:00
free ( cwd ) ;
2010-05-25 15:14:06 +04:00
2014-09-03 19:13:21 +04:00
fprintf ( log , " UMASK:%04o \n " , umask ( 0 ) ) ;
2012-06-01 01:50:07 +04:00
if ( argc > 1 & & STREQ ( argv [ 1 ] , " --close-stdin " ) ) {
if ( freopen ( " /dev/null " , " r " , stdin ) ! = stdin )
2014-09-03 22:59:31 +04:00
goto cleanup ;
2012-06-01 01:50:07 +04:00
usleep ( 100 * 1000 ) ;
}
2010-05-25 15:14:06 +04:00
fprintf ( stdout , " BEGIN STDOUT \n " ) ;
fflush ( stdout ) ;
fprintf ( stderr , " BEGIN STDERR \n " ) ;
fflush ( stderr ) ;
2019-07-25 21:22:10 +03:00
for ( i = 0 ; i < numreadfds ; i + + ) {
fds [ numpollfds ] . fd = readfds [ i ] ;
fds [ numpollfds ] . events = POLLIN ;
fds [ numpollfds ] . revents = 0 ;
numpollfds + + ;
}
2010-05-25 15:14:06 +04:00
for ( ; ; ) {
2019-07-25 21:22:10 +03:00
unsigned ctr = 0 ;
if ( poll ( fds , numpollfds , - 1 ) < 0 ) {
printf ( " poll failed: %s \n " , strerror ( errno ) ) ;
2014-09-03 22:59:31 +04:00
goto cleanup ;
2019-07-25 21:22:10 +03:00
}
for ( i = 0 ; i < numpollfds ; i + + ) {
2020-10-08 17:02:08 +03:00
short revents = POLLIN | POLLHUP | POLLERR ;
# ifdef __APPLE__
/*
* poll ( ) on / dev / null will return POLLNVAL
* Apple - Feedback : FB8785208
*/
revents | = POLLNVAL ;
# endif
if ( fds [ i ] . revents & revents ) {
2019-07-25 21:22:10 +03:00
fds [ i ] . revents = 0 ;
got = read ( fds [ i ] . fd , buf , sizeof ( buf ) ) ;
if ( got < 0 )
goto cleanup ;
if ( got = = 0 ) {
/* do not want to hear from this fd anymore */
fds [ i ] . events = 0 ;
} else {
buffers [ i ] = realloc ( buffers [ i ] , buflen [ i ] + got ) ;
if ( ! buf [ i ] ) {
fprintf ( stdout , " Out of memory! \n " ) ;
goto cleanup ;
}
memcpy ( buffers [ i ] + buflen [ i ] , buf , got ) ;
buflen [ i ] + = got ;
}
}
}
for ( i = 0 ; i < numpollfds ; i + + ) {
if ( fds [ i ] . events ) {
ctr + + ;
break ;
}
}
if ( ctr = = 0 )
2010-05-25 15:14:06 +04:00
break ;
2019-07-25 21:22:10 +03:00
}
for ( i = 0 ; i < numpollfds ; i + + ) {
2020-09-21 20:32:29 +03:00
if ( fwrite ( buffers [ i ] , 1 , buflen [ i ] , stdout ) ! = buflen [ i ] )
2014-09-03 22:59:31 +04:00
goto cleanup ;
2020-09-21 20:32:29 +03:00
if ( fwrite ( buffers [ i ] , 1 , buflen [ i ] , stderr ) ! = buflen [ i ] )
2014-09-03 22:59:31 +04:00
goto cleanup ;
2010-05-25 15:14:06 +04:00
}
fprintf ( stdout , " END STDOUT \n " ) ;
fflush ( stdout ) ;
fprintf ( stderr , " END STDERR \n " ) ;
fflush ( stderr ) ;
2014-09-03 22:59:31 +04:00
ret = EXIT_SUCCESS ;
2010-05-25 15:14:06 +04:00
2014-09-03 22:59:31 +04:00
cleanup :
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( buffers ) ; i + + )
2019-07-25 21:22:10 +03:00
free ( buffers [ i ] ) ;
2017-09-20 14:03:47 +03:00
fclose ( log ) ;
free ( newenv ) ;
2014-09-03 22:59:31 +04:00
return ret ;
2010-05-25 15:14:06 +04:00
}
2012-03-29 13:50:00 +04:00
# else
int
main ( void )
{
return EXIT_AM_SKIP ;
}
# endif