cffa213f66d60ea95e1dfa8e14e578fa6eda9cdb
[monky] / src / hddtemp.c
1 /*
2  * Conky, a system monitor, based on torsmo
3  *
4  * Any original torsmo code is licensed under the BSD license
5  *
6  * All code written since the fork of torsmo is licensed under the GPL
7  *
8  * Please see COPYING for details
9  *
10  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
11  * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al. (see AUTHORS)
12  * All rights reserved.
13  *
14  * This program is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
25  *
26  *  $Id$
27  */
28
29 #include "conky.h"
30 #include <errno.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <netdb.h>
37 #include <sys/select.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40
41 #define BUFLEN 512
42 #define PORT 7634
43
44 char buf[BUFLEN];
45
46 int scan_hddtemp(const char *arg, char **dev, char **addr, int *port)
47 {
48         char buf1[32], buf2[64];
49         int n, ret;
50         
51         ret = sscanf(arg, "%31s %63s %d", buf1, buf2, &n);
52         
53         if (ret < 1)
54                 return -1;
55
56         *dev = strdup(buf1);
57         if (ret >= 2)
58                 *addr = strdup(buf2);
59         else
60                 *addr = strdup("127.0.0.1");
61
62         if (ret == 3) 
63                 *port = n;
64         else
65                 *port = PORT;
66
67         return 0;
68 }
69
70 char *get_hddtemp_info(char *dev, char *hostaddr, int port, char *unit)
71 {
72         int sockfd = 0;
73         struct hostent *he;
74         struct sockaddr_in addr;
75         struct timeval tv;
76         fd_set rfds;
77         int len, i, devlen = strlen(dev);
78         char sep;
79         char *p, *out, *r = NULL;
80         
81         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
82                 perror("socket");
83                 return NULL;
84         }
85
86         he = gethostbyname(hostaddr);
87         if (!he) {
88                 perror("gethostbyname");
89                 goto out;
90         }
91
92         addr.sin_family = AF_INET;
93         addr.sin_port = htons(port);
94         addr.sin_addr = *((struct in_addr *)he->h_addr);
95         memset(&(addr.sin_zero), 0, 8);
96
97         if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
98                 perror("connect");
99                 goto out;
100         }
101
102         FD_ZERO(&rfds);
103         FD_SET(sockfd, &rfds);
104
105         /* We're going to wait up to a quarter a second to see whether
106          * there's any data available. Polling with timeout set to 0
107          * doesn't seem to work with hddtemp. */
108         tv.tv_sec = 0;
109         tv.tv_usec = 250000;
110         
111         i = select(sockfd+1, &rfds, NULL, NULL, &tv);
112         if (i == -1)
113         {
114                 if (errno == EINTR)     /* silently ignore interrupted system call */
115                     goto out;
116                 else
117                     perror("select");
118         }
119
120         /* No data available */
121         if (i <= 0)
122                 goto out;
123         
124         p = buf;
125         len = 0;
126         do {
127                 i = recv(sockfd, p, BUFLEN - (p-buf), 0);
128                 if (i < 0) {
129                         perror("recv");
130                         goto out;
131                 }
132                 len += i;
133                 p += i;
134         } while (i > 0 && p < buf + BUFLEN - 1);
135         
136         if (len < 2) {
137                 goto out;
138         }
139         
140         buf[len] = 0;
141                 
142         /* The first character read is the separator. */
143         sep = buf[0];
144         p = buf+1;
145         
146         while (*p) {
147                 if (!strncmp(p, dev, devlen)) {
148                         p += devlen + 1; 
149                         p = strchr(p, sep);
150                         if (!p) 
151                                 goto out;
152                         p++;
153                         out = p;        
154                         p = strchr(p, sep);
155                         if (!p) 
156                                 goto out;
157                         *p = '\0';
158                         p++;
159                         *unit = *p;     
160                         if (!strncmp(out, "NA", 2)) {
161                                 strcpy(buf, "N/A");
162                                 r = buf;
163                         } else {                                        
164                                 r = out;
165                         }
166                         goto out;
167                 } else {
168                         for (i = 0; i < 5; i++) {
169                                 p = strchr(p, sep);
170                                 if (!p)
171                                         goto out;
172                                 p++;
173                         }
174                 }
175         }
176 out:    close(sockfd);
177         return r;
178 }
179