dynwatch

view watch.c @ 0:ce3c5e4c75bf

dynwatch DynDNS updater for windows
author John Tsiombikas <nuclear@siggraph.org>
date Wed, 18 May 2011 05:53:29 +0300
parents
children
line source
1 /*
2 This file is part of dynwatch, a win32 system tray applet which
3 updates automatically the dyndns entry of quake.gr.
5 Copyright (c) 2005 John Tsiombikas <nuclear@siggraph.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <windows.h>
26 #include <sensapi.h>
27 #include "socklib.h"
28 #include "watch.h"
29 #include "config_parser.h"
30 #include "locator.h"
32 int empty_str(const char *str);
34 static const char *cfg_fname = "dynwatch.conf";
35 char user[256], pass[256], dhost[256], hosts[256];
36 extern int running;
38 static int connected;
40 void init(void) {
41 const struct ConfigOption *opt;
43 SetParserState(PS_AssignmentSymbol, ':');
44 SetParserState(PS_CommentSymbol, '#');
46 if(LoadConfigFile(loc_get_path(cfg_fname, LOC_FILE_CONFIG)) == -1) {
47 err_msg("Could not load config file, please reconfigure");
48 } else {
50 while((opt = GetNextOption())) {
51 if(!strcmp(opt->option, "user")) {
52 strncpy(user, opt->str_value, 256);
53 } else if(!strcmp(opt->option, "pass")) {
54 strncpy(pass, opt->str_value, 256);
55 } else if(!strcmp(opt->option, "dns-host")) {
56 strncpy(dhost, opt->str_value, 256);
57 } else if(!strcmp(opt->option, "hosts")) {
58 strncpy(hosts, opt->str_value, 256);
59 } else {
60 err_msg("Error parsing config file, please reconfigure");
61 user[0] = pass[0] = dhost[0] = hosts[0] = 0;
62 }
63 }
65 if(!empty_str(user) && !empty_str(pass) && !empty_str(dhost) && !empty_str(hosts)) {
66 running = 1;
67 }
68 }
70 DestroyConfigParser();
72 /* force a wsastartup call */
73 sl_set_verbosity(0);
74 sl_connect_tcp("0.0.0.0", 0, 0);
75 sl_set_verbosity(1);
76 }
78 void get_ip_address(struct in_addr *addr) {
79 struct hostent *host;
80 char **str_ptr;
81 static char hostname[512];
83 if(gethostname(hostname, 512) == -1) {
84 err_msg("gethostname() failed\n");
85 }
87 if(!(host = gethostbyname(hostname))) {
88 err_msg("gethostbyname() failed\n");
89 }
91 *addr = *(struct in_addr*)host->h_addr_list[0];
92 }
94 int need_update(void) {
95 unsigned long flags;
96 static struct in_addr addr;
98 if(IsNetworkAlive(&flags)) {
99 /* it was not connected before, we need to update */
100 if(!connected) {
101 get_ip_address(&addr);
102 connected = 1;
103 return 1;
104 }
106 /* it was connected before, but we may have missed a short
107 * disconnect. Check to see if we still have the same ip (not fullproof)
108 */
109 {
110 struct in_addr tmp;
111 get_ip_address(&tmp);
113 if(addr.S_un.S_addr != tmp.S_un.S_addr) {
114 addr = tmp;
115 return 1;
116 }
117 }
119 } else {
120 connected = 0;
121 }
122 return 0;
123 }
126 int update_dns(void) {
127 int s, bytes;
128 static char http_req[512];
129 char *buf, *ptr;
131 if(empty_str(user) || empty_str(pass) || empty_str(dhost) || empty_str(hosts)) {
132 err_msg("missing configuration data, please reconfigure");
133 return -1;
134 }
136 if((s = sl_connect_tcp(0, dhost, 80)) == -1) {
137 connected = 0;
138 return -1;
139 }
141 buf = malloc(4096);
143 sprintf(buf, "update.php?rid=%s&token=%s", user, pass);
144 sprintf(http_req, "GET http://%s/%s HTTP/1.0\r\nUser-Agent: dynwatch/1.0\r\n\r\n", dhost, buf);
146 sl_send_data(s, http_req, strlen(http_req));
147 while((bytes = sl_recv_data(s, buf, 4096))) {
148 if(bytes == -1) break;
150 ptr = strstr(buf, "Updated");
151 if(ptr) {
152 free(buf);
153 info_msg("dns update complete");
154 sl_close_socket(s);
155 return 0;
156 }
157 }
159 free(buf);
160 err_msg("dns update failed");
161 sl_close_socket(s);
162 return -1;
163 }
165 #define HOME_ENV "USERPROFILE"
166 #define DIR_SEP '\\'
167 #define MAX_PATH 512
169 void save_config(void) {
170 FILE *fp;
171 static char path[MAX_PATH];
172 const char *fptr = cfg_fname;
173 char *env, *pptr = path;
175 env = getenv(HOME_ENV);
176 if(env) {
177 while(*env) *pptr++ = *env++;
178 if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP;
179 while(*fptr) *pptr++ = *fptr++;
180 *pptr++ = 0;
181 } else {
182 strcpy(path, cfg_fname);
183 info_msg("warning: no USERPROFILE variable found, saving config to the current dir.");
184 }
186 if(!(fp = fopen(path, "w"))) {
187 err_msg("could not save config file!");
188 return;
189 }
191 fprintf(fp, "dns-host: %s\n", dhost);
192 fprintf(fp, "user: %s\n", user);
193 fprintf(fp, "pass: %s\n", pass);
194 fprintf(fp, "hosts: %s\n", hosts);
196 fclose(fp);
197 }