|
|
|
|
|
|
#include "global.h" |
#include "file_machine.h" |
|
#if defined(HAVE_TERMIOS_H) || defined(HAVE_SYS_TERMIOS_H) || defined(__NT__) |
|
#ifdef HAVE_TERMIOS_H |
#include <termios.h> |
#elif defined(HAVE_SYS_TERMIOS_H) |
|
#include <sys/termios.h> |
#endif |
|
#include <errno.h> |
|
#ifdef HAVE_SYS_IOCTL_H |
#include <sys/ioctl.h> |
#endif |
|
#include "fdlib.h" |
#include "interpret.h" |
#include "mapping.h" |
#include "svalue.h" |
#include "stralloc.h" |
#include "operators.h" |
|
#include "module_support.h" |
|
#include "file.h" |
|
#define sp Pike_sp |
|
|
#if defined(CS5) && defined(CS6) && CS6 == CS5 |
#undef CS5 |
#endif |
#if defined(CS6) && defined(CS7) && CS7 == CS6 |
#undef CS6 |
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef THIS |
#define THIS ((struct my_file *)(Pike_fp->current_storage)) |
#define FD (THIS->box.fd) |
#define ERRNO (THIS->my_errno) |
|
#ifdef HAVE_TCGETATTR |
static int termios_bauds( int speed ) |
{ |
switch (speed) |
{ |
#define TERMIOS_SPEED(B,V) case B: return V; |
#include "termios_flags.h" |
#undef TERMIOS_SPEED |
} |
return speed; |
} |
|
|
#define c_cflag 1 |
#define c_iflag 2 |
#define c_oflag 3 |
#define c_lflag 4 |
#define TERMIOS_FLAG(where,flag,sflag) { where, flag, sflag }, |
#define TERMIOS_CHAR(cc,scc) { 0, cc, scc }, |
static const struct { |
int var; |
int val; |
const char *name; |
} termiosflags[] = { |
#include "termios_flags.h" |
}; |
#undef TERMIOS_CHAR |
#undef TERMIOS_FLAG |
#undef c_cflag |
#undef c_iflag |
#undef c_oflag |
#undef c_lflag |
|
#endif /* HAVE_TCGETATTR */ |
|
void file_tcgetattr(INT32 args) |
{ |
#ifdef HAVE_TCGETATTR |
struct termios ti; |
#endif |
unsigned int n = 0; |
|
if(FD < 0) |
Pike_error("File not open.\n"); |
|
pop_n_elems(args); |
|
#ifdef HAVE_TCGETATTR |
if (tcgetattr(FD,&ti)) |
{ |
ERRNO=errno; |
push_int(0); |
return; |
} |
|
for( n=0; n<NELEM(termiosflags); n++ ) |
{ |
push_text( termiosflags[n].name ); |
switch( termiosflags[n].var ) |
{ |
case 0: push_int( ti.c_cc[termiosflags[n].val] ); break; |
case 1: push_int( (ti.c_cflag & termiosflags[n].val) ? 1 : 0 ); break; |
case 2: push_int( (ti.c_iflag & termiosflags[n].val) ? 1 : 0 ); break; |
case 3: push_int( (ti.c_oflag & termiosflags[n].val) ? 1 : 0 ); break; |
case 4: push_int( (ti.c_lflag & termiosflags[n].val) ? 1 : 0 ); break; |
} |
} |
|
push_static_text("ospeed"); |
push_int(termios_bauds(cfgetospeed(&ti))); |
push_static_text("ispeed"); |
push_int(termios_bauds(cfgetispeed(&ti))); |
n++; |
|
#ifdef CSIZE |
push_static_text("csize"); |
switch (ti.c_cflag&CSIZE) |
{ |
#ifdef CS8 |
case CS8: push_int(8); break; |
#endif |
#ifdef CS7 |
case CS7: push_int(7); break; |
#endif |
#ifdef CS6 |
case CS6: push_int(6); break; |
#endif |
#ifdef CS5 |
case CS5: push_int(5); break; |
#endif |
default: |
push_int(-1); |
} |
n++; |
#endif |
|
#endif /* HAVE_TCGETATTR */ |
|
#ifdef TIOCGWINSZ |
{ |
struct winsize winsize; |
if (!fd_ioctl(FD, TIOCGWINSZ, &winsize)) |
{ |
push_static_text("rows"); |
push_int(winsize.ws_row); |
n++; |
push_static_text("columns"); |
push_int(winsize.ws_col); |
n++; |
} |
} |
#endif |
|
f_aggregate_mapping(n*2); |
} |
|
|
#ifdef HAVE_TCGETATTR |
static int termios_speed( int speed ) |
{ |
switch (speed) |
{ |
#define TERMIOS_SPEED(B,V) case V: return B; |
#include "termios_flags.h" |
#undef TERMIOS_SPEED |
} |
Pike_error("illegal argument 1 to tcsetattr, value of key %s is not a valid baud rate\n","ospeed"); |
} |
|
|
void file_tcsetattr(INT32 args) |
{ |
struct termios ti; |
int optional_actions=TCSANOW; |
struct svalue *tmp; |
unsigned int i; |
|
if(FD < 0) |
Pike_error("File not open.\n"); |
|
if (!args) |
SIMPLE_WRONG_NUM_ARGS_ERROR("tcsetattr", 1); |
|
if (args>1) |
{ |
if (args>2) |
pop_n_elems(args-2); |
if (TYPEOF(sp[-1]) != T_STRING) |
SIMPLE_ARG_TYPE_ERROR("tcsetattr", 2, "string"); |
|
if (!strcmp(sp[-1].u.string->str,"TCSANOW")) |
optional_actions=TCSANOW; |
else if (!strcmp(sp[-1].u.string->str,"TCSADRAIN")) |
optional_actions=TCSADRAIN; |
else if (!strcmp(sp[-1].u.string->str,"TCSAFLUSH")) |
optional_actions=TCSAFLUSH; |
else |
Pike_error("illegal argument 2 to tcsetattr\n"); |
|
pop_stack(); |
} |
|
if (TYPEOF(sp[-1]) != T_MAPPING) |
SIMPLE_ARG_TYPE_ERROR("tcsetattr", 1, "mapping"); |
|
|
if (tcgetattr(FD,&ti)) |
{ |
ERRNO=errno; |
push_int(0); |
return; |
} |
|
for( i=0; i<NELEM(termiosflags); i++ ) |
{ |
if( (tmp=simple_mapping_string_lookup( sp[-1].u.mapping, termiosflags[i].name )) ) |
{ |
if( TYPEOF(*tmp) != PIKE_T_INT ) |
Pike_error("illegal argument 1 to tcsetattr: key %s has illegal value\n",termiosflags[i].name); |
switch( termiosflags[i].var ) |
{ |
case 0: |
ti.c_cc[termiosflags[i].val] = tmp->u.integer; |
break; |
case 1: |
if( tmp->u.integer ) |
ti.c_cflag |= termiosflags[i].val; |
else |
ti.c_cflag &= ~termiosflags[i].val; |
break; |
case 2: |
if( tmp->u.integer ) |
ti.c_iflag |= termiosflags[i].val; |
else |
ti.c_iflag &= ~termiosflags[i].val; |
break; |
case 3: |
if( tmp->u.integer ) |
ti.c_oflag |= termiosflags[i].val; |
else |
ti.c_oflag &= ~termiosflags[i].val; |
break; |
case 4: |
if( tmp->u.integer ) |
ti.c_lflag |= termiosflags[i].val; |
else |
ti.c_lflag &= ~termiosflags[i].val; |
break; |
} |
} |
} |
|
#ifdef CSIZE |
if ( (tmp = simple_mapping_string_lookup( sp[-1].u.mapping, "csize" )) ) |
{ |
if (TYPEOF(*tmp) != T_INT) |
Pike_error("illegal argument 1 to tcsetattr: key %s has illegal value\n","csize"); |
|
switch (tmp->u.integer) |
{ |
#ifdef CS8 |
case 8: ti.c_cflag=(ti.c_cflag&~CSIZE)|CS8; break; |
#endif |
#ifdef CS7 |
case 7: ti.c_cflag=(ti.c_cflag&~CSIZE)|CS7; break; |
#endif |
#ifdef CS6 |
case 6: ti.c_cflag=(ti.c_cflag&~CSIZE)|CS6; break; |
#endif |
#ifdef CS5 |
case 5: ti.c_cflag=(ti.c_cflag&~CSIZE)|CS5; break; |
#endif |
default: |
Pike_error("illegal argument 1 to tcsetattr: value of key %s is not a valid char size\n","csize"); |
} |
} |
#endif |
|
|
if ( (tmp = simple_mapping_string_lookup( sp[-1].u.mapping, "ospeed" )) ) |
{ |
if (TYPEOF(*tmp) != T_INT) |
Pike_error("illegal argument 1 to tcsetattr: key %s has illegal value\n","ospeed"); |
cfsetospeed(&ti,termios_speed(tmp->u.integer)); |
} |
|
if ( (tmp = simple_mapping_string_lookup( sp[-1].u.mapping, "ispeed" )) ) |
{ |
if (TYPEOF(*tmp) != T_INT) |
Pike_error("illegal argument 1 to tcsetattr: key %s has illegal value\n","ospeed"); |
cfsetispeed(&ti,termios_speed(tmp->u.integer)); |
} |
pop_stack(); |
push_int(!tcsetattr(FD,optional_actions,&ti)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void file_tcflush(INT32 args) |
{ |
int action=TCIOFLUSH; |
|
if(args) |
{ |
struct pike_string *a, *s_tciflush, *s_tcoflush, *s_tcioflush; |
MAKE_CONSTANT_SHARED_STRING( s_tciflush, "TCIFLUSH" ); |
MAKE_CONSTANT_SHARED_STRING( s_tcoflush, "TCOFLUSH" ); |
MAKE_CONSTANT_SHARED_STRING( s_tcioflush, "TCIOFLUSH" ); |
get_all_args( NULL, args, "%S", &a ); |
if(a == s_tciflush ) |
action=TCIFLUSH; |
else if(a == s_tcoflush ) |
action=TCOFLUSH; |
|
#ifdef TCIOFLUSH |
else if(a == s_tcioflush ) |
action=TCIOFLUSH; |
#endif |
free_string( s_tcoflush ); |
free_string( s_tciflush ); |
free_string( s_tcioflush ); |
pop_stack(); |
} |
push_int(!tcflush(FD, action)); |
} |
|
|
|
|
|
|
|
|
|
|
|
void file_tcdrain(INT32 args) |
{ |
push_int(!tcdrain(FD)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void file_tcsendbreak(INT32 args) |
{ |
INT_TYPE len=0; |
|
get_all_args(NULL, args, ".%i", &len); |
pop_stack(); |
push_int(!tcsendbreak(FD, len)); |
} |
|
#endif /* HAVE_TCGETATTR */ |
|
#ifdef TIOCSWINSZ |
|
*! |
*! Set the number of rows and columns for a terminal. |
*! |
*! @returns |
*! Returns @expr{1@} on success and @expr{0@} (zero) on failure. |
*! |
*! @seealso |
*! @[tcgetattr()], @[tcsetattr()] |
*/ |
void file_tcsetsize(INT32 args) |
{ |
INT_TYPE rows; |
INT_TYPE cols; |
struct winsize winsize; |
|
get_all_args(NULL, args, "%i%i", &rows, &cols); |
|
winsize.ws_row = rows; |
winsize.ws_col = cols; |
|
push_int(!fd_ioctl(FD, TIOCSWINSZ, &winsize)); |
} |
#endif |
|
|
|
|
|
|
|
|
#endif |
|
|