您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

使用popen()通过套接字执行命令

使用popen()通过套接字执行命令

警告: 这可能(或可能不)满足您的需求,因为我在下面的更正代码中反转了客户端和服务器循环的含义。正如我在上面的评论中提到的:

像这样的应用程序的正常方向是,客户端连接到服务器,并且客户端将命令[从stdin] 读取到服务器[这样做popen]并反馈结果。就是这样ssh。您的方向相反。您所拥有的是您开火sshd并等待ssh连接,然后sshd将命令发送至ssh。换句话说,应切换各侧的回路。

扭转这种局面是使事情对我有意义的唯一途径。如果在您想要的用例中逆转无法正常进行,则下面的代码可能仍会为您提供一些建议。

我通过引入 标记 字符的概念来表示输出结束来解决挂起问题。我从PPP[点对点]协议中借用了这个概念RS-232

标志字符只是一个给定的值(例如0x10),不太可能是正常数据的一部分。由于您的数据很有可能是asciiutf-8,因此0x00-0x1F可以使用该范围内的任何[未使用]字符(即,不要使用tab,cr,换行符等)。

如果您 需要 发送标志字符(即您的数据必须是完整的二进制范围0x00-0xFF),我已经包括了一些实现PPP上面使用的转义码的数据包编码/解码例程。我编写它们,但实际上并没有钩他们。在这种情况下,该标志[和逃生]字符可以是任意 的二进制值通常0xFF0xFE分别。

为简单起见,我将双方合并为一个.c文件。用-s[first] 调用服务器。

无论如何,这是经过测试的代码[请原谅免费的样式清理]:

// inetpair/inetpair -- server/client communication

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

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef unsigned char byte;

#define BUFMAX          1024
int port = 1234;
int opt_svr;
int opt_debug;

#define FLAG            0x10
#define ESC             0x11
#define ESC_FLAG        0x01
#define ESC_ESC         0x02

#define dbgprt(_fmt...) \
    do { \
        if (opt_debug) \
            printf(_fmt); \
    } while (0)

// client
int
client(void)
{
    int sock;
    struct sockaddr_in serv = { 0 };
    char *cp;
    char buf[BUFMAX + 1];
    int nread;
    int flag;
    int exitflg;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    serv.sin_family = AF_INET;
    serv.sin_port = htons(port);
    serv.sin_addr.s_addr = inet_addr("127.0.0.1");

    connect(sock, (struct sockaddr *) &serv, sizeof(serv));

    while (1) {
        cp = fgets(buf,BUFMAX,stdin);
        if (cp == NULL)
            break;

        exitflg = (strcmp(buf,"exit\n") == 0);

        // send the command
        nread = strlen(buf);
        write(sock, buf, nread);

        if (exitflg)
            break;

        while (1) {
            dbgprt("client: PREREAD\n");
            nread = read(sock, buf, 1024);
            dbgprt("client: POSTREAD nread=%d\n",nread);
            if (nread <= 0)
                break;

            cp = memchr(buf,FLAG,nread);
            flag = (cp != NULL);
            if (flag)
                nread = cp - buf;

            write(1,buf,nread);

            if (flag)
                break;
        }
    }

    close(sock);

    return 0;
}

// server
int
server(void)
{
    struct sockaddr_in serv_addr = { 0 };
    int sock;
    int acc_sock;
    char buf[BUFMAX + 1];
    char command[BUFMAX + 1];
    ssize_t nread;
    FILE *pin;
    FILE *xfin;
    char *cp;
    struct sockaddr_in cli_addr = { 0 };

    opt_debug = ! opt_debug;

    dbgprt("[+] Starting\n");

    sock = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(port);
    bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

    listen(sock, 128);

    while (1) {
        socklen_t cli_addrlen = sizeof(cli_addr);

        dbgprt("[+] Waiting for connection\n");
        acc_sock = accept(sock,(struct sockaddr *)&cli_addr,&cli_addrlen);

        dbgprt("[+] Connected\n");

        xfin = fdopen(acc_sock,"r");

        while (1) {
            dbgprt("[+] Waiting for command\n");

            cp = fgets(buf,BUFMAX,xfin);
            if (cp == NULL)
                break;

            cp = strchr(buf,'\n');
            if (cp != NULL)
                *cp = 0;

            dbgprt("[+] Command '%s'\n",buf);

            if (strcmp(buf,"exit") == 0)
                break;

            pin = popen(buf, "r");
            while (1) {
                cp = fgets(command, BUFMAX, pin);
                if (cp == NULL)
                    break;
                nread = strlen(command);
                write(acc_sock, command, nread);
            }
            pclose(pin);

            command[0] = FLAG;
            write(acc_sock,command,1);
        }

        fclose(xfin);
        close(acc_sock);

        dbgprt("[+] Disconnect\n");
    }
}

// packet_encode -- encode packet
// RETURNS: (outlen << 1)
int
packet_encode(void *dst,const void *src,int srclen)
{
    const byte *sp = src;
    byte *dp = dst;
    const byte *ep;
    byte chr;
    int dstlen;

    // encode packet in manner similar to PPP (point-to-point) protocol does
    // over RS-232 line

    ep = sp + srclen;
    for (;  sp < ep;  ++sp) {
        chr = *sp;

        switch (chr) {
        case FLAG:
            *dp++ = ESC;
            *dp++ = ESC_FLAG;
            break;

        case ESC:
            *dp++ = ESC;
            *dp++ = ESC_ESC;
            break;

        default:
            *dp++ = chr;
            break;
        }
    }

    dstlen = dp - (byte *) dst;
    dstlen <<= 1;

    return dstlen;
}

// packet_decode -- decode packet
// RETURNS: (outlen << 1) | flag
int
packet_decode(void *dst,const void *src,int srclen)
{
    const byte *sp = src;
    byte *dp = dst;
    const byte *ep;
    byte chr;
    int flag;
    int dstlen;

    // decode packet in manner similar to PPP (point-to-point) protocol does
    // over RS-232 line

    ep = sp + srclen;
    flag = 0;
    while (sp < ep) {
        chr = *sp++;

        flag = (chr == FLAG);
        if (flag)
            break;

        switch (chr) {
        case ESC:
            chr = *sp++;

            switch (chr) {
            case ESC_FLAG:
                *dp++ = FLAG;
                break;
            case ESC_ESC:
                *dp++ = ESC;
                break;
            }
            break;

        default:
            *dp++ = chr;
            break;
        }
    }

    dstlen = dp - (byte *) dst;
    dstlen <<= 1;

    if (flag)
        dstlen |= 0x01;

    return dstlen;
}

int
main(int argc, char **argv)
{
    char *cp;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        case 'd':
            opt_debug = 1;
            break;

        case 'P':
            port = atoi(cp + 2);
            break;

        case 's':
            opt_svr = 1;
            break;
        }
    }

    if (opt_svr)
        server();
    else
        client();

    return 0;
}
其他 2022/1/1 18:13:39 有737人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶