2008年10月31日 星期五

一個使用waitpid的例子

#include <&stddef.h&>
#include <&signal.h&>
#include <&errno.h&>
#include <&stdio.h&>
#include <&stdlib.h&>
#include <&string.h&>
#include <&fcntl.h&>
#include <&time.h&>
#include <&sys/select.h&>
#include <&sys/wait.h&>
#include <&sys/socket.h&>
#include <&sys/un.h&>
#include "list.h"

#define LOCAL_SOCK_PATH "/home/qustion/tmp/localsee33"
#define MY_MAGIC "jeff-liao"
#define DEBUGFMT "%s(%d)-%s"
#define DEBUGARGS __FILE__,__LINE__,__FUNCTION__
#define FD_MAX(a,b) ((a) > (b) ? (a) : (b))
#define READ_END 0
#define WRITE_END 1
struct my_msg {
struct list_head node;
char magic[32];
char arg[256];
char cmd[256];
pid_t pid;
int exitstatus;
time_t queue_time;
};

static int local_sock = -1;
static int signal_pipe[2] = {-1, -1};

static int init_local_server_socket(void);
static struct my_msg* get_local_msg(void);
static void send_local_msg(char *cmd,char * arg);
static void run_msg(struct my_msg *msg);
static void sig_handler(int signum);
static void reap_sigchilds(void);
static void msg_done(int pid, int exitstatus);
static void msg_queue_delete(struct my_msg *msg);



static int quit=0;
static int sigchilds_waiting=0;
static LIST_HEAD(running_list);

int main (int argc, char *argv[], char *envp[]){
fd_set readfds;
int maxfd;
int fdcount;

struct timeval tv;
int retval;
struct sigaction act;
if(argc >= 2) {
if(!strcmp(argv[1],"client" )){

send_local_msg("/bin/echo","Hello Jeff!");
}else if(!strcmp(argv[1],"server" )){


if ( init_local_server_socket() < 0){
printf(" init_local_server_socket error!\n");
close(local_sock);
exit(1);
}
/* setup signal handler pipe */
retval = pipe(signal_pipe);

if (retval < 0) {
printf("error getting pipes: %s\n", strerror(errno));
exit(1);
}

retval = fcntl(signal_pipe[READ_END], F_GETFL, 0);

if (retval < 0) {
printf("error fcntl on read pipe: %s\n", strerror(errno));
exit(1);
}

retval = fcntl(signal_pipe[READ_END], F_SETFL, retval | O_NONBLOCK);

if (retval < 0) {
printf("error fcntl on read pipe: %s\n", strerror(errno));
exit(1);
}

retval = fcntl(signal_pipe[WRITE_END], F_GETFL, 0);

if (retval < 0) {
printf("error fcntl on write pipe: %s\n", strerror(errno));
exit(1);
}

retval = fcntl(signal_pipe[WRITE_END], F_SETFL, retval | O_NONBLOCK);

if (retval < 0) {
printf("error fcntl on write pipe: %s\n", strerror(errno));
exit(1);
}

memset(&act, 0x00, sizeof(struct sigaction));
act.sa_handler = (void (*)(int)) sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGCHLD, &act, NULL);
sigaction(SIGHUP, &act, NULL);
maxfd=FD_MAX(local_sock,signal_pipe[READ_END]);

while (!quit){

struct my_msg* msg;
FD_ZERO(&readfds);
FD_SET(signal_pipe[READ_END], &readfds);
FD_SET(local_sock, &readfds);
tv.tv_sec = 10;
tv.tv_usec = 0;
fdcount = select(maxfd+1, &readfds, NULL, NULL, &tv);

if (fdcount < 0) {
if (errno != EINTR)
printf("error in select: %s\n", strerror(errno));
continue;
}
if (FD_ISSET(local_sock, &readfds)){
msg=get_local_msg();
if (msg)
run_msg(msg);
}
/* received a signal, clear our notification pipe */
if (FD_ISSET(signal_pipe[READ_END], &readfds)) {
char buf[256];
read(signal_pipe[READ_END], &buf, sizeof(buf));
}

/* forked child has returned */
if (sigchilds_waiting) {
sigchilds_waiting = 0;
reap_sigchilds();
}

}//end of while
}

}else{
printf("Please give one parameter.\n");
exit(0);
}

exit(0);
}
static void sig_handler(int signum)
{
switch (signum) {
case SIGINT:
case SIGTERM:
quit = 1;
break;
case SIGCHLD:
/* set flag, then write to pipe if needed */
sigchilds_waiting = 1;
break;
//case SIGHUP:
// reload_config = 1;
// break;
}

/* write to pipe, which will wakeup select() in our mainloop */
write(signal_pipe[WRITE_END], "", 1);
}
static void reap_sigchilds(void)
{
pid_t pid;
int status;

while (1) {
pid = waitpid(-1, &status, WNOHANG);
if (pid <= 0)
break;
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else if (WIFSIGNALED(status))
status = WTERMSIG(status) + 128;
else
status = 0;
msg_done(pid, status);
}
}
static void msg_done(int pid, int exitstatus)
{
/* find msg associated with pid and delete it */
struct my_msg *msg;

list_for_each_entry(msg, &running_list, node) {
if (msg->pid == pid) {

msg->exitstatus = exitstatus;
msg_queue_delete(msg);

return;
}
}
}
static void msg_queue_delete(struct my_msg *msg)
{
list_del(&msg->node);
free(msg);
}
static void run_msg(struct my_msg *msg){

list_add_tail(&msg->node, &running_list);

if(msg==NULL)
printf("msg is NULL\n");
msg->queue_time = time(NULL);
pid_t pid;
int retval;
char buf[512];
pid = fork();
switch (pid) {
case 0:
/* child */
close(local_sock);
close(signal_pipe[READ_END]);
close(signal_pipe[WRITE_END]);
sprintf(buf,"%s %s",msg->cmd,msg->arg);
printf("Execute commad=%s\n",buf);
retval=system(buf);

if (retval==127 || retval==-1)
exit(1);
exit(0);
case -1:
printf("fork of child failed: %s\n", strerror(errno));
msg_queue_delete(msg);
break;
default:
/* get SIGCHLD in main loop */
printf("msg [cmd=%s,arg=%s,pid=%d] has stayed %ld seconds old\n",msg->cmd,msg->arg,pid,time(NULL)- msg->queue_time);
msg->pid = pid;
}



}
static void send_local_msg(char *cmd,char * arg){

int sock = -1;
struct my_msg ctrl_msg;
struct sockaddr_un saddr;
socklen_t addrlen;
int retval = 1;
sock = socket(AF_LOCAL, SOCK_DGRAM, 0);

memset(&ctrl_msg, 0x00, sizeof(struct my_msg));
strcpy(ctrl_msg.magic, MY_MAGIC);
strcpy(ctrl_msg.cmd, cmd);
strcpy(ctrl_msg.arg, arg);

if (sock == -1) {
err("error getting socket: %s\n", strerror(errno));
exit(0);
}
memset(&saddr, 0x00, sizeof(struct sockaddr_un));
saddr.sun_family = AF_LOCAL;
strcpy(&saddr.sun_path[1], LOCAL_SOCK_PATH);
printf("saddr.sun_path[1]=%s,offset=%d\n",&saddr.sun_path[1], offsetof(struct sockaddr_un, sun_path));
addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]);

retval = sendto(sock, &ctrl_msg, sizeof(ctrl_msg), 0, (struct sockaddr *)&saddr, addrlen);
if (retval == -1) {
err("error sending message: %s\n", strerror(errno));
retval = 1;
} else {
printf("sent message:cmd=%s,arg=%s\n", ctrl_msg.cmd,ctrl_msg.arg);
retval = 0;
}

close(sock);

}

static struct my_msg* get_local_msg(void){

struct my_msg *ctrl_msg;

ctrl_msg= malloc(sizeof(struct my_msg));

if (ctrl_msg == NULL){
printf("1 msg is NULL\n");
return NULL;
}
ssize_t size;
struct msghdr smsg;
struct cmsghdr *cmsg;
struct iovec iov;
struct ucred *cred;
char cred_msg[CMSG_SPACE(sizeof(struct ucred))];

char *pos;
memset(ctrl_msg, 0x00, sizeof(struct my_msg));
iov.iov_base = ctrl_msg;
iov.iov_len = sizeof(struct my_msg);
memset(&smsg, 0x00, sizeof(struct msghdr));
smsg.msg_iov = &iov;
smsg.msg_iovlen = 1;
smsg.msg_control = cred_msg;
smsg.msg_controllen = sizeof(cred_msg);

size = recvmsg(local_sock, &smsg, 0);
if (size < 0) {
printf (DEBUGFMT "\n",DEBUGARGS);
if (errno != EINTR)
err("unable to receive user udevd message: %s\n", strerror(errno));
return;
}
cmsg = CMSG_FIRSTHDR(&smsg);
cred = (struct ucred *) CMSG_DATA(cmsg);
if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {

err("no sender credentials received, message ignored\n");
return;
}


if (strncmp(ctrl_msg->magic, MY_MAGIC, sizeof(MY_MAGIC)) != 0 ) {

printf("message magic '%s' doesn't match, ignore it\n", ctrl_msg->magic);
return;
}

if(ctrl_msg==NULL)
printf(DEBUGFMT"ctrl_msg is NULL\n",DEBUGARGS);

return ctrl_msg;

}

static int init_local_server_socket(void){

struct sockaddr_un saddr;
socklen_t addrlen;
const int feature_on = 1;
int retval;

memset(&saddr, 0x00, sizeof(saddr));
saddr.sun_family = AF_LOCAL;
/* use abstract namespace for socket path */
strcpy(&saddr.sun_path[1], LOCAL_SOCK_PATH );
addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]);

local_sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (local_sock == -1) {
printf("error getting socket: %s\n", strerror(errno));
return -1;
}

/* the bind takes care of ensuring only one copy running */
retval = bind(local_sock, (struct sockaddr *) &saddr, addrlen);
if (retval < 0) {
printf("bind failed: %s\n", strerror(errno));
close(local_sock);
local_sock = -1;
return -1;
}

/* enable receiving of the sender credentials */
setsockopt(local_sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));

return 0;
}

23 則留言:

匿名 提到...

buy tramadol online tramadol online no prescription - tramadol 50mg capsules for dogs

匿名 提到...

generic xanax xanax 2 mg and alcohol - xanax drug misuse

匿名 提到...

buy tramadol online tramadol hcl bp - tramadol for dogs buy

匿名 提到...

xanax online xanax and grapefruit juice - much does 2mg xanax cost street

匿名 提到...

xanax online xanax overdose how many pills - xanax 1mg football

匿名 提到...

buy carisoprodol buy carisoprodol online cheap - carisoprodol 350 mg tablets information

匿名 提到...

xanax no rx xanax side effects pregnancy - xanax sleeping pills alcohol

匿名 提到...

buy tramadol online tramadol for dogs reactions - tramadol 50 mg premature ejaculation

匿名 提到...

buy tramadol online tramadol dosage 12 pound dog - tramadol for dogs and side effects

匿名 提到...

buy tramadol online no prescription tramadol addiction forum 2012 - tramadol addiction dogs

匿名 提到...

buy generic cialis online no prescription where to purchase daily cialis - cialis online united states

匿名 提到...

generic alprazolam xanax bars cheap - xanax dosage recommended

匿名 提到...

buy cialis online cialis online acquisto - cheap cialis 100mg

匿名 提到...

http://landvoicelearning.com/#74967 is tramadol hcl 50 mg an opiate - buy tramadol faq

匿名 提到...

legal buy tramadol online tramadol for dogs take with food - tramadol hydrochloride 50 mg recreational use

匿名 提到...

buy tramadol buy tramadol no prescription overnight - tramadol 50 mg side effects for dogs

匿名 提到...

order tramadol online overnight tramadol withdrawal mayo clinic - tramadol hcl abuse

匿名 提到...

buy tramadol tramadol for purchase no prescription - buy tramadol online saturday delivery

匿名 提到...

buy ativan online ativan hallucinations - ativan dosage status epilepticus

匿名 提到...

buy ativan online buy ativan from india - ativan 2.5 mg

匿名 提到...

http://ranchodelastortugas.com/#50238 xanax for anxiety insomnia - xanax dosage long

匿名 提到...

buy tramadol no rx generic name tramadol hydrochloride - tramadol addiction gaza

匿名 提到...

xanax depression xanax bars injecting - xanax and caffeine effects