ignore EINTR select interrupt
[monky] / src / hddtemp.c
1 #include "conky.h"
2 #include <errno.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <netdb.h>
9 #include <sys/select.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12
13 #define BUFLEN 512
14 #define PORT 7634
15
16 char buf[BUFLEN];
17
18 int scan_hddtemp(const char *arg, char **dev, char **addr, int *port)
19 {
20         char buf1[32], buf2[64];
21         int n, ret;
22         
23         ret = sscanf(arg, "%31s %63s %d", buf1, buf2, &n);
24         
25         if (ret < 1)
26                 return -1;
27
28         *dev = strdup(buf1);
29         if (ret >= 2)
30                 *addr = strdup(buf2);
31         else
32                 *addr = strdup("127.0.0.1");
33
34         if (ret == 3) 
35                 *port = n;
36         else
37                 *port = PORT;
38
39         return 0;
40 }
41
42 char *get_hddtemp_info(char *dev, char *hostaddr, int port, char *unit)
43 {
44         int sockfd = 0;
45         struct hostent *he;
46         struct sockaddr_in addr;
47         struct timeval tv;
48         fd_set rfds;
49         int len, i, devlen = strlen(dev);
50         char sep;
51         char *p, *out, *r = NULL;
52         
53         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
54                 perror("socket");
55                 return NULL;
56         }
57
58         he = gethostbyname(hostaddr);
59         if (!he) {
60                 perror("gethostbyname");
61                 goto out;
62         }
63
64         addr.sin_family = AF_INET;
65         addr.sin_port = htons(port);
66         addr.sin_addr = *((struct in_addr *)he->h_addr);
67         memset(&(addr.sin_zero), 0, 8);
68
69         if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
70                 perror("connect");
71                 goto out;
72         }
73
74         FD_ZERO(&rfds);
75         FD_SET(sockfd, &rfds);
76
77         /* We're going to wait up to a quarter a second to see whether
78          * there's any data available. Polling with timeout set to 0
79          * doesn't seem to work with hddtemp. */
80         tv.tv_sec = 0;
81         tv.tv_usec = 250000;
82         
83         i = select(sockfd+1, &rfds, NULL, NULL, &tv);
84         if (i == -1)
85         {
86                 if (errno == EINTR)     /* silently ignore interrupted system call */
87                     goto out;
88                 else
89                     perror("select");
90         }
91
92         /* No data available */
93         if (i <= 0)
94                 goto out;
95         
96         p = buf;
97         len = 0;
98         do {
99                 i = recv(sockfd, p, BUFLEN - (p-buf), 0);
100                 if (i < 0) {
101                         perror("recv");
102                         goto out;
103                 }
104                 len += i;
105                 p += i;
106         } while (i > 0 && p < buf + BUFLEN - 1);
107         
108         if (len < 2) {
109                 goto out;
110         }
111         
112         buf[len] = 0;
113                 
114         /* The first character read is the separator. */
115         sep = buf[0];
116         p = buf+1;
117         
118         while (*p) {
119                 if (!strncmp(p, dev, devlen)) {
120                         p += devlen + 1; 
121                         p = strchr(p, sep);
122                         if (!p) 
123                                 goto out;
124                         p++;
125                         out = p;        
126                         p = strchr(p, sep);
127                         if (!p) 
128                                 goto out;
129                         *p = '\0';
130                         p++;
131                         *unit = *p;     
132                         if (!strncmp(out, "NA", 2)) {
133                                 strcpy(buf, "N/A");
134                                 r = buf;
135                         } else {                                        
136                                 r = out;
137                         }
138                         goto out;
139                 } else {
140                         for (i = 0; i < 5; i++) {
141                                 p = strchr(p, sep);
142                                 if (!p)
143                                         goto out;
144                                 p++;
145                         }
146                 }
147         }
148 out:    close(sockfd);
149         return r;
150 }
151