infopipe improvements
[monky] / src / remoted.c
1 /*
2 * Conky, a system monitor, based on torsmo
3 *
4 * This program is licensed under BSD license, read COPYING
5 *
6 *  $Id$
7 */
8
9 #include <pthread.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <sys/wait.h>
20 #include <signal.h>
21
22 static pthread_t daemon_thread;
23 static int daemon_status = 0;
24 static char *data;
25
26 /* okay, heres how it will basically work.
27 * when something connects, it will first send the conkyrc on the local (daemonized) server
28 * after this, it will simply continue to send all the buffered text to the remote client
29 * http://analyser.oli.tudelft.nl/beej/mirror/net/html/
30 *  http://www.kegel.com/c10k.html
31 */
32
33 #define MYPORT 3490    // the port users will be connecting to
34
35 #define BACKLOG 10     // how many pending connections queue will hold
36
37 void sigchld_handler(/*int s*/)
38 {
39         while(wait(NULL) > 0);
40 }
41
42 void *daemon_loop()
43 {
44         /* do something */
45
46
47
48         int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
49         struct sockaddr_in my_addr;    // my address information
50         struct sockaddr_in their_addr; // connector's address information
51         int sin_size;
52         struct sigaction sa;
53         int yes=1;
54
55         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
56                 perror("socket");
57                 exit(1);
58         }
59
60         if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
61                 perror("setsockopt");
62                 exit(1);
63         }
64         
65         my_addr.sin_family = AF_INET;         // host byte order
66         my_addr.sin_port = htons(MYPORT);     // short, network byte order
67         my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
68         memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
69
70         if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))
71                    == -1) {
72                 perror("bind");
73                 exit(1);
74                    }
75
76                    if (listen(sockfd, BACKLOG) == -1) {
77                            perror("listen");
78                            exit(1);
79                    }
80
81                    sa.sa_handler = sigchld_handler; // reap all dead processes
82                    sigemptyset(&sa.sa_mask);
83                    sa.sa_flags = SA_RESTART;
84                    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
85                            perror("sigaction");
86                            exit(1);
87                    }
88
89                    while(1) {  // main accept() loop
90                            sin_size = sizeof(struct sockaddr_in);
91                            if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
92                                 &sin_size)) == -1) {
93                                         perror("accept");
94                                         continue;
95                                 }
96                                 printf("server: got connection from %s\n",
97                                        inet_ntoa(their_addr.sin_addr));
98                                 if (!fork()) { // this is the child process
99                                         close(sockfd); // child doesn't need the listener
100                                         if (send(new_fd, data, 14, 0) == -1)
101                                                 perror("send");
102                                         close(new_fd);
103                                         exit(0);
104                                 }
105                                 close(new_fd);  // parent doesn't need this
106                    }
107
108                    return 0;
109 }
110
111 void daemon_run(const char *s)
112 {
113         /* create thread, keep an eye on it */
114         data = (char *)s;
115         int iret;
116         if (!daemon_status) {
117                 daemon_status = 1;
118                 iret = pthread_create(&daemon_thread, NULL, daemon_loop, NULL);
119         } else if (daemon_status == 1) {
120                 /* thread is still running, we'll just wait for it to finish for now */
121                 pthread_join(daemon_thread, NULL);
122                 daemon_status = 0;
123         } else {
124                 /* something else */
125         }
126 }