UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

#1 2004-10-18 05:00 PM

felix
Member
Registered: 2003-12-04
Posts: 171

Re: tty manipulation...

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,

Offline

#2 2004-10-18 07:56 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: tty manipulation...

I believe the STI in TIOCSTI stands for "Simulate Terminal Input"...
(And, the TIOC is "Terminal IOCtl", of course...)  Documentation
on any of the ioctl()'s is very sparse, and you're pretty much
reduced to hunting for existing code that uses it...  (But, sometimes
"man ioctl_list" gives SOME info, at least...)

Here is a quick and dirty example app that uses TIOCSTI:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main (int argc, char *argv[])
{
    char *cmd, *nl = "\n";
    int i, fd = 0;

    if (argc > 1) {
        cmd = argv[1];
    } else {
        cmd = "ls";
    }

    for (i = 0; cmd[i]; i++)
        ioctl (fd, TIOCSTI, cmd+i);

    ioctl (fd, TIOCSTI, nl);

    exit (0);
}

It will execute the given command, by outputing a newline after it...
It just uses FD 0 (stdin) to execute in your current tty, but you
should be able to open() any other tty and have it work on that
one,  instead...

I suspect your problems stem from your messing with the tty
state via tcsetattr()...  I'm unclear as to why you do that...

Offline

#3 2004-10-18 09:08 PM

Anonymous
Member
Registered: 2002-04-16
Posts: 24

Re: tty manipulation...

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main (int argc, char *argv[])
{
    char *cmd, *nl = "\n";
    int i, fd = 0;

    if (argc > 1) {
        cmd = argv[1];
    } else {
        cmd = "ls";
    }

    for (i = 0; cmd[i]; i++)
        ioctl (fd, TIOCSTI, cmd+i);

    ioctl (fd, TIOCSTI, nl);

    exit (0);
}

Offline

#4 2004-10-18 11:46 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: tty manipulation...

Offline

Board footer

Powered by FluxBB