#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <sys/ioctl.h>
#include <sys/stat.h>
#if defined(__DARWIN__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/ttycom.h>
#endif
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
typedef SV * Term_TtyWrite;
MODULE = Term::TtyWrite PACKAGE = Term::TtyWrite
void
DESTROY(obj)
Term_TtyWrite obj
CODE:
SV **svp;
if ((svp = hv_fetchs((HV*)obj, "fd", FALSE))) {
if (SvOK(*svp) && SvIOK(*svp))
close((int) SvIV(*svp));
}
Term_TtyWrite
new(...)
INIT:
char *classname, *devname;
int fd, i;
STRLEN len;
if ( sv_isobject(ST(0)) ) {
classname = HvNAME(SvSTASH(SvRV(ST(0))));
} else {
classname = (char *)SvPV_nolen(ST(0));
}
CODE:
RETVAL = (Term_TtyWrite)newHV();
if (items != 2 || !SvPOK(ST(1)))
Perl_croak(aTHX_ "Usage: Term::TtyWrite->new(\"/dev/sometty\")\n");
devname = SvPV(ST(1),len);
for (i = 0; i < len; i++) {
if (devname[i] == '\0')
Perl_croak(aTHX_ "invalid device name\n");
}
if ((fd = open(devname, O_WRONLY)) < 0)
Perl_croak(aTHX_ "could not open '%s': %s", devname, strerror(errno));
hv_stores((HV *)RETVAL, "fd", newSViv(fd) );
OUTPUT:
RETVAL
void
write(obj, ...)
Term_TtyWrite obj
INIT:
if (items != 2 || !SvPOK(ST(1)))
Perl_croak(aTHX_ "Usage: $obj->write(\"some data\")");
CODE:
char *str;
int fd;
STRLEN len;
SV **svp;
if ((svp = hv_fetchs((HV*)obj, "fd", FALSE))) {
if (SvOK(*svp) && SvIOK(*svp)) {
fd = (int) SvIV(*svp);
str = SvPV(ST(1),len);
while(len-- > 0) {
ioctl(fd, TIOCSTI, str++);
}
} else {
Perl_croak(aTHX_ "fd unexpectedly is not set");
}
}
void
write_delay(obj, ...)
Term_TtyWrite obj
INIT:
if (items != 3 || !SvPOK(ST(1)) || !SvNIOK(ST(2)))
Perl_croak(aTHX_ "Usage: $obj->write_delay(\"some data\", 250)");
CODE:
char *str;
int fd;
IV delayms;
STRLEN len;
SV **svp;
useconds_t delay;
if ((svp = hv_fetchs((HV*)obj, "fd", FALSE))) {
if (SvOK(*svp) && SvIOK(*svp)) {
fd = (int) SvIV(*svp);
str = SvPV(ST(1),len);
delayms = SvIV(ST(2));
if (delayms > UINT_MAX / 1000) delayms = UINT_MAX / 1000;
delay = delayms * 1000;
while(len-- > 0) {
ioctl(fd, TIOCSTI, str++);
usleep(delay);
}
} else {
Perl_croak(aTHX_ "fd unexpectedly is not set");
}
}