scp的prompt为什么遮蔽不掉,网络编制程序Server端
分类:pc28.am神测网

scp的prompt为何掩盖不掉

非确定性信号毕竟发给什么人

事先大家早就编写制定了二个

一、函数名称:

int tcgetattr(int fd, struct termios *termios_p);

 

Linux中经过和线程本是贰个东西,在基础中都是由task_struct结构标示。
互相都以由do_fork内核函数来运营,只是调用do_fork的参数差别。
一经经过独有一个线程,那么发给该进度的功率信号鲜明只可以发给这么些线程;
非连续信号和时限信号管理函数是进度能源,那么当进度有三个线程时,数字信号毕竟发给什么人吧?
自己做了3个试验来切磋那一个难点,实验所采纳的阳台如下:

       我们都知情fork() 独有在Unix/Linux类操作系统才有!因为他俩一向不线程这一说。他们唯有子进度。

二、函数功效:

 The termios functions describe a general terminal interface that is provided to control asynchronous communications ports.

用于获取与极端相关的参数,提供异步通信接口

把scp的正儿八经输出和规范错误都重定向到叁个文件,为啥shell分界面还是能够打出"Enter windows password:"的字符串呢? 

OS: fedora 11
kernel: 2.6.29.4-167.fc11.i686.PAE
gcc: (GCC) 4.4.0 20090506 (Red Hat 4.4.0-4)

       要用到fork那么就亟须用到 waitpid() !

三、头文件

termios.h
unistd.h

scp fromfilename [email protected]:/topath/tofilename 2>&1 > /tmp/tmp.txt 

编写翻译命令:gcc -g -W -Wall -Wextra -o mytest main.c -lpthread

       waitpid函数原型:

四、返回值

0:成功
-1:错误,

Enter windows password: 

实验1
首先用上边包车型大巴代码作测验

 

五、参数表达

fd:文件呈报符
struct termios *termios_p:再次来到值保留在termios结构体中:
           tcflag_t c_iflag;      /* input modes */                                输入情势标志

           tcflag_t c_oflag;      /* output modes */                             输出

           tcflag_t c_cflag;      /* control modes */                             控制

           tcflag_t c_lflag;      /* local modes */                                 本地

           cc_t     c_cc[NCCS];   /* special characters */                      调节字符,保存中断驱动程序中的特殊字符

 

main.c:

// 2011年 11月 29日 星期二 08:37:06 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>

void *work_thread(void *);

void work();

void handler(int);

int main()
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGQUIT, &sa, 0);
    pthread_t tid;
    pthread_create(&tid, 0, work_thread, 0);
    work();
    return 0;
}

void handler(int s)
{
    char buf[32];
    snprintf(buf, sizeof(buf), "n%ld recv signal", syscall(SYS_gettid));
    psignal(s, buf);
}

void *work_thread(void *p)
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGINT, &sa, 0);

    work();
    return (void *)0;
}

void work()
{
    for(;;) {
        pause();
        fprintf(stderr, "I'm Zuro %ldn", syscall(SYS_gettid));
    }

       #include<sys/types.h>   /* 提供品类pid_t的定义 */

六、示例程序:

  1. #include <stdio.h>

  2. #include <termios.h>

  3. #include <unistd.h>
  4. #include <errno.h>
  5. int main(void)
  6. {
  7.     struct termios term; //get terminal interface
  8.     int err;
  9.     if(tcgetattr(STDIN_FILENO, &term)==-1)
  10.     {
  11.         perror("Cannot get standard input description.");
  12.         return 1;
  13.     }
  14.     term.c_cc[VEOF] = (cc_t)0x07;
  15.     err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
  16.     if(err==-1 && err==EINTR)
  17.     {
  18.         perror("Failed to change EOF character.");
  19.         return 1;
  20.     }
  21.     return 0;
  22. }

运维后得以使ctrl D不起功用,使用ctrl G取代ctrl D.

查了openssh的代码,答案很明朗了。 

}

自己在主线程里注册SIGQUIT复信号管理函数,在另一个线程里登记SIGINT实信号管理函数,
唯独当本人实行该程序时无论小编在顶峰键入Ctrl-C(发送SIGINT信号)
还是Ctrl-(发送SIGQUIT复信号),信号都是发放主线程!

       #include<sys/wait.h>

七、补充:

函数tcsetattr 能够设置串口的组织性格,tcgetatt( ) 可以拿走串口的布局特性。在termios 结构中,最主要的是c_cflag,客商通过对其实行赋值能够完毕串口波特率、数据位、甘休位、奇偶校验位等参数的设置。c_cc 数组中的五个变量VMIN 和VTIME 判定是还是不是再次回到输入,c _cc[VTIME]设定字节输入时间测量时间的装置,c _cc[VMIN]设定满意读取成效的最低接收字节数。那多少个变量的值要设定合理,工夫确认保证串口的通讯成功率。

char * 

次第输出如下:

^C
2536 recv signal: Interrupt
I'm Zuro 2536
^C
2536 recv signal: Interrupt
I'm Zuro 2536
^
2536 recv signal: Quit
I'm Zuro 2536
^
2536 recv signal: Quit

 

readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) 

I'm Zuro 2536

用kill命令杀死这么些进度。

实验2
自己把地点的主次修改一下:

       pid_twaitpid(pid_tpid, int *status, int options);

main.c:

// 2011年 11月 29日 星期二 08:37:06 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>

void *work_thread(void *);

void work();

void handler(int);

int main()
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    //sigaction(SIGQUIT, &sa, 0);
    sigaction(SIGSEGV, &sa, 0);
    pthread_t tid;
    pthread_create(&tid, 0, work_thread, 0);
    work();
    return 0;
}

void handler(int s)
{
    char buf[32];
    snprintf(buf, sizeof(buf), "n%ld recv signal", syscall(SYS_gettid));
    psignal(s, buf);
}

void *work_thread(void *p)
{
    for(;;) {
        fprintf(stderr, "I'm Zuro %ldn", syscall(SYS_gettid));
        sleep(2);
        char *p = 0;
        *p = 'a';
    }

    return (void *)0;
}

void work()
{
    for(;;) {
        pause();
        fprintf(stderr, "I'm Zuro %ldn", syscall(SYS_gettid));
    }
}

=====================================================================
今扶桑身在主线程里注册SIGSEGV时域信号管理函数,而在另贰个线程里产生一个SIGSEGV功率信号。
编写翻译实施,等一段时间后Ctrl-C终止该进程。开掘此时能量信号不再发送给主线程,
而是发送给发生SIGSEGV功率信号的那多少个线程!

实验3
自小编再把代码作一下修改:

 

ssize_t nr; 

main.c:

// 2011年 11月 29日 星期二 08:37:06 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>

void *work_thread(void *);

void work();

void handler(int);

int main()
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGQUIT, &sa, 0);
    pthread_t tid;
    pthread_create(&tid, 0, work_thread, 0);

    work();
    return 0;
}

void handler(int s)
{
    char buf[32];
    snprintf(buf, sizeof(buf), "n%ld recv signal", syscall(SYS_gettid));
    psignal(s, buf);
}

void *work_thread(void *p)
{
    /*struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGINT, &sa, 0);*/

    for(;;) {
        fprintf(stderr, "I'm Zuro %ldn", syscall(SYS_gettid));
        sleep(2);
        raise(SIGQUIT);
    }

    return (void *)0;
}

void work()
{
    for(;;) {
        pause();
        fprintf(stderr, "I'm Zuro %ldn", syscall(SYS_gettid));
    }

       参数pid=-1时,等待别的多个子进度退出,未有别的限制,此时waitpid和wait的功用同样。

int input, output, save_errno; 

}

这一次自身在主线程注册SIGQUIT实信号管理函数,而在另贰个线程
调用raise(SIGQUIT)函数发生那个时限信号。注意实验1和尝试3的
不一样:实验1的SIGQUIT信号是由终端shell发送,而实验3的实信号
是由进度本人的一个线程爆发。实验表明:数字信号不是殡葬
给主线程,而是发送给爆发SIGQUIT时限信号的线程。

综上所诉,假设时域信号是由本进程发生,那么非确定性信号发给发生那些数字信号
的线程;假如复信号是由其他进程发生,则时域信号发送给主线程。

摘自 leeshuheng的专栏

Linux中经过和线程本是叁个东西,在根本中都以由task_struct结构标示。 两个都以由do_fork内核函数来运营,只是调用do_fork的...

       参数 status大家设置为NULL。

char ch, *p, *end; 

       参数options提供了一些外加的选项来支配waitpid,WNOHANG常量表示,尽管未有子进度退出,它也会应声赶回,不会像wait那样永久等下去。

struct termios term, oterm; 

       大家希望唯有给waitpid()复信号时,才使用它!

struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; 

       那时,大家要求别的贰个函数sigaction()。

struct sigaction savetstp, savettin, savettou, savepipe; 

       sigaction函数原型:

 

       #include<signal.h>

/* I suppose we could alloc on demand in this case (XXX). */ 

 

if (bufsiz == 0) { 

   int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

errno = EINVAL; 

 

return(NULL); 

       参数 signum=SIGCHLD时,独有子进程甘休恐怕退出才实行调用。

       参数 act是三个对准sigaction结构的指针。

 

       参数 oldact一般废止不用。

restart: 

 

signo = 0; 

       大家最首要安装结构sigaction的sa_handler、sa_mask和sa_flags多少个分子变量就能够!

/* 

      

* Read and write to /dev/tty if available.  If not, read from 

       上边是自己要作为轨范遵循规则:

* stdin and write to stderr unless a tty is required. 

 /**
 * Version: 0.2
 *
 * Description: Add signal
 *
 */ 
 
#include <stdio.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netdb.h>  
#include <arpa/inet.h>  
#include <signal.h>  
#include <sys/wait.h>  
#include <stdlib.h>       /* exit declare */  
#include <unistd.h>       /* fork declare */  
 
#define SERVPORT "2349"  
 
void sigchild_handler() 

    while (waitpid(-1, NULL, WNOHANG) > 0);   

 
int main(int argc, char *argv[]) 

    struct addrinfo hints, *res; 
    int status; 
    int sockfd; 
     
    int connFd; 
    /* struct sockaddr_in cliAddr;  Only IPv4  */ 
    struct sockaddr_storage clientAddr; /* both IPv4 and IPv6 */ 
     
    struct sigaction sa; 
     
    int sendSta; 
    char *msg; 
     
    if (argc != 2) { 
        fprintf(stderr, "Usage: Not found Read File"); 
        return 1; 
    } 
     
    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE; 
     
    status = getaddrinfo(NULL, SERVPORT, &hints, &res); 
     
    if (status != 0) { 
        fprintf(stderr, "getaddrinfo, fail!"); 
        return 2; 
    } 
     
    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 
     
    bind(sockfd, res->ai_addr, res->ai_addrlen); 
     
    listen(sockfd, 5); 
     
    printf("======== Please Wait Client =========n"); 
     
    /* struct sigaction notes from POSIX:
     *
     *  (1) Routines stored in sa_handler should take a single int as
     *      their argument although the POSIX standard does not require this.
     *  (2) The fields sa_handler and sa_sigaction may overlap, and a conforming
     *      application should not use both simultaneously.
     */ 
    sa.sa_handler = sigchild_handler;    
    sigemptyset(&sa.sa_mask);   /* Additional set of signals to be blocked */ 
                                /* during execution of signal-catching function. */ 
    sa.sa_flags = SA_RESTART;   /* Special flags to affect behavior of signal */ 
                                /* SA_RESTART 0x10000000    // Restart syscall on signal return */ 
                                 
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {  /* SIGCHLD 20   // to parent on child stop or exit */ 
        fprintf(stderr, "sigaction fail!"); 
        exit(3);     
    } 
     
    while(1) { // loop forever!  
        char ipstr[INET_ADDRSTRLEN]; 
        void *addr; 
         
        int len = sizeof(clientAddr); 
        connFd = accept(sockfd, (struct sockaddr *)&clientAddr, &len); 
         
        /* View Client IP */ 
        struct sockaddr_in *ipv4 = (struct sockaddr_in *)&clientAddr; 
        addr = &(ipv4->sin_addr); 
     
        inet_ntop(AF_INET, addr, ipstr, sizeof(ipstr)); 
        printf("client: %sn", ipstr); 
         
        if (!fork()) { 
            close(sockfd);  /* child doesn't need the listener */ 
            /* Copy Data */ 
            msg = "The server simply displays a message!"; 
            sendSta = send(connFd, msg, strlen(msg), 0); 
            if (sendSta == -1) 
                fprintf(stderr, "send fail!"); 
            close(connFd); 
            exit(0); 
        } 
         
        close(connFd); 
    } 
     
    close(sockfd); 
    return 0; 

/**
 * Version: 0.2
 *
 * Description: Add signal
 *
 */

*/ 

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>  /* exit declare */
#include <unistd.h>  /* fork declare */

if ((flags & RPP_STDIN) || 

#define SERVPORT "2349"

    (input = output = open(_PATH_TTY, O_RDWR)) == -1) { 

void sigchild_handler()
{
 while (waitpid(-1, NULL, WNOHANG) > 0); 
}

if (flags & RPP_REQUIRE_TTY) { 

int main(int argc, char *argv[])
{
 struct addrinfo hints, *res;
 int status;
 int sockfd;
 
 int connFd;
 /* struct sockaddr_in cliAddr;  Only IPv4  */
 struct sockaddr_storage clientAddr; /* both IPv4 and IPv6 */
 
 struct sigaction sa;
 
 int sendSta;
 char *msg;
 
 if (argc != 2) {
  fprintf(stderr, "Usage: Not found Read File");
  return 1;
 }
 
 memset(&hints, 0, sizeof(hints));
 hints.ai_family = AF_UNSPEC;
 hints.ai_socktype = SOCK_STREAM;
 hints.ai_flags = AI_PASSIVE;
 
 status = getaddrinfo(NULL, SERVPORT, &hints, &res);
 
 if (status != 0) {
  fprintf(stderr, "getaddrinfo, fail!");
  return 2;
 }
 
 sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 
 bind(sockfd, res->ai_addr, res->ai_addrlen);
 
 listen(sockfd, 5);
 
 printf("======== Please Wait Client =========n");
 
 /* struct sigaction notes from POSIX:
   *
   *  (1) Routines stored in sa_handler should take a single int as
   *      their argument although the POSIX standard does not require this.
   *  (2) The fields sa_handler and sa_sigaction may overlap, and a conforming
   *      application should not use both simultaneously.
   */
 sa.sa_handler = sigchild_handler; 
 sigemptyset(&sa.sa_mask); /* Additional set of signals to be blocked */
                               /* during execution of signal-catching function. */
 sa.sa_flags = SA_RESTART; /* Special flags to affect behavior of signal */
        /* SA_RESTART 0x10000000  // Restart syscall on signal return */
        
 if (sigaction(SIGCHLD, &sa, NULL) == -1) { /* SIGCHLD 20 // to parent on child stop or exit */
  fprintf(stderr, "sigaction fail!");
  exit(3); 
 }
 
 while(1) { // loop forever!
  char ipstr[INET_ADDRSTRLEN];
  void *addr;
  
  int len = sizeof(clientAddr);
  connFd = accept(sockfd, (struct sockaddr *)&clientAddr, &len);
  
  /* View Client IP */
  struct sockaddr_in *ipv4 = (struct sockaddr_in *)&clientAddr;
  addr = &(ipv4->sin_addr);
 
  inet_ntop(AF_INET, addr, ipstr, sizeof(ipstr));
  printf("client: %sn", ipstr);
  
  if (!fork()) {
   close(sockfd); /* child doesn't need the listener */
   /* Copy Data */
   msg = "The server simply displays a message!";
   sendSta = send(connFd, msg, strlen(msg), 0);
   if (sendSta == -1)
    fprintf(stderr, "send fail!");
   close(connFd);
   exit(0);
  }
  
  close(connFd);
 }
 
 close(sockfd);
 return 0;
}

errno = ENOTTY; 

 

return(NULL); 

End.

 摘自 xiaobin_HLJ80的专栏

input = STDIN_FILENO; 

大家都清楚fork() 唯有在Unix/Linux类...

output = STDERR_FILENO; 

 

/* 

* Catch signals that would otherwise cause the user to end 

* up with echo turned off in the shell.  Don't worry about 

* things like SIGXCPU and SIGVTALRM for now. 

*/ 

sigemptyset(&sa.sa_mask); 

sa.sa_flags = 0; /* don't restart system calls */ 

sa.sa_handler = handler; 

(void)sigaction(SIGALRM, &sa, &savealrm); 

(void)sigaction(SIGHUP, &sa, &savehup); 

(void)sigaction(SIGINT, &sa, &saveint); 

(void)sigaction(SIGPIPE, &sa, &savepipe); 

(void)sigaction(SIGQUIT, &sa, &savequit); 

(void)sigaction(SIGTERM, &sa, &saveterm); 

(void)sigaction(SIGTSTP, &sa, &savetstp); 

(void)sigaction(SIGTTIN, &sa, &savettin); 

(void)sigaction(SIGTTOU, &sa, &savettou); 

 

/* Turn off echo if possible. */ 

if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { 

memcpy(&term, &oterm, sizeof(term)); 

if (!(flags & RPP_ECHO_ON)) 

term.c_lflag &= ~(ECHO | ECHONL); 

#ifdef VSTATUS 

if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) 

term.c_cc[VSTATUS] = _POSIX_VDISABLE; 

#endif 

(void)tcsetattr(input, _T_FLUSH, &term); 

} else { 

memset(&term, 0, sizeof(term)); 

term.c_lflag |= ECHO; 

memset(&oterm, 0, sizeof(oterm)); 

oterm.c_lflag |= ECHO; 

 

if (!(flags & RPP_STDIN)) 

(void)write(output, prompt, strlen(prompt));

         end = buf bufsiz - 1; 

for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != 'n' && ch != 'r';) { 

if (p < end) { 

if ((flags & RPP_SEVENBIT)) 

ch &= 0x7f; 

if (isalpha(ch)) { 

if ((flags & RPP_FORCELOWER)) 

ch = tolower(ch); 

if ((flags & RPP_FORCEUPPER)) 

ch = toupper(ch); 

*p = ch; 

 

scp会运营二个ssh子进程来变成连接鉴权. 

13996 root       0:00 /usr/local/bin/ssh -x -oForwardAgent no -oPermitLocalCommand no -oClearAllForwardings yes -lusername x.x.x.x scp -t /topath/tofilename 

[email protected][]:/proc/13996/fd> ls -lrt 

total 0 

lrwx------    1 root     root            64 Jan  4 04:12 9 -> /tmp/lock/lock9997 

lrwx------    1 root     root            64 Jan  4 04:12 6 -> /dev/tty 

lrwx------    1 root     root            64 Jan  4 04:12 5 -> socket:[158339] 

lrwx------    1 root     root            64 Jan  4 04:12 4 -> socket:[158338] 

lrwx------    1 root     root            64 Jan  4 04:12 3 -> socket:[160359] 

lrwx------    1 root     root            64 Jan  4 04:12 2 -> /dev/pts/0 

l-wx------    1 root     root            64 Jan  4 04:12 1 -> pipe:[160353] 

lr-x------    1 root     root            64 Jan  4 04:12 0 -> pipe:[160352] 

 

而后可见,ssh正是通过file descriptor 6直接写/dev/tty来把prompt突显到shell分界面的,和规范输出1/标准错误2从未有过任何关系。 

lrwx------    1 root     root            64 Jan  4 04:12 6 -> /dev/tty

 

把scp的正式输出和标准错误都重定向到一个文件,为何shell分界面仍是可以打出Enter windows password:的字符串呢? scp fromf...

本文由pc28.am发布于pc28.am神测网,转载请注明出处:scp的prompt为什么遮蔽不掉,网络编制程序Server端

上一篇:cygwin使用体验,编写翻译运转总体Java工程 下一篇:没有了
猜你喜欢
热门排行
精彩图文