2015-07-30 19:49:42 +03:00
/*
* Copyright ( c ) 1993 , 1994 , 1995 , 1996 Rick Sladkey < jrs @ world . std . com >
* Copyright ( c ) 1996 - 1999 Wichert Akkerman < wichert @ cistron . nl >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "defs.h"
# include <poll.h>
# include "xlat/pollflags.h"
2015-07-30 22:46:11 +03:00
static void
print_pollfd ( struct tcb * tcp , const struct pollfd * fds )
{
tprints ( " {fd= " ) ;
printfd ( tcp , fds - > fd ) ;
if ( fds - > fd > = 0 ) {
tprints ( " , events= " ) ;
printflags ( pollflags , fds - > events , " POLL??? " ) ;
}
tprints ( " } " ) ;
}
2015-07-30 19:49:42 +03:00
static int
2015-07-30 22:46:11 +03:00
decode_poll_entering ( struct tcb * tcp )
2015-07-30 19:49:42 +03:00
{
struct pollfd fds ;
2015-07-30 22:46:11 +03:00
const unsigned int nfds = tcp - > u_arg [ 1 ] ;
const unsigned long size = sizeof ( fds ) * nfds ;
const unsigned long start = tcp - > u_arg [ 0 ] ;
const unsigned long end = start + size ;
unsigned long cur , abbrev_end ;
2015-07-30 19:49:42 +03:00
2015-07-30 22:46:11 +03:00
if ( ! verbose ( tcp ) | | ! start | | ! nfds | |
size / sizeof ( fds ) ! = nfds | | end < start ) {
printaddr ( start ) ;
tprintf ( " , %u, " , nfds ) ;
return 0 ;
}
if ( abbrev ( tcp ) ) {
abbrev_end = start + max_strlen * sizeof ( fds ) ;
if ( abbrev_end < start )
2015-07-30 19:49:42 +03:00
abbrev_end = end ;
2015-07-30 22:46:11 +03:00
} else {
abbrev_end = end ;
}
if ( start > = abbrev_end | | umove ( tcp , start , & fds ) < 0 ) {
printaddr ( start ) ;
tprintf ( " , %u, " , nfds ) ;
return 0 ;
}
tprints ( " [ " ) ;
print_pollfd ( tcp , & fds ) ;
for ( cur = start + sizeof ( fds ) ; cur < end ; cur + = sizeof ( fds ) ) {
tprints ( " , " ) ;
if ( cur > = abbrev_end ) {
tprints ( " ... " ) ;
break ;
2015-07-30 19:49:42 +03:00
}
2015-07-30 22:46:11 +03:00
if ( umove ( tcp , cur , & fds ) < 0 ) {
tprints ( " ??? " ) ;
break ;
2015-07-30 19:49:42 +03:00
}
2015-07-30 22:46:11 +03:00
print_pollfd ( tcp , & fds ) ;
}
tprintf ( " ], %u, " , nfds ) ;
return 0 ;
}
static int
decode_poll_exiting ( struct tcb * tcp , const long pts )
{
struct pollfd fds ;
const unsigned int nfds = tcp - > u_arg [ 1 ] ;
const unsigned long size = sizeof ( fds ) * nfds ;
const unsigned long start = tcp - > u_arg [ 0 ] ;
const unsigned long end = start + size ;
unsigned long cur , abbrev_end ;
static char outstr [ 1024 ] ;
char * outptr ;
2015-07-30 19:49:42 +03:00
# define end_outstr (outstr + sizeof(outstr))
2015-07-30 22:46:11 +03:00
if ( syserror ( tcp ) )
return 0 ;
if ( tcp - > u_rval = = 0 ) {
tcp - > auxstr = " Timeout " ;
return RVAL_STR ;
}
2015-07-30 19:49:42 +03:00
2015-07-30 22:46:11 +03:00
if ( ! verbose ( tcp ) | | ! start | | ! nfds | |
size / sizeof ( fds ) ! = nfds | | end < start )
return 0 ;
if ( abbrev ( tcp ) ) {
abbrev_end = start + max_strlen * sizeof ( fds ) ;
if ( abbrev_end < start )
2015-07-30 19:49:42 +03:00
abbrev_end = end ;
2015-07-30 22:46:11 +03:00
} else {
abbrev_end = end ;
}
2015-07-30 19:49:42 +03:00
2015-07-30 22:46:11 +03:00
outptr = outstr ;
for ( cur = start ; cur < end ; cur + = sizeof ( fds ) ) {
if ( umove ( tcp , cur , & fds ) < 0 ) {
if ( outptr = = outstr )
2015-07-30 19:49:42 +03:00
* outptr + + = ' [ ' ;
2015-07-30 22:46:11 +03:00
else
outptr = stpcpy ( outptr , " , " ) ;
outptr = stpcpy ( outptr , " ??? " ) ;
break ;
2015-07-30 19:49:42 +03:00
}
2015-07-30 22:46:11 +03:00
if ( ! fds . revents )
continue ;
if ( outptr = = outstr )
* outptr + + = ' [ ' ;
else
outptr = stpcpy ( outptr , " , " ) ;
if ( cur > = abbrev_end ) {
outptr = stpcpy ( outptr , " ... " ) ;
break ;
2015-07-30 19:49:42 +03:00
}
2015-07-30 22:46:11 +03:00
static const char fmt [ ] = " {fd=%d, revents= " ;
char fdstr [ sizeof ( fmt ) + sizeof ( int ) * 3 ] ;
sprintf ( fdstr , fmt , fds . fd ) ;
2015-07-30 19:49:42 +03:00
2015-07-30 22:46:11 +03:00
const char * flagstr = sprintflags ( " " , pollflags , fds . revents ) ;
if ( outptr + strlen ( fdstr ) + strlen ( flagstr ) + 1
2015-08-01 11:34:57 +03:00
> = end_outstr - sizeof ( " , ...], ... " ) ) {
2015-07-30 22:46:11 +03:00
outptr = stpcpy ( outptr , " ... " ) ;
break ;
}
outptr = stpcpy ( outptr , fdstr ) ;
outptr = stpcpy ( outptr , flagstr ) ;
* outptr + + = ' } ' ;
}
if ( outptr ! = outstr )
* outptr + + = ' ] ' ;
* outptr = ' \0 ' ;
if ( pts ) {
char tmbuf [ TIMESPEC_TEXT_BUFSIZE ] ;
sprint_timespec ( tmbuf , tcp , pts ) ;
if ( outptr + sizeof ( " , left " ) + strlen ( tmbuf ) < end_outstr ) {
outptr = stpcpy ( outptr , outptr = = outstr ? " left " : " , left " ) ;
outptr = stpcpy ( outptr , tmbuf ) ;
} else {
outptr = stpcpy ( outptr , " , ... " ) ;
}
2015-07-30 19:49:42 +03:00
}
2015-07-30 22:46:11 +03:00
if ( outptr = = outstr )
return 0 ;
tcp - > auxstr = outstr ;
return RVAL_STR ;
# undef end_outstr
2015-07-30 19:49:42 +03:00
}
SYS_FUNC ( poll )
{
if ( entering ( tcp ) ) {
2015-07-30 22:46:11 +03:00
int rc = decode_poll_entering ( tcp ) ;
2015-07-30 19:49:42 +03:00
# ifdef INFTIM
2015-07-30 19:54:31 +03:00
if ( INFTIM = = ( int ) tcp - > u_arg [ 2 ] )
2015-07-30 19:49:42 +03:00
tprints ( " INFTIM " ) ;
else
# endif
2015-07-30 19:54:31 +03:00
tprintf ( " %d " , ( int ) tcp - > u_arg [ 2 ] ) ;
2015-07-30 22:46:11 +03:00
return rc ;
} else {
return decode_poll_exiting ( tcp , 0 ) ;
2015-07-30 19:49:42 +03:00
}
}
SYS_FUNC ( ppoll )
{
if ( entering ( tcp ) ) {
2015-07-30 22:46:11 +03:00
int rc = decode_poll_entering ( tcp ) ;
2015-07-30 19:49:42 +03:00
print_timespec ( tcp , tcp - > u_arg [ 2 ] ) ;
tprints ( " , " ) ;
/* NB: kernel requires arg[4] == NSIG / 8 */
print_sigset_addr_len ( tcp , tcp - > u_arg [ 3 ] , tcp - > u_arg [ 4 ] ) ;
tprintf ( " , %lu " , tcp - > u_arg [ 4 ] ) ;
2015-07-30 22:46:11 +03:00
return rc ;
} else {
return decode_poll_exiting ( tcp , tcp - > u_arg [ 2 ] ) ;
2015-07-30 19:49:42 +03:00
}
}