diff options
| author | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:22 +0100 |
|---|---|---|
| committer | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:22 +0100 |
| commit | 0268977037115539ad65a26e858aa0df8d18cd13 (patch) | |
| tree | f761b541b04d08b75e32efc6c293111c61a8b79c /support | |
| parent | 9e615cb6aa4afcee97f8a1646e5a586261a7b81f (diff) | |
| download | apache2-upstream/2.2.9.tar.gz | |
Upstream tarball 2.2.9upstream/2.2.9
Diffstat (limited to 'support')
| -rw-r--r-- | support/ab.c | 582 | ||||
| -rw-r--r-- | support/htpasswd.c | 34 | ||||
| -rw-r--r-- | support/htpasswd.dsp | 8 | ||||
| -rw-r--r-- | support/rotatelogs.c | 130 | ||||
| -rw-r--r-- | support/suexec.c | 10 | ||||
| -rw-r--r-- | support/win32/ApacheMonitor.c | 492 | ||||
| -rw-r--r-- | support/win32/ApacheMonitor.dsp | 8 | ||||
| -rw-r--r-- | support/win32/ApacheMonitor.h | 1 |
8 files changed, 794 insertions, 471 deletions
diff --git a/support/ab.c b/support/ab.c index 5adf5a5b..e39536d1 100644 --- a/support/ab.c +++ b/support/ab.c @@ -80,6 +80,10 @@ ** Switched to the new abstract pollset API, allowing ab to ** take advantage of future apr_pollset_t scalability improvements. ** Contributed by Brian Pane, August 31, 2002 + ** + ** Version 2.3 + ** SIGINT now triggers output_results(). + ** Contributed by colm, March 30, 2006 **/ /* Note: this version string should start with \d+[\d\.]* and be a valid @@ -91,7 +95,7 @@ * ab - or to due to a change in the distribution it is compiled with * (such as an APR change in for example blocking). */ -#define AP_AB_BASEREVISION "2.0.40-dev" +#define AP_AB_BASEREVISION "2.3" /* * BUGS: @@ -189,6 +193,9 @@ typedef STACK_OF(X509) X509_STACK_TYPE; #if APR_HAVE_CTYPE_H #include <ctype.h> #endif +#if APR_HAVE_LIMITS_H +#include <limits.h> +#endif /* ------------------- DEFINITIONS -------------------------- */ @@ -199,7 +206,7 @@ typedef STACK_OF(X509) X509_STACK_TYPE; #endif /* maximum number of requests on a time limited test */ -#define MAX_REQUESTS 50000 +#define MAX_REQUESTS (INT_MAX > 50000 ? 50000 : INT_MAX) /* good old state hostname */ #define STATE_UNCONNECTED 0 @@ -238,22 +245,22 @@ struct connection { }; struct data { - int read; /* number of bytes read */ - apr_time_t starttime; /* start time of connection in seconds since - * Jan. 1, 1970 */ - apr_interval_time_t waittime; /* Between writing request and reading - * response */ - apr_interval_time_t ctime; /* time in ms to connect */ - apr_interval_time_t time; /* time in ms for connection */ + apr_time_t starttime; /* start time of connection */ + apr_interval_time_t waittime; /* between request and reading response */ + apr_interval_time_t ctime; /* time to connect */ + apr_interval_time_t time; /* time for connection */ }; #define ap_min(a,b) ((a)<(b))?(a):(b) #define ap_max(a,b) ((a)>(b))?(a):(b) +#define ap_round_ms(a) ((apr_time_t)((a) + 500)/1000) +#define ap_double_ms(a) ((double)(a)/1000.0) #define MAX_CONCURRENCY 20000 /* --------------------- GLOBALS ---------------------------- */ int verbosity = 0; /* no verbosity by default */ +int recverrok = 0; /* ok to proceed after socket receive errors */ int posting = 0; /* GET by default */ int requests = 1; /* Number of requests to make */ int heartbeatres = 100; /* How often do we say we're alive */ @@ -262,6 +269,7 @@ int percentile = 1; /* Show percentile served */ int confidence = 1; /* Show confidence estimator and warnings */ int tlimit = 0; /* time limit in secs */ int keepalive = 0; /* try and do keepalive connections */ +int windowsize = 0; /* we use the OS default window size */ char servername[1024]; /* name that server reports */ char *hostname; /* host name from URL */ char *host_field; /* value of "Host:" header field */ @@ -298,15 +306,20 @@ const char *tablestring; const char *trstring; const char *tdstring; -apr_size_t doclen = 0; /* the length the document should be */ -long started = 0; /* number of requests started, so no excess */ -long totalread = 0; /* total number of bytes read */ -long totalbread = 0; /* totoal amount of entity body read */ -long totalposted = 0; /* total number of bytes posted, inc. headers */ -long done = 0; /* number of requests we have done */ -long doneka = 0; /* number of keep alive connections done */ -long good = 0, bad = 0; /* number of good and bad requests */ -long epipe = 0; /* number of broken pipe writes */ +apr_size_t doclen = 0; /* the length the document should be */ +apr_int64_t totalread = 0; /* total number of bytes read */ +apr_int64_t totalbread = 0; /* totoal amount of entity body read */ +apr_int64_t totalposted = 0; /* total number of bytes posted, inc. headers */ +int started = 0; /* number of requests started, so no excess */ +int done = 0; /* number of requests we have done */ +int doneka = 0; /* number of keep alive connections done */ +int good = 0, bad = 0; /* number of good and bad requests */ +int epipe = 0; /* number of broken pipe writes */ +int err_length = 0; /* requests failed due to response length */ +int err_conn = 0; /* requests failed due to connection drop */ +int err_recv = 0; /* requests failed due to broken read */ +int err_except = 0; /* requests failed due to exception */ +int err_response = 0; /* requests with invalid or non-200 response */ #ifdef USE_SSL int is_ssl; @@ -316,11 +329,7 @@ char *ssl_info = NULL; BIO *bio_out,*bio_err; #endif -/* store error cases */ -int err_length = 0, err_conn = 0, err_except = 0; -int err_response = 0; - -apr_time_t start, endtime; +apr_time_t start, lasttime, stoptime; /* global request (and its length) */ char _request[2048]; @@ -334,7 +343,7 @@ char buffer[8192]; int percs[] = {50, 66, 75, 80, 90, 95, 98, 99, 100}; struct connection *con; /* connection array */ -struct data *stats; /* date for each request */ +struct data *stats; /* data for each request */ apr_pool_t *cntxt; apr_pollset_t *readbits; @@ -356,7 +365,7 @@ static void err(char *s) { fprintf(stderr, "%s\n", s); if (done) - printf("Total of %ld requests completed\n" , done); + printf("Total of %d requests completed\n" , done); exit(1); } @@ -370,7 +379,7 @@ static void apr_err(char *s, apr_status_t rv) "%s: %s (%d)\n", s, apr_strerror(rv, buf, sizeof buf), rv); if (done) - printf("Total of %ld requests completed\n" , done); + printf("Total of %d requests completed\n" , done); exit(rv); } @@ -420,7 +429,6 @@ static void ssl_state_cb(const SSL *s, int w, int r) } #ifndef RAND_MAX -#include <limits.h> #define RAND_MAX INT_MAX #endif @@ -609,18 +617,20 @@ static void ssl_proceed_handshake(struct connection *c) static void write_request(struct connection * c) { do { - apr_time_t tnow = apr_time_now(); + apr_time_t tnow; apr_size_t l = c->rwrite; apr_status_t e = APR_SUCCESS; /* prevent gcc warning */ + tnow = lasttime = apr_time_now(); + /* * First time round ? */ if (c->rwrite == 0) { apr_socket_timeout_set(c->aprsock, 0); c->connect = tnow; - c->rwrite = reqlen; c->rwrote = 0; + c->rwrite = reqlen; if (posting) c->rwrite += postlen; } @@ -647,30 +657,19 @@ static void write_request(struct connection * c) #endif e = apr_socket_send(c->aprsock, request + c->rwrote, &l); - /* - * Bail early on the most common case - */ - if (l == c->rwrite) - break; - - if (e != APR_SUCCESS) { - /* - * Let's hope this traps EWOULDBLOCK too ! - */ - if (!APR_STATUS_IS_EAGAIN(e)) { - epipe++; - printf("Send request failed!\n"); - close_connection(c); - } + if (e != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(e)) { + epipe++; + printf("Send request failed!\n"); + close_connection(c); return; } + totalposted += l; c->rwrote += l; c->rwrite -= l; - } while (1); + } while (c->rwrite); - totalposted += c->rwrite; c->state = STATE_READ; - c->endwrite = apr_time_now(); + c->endwrite = lasttime = apr_time_now(); { apr_pollfd_t new_pollfd; new_pollfd.desc_type = APR_POLL_SOCKET; @@ -723,15 +722,14 @@ static int compwait(struct data * a, struct data * b) return 0; } -static void output_results(void) +static void output_results(int sig) { - apr_interval_time_t timetakenusec; - float timetaken; + double timetaken; - endtime = apr_time_now(); - timetakenusec = endtime - start; - timetaken = ((float)apr_time_sec(timetakenusec)) + - ((float)apr_time_usec(timetakenusec)) / 1000000.0F; + if (sig) { + lasttime = apr_time_now(); /* record final time if interrupted */ + } + timetaken = (double) (lasttime - start) / APR_USEC_PER_SEC; printf("\n\n"); printf("Server Software: %s\n", servername); @@ -747,45 +745,43 @@ static void output_results(void) printf("Document Length: %" APR_SIZE_T_FMT " bytes\n", doclen); printf("\n"); printf("Concurrency Level: %d\n", concurrency); - printf("Time taken for tests: %ld.%03ld seconds\n", - (long) apr_time_sec(timetakenusec), - (long) apr_time_usec(timetakenusec)); - printf("Complete requests: %ld\n", done); - printf("Failed requests: %ld\n", bad); + printf("Time taken for tests: %.3f seconds\n", timetaken); + printf("Complete requests: %d\n", done); + printf("Failed requests: %d\n", bad); if (bad) - printf(" (Connect: %d, Length: %d, Exceptions: %d)\n", - err_conn, err_length, err_except); - printf("Write errors: %ld\n", epipe); + printf(" (Connect: %d, Receive: %d, Length: %d, Exceptions: %d)\n", + err_conn, err_recv, err_length, err_except); + printf("Write errors: %d\n", epipe); if (err_response) printf("Non-2xx responses: %d\n", err_response); if (keepalive) - printf("Keep-Alive requests: %ld\n", doneka); - printf("Total transferred: %ld bytes\n", totalread); + printf("Keep-Alive requests: %d\n", doneka); + printf("Total transferred: %" APR_INT64_T_FMT " bytes\n", totalread); if (posting > 0) - printf("Total POSTed: %ld\n", totalposted); - printf("HTML transferred: %ld bytes\n", totalbread); + printf("Total POSTed: %" APR_INT64_T_FMT "\n", totalposted); + printf("HTML transferred: %" APR_INT64_T_FMT " bytes\n", totalbread); /* avoid divide by zero */ - if (timetaken) { + if (timetaken && done) { printf("Requests per second: %.2f [#/sec] (mean)\n", - (float) (done / timetaken)); + (double) done / timetaken); printf("Time per request: %.3f [ms] (mean)\n", - (float) (1000 * concurrency * timetaken / done)); + (double) concurrency * timetaken * 1000 / done); printf("Time per request: %.3f [ms] (mean, across all concurrent requests)\n", - (float) (1000 * timetaken / done)); + (double) timetaken * 1000 / done); printf("Transfer rate: %.2f [Kbytes/sec] received\n", - (float) (totalread / 1024 / timetaken)); + (double) totalread / 1024 / timetaken); if (posting > 0) { printf(" %.2f kb/s sent\n", - (float) (totalposted / timetaken / 1024)); + (double) totalposted / timetaken / 1024); printf(" %.2f kb/s total\n", - (float) ((totalread + totalposted) / timetaken / 1024)); + (double) (totalread + totalposted) / timetaken / 1024); } } - if (requests) { + if (done > 0) { /* work out connection times */ - long i; + int i; apr_time_t totalcon = 0, total = 0, totald = 0, totalwait = 0; apr_time_t meancon, meantot, meand, meanwait; apr_interval_time_t mincon = AB_MAX, mintot = AB_MAX, mind = AB_MAX, @@ -794,119 +790,117 @@ static void output_results(void) apr_interval_time_t mediancon = 0, mediantot = 0, mediand = 0, medianwait = 0; double sdtot = 0, sdcon = 0, sdd = 0, sdwait = 0; - for (i = 0; i < requests; i++) { - struct data s = stats[i]; - mincon = ap_min(mincon, s.ctime); - mintot = ap_min(mintot, s.time); - mind = ap_min(mind, s.time - s.ctime); - minwait = ap_min(minwait, s.waittime); - - maxcon = ap_max(maxcon, s.ctime); - maxtot = ap_max(maxtot, s.time); - maxd = ap_max(maxd, s.time - s.ctime); - maxwait = ap_max(maxwait, s.waittime); - - totalcon += s.ctime; - total += s.time; - totald += s.time - s.ctime; - totalwait += s.waittime; + for (i = 0; i < done; i++) { + struct data *s = &stats[i]; + mincon = ap_min(mincon, s->ctime); + mintot = ap_min(mintot, s->time); + mind = ap_min(mind, s->time - s->ctime); + minwait = ap_min(minwait, s->waittime); + + maxcon = ap_max(maxcon, s->ctime); + maxtot = ap_max(maxtot, s->time); + maxd = ap_max(maxd, s->time - s->ctime); + maxwait = ap_max(maxwait, s->waittime); + + totalcon += s->ctime; + total += s->time; + totald += s->time - s->ctime; + totalwait += s->waittime; } - meancon = totalcon / requests; - meantot = total / requests; - meand = totald / requests; - meanwait = totalwait / requests; + meancon = totalcon / done; + meantot = total / done; + meand = totald / done; + meanwait = totalwait / done; /* calculating the sample variance: the sum of the squared deviations, divided by n-1 */ - for (i = 0; i < requests; i++) { - struct data s = stats[i]; + for (i = 0; i < done; i++) { + struct data *s = &stats[i]; double a; - a = ((double)s.time - meantot); + a = ((double)s->time - meantot); sdtot += a * a; - a = ((double)s.ctime - meancon); + a = ((double)s->ctime - meancon); sdcon += a * a; - a = ((double)s.time - (double)s.ctime - meand); + a = ((double)s->time - (double)s->ctime - meand); sdd += a * a; - a = ((double)s.waittime - meanwait); + a = ((double)s->waittime - meanwait); sdwait += a * a; } - sdtot = (requests > 1) ? sqrt(sdtot / (requests - 1)) : 0; - sdcon = (requests > 1) ? sqrt(sdcon / (requests - 1)) : 0; - sdd = (requests > 1) ? sqrt(sdd / (requests - 1)) : 0; - sdwait = (requests > 1) ? sqrt(sdwait / (requests - 1)) : 0; + sdtot = (done > 1) ? sqrt(sdtot / (done - 1)) : 0; + sdcon = (done > 1) ? sqrt(sdcon / (done - 1)) : 0; + sdd = (done > 1) ? sqrt(sdd / (done - 1)) : 0; + sdwait = (done > 1) ? sqrt(sdwait / (done - 1)) : 0; - if (gnuplot) { - FILE *out = fopen(gnuplot, "w"); - long i; - apr_time_t sttime; - char tmstring[1024];/* XXXX */ - if (!out) { - perror("Cannot open gnuplot output file"); - exit(1); - } - fprintf(out, "starttime\tseconds\tctime\tdtime\tttime\twait\n"); - for (i = 0; i < requests; i++) { - apr_time_t diff = stats[i].time - stats[i].ctime; - - sttime = stats[i].starttime; - (void) apr_ctime(tmstring, sttime); - fprintf(out, "%s\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\n", - tmstring, - sttime, - stats[i].ctime, - diff, - stats[i].time, - stats[i].waittime); - } - fclose(out); - } /* * XXX: what is better; this hideous cast of the compradre function; or * the four warnings during compile ? dirkx just does not know and * hates both/ */ - qsort(stats, requests, sizeof(struct data), + qsort(stats, done, sizeof(struct data), (int (*) (const void *, const void *)) compradre); - if ((requests > 1) && (requests % 2)) - mediancon = (stats[requests / 2].ctime + stats[requests / 2 + 1].ctime) / 2; + if ((done > 1) && (done % 2)) + mediancon = (stats[done / 2].ctime + stats[done / 2 + 1].ctime) / 2; else - mediancon = stats[requests / 2].ctime; + mediancon = stats[done / 2].ctime; - qsort(stats, requests, sizeof(struct data), + qsort(stats, done, sizeof(struct data), (int (*) (const void *, const void *)) compri); - if ((requests > 1) && (requests % 2)) - mediand = (stats[requests / 2].time + stats[requests / 2 + 1].time \ - -stats[requests / 2].ctime - stats[requests / 2 + 1].ctime) / 2; + if ((done > 1) && (done % 2)) + mediand = (stats[done / 2].time + stats[done / 2 + 1].time \ + -stats[done / 2].ctime - stats[done / 2 + 1].ctime) / 2; else - mediand = stats[requests / 2].time - stats[requests / 2].ctime; + mediand = stats[done / 2].time - stats[done / 2].ctime; - qsort(stats, requests, sizeof(struct data), + qsort(stats, done, sizeof(struct data), (int (*) (const void *, const void *)) compwait); - if ((requests > 1) && (requests % 2)) - medianwait = (stats[requests / 2].waittime + stats[requests / 2 + 1].waittime) / 2; + if ((done > 1) && (done % 2)) + medianwait = (stats[done / 2].waittime + stats[done / 2 + 1].waittime) / 2; else - medianwait = stats[requests / 2].waittime; + medianwait = stats[done / 2].waittime; - qsort(stats, requests, sizeof(struct data), + qsort(stats, done, sizeof(struct data), (int (*) (const void *, const void *)) comprando); - if ((requests > 1) && (requests % 2)) - mediantot = (stats[requests / 2].time + stats[requests / 2 + 1].time) / 2; + if ((done > 1) && (done % 2)) + mediantot = (stats[done / 2].time + stats[done / 2 + 1].time) / 2; else - mediantot = stats[requests / 2].time; + mediantot = stats[done / 2].time; printf("\nConnection Times (ms)\n"); + /* + * Reduce stats from apr time to milliseconds + */ + mincon = ap_round_ms(mincon); + mind = ap_round_ms(mind); + minwait = ap_round_ms(minwait); + mintot = ap_round_ms(mintot); + meancon = ap_round_ms(meancon); + meand = ap_round_ms(meand); + meanwait = ap_round_ms(meanwait); + meantot = ap_round_ms(meantot); + mediancon = ap_round_ms(mediancon); + mediand = ap_round_ms(mediand); + medianwait = ap_round_ms(medianwait); + mediantot = ap_round_ms(mediantot); + maxcon = ap_round_ms(maxcon); + maxd = ap_round_ms(maxd); + maxwait = ap_round_ms(maxwait); + maxtot = ap_round_ms(maxtot); + sdcon = ap_double_ms(sdcon); + sdd = ap_double_ms(sdd); + sdwait = ap_double_ms(sdwait); + sdtot = ap_double_ms(sdtot); if (confidence) { -#define CONF_FMT_STRING "%5" APR_TIME_T_FMT " %4d %5.1f %6" APR_TIME_T_FMT " %7" APR_TIME_T_FMT "\n" +#define CONF_FMT_STRING "%5" APR_TIME_T_FMT " %4" APR_TIME_T_FMT " %5.1f %6" APR_TIME_T_FMT " %7" APR_TIME_T_FMT "\n" printf(" min mean[+/-sd] median max\n"); printf("Connect: " CONF_FMT_STRING, - mincon, (int) (meancon + 0.5), sdcon, mediancon, maxcon); + mincon, meancon, sdcon, mediancon, maxcon); printf("Processing: " CONF_FMT_STRING, - mind, (int) (meand + 0.5), sdd, mediand, maxd); + mind, meand, sdd, mediand, maxd); printf("Waiting: " CONF_FMT_STRING, - minwait, (int) (meanwait + 0.5), sdwait, medianwait, maxwait); + minwait, meanwait, sdwait, medianwait, maxwait); printf("Total: " CONF_FMT_STRING, - mintot, (int) (meantot + 0.5), sdtot, mediantot, maxtot); + mintot, meantot, sdtot, mediantot, maxtot); #undef CONF_FMT_STRING #define SANE(what,mean,median,sd) \ @@ -928,51 +922,73 @@ static void output_results(void) else { printf(" min avg max\n"); #define CONF_FMT_STRING "%5" APR_TIME_T_FMT " %5" APR_TIME_T_FMT "%5" APR_TIME_T_FMT "\n" - printf("Connect: " CONF_FMT_STRING, - mincon, meancon, maxcon); - printf("Processing: " CONF_FMT_STRING, - mintot - mincon, meantot - meancon, maxtot - maxcon); - printf("Total: " CONF_FMT_STRING, - mintot, meantot, maxtot); + printf("Connect: " CONF_FMT_STRING, mincon, meancon, maxcon); + printf("Processing: " CONF_FMT_STRING, mintot - mincon, + meantot - meancon, + maxtot - maxcon); + printf("Total: " CONF_FMT_STRING, mintot, meantot, maxtot); #undef CONF_FMT_STRING } /* Sorted on total connect times */ - if (percentile && (requests > 1)) { + if (percentile && (done > 1)) { printf("\nPercentage of the requests served within a certain time (ms)\n"); for (i = 0; i < sizeof(percs) / sizeof(int); i++) { if (percs[i] <= 0) printf(" 0%% <0> (never)\n"); else if (percs[i] >= 100) printf(" 100%% %5" APR_TIME_T_FMT " (longest request)\n", - stats[requests - 1].time); + ap_round_ms(stats[done - 1].time)); else printf(" %d%% %5" APR_TIME_T_FMT "\n", percs[i], - stats[(int) (requests * percs[i] / 100)].time); + ap_round_ms(stats[(int) (done * percs[i] / 100)].time)); } } if (csvperc) { FILE *out = fopen(csvperc, "w"); - int i; if (!out) { perror("Cannot open CSV output file"); exit(1); } fprintf(out, "" "Percentage served" "," "Time in ms" "\n"); for (i = 0; i < 100; i++) { - apr_time_t t; + double t; if (i == 0) - t = stats[0].time; + t = ap_double_ms(stats[0].time); else if (i == 100) - t = stats[requests - 1].time; + t = ap_double_ms(stats[done - 1].time); else - t = stats[(int) (0.5 + requests * i / 100.0)].time; - fprintf(out, "%d,%e\n", i, (double)t); + t = ap_double_ms(stats[(int) (0.5 + done * i / 100.0)].time); + fprintf(out, "%d,%.3f\n", i, t); + } + fclose(out); + } + if (gnuplot) { + FILE *out = fopen(gnuplot, "w"); + char tmstring[APR_CTIME_LEN]; + if (!out) { + perror("Cannot open gnuplot output file"); + exit(1); + } + fprintf(out, "starttime\tseconds\tctime\tdtime\tttime\twait\n"); + for (i = 0; i < done; i++) { + (void) apr_ctime(tmstring, stats[i].starttime); + fprintf(out, "%s\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT + "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT + "\t%" APR_TIME_T_FMT "\n", tmstring, + apr_time_sec(stats[i].starttime), + ap_round_ms(stats[i].ctime), + ap_round_ms(stats[i].time - stats[i].ctime), + ap_round_ms(stats[i].time), + ap_round_ms(stats[i].waittime)); } fclose(out); } + } + if (sig) { + exit(1); } } @@ -982,10 +998,7 @@ static void output_results(void) static void output_html_results(void) { - long timetaken; - - endtime = apr_time_now(); - timetaken = (long)((endtime - start) / 1000); + double timetaken = (double) (lasttime - start) / APR_USEC_PER_SEC; printf("\n\n<table %s>\n", tablestring); printf("<tr %s><th colspan=2 %s>Server Software:</th>" @@ -1007,14 +1020,13 @@ static void output_html_results(void) "<td colspan=2 %s>%d</td></tr>\n", trstring, tdstring, tdstring, concurrency); printf("<tr %s><th colspan=2 %s>Time taken for tests:</th>" - "<td colspan=2 %s>%" APR_INT64_T_FMT ".%03ld seconds</td></tr>\n", - trstring, tdstring, tdstring, apr_time_sec(timetaken), - (long)apr_time_usec(timetaken)); + "<td colspan=2 %s>%.3f seconds</td></tr>\n", + trstring, tdstring, tdstring, timetaken); printf("<tr %s><th colspan=2 %s>Complete requests:</th>" - "<td colspan=2 %s>%ld</td></tr>\n", + "<td colspan=2 %s>%d</td></tr>\n", trstring, tdstring, tdstring, done); printf("<tr %s><th colspan=2 %s>Failed requests:</th>" - "<td colspan=2 %s>%ld</td></tr>\n", + "<td colspan=2 %s>%d</td></tr>\n", trstring, tdstring, tdstring, bad); if (bad) printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n", @@ -1025,56 +1037,65 @@ static void output_html_results(void) trstring, tdstring, tdstring, err_response); if (keepalive) printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>" - "<td colspan=2 %s>%ld</td></tr>\n", + "<td colspan=2 %s>%d</td></tr>\n", trstring, tdstring, tdstring, doneka); printf("<tr %s><th colspan=2 %s>Total transferred:</th>" - "<td colspan=2 %s>%ld bytes</td></tr>\n", + "<td colspan=2 %s>%" APR_INT64_T_FMT " bytes</td></tr>\n", trstring, tdstring, tdstring, totalread); if (posting > 0) printf("<tr %s><th colspan=2 %s>Total POSTed:</th>" - "<td colspan=2 %s>%ld</td></tr>\n", + "<td colspan=2 %s>%" APR_INT64_T_FMT "</td></tr>\n", trstring, tdstring, tdstring, totalposted); printf("<tr %s><th colspan=2 %s>HTML transferred:</th>" - "<td colspan=2 %s>%ld bytes</td></tr>\n", + "<td colspan=2 %s>%" APR_INT64_T_FMT " bytes</td></tr>\n", trstring, tdstring, tdstring, totalbread); /* avoid divide by zero */ if (timetaken) { printf("<tr %s><th colspan=2 %s>Requests per second:</th>" "<td colspan=2 %s>%.2f</td></tr>\n", - trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken); + trstring, tdstring, tdstring, (double) done * 1000 / timetaken); printf("<tr %s><th colspan=2 %s>Transfer rate:</th>" "<td colspan=2 %s>%.2f kb/s received</td></tr>\n", - trstring, tdstring, tdstring, (float) (totalread) / timetaken); + trstring, tdstring, tdstring, (double) totalread / timetaken); if (posting > 0) { printf("<tr %s><td colspan=2 %s> </td>" "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n", trstring, tdstring, tdstring, - (float) (totalposted) / timetaken); + (double) totalposted / timetaken); printf("<tr %s><td colspan=2 %s> </td>" "<td colspan=2 %s>%.2f kb/s total</td></tr>\n", trstring, tdstring, tdstring, - (float) (totalread + totalposted) / timetaken); + (double) (totalread + totalposted) / timetaken); } } { /* work out connection times */ - long i; + int i; apr_interval_time_t totalcon = 0, total = 0; apr_interval_time_t mincon = AB_MAX, mintot = AB_MAX; apr_interval_time_t maxcon = 0, maxtot = 0; - for (i = 0; i < requests; i++) { - struct data s = stats[i]; - mincon = ap_min(mincon, s.ctime); - mintot = ap_min(mintot, s.time); - maxcon = ap_max(maxcon, s.ctime); - maxtot = ap_max(maxtot, s.time); - totalcon += s.ctime; - total += s.time; + for (i = 0; i < done; i++) { + struct data *s = &stats[i]; + mincon = ap_min(mincon, s->ctime); + mintot = ap_min(mintot, s->time); + maxcon = ap_max(maxcon, s->ctime); + maxtot = ap_max(maxtot, s->time); + totalcon += s->ctime; + total += s->time; } - - if (requests > 0) { /* avoid division by zero (if 0 requests) */ + /* + * Reduce stats from apr time to milliseconds + */ + mincon = ap_round_ms(mincon); + mintot = ap_round_ms(mintot); + maxcon = ap_round_ms(maxcon); + maxtot = ap_round_ms(maxtot); + totalcon = ap_round_ms(totalcon); + total = ap_round_ms(total); + + if (done > 0) { /* avoid division by zero (if 0 done) */ printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n", trstring, tdstring); printf("<tr %s><th %s> </th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n", @@ -1083,18 +1104,18 @@ static void output_html_results(void) "<td %s>%5" APR_TIME_T_FMT "</td>" "<td %s>%5" APR_TIME_T_FMT "</td>" "<td %s>%5" APR_TIME_T_FMT "</td></tr>\n", - trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon); + trstring, tdstring, tdstring, mincon, tdstring, totalcon / done, tdstring, maxcon); printf("<tr %s><th %s>Processing:</th>" "<td %s>%5" APR_TIME_T_FMT "</td>" "<td %s>%5" APR_TIME_T_FMT "</td>" "<td %s>%5" APR_TIME_T_FMT "</td></tr>\n", trstring, tdstring, tdstring, mintot - mincon, tdstring, - (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon); + (total / done) - (totalcon / done), tdstring, maxtot - maxcon); printf("<tr %s><th %s>Total:</th>" "<td %s>%5" APR_TIME_T_FMT "</td>" "<td %s>%5" APR_TIME_T_FMT "</td>" "<td %s>%5" APR_TIME_T_FMT "</td></tr>\n", - trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot); + trstring, tdstring, tdstring, mintot, tdstring, total / done, tdstring, maxtot); } printf("</table>\n"); } @@ -1118,8 +1139,9 @@ static void start_connect(struct connection * c) c->gotheader = 0; c->rwrite = 0; if (c->ctx) - apr_pool_destroy(c->ctx); - apr_pool_create(&c->ctx, cntxt); + apr_pool_clear(c->ctx); + else + apr_pool_create(&c->ctx, cntxt); if ((rv = apr_socket_create(&c->aprsock, destsa->family, SOCK_STREAM, 0, c->ctx)) != APR_SUCCESS) { @@ -1129,7 +1151,21 @@ static void start_connect(struct connection * c) != APR_SUCCESS) { apr_err("socket nonblock", rv); } - c->start = apr_time_now(); + + if (windowsize != 0) { + rv = apr_socket_opt_set(c->aprsock, APR_SO_SNDBUF, + windowsize); + if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) { + apr_err("socket send buffer", rv); + } + rv = apr_socket_opt_set(c->aprsock, APR_SO_RCVBUF, + windowsize); + if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) { + apr_err("socket receive buffer", rv); + } + } + + c->start = lasttime = apr_time_now(); #ifdef USE_SSL if (is_ssl) { BIO *bio; @@ -1220,18 +1256,16 @@ static void close_connection(struct connection * c) } /* save out time */ if (done < requests) { - struct data s; - if ((done) && heartbeatres && !(done % heartbeatres)) { - fprintf(stderr, "Completed %ld requests\n", done); + struct data *s = &stats[done++]; + c->done = lasttime = apr_time_now(); + s->starttime = c->start; + s->ctime = ap_max(0, c->connect - c->start); + s->time = ap_max(0, c->done - c->start); + s->waittime = ap_max(0, c->beginread - c->endwrite); + if (heartbeatres && !(done % heartbeatres)) { + fprintf(stderr, "Completed %d requests\n", done); fflush(stderr); } - c->done = apr_time_now(); - s.read = c->read; - s.starttime = c->start; - s.ctime = ap_max(0, (c->connect - c->start) / 1000); - s.time = ap_max(0, (c->done - c->start) / 1000); - s.waittime = ap_max(0, (c->beginread - c->endwrite) / 1000); - stats[done++] = s; } } @@ -1304,10 +1338,18 @@ static void read_connection(struct connection * c) } /* catch legitimate fatal apr_socket_recv errors */ else if (status != APR_SUCCESS) { - err_except++; /* XXX: is this the right error counter? */ - /* XXX: Should errors here be fatal, or should we allow a - * certain number of them before completely failing? -aaron */ - apr_err("apr_socket_recv", status); + err_recv++; + if (recverrok) { + bad++; + close_connection(c); + if (verbosity >= 1) { + char buf[120]; + fprintf(stderr,"%s: %s (%d)\n", "apr_socket_recv", apr_strerror(status, buf, sizeof buf), status); + } + return; + } else { + apr_err("apr_socket_recv", status); + } } } @@ -1329,8 +1371,8 @@ static void read_connection(struct connection * c) status = apr_xlate_conv_buffer(from_ascii, buffer, &inbytes_left, c->cbuff + c->cbx, &outbytes_left); if (status || inbytes_left || outbytes_left) { - fprintf(stderr, "only simple translation is supported (%d/%u/%u)\n", - status, inbytes_left, outbytes_left); + fprintf(stderr, "only simple translation is supported (%d/%" APR_SIZE_T_FMT + "/%" APR_SIZE_T_FMT ")\n", status, inbytes_left, outbytes_left); exit(1); } #else @@ -1424,8 +1466,14 @@ static void read_connection(struct connection * c) cl = strstr(c->cbuff, "Content-length:"); if (cl) { c->keepalive = 1; - c->length = atoi(cl + 16); + /* response to HEAD doesn't have entity body */ + c->length = posting >= 0 ? atoi(cl + 16) : 0; } + /* The response may not have a Content-Length header */ + if (!cl) { + c->keepalive = 1; + c->length = 0; + } } c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy; totalbread += c->bread; @@ -1450,26 +1498,25 @@ static void read_connection(struct connection * c) err_length++; } if (done < requests) { - struct data s; + struct data *s = &stats[done++]; doneka++; - if (done && heartbeatres && !(done % heartbeatres)) { - fprintf(stderr, "Completed %ld requests\n", done); + c->done = apr_time_now(); + s->starttime = c->start; + s->ctime = ap_max(0, c->connect - c->start); + s->time = ap_max(0, c->done - c->start); + s->waittime = ap_max(0, c->beginread - c->endwrite); + if (heartbeatres && !(done % heartbeatres)) { + fprintf(stderr, "Completed %d requests\n", done); fflush(stderr); } - c->done = apr_time_now(); - s.read = c->read; - s.starttime = c->start; - s.ctime = ap_max(0, (c->connect - c->start) / 1000); - s.waittime = ap_max(0, (c->beginread - c->endwrite) / 1000); - s.time = ap_max(0, (c->done - c->start) / 1000); - stats[done++] = s; } c->keepalive = 0; c->length = 0; c->gotheader = 0; c->cbx = 0; c->read = c->bread = 0; - c->start = c->connect = apr_time_now(); /* zero connect time with keep-alive */ + /* zero connect time with keep-alive */ + c->start = c->connect = lasttime = apr_time_now(); write_request(c); } } @@ -1480,9 +1527,9 @@ static void read_connection(struct connection * c) static void test(void) { - apr_time_t now; + apr_time_t stoptime; apr_int16_t rv; - long i; + int i; apr_status_t status; int snprintf_res = 0; #ifdef NOT_ASCII @@ -1507,8 +1554,6 @@ static void test(void) fflush(stdout); } - now = apr_time_now(); - con = calloc(concurrency, sizeof(struct connection)); stats = calloc(requests, sizeof(struct data)); @@ -1595,8 +1640,9 @@ static void test(void) status = apr_xlate_conv_buffer(to_ascii, request, &inbytes_left, request, &outbytes_left); if (status || inbytes_left || outbytes_left) { - fprintf(stderr, "only simple translation is supported (%d/%u/%u)\n", - status, inbytes_left, outbytes_left); + fprintf(stderr, "only simple translation is supported (%d/%" + APR_SIZE_T_FMT "/%" APR_SIZE_T_FMT ")\n", + status, inbytes_left, outbytes_left); exit(1); } #endif /* NOT_ASCII */ @@ -1611,7 +1657,13 @@ static void test(void) } /* ok - lets start */ - start = apr_time_now(); + start = lasttime = apr_time_now(); + stoptime = tlimit ? (start + apr_time_from_sec(tlimit)) : AB_MAX; + +#ifdef SIGINT + /* Output the results if the user terminates the run early. */ + apr_signal(SIGINT, output_results); +#endif /* initialise lots of requests */ for (i = 0; i < concurrency; i++) { @@ -1619,18 +1671,9 @@ static void test(void) start_connect(&con[i]); } - while (done < requests) { + do { apr_int32_t n; - apr_int32_t timed; - const apr_pollfd_t *pollresults; - - /* check for time limit expiry */ - now = apr_time_now(); - timed = (apr_int32_t)apr_time_sec(now - start); - if (tlimit && timed >= tlimit) { - requests = done; /* so stats are correct */ - break; /* no need to do another round */ - } + const apr_pollfd_t *pollresults; n = concurrency; status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults); @@ -1645,7 +1688,7 @@ static void test(void) const apr_pollfd_t *next_fd = &(pollresults[i]); struct connection *c; - c = next_fd->client_data; + c = next_fd->client_data; /* * If the connection isn't connected how can we check it? @@ -1733,17 +1776,17 @@ static void test(void) apr_pollset_add(readbits, &new_pollfd); } } - } - + } while (lasttime < stoptime && done < requests); + if (heartbeatres) - fprintf(stderr, "Finished %ld requests\n", done); + fprintf(stderr, "Finished %d requests\n", done); else printf("..done\n"); if (use_html) output_html_results(); else - output_results(); + output_results(0); } /* ------------------------------------------------------- */ @@ -1752,16 +1795,16 @@ static void test(void) static void copyright(void) { if (!use_html) { - printf("This is ApacheBench, Version %s\n", AP_AB_BASEREVISION " <$Revision: 1.146 $> apache-2.0"); + printf("This is ApacheBench, Version %s\n", AP_AB_BASEREVISION " <$Revision: 655654 $>"); printf("Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); - printf("Copyright 2006 The Apache Software Foundation, http://www.apache.org/\n"); + printf("Licensed to The Apache Software Foundation, http://www.apache.org/\n"); printf("\n"); } else { printf("<p>\n"); - printf(" This is ApacheBench, Version %s <i><%s></i> apache-2.0<br>\n", AP_AB_BASEREVISION, "$Revision: 1.146 $"); + printf(" This is ApacheBench, Version %s <i><%s></i><br>\n", AP_AB_BASEREVISION, "$Revision: 655654 $"); printf(" Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n"); - printf(" Copyright 2006 The Apache Software Foundation, http://www.apache.org/<br>\n"); + printf(" Licensed to The Apache Software Foundation, http://www.apache.org/<br>\n"); printf("</p>\n<p>\n"); } } @@ -1774,12 +1817,17 @@ static void usage(const char *progname) "[s]" #endif "://]hostname[:port]/path\n", progname); +/* 80 column ruler: ******************************************************************************** + */ fprintf(stderr, "Options are:\n"); fprintf(stderr, " -n requests Number of requests to perform\n"); fprintf(stderr, " -c concurrency Number of multiple requests to make\n"); fprintf(stderr, " -t timelimit Seconds to max. wait for responses\n"); - fprintf(stderr, " -p postfile File containing data to POST\n"); - fprintf(stderr, " -T content-type Content-type header for POSTing\n"); + fprintf(stderr, " -b windowsize Size of TCP send/receive buffer, in bytes\n"); + fprintf(stderr, " -p postfile File containing data to POST. Remember also to set -T\n"); + fprintf(stderr, " -T content-type Content-type header for POSTing, eg.\n"); + fprintf(stderr, " 'application/x-www-form-urlencoded'\n"); + fprintf(stderr, " Default is 'text/plain'\n"); fprintf(stderr, " -v verbosity How much troubleshooting info to print\n"); fprintf(stderr, " -w Print out results in HTML tables\n"); fprintf(stderr, " -i Use HEAD instead of GET\n"); @@ -1800,6 +1848,7 @@ static void usage(const char *progname) fprintf(stderr, " -S Do not show confidence estimators and warnings.\n"); fprintf(stderr, " -g filename Output collected data to gnuplot format file.\n"); fprintf(stderr, " -e filename Output CSV file with percentages served\n"); + fprintf(stderr, " -r Don't exit on socket receive errors.\n"); fprintf(stderr, " -h Display usage information (this message)\n"); #ifdef USE_SSL fprintf(stderr, " -Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)\n"); @@ -1898,7 +1947,12 @@ static int open_postfile(const char *pfile) return rv; } - apr_file_info_get(&finfo, APR_FINFO_NORM, postfd); + rv = apr_file_info_get(&finfo, APR_FINFO_NORM, postfd); + if (rv != APR_SUCCESS) { + fprintf(stderr, "ab: Could not stat POST data file (%s): %s\n", pfile, + apr_strerror(rv, errmsg, sizeof errmsg)); + return rv; + } postlen = (apr_size_t)finfo.size; postdata = malloc(postlen); if (!postdata) { @@ -1962,7 +2016,7 @@ int main(int argc, const char * const argv[]) #endif apr_getopt_init(&opt, cntxt, argc, argv); - while ((status = apr_getopt(opt, "n:c:t:T:p:v:kVhwix:y:z:C:H:P:A:g:X:de:Sq" + while ((status = apr_getopt(opt, "n:c:t:b:T:p:v:rkVhwix:y:z:C:H:P:A:g:X:de:Sq" #ifdef USE_SSL "Z:f:" #endif @@ -1970,7 +2024,7 @@ int main(int argc, const char * const argv[]) switch (c) { case 'n': requests = atoi(optarg); - if (!requests) { + if (requests <= 0) { err("Invalid number of requests\n"); } break; @@ -1983,6 +2037,9 @@ int main(int argc, const char * const argv[]) case 'c': concurrency = atoi(optarg); break; + case 'b': + windowsize = atoi(optarg); + break; case 'i': if (posting == 1) err("Cannot mix POST and HEAD\n"); @@ -2010,6 +2067,9 @@ int main(int argc, const char * const argv[]) exit(r); } break; + case 'r': + recverrok = 1; + break; case 'v': verbosity = atoi(optarg); break; diff --git a/support/htpasswd.c b/support/htpasswd.c index 6bce702d..2eadc78e 100644 --- a/support/htpasswd.c +++ b/support/htpasswd.c @@ -115,6 +115,30 @@ static void to64(char *s, unsigned long v, int n) } } +static void generate_salt(char *s, size_t size) +{ + static unsigned char tbl[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + size_t i; + for (i = 0; i < size; ++i) { + int idx = (int) (64.0 * rand() / (RAND_MAX + 1.0)); + s[i] = tbl[idx]; + } +} + +static apr_status_t seed_rand(void) +{ + int seed = 0; + apr_status_t rv; + rv = apr_generate_random_bytes((unsigned char*) &seed, sizeof(seed)); + if (rv) { + apr_file_printf(errfile, "Unable to generate random bytes: %pm" NL, &rv); + return rv; + } + srand(seed); + return rv; +} + static void putline(apr_file_t *f, const char *l) { apr_file_puts(l, f); @@ -162,8 +186,10 @@ static int mkrecord(char *user, char *record, apr_size_t rlen, char *passwd, break; case ALG_APMD5: - (void) srand((int) time((time_t *) NULL)); - to64(&salt[0], rand(), 8); + if (seed_rand()) { + break; + } + generate_salt(&salt[0], 8); salt[8] = '\0'; apr_md5_encode((const char *)pw, (const char *)salt, @@ -178,7 +204,9 @@ static int mkrecord(char *user, char *record, apr_size_t rlen, char *passwd, #if !(defined(WIN32) || defined(NETWARE)) case ALG_CRYPT: default: - (void) srand((int) time((time_t *) NULL)); + if (seed_rand()) { + break; + } to64(&salt[0], rand(), 8); salt[8] = '\0'; diff --git a/support/htpasswd.dsp b/support/htpasswd.dsp index 871316f6..4bd9b536 100644 --- a/support/htpasswd.dsp +++ b/support/htpasswd.dsp @@ -49,8 +49,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console -# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /debug /opt:ref +# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib rpcrt4.lib /nologo /subsystem:console +# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib rpcrt4.lib /nologo /subsystem:console /debug /opt:ref # Begin Special Build Tool TargetPath=.\Release\htpasswd.exe SOURCE="$(InputPath)" @@ -79,8 +79,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug -# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug +# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib rpcrt4.lib /nologo /subsystem:console /incremental:no /debug +# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib shell32.lib rpcrt4.lib /nologo /subsystem:console /incremental:no /debug # Begin Special Build Tool TargetPath=.\Debug\htpasswd.exe SOURCE="$(InputPath)" diff --git a/support/rotatelogs.c b/support/rotatelogs.c index a408540a..8fd99dc7 100644 --- a/support/rotatelogs.c +++ b/support/rotatelogs.c @@ -31,6 +31,9 @@ * interval. NB: Using -l in an environment which changes the GMT offset * (such as for BST or DST) can lead to unpredictable results! * + * -f option added Feb, 2008. This causes rotatelog to open/create + * the logfile as soon as it's started, not as soon as it sees + * data. */ @@ -55,7 +58,7 @@ #endif #define BUFSIZE 65536 -#define ERRMSGSZ 128 +#define ERRMSGSZ 256 #ifndef MAX_PATH #define MAX_PATH 1024 @@ -67,7 +70,7 @@ static void usage(const char *argv0, const char *reason) fprintf(stderr, "%s\n", reason); } fprintf(stderr, - "Usage: %s [-l] <logfile> " + "Usage: %s [-l] [-f] <logfile> " "{<rotation time in seconds>|<rotation size in megabytes>} " "[offset minutes from UTC]\n\n", argv0); @@ -92,6 +95,21 @@ static void usage(const char *argv0, const char *reason) exit(1); } +static int get_now(int use_localtime, int utc_offset) +{ + apr_time_t tNow = apr_time_now(); + if (use_localtime) { + /* Check for our UTC offset before using it, since it might + * change if there's a switch between standard and daylight + * savings time. + */ + apr_time_exp_t lt; + apr_time_exp_lt(<, tNow); + utc_offset = lt.tm_gmtoff; + } + return (int)apr_time_sec(tNow) + utc_offset; +} + int main (int argc, const char * const argv[]) { char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ]; @@ -101,10 +119,13 @@ int main (int argc, const char * const argv[]) apr_size_t nRead, nWrite; int use_strftime = 0; int use_localtime = 0; + int bypass_io = 0; int now = 0; const char *szLogRoot; apr_file_t *f_stdin, *nLogFD = NULL, *nLogFDprev = NULL; apr_pool_t *pool; + apr_pool_t *pfile = NULL; + apr_pool_t *pfile_prev = NULL; apr_getopt_t *opt; apr_status_t rv; char c; @@ -116,11 +137,14 @@ int main (int argc, const char * const argv[]) apr_pool_create(&pool, NULL); apr_getopt_init(&opt, pool, argc, argv); - while ((rv = apr_getopt(opt, "l", &c, &optarg)) == APR_SUCCESS) { + while ((rv = apr_getopt(opt, "lf", &c, &optarg)) == APR_SUCCESS) { switch (c) { case 'l': use_localtime = 1; break; + case 'f': + bypass_io = 1; + break; } } @@ -166,21 +190,20 @@ int main (int argc, const char * const argv[]) for (;;) { nRead = sizeof(buf); - if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS) { - exit(3); + /* + * Bypass reading stdin if we are forcing the logfile + * to be opened as soon as we start. Since we won't be + * writing anything, we just want to open the file. + * First time through is the only time we do this + * since we reset bypass_io after the 1st loop + */ + if (!bypass_io) { + if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS) { + exit(3); + } } if (tRotation) { - /* - * Check for our UTC offset every time through the loop, since - * it might change if there's a switch between standard and - * daylight savings time. - */ - if (use_localtime) { - apr_time_exp_t lt; - apr_time_exp_lt(<, apr_time_now()); - utc_offset = lt.tm_gmtoff; - } - now = (int)(apr_time_now() / APR_USEC_PER_SEC) + utc_offset; + now = get_now(use_localtime, utc_offset); if (nLogFD != NULL && now >= tLogEnd) { nLogFDprev = nLogFD; nLogFD = NULL; @@ -213,16 +236,7 @@ int main (int argc, const char * const argv[]) tLogStart = (now / tRotation) * tRotation; } else { - if (use_localtime) { - /* Check for our UTC offset before using it, since it might - * change if there's a switch between standard and daylight - * savings time. - */ - apr_time_exp_t lt; - apr_time_exp_lt(<, apr_time_now()); - utc_offset = lt.tm_gmtoff; - } - tLogStart = (int)apr_time_sec(apr_time_now()) + utc_offset; + tLogStart = get_now(use_localtime, utc_offset); } if (use_strftime) { @@ -237,8 +251,10 @@ int main (int argc, const char * const argv[]) sprintf(buf2, "%s.%010d", szLogRoot, tLogStart); } tLogEnd = tLogStart + tRotation; + pfile_prev = pfile; + apr_pool_create(&pfile, pool); rv = apr_file_open(&nLogFD, buf2, APR_WRITE | APR_CREATE | APR_APPEND, - APR_OS_DEFAULT, pool); + APR_OS_DEFAULT, pfile); if (rv != APR_SUCCESS) { char error[120]; @@ -253,6 +269,8 @@ int main (int argc, const char * const argv[]) } else { nLogFD = nLogFDprev; + apr_pool_destroy(pfile); + pfile = pfile_prev; /* Try to keep this error message constant length * in case it occurs several times. */ apr_snprintf(errbuf, sizeof errbuf, @@ -269,26 +287,58 @@ int main (int argc, const char * const argv[]) } else if (nLogFDprev) { apr_file_close(nLogFDprev); + if (pfile_prev) { + apr_pool_destroy(pfile_prev); + } } nMessCount = 0; } - nWrite = nRead; - apr_file_write(nLogFD, buf, &nWrite); - if (nWrite != nRead) { - nMessCount++; - sprintf(errbuf, - "Error writing to log file. " - "%10d messages lost.\n", - nMessCount); - nWrite = strlen(errbuf); - apr_file_trunc(nLogFD, 0); - if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) { - fprintf(stderr, "Error writing to the file %s\n", buf2); + /* + * If we just bypassed reading stdin, due to bypass_io, + * then we have nothing to write, so skip this. + */ + if (!bypass_io) { + nWrite = nRead; + rv = apr_file_write(nLogFD, buf, &nWrite); + if (rv == APR_SUCCESS && nWrite != nRead) { + /* buffer partially written, which for rotatelogs means we encountered + * an error such as out of space or quota or some other limit reached; + * try to write the rest so we get the real error code + */ + apr_size_t nWritten = nWrite; + + nRead = nRead - nWritten; + nWrite = nRead; + rv = apr_file_write(nLogFD, buf + nWritten, &nWrite); + } + if (nWrite != nRead) { + char strerrbuf[120]; + apr_off_t cur_offset; + + cur_offset = 0; + if (apr_file_seek(nLogFD, APR_CUR, &cur_offset) != APR_SUCCESS) { + cur_offset = -1; + } + apr_strerror(rv, strerrbuf, sizeof strerrbuf); + nMessCount++; + apr_snprintf(errbuf, sizeof errbuf, + "Error %d writing to log file at offset %" APR_OFF_T_FMT ". " + "%10d messages lost (%s)\n", + rv, cur_offset, nMessCount, strerrbuf); + nWrite = strlen(errbuf); + apr_file_trunc(nLogFD, 0); + if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) { + fprintf(stderr, "Error writing to the file %s\n", buf2); exit(2); + } + } + else { + nMessCount++; } } else { - nMessCount++; + /* now worry about reading 'n writing all the time */ + bypass_io = 0; } } /* Of course we never, but prevent compiler warnings */ diff --git a/support/suexec.c b/support/suexec.c index 1037a06c..59371be0 100644 --- a/support/suexec.c +++ b/support/suexec.c @@ -395,13 +395,15 @@ int main(int argc, char *argv[]) log_err("invalid target group name: (%s)\n", target_gname); exit(106); } - gid = gr->gr_gid; - actual_gname = strdup(gr->gr_name); } else { - gid = atoi(target_gname); - actual_gname = strdup(target_gname); + if ((gr = getgrgid(atoi(target_gname))) == NULL) { + log_err("invalid target group id: (%s)\n", target_gname); + exit(106); + } } + gid = gr->gr_gid; + actual_gname = strdup(gr->gr_name); #ifdef _OSD_POSIX /* diff --git a/support/win32/ApacheMonitor.c b/support/win32/ApacheMonitor.c index fa5a3f89..6d97fb7b 100644 --- a/support/win32/ApacheMonitor.c +++ b/support/win32/ApacheMonitor.c @@ -23,7 +23,7 @@ * ==================================================================== */ -#define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 #ifndef STRICT #define STRICT #endif @@ -33,7 +33,6 @@ #if defined(_MSC_VER) && _MSC_VER >= 1400 #define _CRT_SECURE_NO_DEPRECATE -#pragma warning(disable: 4996) #endif #include <windows.h> @@ -43,8 +42,16 @@ #include <shlobj.h> #include <stdlib.h> #include <stdio.h> +#include <WtsApi32.h> +#include <tchar.h> #include "ApacheMonitor.h" +#ifndef AM_STRINGIFY +/** Properly quote a value as a string in the C preprocessor */ +#define AM_STRINGIFY(n) AM_STRINGIFY_HELPER(n) +/** Helper macro for AM_STRINGIFY */ +#define AM_STRINGIFY_HELPER(n) #n +#endif #define OS_VERSION_WIN9X 1 #define OS_VERSION_WINNT 2 @@ -68,24 +75,24 @@ typedef struct _st_APACHE_SERVICE { - LPSTR szServiceName; - LPSTR szDisplayName; - LPSTR szDescription; - LPSTR szImagePath; - LPSTR szComputerName; + LPTSTR szServiceName; + LPTSTR szDisplayName; + LPTSTR szDescription; + LPTSTR szImagePath; + LPTSTR szComputerName; DWORD dwPid; } ST_APACHE_SERVICE; typedef struct _st_MONITORED_COMPUTERS { - LPSTR szComputerName; + LPTSTR szComputerName; HKEY hRegistry; } ST_MONITORED_COMP; /* Global variables */ HINSTANCE g_hInstance = NULL; -CHAR *g_szTitle; /* The title bar text */ -CHAR *g_szWindowClass; /* Window Class Name */ +TCHAR *g_szTitle; /* The title bar text */ +TCHAR *g_szWindowClass; /* Window Class Name */ HICON g_icoStop; HICON g_icoRun; UINT g_bUiTaskbarCreated; @@ -113,10 +120,10 @@ HANDLE g_hpipeStdError; LANGID g_LangID; PROCESS_INFORMATION g_lpRedirectProc; CRITICAL_SECTION g_stcSection; -LPSTR g_szLocalHost; +LPTSTR g_szLocalHost; /* locale language support */ -static CHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1]; +static TCHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1]; void am_ClearServicesSt() @@ -160,11 +167,11 @@ void am_ClearComputersSt() } -BOOL am_IsComputerConnected(LPSTR szComputerName) +BOOL am_IsComputerConnected(LPTSTR szComputerName) { int i = 0; while (g_stComputers[i].szComputerName != NULL) { - if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) { + if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) { return TRUE; } ++i; @@ -173,11 +180,11 @@ BOOL am_IsComputerConnected(LPSTR szComputerName) } -void am_DisconnectComputer(LPSTR szComputerName) +void am_DisconnectComputer(LPTSTR szComputerName) { int i = 0, j; while (g_stComputers[i].szComputerName != NULL) { - if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) { + if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) { break; } ++i; @@ -195,7 +202,7 @@ void am_DisconnectComputer(LPSTR szComputerName) } -void ErrorMessage(LPCSTR szError, BOOL bFatal) +void ErrorMessage(LPCTSTR szError, BOOL bFatal) { LPVOID lpMsgBuf = NULL; if (szError) { @@ -207,8 +214,8 @@ void ErrorMessage(LPCSTR szError, BOOL bFatal) FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), g_LangID, - (LPSTR) &lpMsgBuf, 0, NULL); - MessageBox(NULL, (LPCSTR)lpMsgBuf, + (LPTSTR) &lpMsgBuf, 0, NULL); + MessageBox(NULL, (LPCTSTR)lpMsgBuf, g_lpMsg[IDS_MSG_ERROR - IDS_MSG_FIRST], MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION)); LocalFree(lpMsgBuf); @@ -219,14 +226,37 @@ void ErrorMessage(LPCSTR szError, BOOL bFatal) } -BOOL am_ConnectComputer(LPSTR szComputerName) +int am_RespawnAsUserAdmin(HWND hwnd, DWORD op, LPCTSTR szService, + LPCTSTR szComputerName) +{ + TCHAR args[MAX_PATH + MAX_COMPUTERNAME_LENGTH + 12]; + + if (g_dwOSVersion < OS_VERSION_WIN2K) { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], FALSE); + return 0; + } + + _sntprintf(args, sizeof(args) / sizeof(TCHAR), + _T("%d \"%s\" \"%s\""), op, szService, + szComputerName ? szComputerName : _T("")); + if (!ShellExecute(hwnd, _T("runas"), __targv[0], args, NULL, SW_NORMAL)) { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], + FALSE); + return 0; + } + + return 1; +} + + +BOOL am_ConnectComputer(LPTSTR szComputerName) { int i = 0; HKEY hKeyRemote; - char szTmp[MAX_PATH]; + TCHAR szTmp[MAX_PATH]; while (g_stComputers[i].szComputerName != NULL) { - if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) { + if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) { return FALSE; } ++i; @@ -236,22 +266,23 @@ BOOL am_ConnectComputer(LPSTR szComputerName) } if (RegConnectRegistry(szComputerName, HKEY_LOCAL_MACHINE, &hKeyRemote) != ERROR_SUCCESS) { - sprintf(szTmp, g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST], - szComputerName); + _sntprintf(szTmp, sizeof(szTmp) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST], + szComputerName); ErrorMessage(szTmp, FALSE); return FALSE; } else { - g_stComputers[i].szComputerName = strdup(szComputerName); + g_stComputers[i].szComputerName = _tcsdup(szComputerName); g_stComputers[i].hRegistry = hKeyRemote; return TRUE; } } -LPSTR GetStringRes(int id) +LPTSTR GetStringRes(int id) { - static CHAR buffer[MAX_PATH]; + static TCHAR buffer[MAX_PATH]; buffer[0] = 0; LoadString(GetModuleHandle(NULL), id, buffer, MAX_PATH); @@ -327,22 +358,24 @@ static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage) nid.hIcon = NULL; } if (n == i && n > 0) { - lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]); + _tcscpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]); } else if (n) { - sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i); + _sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i); } else if (i) { - sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i); + _sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i); } else { - lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]); + _tcscpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]); } Shell_NotifyIcon(dwMessage, &nid); } -void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, +void appendMenuItem(HMENU hMenu, UINT uMenuId, LPTSTR szName, BOOL fDefault, BOOL fEnabled) { MENUITEMINFO mii; @@ -350,7 +383,7 @@ void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; - if (lstrlen(szName)) + if (_tcslen(szName)) { mii.fType = MFT_STRING; mii.wID = uMenuId; @@ -370,7 +403,7 @@ void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, void appendServiceMenu(HMENU hMenu, UINT uMenuId, - LPSTR szServiceName, BOOL fRunning) + LPTSTR szServiceName, BOOL fRunning) { MENUITEMINFO mii; HMENU smh; @@ -415,7 +448,7 @@ void ShowTryPopupMenu(HWND hWnd) g_lpMsg[IDS_MSG_MNUSERVICES - IDS_MSG_FIRST], FALSE, TRUE); } - appendMenuItem(hMenu, 0, "", FALSE, TRUE); + appendMenuItem(hMenu, 0, _T(""), FALSE, TRUE); appendMenuItem(hMenu, IDM_EXIT, g_lpMsg[IDS_MSG_MNUEXIT - IDS_MSG_FIRST], FALSE, TRUE); @@ -489,7 +522,7 @@ BOOL CenterWindow(HWND hwndChild) } -static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) +static void addListBoxItem(HWND hDlg, LPTSTR lpStr, HBITMAP hBmp) { LRESULT nItem; @@ -498,7 +531,7 @@ static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) } -static void addListBoxString(HWND hListBox, LPSTR lpStr) +static void addListBoxString(HWND hListBox, LPTSTR lpStr) { static int nItems = 0; if (!g_bDlgServiceOn) { @@ -516,6 +549,32 @@ static void addListBoxString(HWND hListBox, LPSTR lpStr) } +#ifndef UNICODE +#define addListBoxStringA addListBoxString +#else +static void addListBoxStringA(HWND hListBox, LPSTR lpStr) +{ + static int nItems = 0; + TCHAR WStr[16384]; + + if (!g_bDlgServiceOn) { + return; + } + if (!MultiByteToWideChar(CP_ACP, 0, lpStr, (int)strlen(lpStr) + 1, + WStr, (int) (sizeof(WStr) / sizeof(TCHAR)))) + return; + ++nItems; + if (nItems > MAX_LOADSTRING) + { + SendMessage(hListBox, LB_RESETCONTENT, 0, 0); + nItems = 1; + } + ListBox_SetCurSel(hListBox, + ListBox_AddString(hListBox, WStr)); +} +#endif + + static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter) { static BYTE lpBuffer[MAX_PATH+1]; @@ -530,7 +589,7 @@ static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter) if (ch == '\n' || nPtr >= MAX_PATH) { lpBuffer[nPtr] = '\0'; - addListBoxString(g_hwndStdoutList, lpBuffer); + addListBoxStringA(g_hwndStdoutList, lpBuffer); nPtr = 0; } else if (ch == '\t' && nPtr < (MAX_PATH - 4)) @@ -563,7 +622,7 @@ DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter) } -BOOL RunRedirectedConsole(LPSTR szCmdLine) +BOOL RunRedirectedConsole(LPTSTR szCmdLine) { DWORD dwThreadId; HANDLE hProc; @@ -630,7 +689,7 @@ BOOL RunRedirectedConsole(LPSTR szCmdLine) } -BOOL RunAndForgetConsole(LPSTR szCmdLine, BOOL bRedirectConsole) +BOOL RunAndForgetConsole(LPTSTR szCmdLine, BOOL bRedirectConsole) { STARTUPINFO stInfo; PROCESS_INFORMATION prInfo; @@ -669,12 +728,12 @@ BOOL RunAndForgetConsole(LPSTR szCmdLine, BOOL bRedirectConsole) } -BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, - LPSTR szComputerName, DWORD dwCommand) +BOOL ApacheManageService(LPCTSTR szServiceName, LPCTSTR szImagePath, + LPTSTR szComputerName, DWORD dwCommand) { - CHAR szBuf[MAX_PATH]; - CHAR szMsg[MAX_PATH]; - LPSTR sPos; + TCHAR szBuf[MAX_PATH]; + TCHAR szMsg[MAX_PATH]; + LPTSTR sPos; BOOL retValue; BOOL serviceFlag = TRUE; SC_HANDLE schService; @@ -684,32 +743,33 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (g_dwOSVersion == OS_VERSION_WIN9X) { - sPos = strstr(szImagePath, "-k start"); + sPos = _tcsstr(szImagePath, _T("-k start")); if (sPos) { - lstrcpyn(szBuf, szImagePath, (int)(sPos - szImagePath)); + _tcsncpy(szBuf, szImagePath, (int)(sPos - szImagePath)); switch (dwCommand) { case SERVICE_CONTROL_STOP: - lstrcat(szBuf, " -k shutdown -n "); + _tcscat(szBuf, _T(" -k shutdown -n ")); break; case SERVICE_CONTROL_CONTINUE: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); - lstrcat(szBuf, " -k start -n "); + _tcscat(szBuf, _T(" -k start -n ")); serviceFlag = FALSE; break; case SERVICE_APACHE_RESTART: - lstrcat(szBuf, " -k restart -n "); + _tcscat(szBuf, _T(" -k restart -n ")); break; default: return FALSE; } - lstrcat(szBuf, szServiceName); + _tcscat(szBuf, szServiceName); } else { return FALSE; @@ -725,8 +785,9 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, } else if (!serviceFlag) { - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); g_bConsoleRun = FALSE; SetCursor(g_hCursorArrow); @@ -738,13 +799,29 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, schSCManager = OpenSCManager(szComputerName, NULL, SC_MANAGER_CONNECT); if (!schSCManager) { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], + FALSE); return FALSE; } schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL); - if (schService != NULL) + if (schService == NULL) + { + /* Avoid recursion of ImagePath NULL (from this Respawn) */ + if (szImagePath) { + am_RespawnAsUserAdmin(g_hwndMain, dwCommand, + szServiceName, szComputerName); + } + else { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], + FALSE); + } + CloseServiceHandle(schSCManager); + return FALSE; + } + else { retValue = FALSE; g_bConsoleRun = TRUE; @@ -752,8 +829,9 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, switch (dwCommand) { case SERVICE_CONTROL_STOP: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); if (ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) { @@ -774,17 +852,18 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (schSStatus.dwCurrentState == SERVICE_STOPPED) { retValue = TRUE; - sprintf(szMsg, - g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); } } break; case SERVICE_CONTROL_CONTINUE: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); if (StartService(schService, 0, NULL)) @@ -806,17 +885,18 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (schSStatus.dwCurrentState == SERVICE_RUNNING) { retValue = TRUE; - sprintf(szMsg, - g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); } } break; case SERVICE_APACHE_RESTART: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); if (ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) @@ -841,9 +921,9 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (schSStatus.dwCurrentState == SERVICE_RUNNING) { retValue = TRUE; - sprintf(szMsg, - g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); } break; @@ -858,10 +938,6 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, SetCursor(g_hCursorArrow); return retValue; } - else { - g_bRescanServices = TRUE; - } - CloseServiceHandle(schSCManager); return FALSE; } @@ -869,7 +945,7 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, } -BOOL IsServiceRunning(LPCSTR szServiceName, LPCSTR szComputerName, +BOOL IsServiceRunning(LPCTSTR szServiceName, LPCTSTR szComputerName, LPDWORD lpdwPid) { DWORD dwPid; @@ -880,7 +956,7 @@ BOOL IsServiceRunning(LPCSTR szServiceName, LPCSTR szComputerName, if (g_dwOSVersion == OS_VERSION_WIN9X) { - hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName); + hWnd = FindWindow(_T("ApacheWin95ServiceMonitor"), szServiceName); if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid)) { *lpdwPid = 1; @@ -949,11 +1025,11 @@ BOOL FindRunningServices(void) BOOL GetApacheServicesStatus() { - CHAR szKey[MAX_PATH]; - CHAR achKey[MAX_PATH]; - CHAR szImagePath[MAX_PATH]; - CHAR szBuf[MAX_PATH]; - CHAR szTmp[MAX_PATH]; + TCHAR szKey[MAX_PATH]; + TCHAR achKey[MAX_PATH]; + TCHAR szImagePath[MAX_PATH]; + TCHAR szBuf[MAX_PATH]; + TCHAR szTmp[MAX_PATH]; HKEY hKey, hSubKey, hKeyRemote; DWORD retCode, rv, dwKeyType; DWORD dwBufLen = MAX_PATH; @@ -966,7 +1042,7 @@ BOOL GetApacheServicesStatus() while (g_stComputers[computers].szComputerName != NULL) { hKeyRemote = g_stComputers[computers].hRegistry; retCode = RegOpenKeyEx(hKeyRemote, - "System\\CurrentControlSet\\Services\\", + _T("System\\CurrentControlSet\\Services\\"), 0, KEY_READ, &hKey); if (retCode != ERROR_SUCCESS) { @@ -978,60 +1054,57 @@ BOOL GetApacheServicesStatus() retCode = RegEnumKey(hKey, i, achKey, MAX_PATH); if (retCode == ERROR_SUCCESS) { - lstrcpy(szKey, "System\\CurrentControlSet\\Services\\"); - lstrcat(szKey, achKey); + _tcscpy(szKey, _T("System\\CurrentControlSet\\Services\\")); + _tcscat(szKey, achKey); if (RegOpenKeyEx(hKeyRemote, szKey, 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) { dwBufLen = MAX_PATH; - rv = RegQueryValueEx(hSubKey, "ImagePath", NULL, - &dwKeyType, szImagePath, &dwBufLen); + rv = RegQueryValueEx(hSubKey, _T("ImagePath"), NULL, + &dwKeyType, (LPBYTE)szImagePath, &dwBufLen); if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ || dwKeyType == REG_EXPAND_SZ) && dwBufLen) { - lstrcpy(szBuf, szImagePath); + _tcscpy(szBuf, szImagePath); CharLower(szBuf); /* the service name could be httpd*.exe or Apache*.exe */ - if (((strstr(szBuf, "\\apache") != NULL) - || (strstr(szBuf, "\\httpd") != NULL)) - && strstr(szBuf, ".exe") - && (strstr(szBuf, "--ntservice") != NULL - || strstr(szBuf, "-k ") != NULL)) + if (((_tcsstr(szBuf, _T("\\apache")) != NULL) + || (_tcsstr(szBuf, _T("\\httpd")) != NULL)) + && _tcsstr(szBuf, _T(".exe")) + && (_tcsstr(szBuf, _T("--ntservice")) != NULL + || _tcsstr(szBuf, _T("-k ")) != NULL)) { - g_stServices[stPos].szServiceName = strdup(achKey); - g_stServices[stPos].szImagePath = - strdup(szImagePath); + g_stServices[stPos].szServiceName = _tcsdup(achKey); + g_stServices[stPos].szImagePath = _tcsdup(szImagePath); g_stServices[stPos].szComputerName = - strdup(g_stComputers[computers].szComputerName); + _tcsdup(g_stComputers[computers].szComputerName); dwBufLen = MAX_PATH; - if (RegQueryValueEx(hSubKey, "Description", NULL, - &dwKeyType, szBuf, &dwBufLen) + if (RegQueryValueEx(hSubKey, _T("Description"), NULL, + &dwKeyType, (LPBYTE)szBuf, &dwBufLen) == ERROR_SUCCESS) { - g_stServices[stPos].szDescription = - strdup(szBuf); + g_stServices[stPos].szDescription = _tcsdup(szBuf); } dwBufLen = MAX_PATH; - if (RegQueryValueEx(hSubKey, "DisplayName", NULL, - &dwKeyType, szBuf, &dwBufLen) + if (RegQueryValueEx(hSubKey, _T("DisplayName"), NULL, + &dwKeyType, (LPBYTE)szBuf, &dwBufLen) == ERROR_SUCCESS) { - if (strcmp(g_stComputers[computers] + if (_tcscmp(g_stComputers[computers] .szComputerName, g_szLocalHost) != 0) { - strcpy(szTmp, g_stComputers[computers] + _tcscpy(szTmp, g_stComputers[computers] .szComputerName + 2); - strcat(szTmp, "@"); - strcat(szTmp, szBuf); + _tcscat(szTmp, _T("@")); + _tcscat(szTmp, szBuf); } else { - strcpy(szTmp, szBuf); + _tcscpy(szTmp, szBuf); } - g_stServices[stPos].szDisplayName - = strdup(szTmp); + g_stServices[stPos].szDisplayName = _tcsdup(szTmp); } ++stPos; @@ -1055,7 +1128,7 @@ BOOL GetApacheServicesStatus() LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; + TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; switch (message) { case WM_INITDIALOG: @@ -1070,14 +1143,14 @@ LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, switch (LOWORD(wParam)) { case IDOK: - memset(szCmp, 0, MAX_COMPUTERNAME_LENGTH+4); - strcpy(szCmp, "\\\\"); + memset(szCmp, 0, sizeof(szCmp)); + _tcscpy(szCmp, _T("\\\\")); SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_GETTEXT, (WPARAM) MAX_COMPUTERNAME_LENGTH, (LPARAM) szCmp+2); - strupr(szCmp); - if (strlen(szCmp) < 3) { + _tcsupr(szCmp); + if (_tcslen(szCmp) < 3) { EndDialog(hDlg, TRUE); return TRUE; } @@ -1096,7 +1169,7 @@ LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, memset(&bi, 0, sizeof(BROWSEINFO)); SHGetSpecialFolderLocation(hDlg, CSIDL_NETWORK, &il); - bi.lpszTitle = "ApacheMonitor :\nSelect Network Computer!"; + bi.lpszTitle = _T("ApacheMonitor :\nSelect Network Computer!"); bi.pszDisplayName = szCmp; bi.hwndOwner = hDlg; bi.ulFlags = BIF_BROWSEFORCOMPUTER; @@ -1135,7 +1208,7 @@ LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - CHAR szBuf[MAX_PATH]; + TCHAR szBuf[MAX_PATH]; HWND hListBox; static HWND hStatusBar; TEXTMETRIC tm; @@ -1146,7 +1219,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, LPMEASUREITEMSTRUCT lpmis; LPDRAWITEMSTRUCT lpdis; - memset(szBuf, 0, MAX_PATH); + memset(szBuf, 0, sizeof(szBuf)); switch (message) { case WM_INITDIALOG: @@ -1179,7 +1252,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT); hStatusBar = CreateStatusWindow(0x0800 /* SBT_TOOLTIPS */ | WS_CHILD | WS_VISIBLE, - "", hDlg, IDC_STATBAR); + _T(""), hDlg, IDC_STATBAR); if (GetApacheServicesStatus()) { i = 0; @@ -1210,7 +1283,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, case WM_UPDATEMESSAGE: hListBox = GetDlgItem(hDlg, IDL_SERVICES); SendMessage(hListBox, LB_RESETCONTENT, 0, 0); - SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)""); + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T("")); Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE); Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE); Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE); @@ -1299,7 +1372,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE); Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE); } - if (strcmp(g_stServices[lpdis->itemID].szComputerName, + if (_tcscmp(g_stServices[lpdis->itemID].szComputerName, g_szLocalHost) == 0) { Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE); } @@ -1312,7 +1385,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, (LPARAM)g_stServices[lpdis->itemID].szDescription); } else { - SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)""); + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T("")); } SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); @@ -1324,7 +1397,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1)); } - TextOut(lpdis->hDC, XBITMAP + 6, y, szBuf, (int)strlen(szBuf)); + TextOut(lpdis->hDC, XBITMAP + 6, y, szBuf, (int)_tcslen(szBuf)); break; case ODA_FOCUS: @@ -1399,7 +1472,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, case IDC_SMANAGER: if (g_dwOSVersion >= OS_VERSION_WIN2K) { - ShellExecute(hDlg, "open", "services.msc", "/s", + ShellExecute(hDlg, _T("open"), _T("services.msc"), _T("/s"), NULL, SW_NORMAL); } else { @@ -1612,7 +1685,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, case IDC_SMANAGER: if (g_dwOSVersion >= OS_VERSION_WIN2K) { - ShellExecute(NULL, "open", "services.msc", "/s", + ShellExecute(NULL, _T("open"), _T("services.msc"), _T("/s"), NULL, SW_NORMAL); } else { @@ -1634,18 +1707,86 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, } +static int KillAWindow(HWND appwindow) +{ + HANDLE appproc; + DWORD procid; + BOOL postres; + + SetLastError(0); + GetWindowThreadProcessId(appwindow, &procid); + if (GetLastError()) + return(2); + + appproc = OpenProcess(SYNCHRONIZE, 0, procid); + postres = PostMessage(appwindow, WM_COMMAND, IDM_EXIT, 0); + if (appproc && postres) { + if (WaitForSingleObject(appproc, 10 /* seconds */ * 1000) + == WAIT_OBJECT_0) { + CloseHandle(appproc); + return (0); + } + } + if (appproc) + CloseHandle(appproc); + + if ((appproc = OpenProcess(PROCESS_TERMINATE, 0, procid)) != NULL) { + if (TerminateProcess(appproc, 0)) { + CloseHandle(appproc); + return (0); + } + CloseHandle(appproc); + } + + /* Perhaps we were short of permissions? */ + return (2); +} + + +static int KillAllMonitors(void) +{ + HWND appwindow; + int exitcode = 0; + PWTS_PROCESS_INFO tsProcs; + DWORD tsProcCount, i; + DWORD thisProcId; + + /* This is graceful, close our own Window, clearing the icon */ + if ((appwindow = FindWindow(g_szWindowClass, g_szTitle)) != NULL) + exitcode = KillAWindow(appwindow); + + if (g_dwOSVersion < OS_VERSION_WIN2K) + return exitcode; + + thisProcId = GetCurrentProcessId(); + + if (!WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, + &tsProcs, &tsProcCount)) + return exitcode; + + /* This is ungraceful; close other Windows, with a lingering icon. + * Since on terminal server it's not possible to post the message + * to exit across sessions, we have to suffer this side effect + * of a taskbar 'icon' which will evaporate the next time that + * the user hovers over it or when the taskbar area is updated. + */ + for (i = 0; i < tsProcCount; ++i) { + if (_tcscmp(tsProcs[i].pProcessName, _T(AM_STRINGIFY(BIN_NAME))) == 0 + && tsProcs[i].ProcessId != thisProcId) + WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE, + tsProcs[i].ProcessId, 1); + } + WTSFreeMemory(tsProcs); + return exitcode; +} + + /* Create main invisible window */ HWND CreateMainWindow(HINSTANCE hInstance) { HWND hWnd = NULL; WNDCLASSEX wcex; - if (!GetSystemOSVersion(&g_dwOSVersion)) - { - ErrorMessage(NULL, TRUE); - return hWnd; - } - wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; @@ -1668,42 +1809,89 @@ HWND CreateMainWindow(HINSTANCE hInstance) NULL, NULL, hInstance, NULL); } return hWnd; - } +#ifndef UNICODE +/* Borrowed from CRT internal.h for _MBCS argc/argv parsing in this GUI app */ +int __cdecl _setargv(void); +#endif + int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { - CHAR szTmp[MAX_LOADSTRING]; - CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; + TCHAR szTmp[MAX_LOADSTRING]; + TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; MSG msg; - /* single instance mutex */ - HANDLE hMutex; + /* existing window */ + HWND appwindow; + DWORD dwControl; int i; DWORD d; + if (!GetSystemOSVersion(&g_dwOSVersion)) + { + ErrorMessage(NULL, TRUE); + return 1; + } + g_LangID = GetUserDefaultLangID(); if ((g_LangID & 0xFF) != LANG_ENGLISH) { g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); } for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) { LoadString(hInstance, i, szTmp, MAX_LOADSTRING); - g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp); + g_lpMsg[i - IDS_MSG_FIRST] = _tcsdup(szTmp); } LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING); d = MAX_COMPUTERNAME_LENGTH+1; - strcpy(szCmp, "\\\\"); + _tcscpy(szCmp, _T("\\\\")); GetComputerName(szCmp + 2, &d); - strupr(szCmp); - g_szLocalHost = strdup(szCmp); + _tcsupr(szCmp); + g_szLocalHost = _tcsdup(szCmp); memset(g_stComputers, 0, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS); - g_stComputers[0].szComputerName = strdup(szCmp); + g_stComputers[0].szComputerName = _tcsdup(szCmp); g_stComputers[0].hRegistry = HKEY_LOCAL_MACHINE; - g_szTitle = strdup(szTmp); + g_szTitle = _tcsdup(szTmp); LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING); - g_szWindowClass = strdup(szTmp); + g_szWindowClass = _tcsdup(szTmp); + + appwindow = FindWindow(g_szWindowClass, g_szTitle); + +#ifdef UNICODE + __wargv = CommandLineToArgvW(GetCommandLineW(), &__argc); +#else + _setargv(); +#endif + + if ((__argc == 2) && (_tcscmp(__targv[1], _T("--kill")) == 0)) + { + /* Off to chase and close up every ApacheMonitor taskbar window */ + return KillAllMonitors(); + } + else if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K)) + { + dwControl = _ttoi(__targv[1]); + if ((dwControl != SERVICE_CONTROL_CONTINUE) && + (dwControl != SERVICE_APACHE_RESTART) && + (dwControl != SERVICE_CONTROL_STOP)) + { + return 1; + } + + /* Chase down and close up our session's previous window */ + if ((appwindow) != NULL) + KillAWindow(appwindow); + } + else if (__argc != 1) { + return 1; + } + else if (appwindow) + { + ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE); + return 0; + } g_icoStop = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); @@ -1722,26 +1910,20 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR); - hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX"); - if ((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) - { - ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE); - if (hMutex) { - CloseHandle(hMutex); - } - return 0; - } - memset(g_stServices, 0, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES); CoInitialize(NULL); InitCommonControls(); g_hInstance = hInstance; g_hwndMain = CreateMainWindow(hInstance); - g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated"); + g_bUiTaskbarCreated = RegisterWindowMessage(_T("TaskbarCreated")); InitializeCriticalSection(&g_stcSection); g_hwndServiceDlg = NULL; if (g_hwndMain != NULL) { + /* To avoid recursion, pass ImagePath NULL (a noop on NT and later) */ + if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K)) + ApacheManageService(__targv[2], NULL, __targv[3], dwControl); + while (GetMessage(&msg, NULL, 0, 0) == TRUE) { TranslateMessage(&msg); @@ -1751,7 +1933,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } am_ClearComputersSt(); DeleteCriticalSection(&g_stcSection); - CloseHandle(hMutex); DestroyIcon(g_icoStop); DestroyIcon(g_icoRun); DestroyCursor(g_hCursorHourglass); @@ -1761,3 +1942,4 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, CoUninitialize(); return 0; } + diff --git a/support/win32/ApacheMonitor.dsp b/support/win32/ApacheMonitor.dsp index 853ddbc6..84369aaa 100644 --- a/support/win32/ApacheMonitor.dsp +++ b/support/win32/ApacheMonitor.dsp @@ -52,8 +52,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /opt:ref +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /debug /opt:ref # Begin Special Build Tool TargetPath=.\Release\ApacheMonitor.exe SOURCE="$(InputPath)" @@ -84,8 +84,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /incremental:no /debug +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /debug +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /incremental:no /debug # Begin Special Build Tool TargetPath=.\Debug\ApacheMonitor.exe SOURCE="$(InputPath)" diff --git a/support/win32/ApacheMonitor.h b/support/win32/ApacheMonitor.h index 8a64b870..085c45f8 100644 --- a/support/win32/ApacheMonitor.h +++ b/support/win32/ApacheMonitor.h @@ -18,6 +18,7 @@ * @file ApacheMonitor.h * @brief Resource definitions for ApacheMonitor.rc and ApacheMonitor.c */ +#define BIN_NAME ApacheMonitor.exe #define IDD_DLGSERVICES 101 #define IDS_APMONITORTITLE 102 |
