00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 #include <stdio.h>
00089 #include <time.h>
00090 #ifndef __CYGWIN__
00091 #include <windows.h>
00092 #endif
00093 #include <curl/curl.h>
00094
00095
00096 #define MAX_STRING 256
00097 #define MAX_STRING1 MAX_STRING+1
00098
00099 #define SYNCTIME_UA "synctime/1.0"
00100
00101 typedef struct
00102 {
00103 char http_proxy[MAX_STRING1];
00104 char proxy_user[MAX_STRING1];
00105 char timeserver[MAX_STRING1];
00106 } conf_t;
00107
00108 const char DefaultTimeServer[3][MAX_STRING1] =
00109 {
00110 "http://pool.ntp.org/",
00111 "http://nist.time.gov/",
00112 "http://www.google.com/"
00113 };
00114
00115 const char *DayStr[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
00116 const char *MthStr[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
00117 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
00118
00119 int ShowAllHeader;
00120 int AutoSyncTime;
00121 SYSTEMTIME SYSTime;
00122 SYSTEMTIME LOCALTime;
00123
00124 #define HTTP_COMMAND_HEAD 0
00125 #define HTTP_COMMAND_GET 1
00126
00127
00128 size_t SyncTime_CURL_WriteOutput(void *ptr, size_t size, size_t nmemb,
00129 void *stream)
00130 {
00131 fwrite(ptr, size, nmemb, stream);
00132 return (nmemb*size);
00133 }
00134
00135 size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb,
00136 void *stream)
00137 {
00138 int i, RetVal;
00139 char TmpStr1[26], TmpStr2[26];
00140
00141 if(ShowAllHeader == 1)
00142 fprintf(stderr, "%s", (char *)(ptr));
00143
00144 if(strncmp((char *)(ptr), "Date:", 5) == 0) {
00145 if(ShowAllHeader == 0)
00146 fprintf(stderr, "HTTP Server. %s", (char *)(ptr));
00147
00148 if(AutoSyncTime == 1) {
00149 *TmpStr1 = 0;
00150 *TmpStr2 = 0;
00151 if(strlen((char *)(ptr)) > 50)
00152
00153 AutoSyncTime = 0;
00154 else {
00155 RetVal = sscanf((char *)(ptr), "Date: %s %hu %s %hu %hu:%hu:%hu",
00156 TmpStr1, &SYSTime.wDay, TmpStr2, &SYSTime.wYear,
00157 &SYSTime.wHour, &SYSTime.wMinute, &SYSTime.wSecond);
00158
00159 if(RetVal == 7) {
00160 SYSTime.wMilliseconds = 500;
00161 for(i=0; i<12; i++) {
00162 if(strcmp(MthStr[i], TmpStr2) == 0) {
00163 SYSTime.wMonth = i+1;
00164 break;
00165 }
00166 }
00167 AutoSyncTime = 3;
00168 }
00169 else {
00170 AutoSyncTime = 0;
00171 }
00172 }
00173 }
00174 }
00175
00176 if(strncmp((char *)(ptr), "X-Cache: HIT", 12) == 0) {
00177 fprintf(stderr, "ERROR: HTTP Server data is cached."
00178 " Server Date is no longer valid.\n");
00179 AutoSyncTime = 0;
00180 }
00181 return (nmemb*size);
00182 }
00183
00184 void SyncTime_CURL_Init(CURL *curl, char *proxy_port,
00185 char *proxy_user_password)
00186 {
00187 if(strlen(proxy_port) > 0)
00188 curl_easy_setopt(curl, CURLOPT_PROXY, proxy_port);
00189
00190 if(strlen(proxy_user_password) > 0)
00191 curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_password);
00192
00193 #ifdef SYNCTIME_UA
00194 curl_easy_setopt(curl, CURLOPT_USERAGENT, SYNCTIME_UA);
00195 #endif
00196 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, *SyncTime_CURL_WriteOutput);
00197 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, *SyncTime_CURL_WriteHeader);
00198 }
00199
00200 int SyncTime_CURL_Fetch(CURL *curl, char *URL_Str, char *OutFileName,
00201 int HttpGetBody)
00202 {
00203 FILE *outfile;
00204 CURLcode res;
00205
00206 outfile = NULL;
00207 if(HttpGetBody == HTTP_COMMAND_HEAD)
00208 curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
00209 else {
00210 outfile = fopen(OutFileName, "wb");
00211 curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
00212 }
00213
00214 curl_easy_setopt(curl, CURLOPT_URL, URL_Str);
00215 res = curl_easy_perform(curl);
00216 if(outfile != NULL)
00217 fclose(outfile);
00218 return res;
00219 }
00220
00221 void showUsage(void)
00222 {
00223 fprintf(stderr, "SYNCTIME: Synchronising computer clock with time server"
00224 " using HTTP protocol.\n");
00225 fprintf(stderr, "Usage : SYNCTIME [Option]\n");
00226 fprintf(stderr, "Options :\n");
00227 fprintf(stderr, " --server=WEBSERVER Use this time server instead"
00228 " of default.\n");
00229 fprintf(stderr, " --showall Show all HTTP header.\n");
00230 fprintf(stderr, " --synctime Synchronising computer clock"
00231 " with time server.\n");
00232 fprintf(stderr, " --proxy-user=USER[:PASS] Set proxy username and"
00233 " password.\n");
00234 fprintf(stderr, " --proxy=HOST[:PORT] Use HTTP proxy on given"
00235 " port.\n");
00236 fprintf(stderr, " --help Print this help.\n");
00237 fprintf(stderr, "\n");
00238 return;
00239 }
00240
00241 int conf_init(conf_t *conf)
00242 {
00243 int i;
00244
00245 *conf->http_proxy = 0;
00246 for(i=0; i<MAX_STRING1; i++)
00247 conf->proxy_user[i] = 0;
00248 *conf->timeserver = 0;
00249 return 1;
00250 }
00251
00252 int main(int argc, char *argv[])
00253 {
00254 CURL *curl;
00255 conf_t conf[1];
00256 int OptionIndex;
00257 struct tm *lt;
00258 struct tm *gmt;
00259 time_t tt;
00260 time_t tt_local;
00261 time_t tt_gmt;
00262 double tzonediffFloat;
00263 int tzonediffWord;
00264 char timeBuf[61];
00265 char tzoneBuf[16];
00266 int RetValue;
00267
00268 OptionIndex = 0;
00269 ShowAllHeader = 0;
00270 AutoSyncTime = 0;
00271 RetValue = 0;
00272 conf_init(conf);
00273
00274 if(argc > 1) {
00275 while(OptionIndex < argc) {
00276 if(strncmp(argv[OptionIndex], "--server=", 9) == 0)
00277 snprintf(conf->timeserver, MAX_STRING, "%s", &argv[OptionIndex][9]);
00278
00279 if(strcmp(argv[OptionIndex], "--showall") == 0)
00280 ShowAllHeader = 1;
00281
00282 if(strcmp(argv[OptionIndex], "--synctime") == 0)
00283 AutoSyncTime = 1;
00284
00285 if(strncmp(argv[OptionIndex], "--proxy-user=", 13) == 0)
00286 snprintf(conf->proxy_user, MAX_STRING, "%s", &argv[OptionIndex][13]);
00287
00288 if(strncmp(argv[OptionIndex], "--proxy=", 8) == 0)
00289 snprintf(conf->http_proxy, MAX_STRING, "%s", &argv[OptionIndex][8]);
00290
00291 if((strcmp(argv[OptionIndex], "--help") == 0) ||
00292 (strcmp(argv[OptionIndex], "/?") == 0)) {
00293 showUsage();
00294 return 0;
00295 }
00296 OptionIndex++;
00297 }
00298 }
00299
00300 if(*conf->timeserver == 0)
00301 snprintf(conf->timeserver, MAX_STRING, "%s", DefaultTimeServer[0]);
00302
00303
00304 curl_global_init(CURL_GLOBAL_ALL);
00305 curl = curl_easy_init();
00306 if(curl) {
00307 SyncTime_CURL_Init(curl, conf->http_proxy, conf->proxy_user);
00308
00309
00310 tt = time(0);
00311 lt = localtime(&tt);
00312 tt_local = mktime(lt);
00313 gmt = gmtime(&tt);
00314 tt_gmt = mktime(gmt);
00315 tzonediffFloat = difftime(tt_local, tt_gmt);
00316 tzonediffWord = (int)(tzonediffFloat/3600.0);
00317
00318 if((double)(tzonediffWord * 3600) == tzonediffFloat)
00319 snprintf(tzoneBuf, 15, "%+03d'00'", tzonediffWord);
00320 else
00321 snprintf(tzoneBuf, 15, "%+03d'30'", tzonediffWord);
00322
00323
00324 GetSystemTime(&SYSTime);
00325 GetLocalTime(&LOCALTime);
00326 snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ",
00327 DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay,
00328 MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
00329 LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
00330 LOCALTime.wMilliseconds);
00331
00332 fprintf(stderr, "Fetch: %s\n\n", conf->timeserver);
00333 fprintf(stderr, "Before HTTP. Date: %s%s\n\n", timeBuf, tzoneBuf);
00334
00335
00336 SyncTime_CURL_Fetch(curl, conf->timeserver, "index.htm",
00337 HTTP_COMMAND_HEAD);
00338
00339 GetLocalTime(&LOCALTime);
00340 snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ",
00341 DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay,
00342 MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
00343 LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
00344 LOCALTime.wMilliseconds);
00345 fprintf(stderr, "\nAfter HTTP. Date: %s%s\n", timeBuf, tzoneBuf);
00346
00347 if(AutoSyncTime == 3) {
00348
00349 if(!SetSystemTime(&SYSTime)) {
00350 fprintf(stderr, "ERROR: Unable to set system time.\n");
00351 RetValue = 1;
00352 }
00353 else {
00354
00355 GetLocalTime(&LOCALTime);
00356 snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ",
00357 DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay,
00358 MthStr[LOCALTime.wMonth-1], LOCALTime.wYear,
00359 LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond,
00360 LOCALTime.wMilliseconds);
00361 fprintf(stderr, "\nNew System's Date: %s%s\n", timeBuf, tzoneBuf);
00362 }
00363 }
00364
00365
00366 conf_init(conf);
00367 curl_easy_cleanup(curl);
00368 }
00369 return RetValue;
00370 }