Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 45 46 47 48 49 50 51  52 53 54 55 56 57 58 ... 87
     *      ввода/вывода select() и псевдотерминал (пара ttyp+ptyp).
     */

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include   /* NOFILE */
    #include 
    #include 
    #include 

    #ifdef TERMIOS
    # include 
    # define TERMIO struct termios
    # define GTTY(fd, tadr)  tcgetattr(fd, tadr)
    # define STTY(fd, tadr)  tcsetattr(fd, TCSADRAIN, tadr)
    #else
    # include 
    # define TERMIO struct termio
    # define GTTY(fd, tadr) ioctl(fd, TCGETA,  tadr)
    # define STTY(fd, tadr) ioctl(fd, TCSETAW, tadr)
    #endif

А. Богатырев, 1992-95                  - 263 -                              Си в UNIX

    #ifdef __SVR4
    # include    /* STREAMS i/o */
    extern char *ptsname();
    #endif

    #if defined(ISC2_2)
    # include 
    #else
    # include 
    #endif

    #ifndef BSIZE
    # define BSIZE 512
    #endif

    #define LOGFILE         "/usr/spool/scriptlog"
    #define max(a,b)        ((a) > (b) ? (a) : (b))
    extern int errno;
    TERMIO told, tnew, ttypmodes;
    FILE *fpscript = NULL;  /* файл с трассировкой (если надо) */
    int go = 0;

    int scriptflg  = 0;
    int halfflag   = 0;      /* HALF DUPLEX */
    int autoecho   = 0;
    char *protocol = "typescript";

    #define STDIN   0 /* fileno(stdin)   */
    #define STDOUT  1 /* fileno(stdout)  */
    #define STDERR  2 /* fileno(stderr)  */

    /* какие каналы связаны с терминалом? */
    int tty_stdin, tty_stdout, tty_stderr;
    int TTYFD;

    void wm_checkttys(){
            TERMIO t;
            tty_stdin  = ( GTTY(STDIN,  &t) >= 0 );
            tty_stdout = ( GTTY(STDOUT, &t) >= 0 );
            tty_stderr = ( GTTY(STDERR, &t) >= 0 );

            if     ( tty_stdin  )  TTYFD = STDIN;
            else if( tty_stdout )  TTYFD = STDOUT;
            else if( tty_stderr )  TTYFD = STDERR;
            else {
                    fprintf(stderr, "Cannot access tty\n");
                    exit(7);
            }
    }

А. Богатырев, 1992-95                  - 264 -                              Си в UNIX

    /* Описатель трассируемого процесса */
    struct ptypair {
            char line[25];          /* терминальная линия: /dev/ttyp? */
            int pfd;                /* дескриптор master pty          */
            long in_bytes;          /* прочтено байт с клавиатуры     */
            long out_bytes;         /* послано байт на экран          */
            int pid;                /* идентификатор процесса         */
            time_t t_start, t_stop; /* время запуска и окончания      */
            char *command;          /* запущенная команда             */
    } PP;

    /* Эта функция вызывается при окончании трассируемого процесса -
     * по сигналу SIGCLD
     */
    char Reason[128];
    void ondeath(sig){
            int pid;
            extern void wm_done();
            int status;
            int fd;

            /* выявить причину окончания процесса */
            while((pid = wait(&status)) > 0 ){
              if( WIFEXITED(status))
                  sprintf( Reason, "Pid %d died with retcode %d",
                                        pid, WEXITSTATUS(status));
                else if( WIFSIGNALED(status)) {
                  sprintf( Reason, "Pid %d killed by signal #%d",
                                        pid, WTERMSIG(status));
    #ifdef WCOREDUMP
                  if(WCOREDUMP(status)) strcat( Reason, " Core dumped" );
    #endif
                } else if( WIFSTOPPED(status))
                  sprintf( Reason, "Pid %d suspended by signal #%d",
                                        pid, WSTOPSIG(status));
            }
            wm_done(0);
    }

    void wm_init(){
            wm_checkttys();

            GTTY(TTYFD, &told);

            /* Сконструировать "сырой" режим для нашего _базового_ терминала */
            tnew = told;

            tnew.c_cc[VINTR]  = '\0';
            tnew.c_cc[VQUIT]  = '\0';
            tnew.c_cc[VERASE] = '\0';
            tnew.c_cc[VKILL]  = '\0';
    #ifdef VSUSP
            tnew.c_cc[VSUSP]  = '\0';
    #endif

А. Богатырев, 1992-95                  - 265 -                              Си в UNIX

            /* CBREAK */
            tnew.c_cc[VMIN]   = 1;
            tnew.c_cc[VTIME]  = 0;

            tnew.c_cflag &= ~(PARENB|CSIZE);
            tnew.c_cflag |=   CS8;
            tnew.c_iflag &= ~(ISTRIP|ICRNL);
            tnew.c_lflag &= ~(ICANON|ECHO|ECHOK|ECHOE|XCASE);

            tnew.c_oflag &= ~OLCUC;
            /* но оставить c_oflag ONLCR и TAB3, если они были */

            /* моды для псевдотерминала */
            ttypmodes = told;
            /* не выполнять преобразования на выводе:
             * ONLCR:       \n --> \r\n
             * TAB3:        \t --> пробелы
             */
            ttypmodes.c_oflag &= ~(ONLCR|TAB3);

            (void) signal(SIGCLD, ondeath);
    }

    void wm_fixtty(){
            STTY(TTYFD, &tnew);
    }
    void wm_resettty(){
            STTY(TTYFD, &told);
    }

    /* Подобрать свободный псевдотерминал для трассируемого процесса */
    struct ptypair wm_ptypair(){
            struct ptypair p;

    #ifdef __SVR4
            p.pfd = (-1); p.pid = 0;
            p.in_bytes = p.out_bytes = 0;

            /* Открыть master side пары pty (еще есть slave) */
            if((p.pfd = open( "/dev/ptmx", O_RDWR)) < 0 ){
                /* Это клонируемый STREAMS driver.
                 * Поскольку он клонируемый, то есть создающий новое псевдоустройство
                 * при каждом открытии, то на master-стороне может быть только
                 * единственный процесс!
                 */
                perror( "Open /dev/ptmx" );
                goto err;
            }

А. Богатырев, 1992-95                  - 266 -                              Си в UNIX

    # ifdef notdef
            /* Сделать права доступа к slave-стороне моими. */
            if( grantpt (p.pfd) < 0 ){
                    perror( "grantpt");
                    exit(errno);
            }
    # endif
            /* Разблокировать slave-сторону псевдотерминала:
               позволить первый open() для нее */
            if( unlockpt(p.pfd) < 0 ){
                    perror( "unlockpt");
                    exit(errno);
            }

            /* Получить и записать имя нового slave-устройства-файла. */
            strcpy( p.line, ptsname(p.pfd));

    #else
            register i;
            char c;
            struct stat st;

            p.pfd = (-1); p.pid = 0;
            p.in_bytes = p.out_bytes = 0;

            strcpy( p.line, "/dev/ptyXX" );

            for( c = 'p'; c <= 's'; c++ ){
                    p.line[ strlen("/dev/pty") ] = c;
                    p.line[ strlen("/dev/ptyp")] = '0';
                    if( stat(p.line, &st) < 0 )
                            goto err;
                    for(i=0; i < 16; i++){
                            p.line[ strlen("/dev/ptyp") ] =
                                    "0123456789abcdef" [i] ;
                            if((p.pfd = open( p.line, O_RDWR )) >= 0 ){
                                    p.line[ strlen("/dev/") ] = 't';
                                    return p;
                            }
                    }
            }
    #endif
    err:    return p;
    }

А. Богатырев, 1992-95                  - 267 -                              Си в UNIX

    /* Ведение статистики по вызовам script */
    void write_stat( in_bytes, out_bytes, time_here , name, line, at )
            long in_bytes, out_bytes;
            time_t time_here;
            char *name;
            char *line;
            char *at;
    {
            FILE *fplog;
            struct flock lock;

            if((fplog = fopen( LOGFILE, "a" )) == NULL )
                    return;

            lock.l_type   = F_WRLCK;
            lock.l_whence = 0;
            lock.l_start  = 0;
            lock.l_len    = 0;  /* заблокировать весь файл */
            fcntl  ( fileno(fplog), F_SETLKW, &lock );

            fprintf( fplog, "%s (%s) %ld bytes_in %ld bytes_out %ld secs %s %s %s",
                             PP.command, Reason, in_bytes, out_bytes,
                             time_here, name, line, at );
            fflush ( fplog );

            lock.l_type = F_UNLCK;
            lock.l_whence = 0;
            lock.l_start  = 0;
            lock.l_len    = 0;  /* разблокировать весь файл */
            fcntl  ( fileno(fplog), F_SETLK, &lock );

            fclose ( fplog );
    }

    void wm_done(sig){
            char *getlogin(), *getenv(), *logname = getlogin();
            time( &PP.t_stop );  /* запомнить время окончания */

            wm_resettty();   /* восстановить режим базового терминала */
            if( fpscript )
                    fclose(fpscript);
            if( PP.pid > 0 ) kill( SIGHUP, PP.pid ); /* "обрыв связи" */

            if( go ) write_stat( PP.in_bytes, PP.out_bytes,
                                 PP.t_stop - PP.t_start,
                                 logname ? logname : getenv("LOGNAME"),
                                 PP.line, ctime(&PP.t_stop) );
            printf( "\n" );
            exit(0);
    }

А. Богатырев, 1992-95                  - 268 -                              Си в UNIX

    /* Запуск трассируемого процесса на псевдотерминале */
    void wm_startshell (ac, av)
            char **av;
    {
            int child, fd, sig;

            if( ac == 0 ){
                    static char *avshell[] = { "/bin/sh", "-i", NULL };
                    av = avshell;
            }
            if((child = fork()) < 0 ){
                    perror("fork");
                    wm_done(errno);
            }
            if( child == 0 ){       /* SON */
                    if( tty_stdin )
                            setpgrp(); /* отказ от управляющего терминала */

                    /* получить новый управляющий терминал */
                    if((fd = open( PP.line, O_RDWR )) < 0 ){
                            exit(errno);
                    }

                    /* закрыть лишние каналы */
                    if( fpscript )
                            fclose(fpscript);
                    close( PP.pfd );

    #ifdef __SVR4
                    /* Push pty compatibility modules onto stream */
                    ioctl(fd, I_PUSH, "ptem");     /* pseudo tty module */
                    ioctl(fd, I_PUSH, "ldterm");   /* line discipline module */
                    ioctl(fd, I_PUSH, "ttcompat"); /* BSD ioctls module */
    #endif

                    /* перенаправить каналы, связанные с терминалом */
                    if( fd != STDIN  && tty_stdin  ) dup2(fd, STDIN);
                    if( fd != STDOUT && tty_stdout ) dup2(fd, STDOUT);
                    if( fd != STDERR && tty_stderr ) dup2(fd, STDERR);
                    if( fd > STDERR )
                        (void) close(fd);

                    /* установить моды терминала */
                    STTY(TTYFD, &ttypmodes);

                    /* восстановить реакции на сигналы */
                    for(sig=1; sig < NSIG; sig++)
                            signal( sig, SIG_DFL );

                    execvp(av[0], av);
                    system( "echo OBLOM > HELP.ME");
                    perror("execl");
                    exit(errno);

А. Богатырев, 1992-95                  - 269 -                              Си в UNIX

            } else {                /* FATHER */
Предыдущая страница Следующая страница
1 ... 45 46 47 48 49 50 51  52 53 54 55 56 57 58 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама