应该将哪些字节写入pty以生成KEY_HOME?

如何解决应该将哪些字节写入pty以生成KEY_HOME?

我正在尝试测试一个ncurses应用程序。应该将哪些字节发送到pty主站,以触发KEY_RESIZE,KEY_HOME,KEY_END等的密钥代码?

下面有一些代码,我真正希望没有人会浪费时间,但是会包括完整性。此代码的行为如下:

$ perl -e "print pack('c',8)" | ./wrappty ./show-key
KEY_BACKSPACE

也就是说,如果我将0x08写入pty,则ncurses应用程序会将其视为退格键。应该写入什么字节序列以触发其他键代码?我可能会猜测一个特定的字节序列取决于终端,所以我想知道是否有ptys的标准,或者是否有一种确定正确字节序列的合理方法。

wrappty.c:

#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <unistd.h>
#ifdef __linux__
# include <pty.h>
# include <utmp.h>
#else
# include <util.h>
#endif

static void
show_data(const char *t,ssize_t s)
{
        for( ; s > 0; t++,s-- ) {
                const char *fmt = isprint(*t) ? "%c" : "0x%02x";
                fprintf(stderr,fmt,*(unsigned char *)t);
        }
        fflush(stderr);
}

static ssize_t
send_msg(int fd,int b)
{
        char buf[1024];
        if( b != EOF ) {
                write(fd,&b,1);
        }
        ssize_t s;
        while( (s = read(fd,buf,sizeof buf)) == sizeof buf ) {
                show_data(buf,s);
        }
        show_data(buf,s);
        return s;
}

static void
wait_for(int fd,const char *expect,size_t siz)
{
        int rc = 0;
        char buf[1024];
        char *a = buf;
        assert(siz < sizeof buf);
        char *end = buf + siz;

        while( a < end ) {
                ssize_t s = read(fd,a,end - a);
                char *e = a + s;
                rc += 1;
                while( a < e && *a++ == *expect++ ) {
                        ;
                }
                if( s < 1 || a < e ) {
                        fprintf(stderr,"Ivalid data\nReceived: ");
                        show_data(buf,e - buf);
                        fprintf(stderr,"\nExpected: ");
                        show_data(expect,siz);
                        fputc('\n',stderr);
                        exit(1);
                }
        }
}

void noop(int sig,siginfo_t *i,void *v) { (void)sig; (void)i; (void)v; }

int
main(int argc,char **argv)
{
        int primary,secondary,c;

        struct winsize ws = { .ws_row = 24,.ws_col = 80 };

        (void) argc;
        if( openpty(&primary,&secondary,NULL,&ws) ) {
                err(EXIT_FAILURE,"openpty");
        }
        switch( fork() ) {
        case -1:
                err(1,"fork");
                break;
        case 0:
                if( close(primary) ) {
                        err(EXIT_FAILURE,"close");
                }
                if( login_tty(secondary) ) {
                        err(EXIT_FAILURE,"login_tty");
                }
                execvp(argv[1],argv + 1);
                err(EXIT_FAILURE,"execvp %s",argv[1]);
        }
        /* Parent */
        if( close(secondary) ) {
                err(EXIT_FAILURE,"close");
        }

        /* Initialization sequence from ncurses on macos */
        char *expected = "\x1b(B\x1b)0\x1b[?1049h\x1b[1;24r\x1b[m\x0f\x1b[4l"
                "\x1b[?1h\x1b=\x1b[H\x1b[J";
        struct sigaction act;
        memset(&act,sizeof act);
        act.sa_sigaction = noop;
        if( sigaction( SIGALRM,&act,NULL ) ) {
                perror("sigaction");
                return EXIT_FAILURE;
        }
        struct timeval tp = {.tv_sec = 0,.tv_usec = 500000 };
        struct itimerval t = { .it_interval = tp,.it_value = tp };
        setitimer(ITIMER_REAL,&t,NULL);
        wait_for(primary,expected,strlen(expected));
        while( (c = getchar()) != EOF ) {
                send_msg(primary,c);
        }

        send_msg(primary,EOF);
        fputc('\n',stderr);
        return 0;
}

show-key.c:

#define _POSIX_C_SOURCE 200809L                                                    
#define _XOPEN_SOURCE 600                                                          
#define _XOPEN_SOURCE_EXTENDED                                                     
#define _DARWIN_C_SOURCE                                                           
                                                                                   
#include <ctype.h>                                                                 
#include <curses.h>                                                                
#include <err.h>                                                                   
#include <fcntl.h>                                                                 
#include <limits.h>                                                                
#include <stdlib.h>                                                                
#include <string.h>                                                                
#include <signal.h>                                                                
#include <unistd.h>                                                                
                                                                                   
int xopen(const char *path,int flags);                                            
void                                                                               
handle(int sig,void *v)                                             
{                                                                                  
        (void)i;                                                                   
        (void)v;                                                                   
        char *n = NULL;                                                            
        switch(sig) {                                                              
        case SIGHUP:  n =  "SIGHUP\n"; break;                                      
        case SIGTERM:  n = "SIGTERM\n"; break;                                     
        case SIGINT:  n =  "SIGINT\n"; break;                                      
        }                                                                          
        if(n)                                                                      
                write(2,n,strlen(n));                                            
        return;                                                                    
}                                                                                  

int                                                                                
main(int argc,char **argv)                                                        
{                                                                                  
        int r;                                                                     
        wint_t w = 0;                                                              
        if( argc > 1 ) {                                                           
                int fd = xopen(argv[1],O_WRONLY);                                 
                dup2(fd,STDERR_FILENO);                                           
        }                                                                          
        unsetenv("COLUMNS");                                                       
        unsetenv("LINES");                                                         
        struct sigaction act;                                                      
        memset(&act,sizeof act);                                               
        act.sa_sigaction = handle;                                                 
        if( sigaction( SIGTERM,NULL ) ) { perror("sigaction"); exit(1); }   
        if( sigaction( SIGINT,NULL ) ) { perror("sigaction"); exit(1); }    
        if( sigaction( SIGHUP,NULL ) ) { perror("sigaction"); exit(1); }    
        if( initscr() == NULL ) {                                                  
                err(1,"initscr");                                                 
        }                                                                          
        noecho();                                                                  
        keypad(stdscr,true);                                                      
        while( (r = get_wch(&w)) != ERR ) {                                        
                char *d = NULL;                                                    
                if( r == KEY_CODE_YES ) switch(w) {                                
                case KEY_RESIZE: d = "KEY_RESIZE"; break;                          
                case KEY_HOME: d = "KEY_HOME"; break;                              
                case KEY_END: d = "KEY_END"; break;                                
                case KEY_PPAGE: d = "KEY_PPAGE"; break;                            
                case KEY_NPAGE: d = "KEY_NPAGE"; break;                            
                case KEY_BACKSPACE: d = "KEY_BACKSPACE"; break;                    
                case KEY_DC: d = "KEY_DC"; break;                                  
                case KEY_IC: d = "KEY_IC"; break;                                  
                case KEY_BTAB: d = "KEY_BTAB"; break;                              
                case KEY_ENTER: d = "KEY_ENTER"; break;                            
                case KEY_UP: d = "KEY_UP"; break;                                  
                case KEY_DOWN: d = "KEY_DOWN"; break;                              
                case KEY_RIGHT: d = "KEY_RIGHT"; break;                            
                case KEY_LEFT: d = "KEY_LEFT"; break;                              
                }                                                                  
                if( d != NULL ) {                                                  
                        /*printw("(%s)",d);*/                                     
                        fprintf(stderr,"%s",d);                                  
                } else {                                                           
                        /*printw("%lc",w);*/                                      
                        fprintf(stderr,"%lc",w);                                 
                }                                                                  
                /*doupdate();*/                                                    
                fflush(stderr);                                                    
        } 
        endwin();                                                                  
        fprintf(stderr,"ERR\n");                                                  
        return 0;                                                                  
}                                                                                  
                                                                                   
int                                                                                
xopen(const char *path,int flags)                                                 
{                                                                                  
        int f = open(path,flags);                                                 
        if( f == -1 ) {                                                            
                perror(path);                                                      
                exit(EXIT_FAILURE);                                                
        }                                                                          
        return f;                                                                  
} 

解决方法

使用tigetstr来获取与键相对应的字符串。大多数与诅咒名称很容易相关(在getch联机帮助页中列出):

foo = tigetstr("khome"); // KEY_HOME

拥有一张桌子会很好,但是由于命名约定是直观,因此似乎没有人感到需要...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-