execl doesn't work in a while(1) loop, server side; C script
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
v开发者_Python百科oid 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;
}
@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.
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
.
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.
精彩评论