felix
10-18-2004, 05:00 PM
Hello,
I'm looking at tty manipulation. I tryed to figure out a application like screen (screen -x) where we can see what some user is making in other tty, but i tryed to do it without logged user confirmation (like screen require). This can be useful for me admin my server, maybe for others too. :)
I searched sources at internet, looked some man, but somethings isn't clean yet.. :(
The code is like that
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#define DEVICE "/dev/pts/3"
struct termios save_termios;
int ttysavefd = -1;
enum { RESET, DIRTY } ttystate = RESET;
int tty_dirtyterm (int fd);
int tty_reset (int fd);
int main(void){
char c;
char moo[2];
/* open device */
int fd = open(DEVICE,O_RDWR);
if(fd == -1)
{
perror("open DEVICE");
exit(1);
}
/* Unbuffered output */
setvbuf(stdout, NULL, _IONBF, 0);
/* Read input and write it to stdout */
while(1){
if(read(fd,&c,1) > 0){
c &= 255;
sprintf(moo, "%c", c);
if ( c == 127){
printf("\b \b");
fflush(stdout);
}
if ( c == 10 || c == 13){
printf("\n");
fflush(stdout);
}
putchar(c);
fflush(stdout);
//write(fd, &c, sizeof(c));
tty_dirtyterm(STDIN_FILENO);
ioctl(fd, TIOCSTI, moo);
}
else
usleep(1);
}
tty_reset(STDIN_FILENO);
close(fd);
return 0;
}
int tty_dirtyterm (int fd) {
struct termios buf;
if (tcgetattr(fd, &save_termios) < 0)
return(-1);
buf = save_termios;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSAFLUSH, &buf) <0)
return(-1);
ttystate = DIRTY;
ttysavefd = fd;
return(0);
}
int tty_reset (int fd) {
if (ttystate == RESET)
return(0);
if (tcsetattr(fd, TCSAFLUSH, &save_termios) < 0)
return(-1);
ttystate = RESET;
return(0);
}
Let's to the problems.. hehehe
1 - If I use ioctl() to send message to the original tty, it is send, but not printed in my tty as it should since i call printf() or putc() before it. If I comment ioctl() and uncomment write() then i see all that is typed at the user tty, but in the user tty only appear what he types in the some-line (overwriting what was wroten) and never executing this commands (only showing it). What i'm doing wrong ? How can i fix it ?
2 - How tty know that it should execute a command ? For example, if i send via write a "ls" it will not be executed, it will be only showed. But if i send via ioctl() it will be executed. I thinked that a \r\n that indicate that it should be executed (like a enter) but i'm wrong. How it works ?
3 - I looked at man ioctl and i couldn't find what does TIOCSTI! Someone know what it does ?
4 - Can i execute commands in the tty via write instead ioctl() ? How ?
Thks
Regards,
I'm looking at tty manipulation. I tryed to figure out a application like screen (screen -x) where we can see what some user is making in other tty, but i tryed to do it without logged user confirmation (like screen require). This can be useful for me admin my server, maybe for others too. :)
I searched sources at internet, looked some man, but somethings isn't clean yet.. :(
The code is like that
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#define DEVICE "/dev/pts/3"
struct termios save_termios;
int ttysavefd = -1;
enum { RESET, DIRTY } ttystate = RESET;
int tty_dirtyterm (int fd);
int tty_reset (int fd);
int main(void){
char c;
char moo[2];
/* open device */
int fd = open(DEVICE,O_RDWR);
if(fd == -1)
{
perror("open DEVICE");
exit(1);
}
/* Unbuffered output */
setvbuf(stdout, NULL, _IONBF, 0);
/* Read input and write it to stdout */
while(1){
if(read(fd,&c,1) > 0){
c &= 255;
sprintf(moo, "%c", c);
if ( c == 127){
printf("\b \b");
fflush(stdout);
}
if ( c == 10 || c == 13){
printf("\n");
fflush(stdout);
}
putchar(c);
fflush(stdout);
//write(fd, &c, sizeof(c));
tty_dirtyterm(STDIN_FILENO);
ioctl(fd, TIOCSTI, moo);
}
else
usleep(1);
}
tty_reset(STDIN_FILENO);
close(fd);
return 0;
}
int tty_dirtyterm (int fd) {
struct termios buf;
if (tcgetattr(fd, &save_termios) < 0)
return(-1);
buf = save_termios;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSAFLUSH, &buf) <0)
return(-1);
ttystate = DIRTY;
ttysavefd = fd;
return(0);
}
int tty_reset (int fd) {
if (ttystate == RESET)
return(0);
if (tcsetattr(fd, TCSAFLUSH, &save_termios) < 0)
return(-1);
ttystate = RESET;
return(0);
}
Let's to the problems.. hehehe
1 - If I use ioctl() to send message to the original tty, it is send, but not printed in my tty as it should since i call printf() or putc() before it. If I comment ioctl() and uncomment write() then i see all that is typed at the user tty, but in the user tty only appear what he types in the some-line (overwriting what was wroten) and never executing this commands (only showing it). What i'm doing wrong ? How can i fix it ?
2 - How tty know that it should execute a command ? For example, if i send via write a "ls" it will not be executed, it will be only showed. But if i send via ioctl() it will be executed. I thinked that a \r\n that indicate that it should be executed (like a enter) but i'm wrong. How it works ?
3 - I looked at man ioctl and i couldn't find what does TIOCSTI! Someone know what it does ?
4 - Can i execute commands in the tty via write instead ioctl() ? How ?
Thks
Regards,