execl 在服务器端的 while(1) 循环中不起作用; C脚本

发布于 2024-08-30 16:30:26 字数 1891 浏览 3 评论 0原文

我有一个小 C 脚本的问题,它应该作为服务器运行并为每条到达的消息启动一个弹出窗口。 execl 语法是正确的,因为如果我尝试一个小脚本,

main() { execl(...); }

它就可以工作。

当我将它放入 while(1) 循环中时,它不起作用。其他一切都正常,例如 printf 或字符串操作,但 execl 不行。即使我分叉也不起作用。 我怎样才能让它发挥作用?

我尝试过使用 fork(),但它也不起作用。

这是完整的服务器 C 代码。

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>

#define BUFLEN 512
#define PORT 9930

void diep(char *s) {
     perror(s);
     exit(1);
}

int main() {
    struct sockaddr_in si_me, si_other;
    int s, i, slen=sizeof(si_other), broadcastPermission;
    char buf[100], zeni[BUFLEN];

    if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
       diep("socket");

    broadcastPermission = 1;
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void *) &broadcastPermission, sizeof(broadcastPermission)) < 0)
        diep("setsockopt() failed");

    memset((char *) &si_me, 0, sizeof(si_me));
    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORT);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, &si_me, sizeof(si_me))==-1)
       diep("bind");

    while (1) {
        if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1) diep("recvfrom()");
        //printf("Received packet from %s:%d\nData: %s\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);

 strcpy(zeni, "");
 strcat(zeni, "zenity --warning --title Hack!! --text ");
 strcat(zeni, buf);
 printf("cmd: %s\n", zeni);
 //system (zeni);
 execl("/usr/bin/zenity", "/usr/bin/zenity", "--warning", "--title", "Warn!", "--text", buf, (char *) NULL);
    }

    close(s);
    return 0;

}

I have a problem with a little C script which should run as a server and launch a popup for every message arriving.
The execl syntax is correct because if I try a little script with

main() { execl(...); }

it works.

When I put it in a while(1) loop it doesn't work. Everything else is working, like printf or string operation, but not the execl. Even if I fork it doesn't work.
How can I make it work?

And I've tried with the fork(), but it doesn't work either.

Here's the complete server C code.

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>

#define BUFLEN 512
#define PORT 9930

void diep(char *s) {
     perror(s);
     exit(1);
}

int main() {
    struct sockaddr_in si_me, si_other;
    int s, i, slen=sizeof(si_other), broadcastPermission;
    char buf[100], zeni[BUFLEN];

    if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
       diep("socket");

    broadcastPermission = 1;
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void *) &broadcastPermission, sizeof(broadcastPermission)) < 0)
        diep("setsockopt() failed");

    memset((char *) &si_me, 0, sizeof(si_me));
    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORT);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, &si_me, sizeof(si_me))==-1)
       diep("bind");

    while (1) {
        if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1) diep("recvfrom()");
        //printf("Received packet from %s:%d\nData: %s\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);

 strcpy(zeni, "");
 strcat(zeni, "zenity --warning --title Hack!! --text ");
 strcat(zeni, buf);
 printf("cmd: %s\n", zeni);
 //system (zeni);
 execl("/usr/bin/zenity", "/usr/bin/zenity", "--warning", "--title", "Warn!", "--text", buf, (char *) NULL);
    }

    close(s);
    return 0;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

知足的幸福 2024-09-06 16:30:26

@jweyrich 已经指出了使用 recvfrom 的一些问题,但是还有一个更根本的问题。该代码

while (1) {
    recvfrom(...);
    execl(...);
}

最多只会执行一次。这是因为 exec 系列系统调用(包括 execl)将当前执行的程序替换为 execl 调用中给出的程序。实际上,execl 永远不会返回,除非出现错误。

要在unix中创建新的子进程,必须首先调用fork,它克隆现有进程,然后在子进程中调用execl(或一些相关的系统调用)来将子进程替换为您实际要运行的程序。手动正确执行此操作有些棘手,因此 system 函数会为您完成此操作,但它有其自身的缺点。

@jweyrich has already pointed out some problems with your use of recvfrom, however there is a more fundamental problem. The code

while (1) {
    recvfrom(...);
    execl(...);
}

will only ever execute at most once. This because the exec family of system calls (including execl) replace the the program currently executing with the one given in the call to execl. In effect, execl never returns, except with an error.

To create a new child process in unix, you must first call fork, which clones the existing process, and then within the child call execl (or some related system call) to replace child process with the program you actually want to run. Doing this correctly manually is somewhat tricky, so the system function wraps this up for you, however it has it's own drawbacks.

吹泡泡o 2024-09-06 16:30:26

recvfrom 的调用中存在堆栈溢出。

recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)

我相信你混合了两个缓冲区。您使用的是 buf,其大小为 100,但指定其大小为 BUFLEN,即 512。每当有人发送超过 100 个字节时,您的程序很可能会崩溃。

除此之外,recvfrom 可能不会返回,因为它没有接收到任何内容。你的 printf 正在执行吗?


更新:正如 @Daniel 和 @Dale 所指出的,除非发生错误,否则 execl 不会返回。引用手册页:

exec 函数系列用新的进程映像替换当前进程映像。

作为替代方案,您可以使用system

There's a stack overflow in your call to recvfrom.

recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)

I believe you mixed the 2 buffers. You're using buf, which has size 100, but telling its size is BUFLEN, which is 512. Whenever someone sends more than 100 bytes, it's very likely your program is going to crash.

Besides that, it's possible that the recvfrom is not returning because it isn't receiving anything. Is your printf being executed?


UPDATE: as pointed by @Daniel and @Dale, execl won't return unless an error occurs. Quoting from the man-page:

The exec family of functions replaces the current process image with a new process image.

As alternative, you can use system.

晚雾 2024-09-06 16:30:26

请阅读 exec(3) 手册页。

在你的情况下 execl 系统调用将用以下图像替换当前进程图像
/usr/bin/zenity”。

您有两种解决方案:使用您尝试过的 system(3) 或执行 fork 并在子进程中运行 execlp。

Please read exec(3) man page.

In your case execl system call will replace current processes image with the image of
/usr/bin/zenity".

You have two solutions: use system(3) as you tried there or do a fork and inside the child run execlp.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文