Fix range off by one bug. Properly fix local doc link. Add glob support to SMTP sends

This commit is contained in:
dac%x.cx 2004-09-07 23:15:24 +00:00
Родитель e237ef56e9
Коммит eab4a51869
17 изменённых файлов: 387 добавлений и 2056 удалений

Просмотреть файл

@ -1,873 +0,0 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/*
bench.c has all the OS independent utilities.
*/
#include "bench.h"
/* allocate memory and exit if out of memory */
void *
mymalloc(size_t size)
{
void *ptr;
ptr = malloc(size);
if (ptr == NULL)
errexit(stderr, "Call to malloc(%d) failed\n", size);
return(ptr);
}
void *
mycalloc(size_t size)
{
void *retp;
if ((retp = mymalloc(size)) == NULL)
return NULL;
memset(retp, 0, size);
return(retp);
}
/* allocate memory and exit if out of memory */
void *
myrealloc(void *ptr, size_t size)
{
ptr = realloc(ptr, size);
if (ptr == NULL)
errexit(stderr, "Call to realloc(%d, %d) failed\n", ptr, size);
return(ptr);
}
void
myfree(void *ptr)
{
free(ptr);
}
char *
mystrdup(const char *cp)
{
char *retcp;
if ((retcp = (char *)mymalloc(strlen(cp)+1)) == NULL)
return NULL;
strcpy(retcp, cp);
return retcp;
}
/*
* waitReadWrite(int fd, int flags)
* parameter: fd: file descriptor
* read_write: 0 --> read
* 1 --> write
* 2 --> read & write
* return: NON-Zero something is read
* 0 sth is wrong
*/
#define CHECK_READ 0x0
#define CHECK_WRITE 0x1
#define CHECK_RW 0x2
#define CHECK_ALL 0x3
#define CHECK_FOREVER 0x4
#define waitReadable(fd) waitReadWrite((fd),CHECK_READ)
#define waitWriteable(fd) waitReadWrite((fd),CHECK_WRITE)
#define waitWriteableForever(fd) waitReadWrite((fd),CHECK_WRITE | CHECK_FOREVER)
/* Return 1 if bytes readable; 0 if error or time up */
int
waitReadWrite(int fd, int flags)
{
#ifdef _WIN32
return 0;
#else
struct pollfd pfd;
int timeleft;
int ret;
int timeouts = 0;
pfd.fd = fd;
pfd.events = POLLHUP;
if ((flags & CHECK_ALL) == CHECK_READ) {
pfd.events |= POLLIN;
} else if ((flags & CHECK_ALL) == CHECK_WRITE) {
pfd.events |= POLLOUT;
} else if ((flags & CHECK_ALL) == CHECK_RW) {
pfd.events |= (POLLIN | POLLOUT);
}
for (;;) {
if (flags & CHECK_FOREVER) { /* for writing status out */
timeleft = 60;
} else {
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(stderr, "waitReadWrite gf_timeexpired=%d\n",
gf_timeexpired);
return 0;
}
timeleft = 5;
}
/*fprintf(stderr, "poll(%d,%d)\n", fd, timeleft*1000);*/
ret = poll(&pfd, 1, timeleft*1000);
/*fprintf(stderr, "poll(%d,%d)=%d\n", fd, timeleft*1000, ret);*/
if (ret == 0) {
if (!(flags & CHECK_FOREVER) && (++timeouts >= 12)) {
return 0; /* time out after 60sec total */
}
continue;
}
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
D_PRINTF(stderr, "waitReadWrite error ret=%d\n", ret);
break;
}
return 1;
}
/* error */
return 0;
#endif
}
int
retryRead(ptcx_t ptcx, SOCKET sock, char *buf, int count)
{
int ret;
int bytesread = 0;
D_PRINTF(debugfile, "retryRead(%d, %d (gf_timeexpired=%d))\n",
sock, count, gf_timeexpired);
while (count) {
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF (debugfile, "retryRead gf_timeexpired\n");
strcpy (ptcx->errMsg, "retryRead:TIMEOUT");
break;
}
if (0 == waitReadable (sock)) {
D_PRINTF (debugfile, "retryRead waitReadable time/error\n");
strcpy (ptcx->errMsg, "waitReadable TIMEOUT<retryRead");
break;
}
ret = NETREAD(sock, buf, count);
if (ret < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN) {
if (bytesread > 0)
break; /* return what we got so far */
if (waitReadable(sock)) {
continue;
}
}
if (bytesread == 0) {
bytesread = -1;
}
sprintf (ptcx->errMsg, "retryRead(sock=%d) IO error", sock);
break;
}
bytesread += ret;
buf += ret;
count -= ret;
break; /* return any good bytes */
}
D_PRINTF(debugfile, "retryRead(%d, %d)=%d\n", sock, count, bytesread);
return bytesread;
}
int
retryWrite(ptcx_t ptcx, SOCKET sock, char *buf, int count)
{
int ret;
int byteswritten = 0;
D_PRINTF(debugfile, "retryWrite(%d, %d)\n", sock, count);
while (count) {
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF (debugfile, "retryWrite gf_timeexpired\n");
strcpy (ptcx->errMsg, "read:timeout");
break;
}
ret = NETWRITE(sock, buf, count);
if (ret < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN) {
if (waitWriteable(sock)) {
continue;
}
}
if (byteswritten == 0) {
byteswritten = -1;
}
sprintf (ptcx->errMsg,
"retryWrite(sock=%d, n=%d) IO error", sock, count);
break;
}
byteswritten += ret;
buf += ret;
count -= ret;
}
D_PRINTF(debugfile, "retryWrite(%d, %d)=%d\n", sock, count, byteswritten);
return byteswritten;
}
int
readResponse(ptcx_t ptcx, SOCKET sock, char *buffer, int buflen)
{
/* read the server response and do nothing with it */
int totalbytesread = 0;
int resplen = 0;
int bytesread;
char *offset;
memset (buffer, 0, sizeof(buffer));
while (totalbytesread < buflen)
{
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"readResponse() Time expired.\n");
break;
}
if ((bytesread = retryRead(ptcx, sock, buffer+totalbytesread,
buflen-totalbytesread)) <= 0) {
strcat (ptcx->errMsg, "<ReadResponse");
return -1;
}
totalbytesread += bytesread;
buffer[totalbytesread] = 0;
/* search for end of response (assume single line) */
if ((offset = strstr(buffer, "\n"))) {
resplen = offset - buffer + 1;
break;
} else if ((offset = strstr(buffer, "\r\n"))) {
resplen = offset - buffer + 2;
break;
}
}
D_PRINTF(debugfile, "Read from server: %s\n", buffer );
ptcx->bytesread += resplen;
return resplen;
}
/* expects pointers to buffers of these sizes */
/* char command[MAX_COMMAND_LEN] */
/* char response[MAX_RESPONSE_LEN] */
int
doCommandResponse(ptcx_t ptcx, SOCKET sock, char *command, char *response, int resplen)
{
int ret;
if (response == NULL)
return -1;
memset(response, 0, resplen);
/* send the command already formatted */
if ((ret = sendCommand(ptcx, sock, command)) == -1) {
strcat (ptcx->errMsg, "<doCommandResponse");
return -1;
}
/* read server response line */
if ((ret = readResponse(ptcx, sock, response, resplen)) <= 0) {
strcat (ptcx->errMsg, "<doCommandResponse");
return -1;
}
return ret;
}
int
sendCommand(ptcx_t ptcx, SOCKET sock, char *command)
{
int writelen;
int sentbytes = 0;
int sent;
D_PRINTF(debugfile, "sendCommand(%s)\n", command );
writelen = strlen(command);
while (sentbytes < writelen) {
if ((sent = retryWrite(ptcx, sock, command + sentbytes,
writelen - sentbytes)) == -1) {
strcat (ptcx->errMsg, "<sendCommand");
return -1;
}
sentbytes += sent;
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"sendCommand() Time expired.\n");
break;
}
}
ptcx->byteswritten += sentbytes;
return sentbytes;
}
/* assumes we already included the <CRLF>.<CRLF> at the end of message */
int
sendMessage(ptcx_t ptcx, SOCKET sock, char *message)
{
int writelen;
int sentbytes = 0;
int sent;
writelen = strlen(message);
D_PRINTF(debugfile, "Writing message to server: len=%d\n", writelen );
while (sentbytes < writelen) {
if ((sent = retryWrite(ptcx, sock, message + sentbytes,
writelen - sentbytes)) == -1) {
strcat (ptcx->errMsg, "<sendMessage");
return -1;
}
sentbytes += sent;
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"sendMessage() Time expired.\n");
break;
}
}
ptcx->byteswritten += sentbytes;
return sentbytes;
}
/* This is how status messages are sent */
int
sendOutput(int fd, char *string)
{
int writelen;
int sentbytes = 0;
int sent;
/*D_PRINTF(stderr, "sendOutput(%d, %s)\n", fd, string );*/
writelen = strlen(string);
while (sentbytes < writelen) {
sent = OUTPUT_WRITE(fd, string + sentbytes, writelen - sentbytes);
if (sent == -1) {
if (errno == EINTR)
continue;
if (errno == EAGAIN) {
if (waitWriteableForever(fd))
continue;
else
returnerr(stderr,
"sendOutput(%d) - Got EAGAIN and fd not ready\n",
fd); /* has this ever happened? die??? */
}
return -1;
}
sentbytes += sent;
#if 0
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(stderr,"sendOutput() Time expired.\n");
break;
}
#endif
}
return sentbytes;
}
/* read from socket until we find <CRLF>.<CRLF> */
int
retrMsg(ptcx_t ptcx, char *buffer, int maxBytes, SOCKET sock)
{
int totalbytesread = 0;
int bytesread;
int sz;
char garbage[10000], *sp;
if (buffer) {
sp = buffer;
sz = maxBytes-1;
} else {
sp = garbage;
sz = sizeof (garbage)-1;
}
while (!buffer || (totalbytesread < maxBytes)) {
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"Time expired while reading messages - in retrMsg\n");
break;
}
bytesread = retryRead(ptcx, sock,
sp+totalbytesread, sz-totalbytesread);
/*D_PRINTF (stderr, "retrMsg: got %d bytes\n", bytesread);*/
if (bytesread <= 0) {
strcat (ptcx->errMsg, "<retrMsg");
return -1;
}
ptcx->bytesread += bytesread;
totalbytesread += bytesread;
sp[totalbytesread] = 0; /* terminate string */
if (NULL != strstr (sp, "\r\n.\r\n")) {
D_PRINTF (stderr, "retrMsg: saw terminating string\n");
break;
}
if (!strncmp (sp, "-ERR", 4)) { /* watch for error response */
trimEndWhite (sp);
sprintf (ptcx->errMsg, "retrMsg: ERROR response=[%.40s]", sp);
return -1;
}
if (!buffer && (totalbytesread > 5)) { /* reset our scratch buffer */
int i;
char *from, *to;
/* shuffle last 5 bytes to start */
from = sp + totalbytesread - 5;
to = garbage;
for (i=5; i > 0; --i)
*to++ = *from++;
totalbytesread = 5;
}
}
return totalbytesread;
}
/*
Record current time
*/
int
timeval_stamp(struct timeval *tv)
{
int rc;
rc = GETTIMEOFDAY(tv, NULL);
if (rc != 0) {
errexit(stderr, "Error from gettimeofday()\n");
}
return rc;
}
/*
This is the main event timing routine. This resets counters
Note that event timing cannot be nested.
*/
void
event_start(ptcx_t ptcx, event_timer_t *pevent)
{
ptcx->bytesread = 0;
ptcx->byteswritten = 0;
timeval_stamp(&ptcx->starttime);
}
/*
This ends an event and increments the counters
Multiple stops are no longer allowed. (broke min, max, and sum of t*t)
*/
void
event_stop(ptcx_t ptcx, event_timer_t *pevent)
{
struct timeval tv;
double t;
timeval_stamp(&tv); /* get the time */
if (gf_timeexpired >= EXIT_FAST) { /* if aborting run, ignore it */
return;
}
pevent->trys++; /* count try with time */
pevent->bytesread += ptcx->bytesread;
pevent->byteswritten += ptcx->byteswritten;
t = compdifftime_double(&tv, &ptcx->starttime); /* find time span */
pevent->elapsedtime += t;
pevent->elapsedtimesq += t * t;
if (t > pevent->maxtime) /* check max time */
pevent->maxtime = t;
/* this gets initialized to 0.0 */
if (!pevent->mintime || /* check min time */
((t > 0.0) && (t < pevent->mintime))) /* smallest non 0 time */
pevent->mintime = t;
}
/*
reset the event structure
*/
void
event_reset(event_timer_t *pevent)
{
memset(pevent, 0, sizeof(event_timer_t));
}
/*
Add pincr event into psum event
*/
void
event_sum(event_timer_t *psum, event_timer_t *pincr)
{
psum->trys += pincr->trys;
psum->errs += pincr->errs;
psum->bytesread += pincr->bytesread;
psum->byteswritten += pincr->byteswritten;
psum->elapsedtime += pincr->elapsedtime;
psum->elapsedtimesq += pincr->elapsedtimesq;
if (pincr->maxtime > psum->maxtime)
psum->maxtime = pincr->maxtime;
if (!psum->mintime ||
((pincr->mintime > 0.0) && (pincr->mintime < psum->mintime)))
psum->mintime = pincr->mintime;
}
/* Format string for every timer. Must match event_to_text */
const char *gs_eventToTextFormat = "Try+Error/BytesR+BytesW/Time[TimeMin,TimeMax]Time2";
/*
Output event into ebuf.
*/
char *
event_to_text(event_timer_t *pevent, char *ebuf)
{
/* these have to be sane to avoid overflowing the print buffer */
assert (pevent->bytesread < 1.0e20);
assert (pevent->byteswritten < 1.0e20);
assert (pevent->elapsedtime < 1.0e10);
assert (pevent->maxtime < 1.0e10);
assert (pevent->elapsedtimesq < 1.0e20);
if (pevent->elapsedtime) {
sprintf(ebuf, "%ld+%ld/%.0f+%.0f/%.6f[%.6f,%.6f]%.6f",
pevent->trys, pevent->errs,
pevent->bytesread, pevent->byteswritten,
pevent->elapsedtime,
pevent->mintime,
pevent->maxtime,
pevent->elapsedtimesq);
} else { /* trim extra 0s for simple case*/
sprintf(ebuf, "%ld+%ld/%.0f+%.0f/0.0[0.0,0.0]0.0",
pevent->trys, pevent->errs,
pevent->bytesread, pevent->byteswritten);
}
return ebuf;
}
/*
Given the last value we returned, return the next sequential or random value
If the initial value is out of the range, a valid number will be returned.
*/
unsigned long
rangeNext (range_t *range, unsigned long last)
{
unsigned long n;
assert (range != NULL);
if (range->span == 0) /* empty range (span = 0) */
return range->first;
if (range->sequential > 0) { /* incrementing sequential */
n = last + 1;
} else if (range->sequential < 0) { /* decrementing sequential */
n = last - 1;
} else { /* random */
n = range->first + (RANDOM() % range->span);
assert ((n >= range->first) && (n <= range->last));
}
/* check range */
if (n > range->last) n = range->first;
if (n < range->first) n = range->last;
return n;
}
/*
Setup range given a first and last valid values (inclusive)
Direction: + incrementing, 0 random, - decrementing
If first and last are reversed, it will adjust accordingly
*/
void
rangeSetFirstLast (range_t *range,
unsigned long first,
unsigned long last,
int dir)
{
assert (range != NULL);
if (last > first) {
range->first = first;
range->last = last;
range->sequential = dir;
} else {
range->first = last;
range->last = first;
range->sequential = -dir;
}
range->span = range->last - range->first;
}
/*
Setup range given a first valid value (inclusive) and number (1..)
Direction: + incrementing, 0 random, - decrementing
*/
void
rangeSetFirstCount (range_t *range,
unsigned long first,
unsigned long num,
int dir)
{
assert (range != NULL);
if (num > 0) --num; /* adjust to internal notation */
range->first = first;
range->span = num;
range->last = range->first + range->span;
range->sequential = dir;
}
/*
Given a specified range, split it based on process and thread
*/
void
rangeSplit (range_t *whole, range_t *sub, int pnum, int tnum)
{
unsigned long perproc, first, count;
if (!whole->sequential) { /* just copy it */
sub->first = whole->first;
sub->last = whole->last;
sub->span = whole->span;
sub->sequential = whole->sequential;
return;
}
/* To avoid cumulative rounding errors,
the 0th process/thread rounds up, all others round down */
perproc = (pnum > 0)
? (whole->span+1) / gn_numprocs
: (whole->span+1 + gn_numprocs - 1) / gn_numprocs;
if (perproc <= 0) perproc = 1; /* in case logins > processes */
if (gn_numthreads > 0) {
unsigned long perthread;
perthread = (tnum > 0)
? perproc / gn_numthreads
: (perproc + gn_numthreads - 1) / gn_numthreads;
if (perthread <= 0) perthread = 1; /* in case logins > threads */
first = whole->first + (perproc * pnum) + (perthread * tnum);
count = perthread;
} else {
first = whole->first + (perproc * pnum);
count = perproc;
}
/* If logins > processes*threads, we have to wrap the space */
while (first >= (whole->first + whole->span+1)) {
first -= whole->span+1;
}
assert (first >= whole->first);
rangeSetFirstCount (sub, first, count, whole->sequential);
}
/*
clear protocol independ parts of cmd_stats_t
*/
void
cmdStatsInit (cmd_stats_t *p)
{
assert (NULL != p);
p->totalerrs = 0;
p->totalcommands = 0;
event_reset (&p->combined);
event_reset (&p->idle);
}
void
stats_init(stats_t *p)
{
memset(p, 0, sizeof(*p));
}
/*
Given a buffer, trim tailing CR-NL and whitespace from it
Moves 0 terminator to exclude extra portion.
*/
void
trimEndWhite (char *buff)
{
char *cp;
if (!buff) return;
for (cp = buff; *cp; ++cp); /* find the end */
while (cp > buff) {
--cp;
if ((*cp != '\n') && (*cp !='\r')
&& (*cp != '\t') && (*cp != ' ')) return;
*cp = 0;
}
}
#if 0 /* never used */
int
timeval_clear(struct timeval *tv)
{
if (tv == NULL)
return -1;
tv->tv_sec = 0;
tv->tv_usec = 0;
return 0;
}
/* timetextbuf should be (SIZEOF_TIMEVALTEXT + 1) */
char *
timeval_to_text(const struct timeval *the_timeval, char *timetextbuf)
{
/*
* given a timeval (seconds and microseconds), put the text
* "seconds.microseconds" into timeval_as_text
*/
int seconds, microseconds;
seconds = the_timeval->tv_sec;
microseconds = the_timeval->tv_usec;
sprintf(timetextbuf, "%10d.%6.6d\t", seconds, microseconds);
return timetextbuf;
}
/* doubletextbuf should be (SIZEOF_DOUBLETEXT+1) */
char *
double_to_text(const double the_double, char *doubletextbuf)
{
/*
* given a double, return text
*/
sprintf(doubletextbuf, "%17.01f\t", the_double);
return(doubletextbuf);
}
struct timeval
text_to_timeval(ptcx_t ptcx, char *timeval_as_text) {
long int seconds, microseconds;
struct timeval the_timeval;
D_PRINTF(debugfile,"T/%d %s\n", (int)timeval_as_text, timeval_as_text);
sscanf(timeval_as_text, "%ld.%ld", &seconds, &microseconds);
the_timeval.tv_sec = seconds;
the_timeval.tv_usec = microseconds;
return the_timeval;
}
double
text_to_double(ptcx_t ptcx, char *double_as_text) {
double the_double = 0;
int returnval = 0;
D_PRINTF(debugfile,"D/%d %s\n", (int)double_as_text, double_as_text);
returnval = sscanf(double_as_text, "%lf", &the_double);
if (returnval == 1)
return(the_double);
else
return(0.0);
}
#endif
#if 0
/* not currently used, but useful for debugging */
void
dumpevent(ptcx_t ptcx, event_timer_t *pevent)
{
D_PRINTF(debugfile, "trys=%d errs=%d br=%f bw=%f elapsed=%f sq=%f\n",
pevent->trys, pevent->errs,
pevent->bytesread, pevent->byteswritten,
pevent->elapsedtime,
pevent->elapsedtimesq);
}
void
dumptimer(ptcx_t ptcx, cmd_stats_t *rqsttimer)
{
if (gn_debug) {
D_PRINTF(debugfile, "Connect: ");
dumpevent(ptcx, &rqsttimer->connect);
D_PRINTF(debugfile, "Banner: ");
dumpevent(ptcx, &rqsttimer->banner);
D_PRINTF(debugfile, "Login: ");
dumpevent(ptcx, &rqsttimer->login);
D_PRINTF(debugfile, "Cmd: ");
dumpevent(ptcx, &rqsttimer->cmd);
D_PRINTF(debugfile, "MsgRead: ");
dumpevent(ptcx, &rqsttimer->msgread);
D_PRINTF(debugfile, "MsgWrite: ");
dumpevent(ptcx, &rqsttimer->msgwrite);
D_PRINTF(debugfile, "Idle: ");
dumpevent(ptcx, &rqsttimer->idle);
D_PRINTF(debugfile, "Logout: ");
dumpevent(ptcx, &rqsttimer->logout);
}
}
#endif

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -372,7 +372,6 @@ extern void rqstat_to_buffer(char *buf, char *comm, cmd_stats_t *stats);
extern int readResponse(ptcx_t ptcx, SOCKET sock, char *buffer, int buflen);
extern int sendCommand(ptcx_t ptcx, SOCKET sock, char *command);
extern int doCommandResponse(ptcx_t ptcx, SOCKET sock, char *command, char *response, int resplen);
extern int sendMessage(ptcx_t ptcx, SOCKET sock, char *message);
extern int sendOutput(int fd, char *command);
extern int retrMsg(ptcx_t ptcx, char *buffer, int maxBytes, SOCKET sock);
extern void trimEndWhite (char *buff);

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file

Просмотреть файл

@ -1,60 +0,0 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/* http-util.h -- Shared HTTP functions */
#define HTTP_HEADER_BREAK "\r\n\r\n"
#define HTTP_CONTENT_TYPE_POST "Content-type: application/x-www-form-urlencoded"
#define HTTP_CONTENT_LENGTH "Content-length:"
#define HTTP_LOCATION "Location:"
#define HTTP_PROTOCOL "http://"
#define HTTP_MAX_RECONNECTS 5 /* max to reconnect/retry a command */
/* Callback type for parsing messages on the fly */
typedef int (*parseMsgPtr_t)(
ptcx_t, pmail_command_t, void *me,
char *buffer, int bytesInBuffer, char **searchStr, const char **findStr);
extern int HttpConnect(ptcx_t ptcx, resolved_addr_t *hostInfo,
event_timer_t *timer);
extern int HttpReadResponse(ptcx_t ptcx, mail_command_t *cmd, void *me,
char *responce, int resplen,
parseMsgPtr_t msgParse);
extern int HttpCommandResponse (ptcx_t ptcx, mail_command_t *cmd, void *me,
resolved_addr_t *hostInfo, event_timer_t *reconnect,
event_timer_t *timer, char *command, char *response, int resplen,
parseMsgPtr_t msgParse);

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -72,9 +72,12 @@ typedef struct _doIMAP4_state {
int *searchSchedule;
} doIMAP4_state_t;
/* IMAP flags definitions */
#define leaveMailOnServer 0x01
#define leaveMailUnseen 0x02
static void doImap4Exit (ptcx_t ptcx, doIMAP4_state_t *me);
#define IMAP_LEAVE_UNSEEN 2
static int
ImapParseNameValue (pmail_command_t cmd,
@ -87,17 +90,21 @@ ImapParseNameValue (pmail_command_t cmd,
if (pishParseNameValue(cmd, name, tok) == 0)
; /* done */
else if (strcmp(name, "leavemailonserver") == 0) {
int v = atoi(tok);
if (v <= 0) { /* turn off */
pish->leaveMailOnServer = 0;
} else if (0 == pish->leaveMailOnServer) { /* turn on if < leavemailunseen */
pish->leaveMailOnServer = 1;
if (atoi(tok) > 0) {
pish->flags |= leaveMailOnServer;
} else { /* turn on if < leavemailunseen */
pish->flags &= ~leaveMailOnServer;
}
D_PRINTF (stderr, "leaveMailOnServer=%d\n", pish->leaveMailOnServer);
/*D_PRINTF (stderr, "leaveMailOnServer=%d\n", pish->leaveMailOnServer);*/
}
else if (strcmp(name, "leavemailunseen") == 0) {
pish->leaveMailOnServer = IMAP_LEAVE_UNSEEN * (atoi(tok) > 0);
D_PRINTF (stderr, "leaveMailOnServer=%d\n", pish->leaveMailOnServer);
if (atoi(tok) > 0) {
/* leaving mail unseen implies leaving on server */
pish->flags |= leaveMailUnseen | leaveMailOnServer;
} else { /* turn on if < leavemailunseen */
pish->flags &= ~leaveMailUnseen;
}
/*D_PRINTF (stderr, "leaveMailOnServer=%d\n", pish->leaveMailOnServer);*/
}
else {
return -1;
@ -834,15 +841,15 @@ imapRetrRecentMessages(ptcx_t ptcx,
}
/* if we're told to leave mail on server, do not delete the message */
if (pish->leaveMailOnServer < IMAP_LEAVE_UNSEEN) {
if (0 == pish->leaveMailOnServer) {
/* mark the msg \deleted and \seen */
sprintf(command, "%d STORE %d +FLAGS (\\DELETED \\SEEN)%s",
++pIMAP->seq_num,i, CRLF);
} else {
if (!(pish->flags & leaveMailUnseen)) {
if (pish->flags & leaveMailOnServer) { /* just mark seen */
/* mark the msg \seen needed??? */
sprintf(command, "%d STORE %d +FLAGS (\\SEEN)%s",
++pIMAP->seq_num,i, CRLF);
} else { /* delete message */
/* mark the msg \deleted and \seen */
sprintf(command, "%d STORE %d +FLAGS (\\DELETED \\SEEN)%s",
++pIMAP->seq_num,i, CRLF);
}
event_start(ptcx, &stats->cmd);
rc = doImapCommandResponse(ptcx, sock, pIMAP->seq_num,
@ -859,7 +866,7 @@ imapRetrRecentMessages(ptcx_t ptcx,
}
}
if (0 == pish->leaveMailOnServer) { /* expunge if we are deleting */
if (!(pish->flags & leaveMailOnServer)) { /* expunge if we are deleting */
/* EXPUNGE \deleted messages */
sprintf(command, "%d EXPUNGE%s", ++pIMAP->seq_num, CRLF);
event_start(ptcx, &stats->cmd);

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file

Просмотреть файл

@ -1,633 +0,0 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/*
* parse the workload description file
*
*/
#include "bench.h"
/* global variables */
param_list_t *g_default_params; /* list of default values */
/* Find a protocol in the global protocol list */
protocol_t *
protocol_get (char *name)
{
protocol_t *pp;
for (pp=g_protocols; pp->name != NULL; ++pp) {
/* we only check the length of the registered protocol name */
/* that way NAME can have additonal stuff after it */
/* This is much better than the old single letter checking */
if (0 == strnicmp (name, pp->name, strlen (pp->name)))
return pp;
}
return NULL;
}
/*
converts a string of the form #x to seconds
where x can be a unit specifier of
d or D days
h or H hours
m or M minutes
s or S seconds
the default is seconds
*/
int
time_atoi(const char *pstr)
{
int ret=0;
int len = strlen(pstr);
if (!pstr[0]) return 0;
switch (pstr[len-1]) {
case 'd': /* days */
case 'D':
ret = 24 * 60 * 60 * atoi(pstr);
break;
case 'h': /* hours */
case 'H':
ret = 60 * 60 * atoi(pstr);
break;
case 'm': /* minutes */
case 'M':
ret = 60 * atoi(pstr);
break;
case 's': /* seconds */
case 'S':
default:
ret = atoi(pstr);
break;
}
return ret;
}
/*
Simple keyword indexed string storage
This kind of thing has been invented many times. Once more with gusto!
*/
param_list_t *
paramListInit (void)
{
param_list_t *np = (param_list_t *)mycalloc (sizeof (param_list_t));
return np;
}
/* paramListAdd returns: 1 update existing value, 0 new, -1 out of memory */
int
paramListAdd (param_list_t *list,
const char *name,
const char *value)
{
param_list_t *pl;
int found = 0;
assert (list != NULL);
assert (name != NULL);
assert (value != NULL);
if (NULL == list->name) { /* first one special case */
list->name = mystrdup (name);
if (NULL == list->name) return -1; /* out of memory */
list->value = mystrdup (value);
if (NULL == list->value) return -1; /* out of memory */
return 0;
}
for (pl = list; pl->next; pl = pl->next) {
if (0 == strcmp (pl->name, name)) {
found = 1;
break;
}
}
if (found) {
free (pl->value);
pl->value = mystrdup (value);
if (NULL == pl->value) return -1; /* out of memory */
return 1;
} else {
param_list_t *np = (param_list_t *)mycalloc (sizeof (param_list_t));
if (NULL == np) return -1; /* out of memory */
np->name = mystrdup (name);
if (NULL == np->name) return -1; /* out of memory */
np->value = mystrdup (value);
if (NULL == np->value) return -1; /* out of memory */
pl->next = np;
return 0;
}
}
/* paramListGet returns value or NULL */
char *
paramListGet (param_list_t *list,
const char *name)
{
param_list_t *pl;
assert (list != NULL);
assert (name != NULL);
for (pl = list; pl->next; pl = pl->next) {
if (0 == strcmp (pl->name, name)) {
return pl->value;
}
}
return NULL;
}
/*
Simple keyword indexed string storage
This kind of thing has been invented many times. Once more with gusto!
*/
string_list_t *
stringListInit (const char *value)
{
string_list_t *np = (string_list_t *)mycalloc (sizeof (string_list_t));
if (value)
np->value = mystrdup (value); /* This can be NULL */
return np;
}
void
stringListFree (string_list_t *list)
{
string_list_t *pl, *next;
assert (list != NULL);
for (pl = list; pl; pl = next) {
next = pl->next;
if (pl->value)
free (pl->value);
free (pl);
}
}
/* stringListAdd returns: 0 new, -1 out of memory */
int
stringListAdd (string_list_t *list,
const char *value)
{
string_list_t *pl;
string_list_t *np;
assert (list != NULL);
assert (value != NULL);
if (NULL == list->value) { /* first one special case */
list->value = mystrdup (value);
if (NULL == list->value) return -1; /* out of memory */
return 0;
}
for (pl = list; pl->next; pl = pl->next)
; /* skip to end */
np = (string_list_t *)mycalloc (sizeof (string_list_t));
if (NULL == np)
return -1; /* out of memory */
np->value = mystrdup (value);
if (NULL == np->value)
return -1; /* out of memory */
pl->next = np;
return 0;
}
/* return non 0 if whitespace */
#define IS_WHITE(c) ((' ' == (c)) || '\t' == (c))
#define IS_TERM(c) (('\r' == (c)) || '\n' == (c))
#define IS_NUM(c) (('0' <= (c)) && ('9' >= (c)))
/*
Get a 'line' from a text buffer (terminated by CR-NL or NL)
Handle comments.
Skip empty lines.
Handle continued lines (backslash as last character)
Return the pointer to the next line (or NULL at end)
*/
char *
get_line_from_buffer (char *buffer, /* buffer to sort through */
char *line, /* line buffer to fill in */
int *lineCount, /* count of lines */
int continuation) /* part of previous line */
{
char *end, *start;
char *next;
int len;
assert (buffer != NULL);
assert (line != NULL);
next = strchr (buffer, '\n');
if (next) {
++next; /* start point for next line */
} else if (strlen (buffer) > 0) {
d_printf (stderr, "Last line missing NEWLINE\n");
} else { /* done with buffer */
*line = 0;
return NULL;
}
if (lineCount) ++(*lineCount); /* increment line count */
if (continuation) {
/* continuation lines keep everything */
start = buffer;
end = next-1;
} else {
/* find usefull text */
len = strcspn (buffer, "#\r\n");
if (!len) { /* empty line, go to next */
return get_line_from_buffer (next, line, lineCount, continuation);
}
/* skip trailing white too */
for (end = buffer + len; end > buffer; --end) {
if (!IS_WHITE (end[-1])) break;
}
if (end == buffer) { /* blank line */
return get_line_from_buffer (next, line, lineCount, continuation);
}
/* find leading whitespace */
start = buffer + strspn (buffer, " \t");
}
assert (end > start); /* we should have found blank above */
strncpy(line, start, end - start); /* get a line */
line[end-start] = '\0';
if (line[end-start-1] == '\\') { /* continuation line */
return get_line_from_buffer (next, &line[end-start-1], lineCount, 1);
}
D_PRINTF(stderr, "clean line [%s]\n", line);
return next;
}
/*
return 1 if for us, 0 if everyone, -1 if not for us
*/
int
check_hostname_attribute (const char *line)
{
char *hostp;
/* Section open, check if for us */
if ((hostp = strstr(line, "hosts="))
|| (hostp = strstr(line, "HOSTS="))) {
hostp = strchr (hostp, '='); /* skip to the equals */
assert (hostp != NULL);
/* look for our hostname */
if (strstr(hostp, gs_parsename) != NULL) {
/* should check for complete string match */
return 1;
} else {
return -1;
}
}
/* not host specific */
return 0;
}
/*
Protocol independent parsing
*/
int
cmdParseNameValue (pmail_command_t cmd,
char *name,
char *tok)
{
if (strcmp(name, "numloops") == 0)
cmd->numLoops = atoi(tok);
else if (strcmp(name, "throttle") == 0)
cmd->throttle = atoi(tok);
else if (strcmp(name, "weight") == 0)
cmd->weight = atoi(tok);
else if (strcmp(name, "idletime") == 0)
cmd->idleTime = time_atoi(tok);
else if (strcmp(name, "blockid") == 0)
cmd->blockID = time_atoi(tok);
else if (strcmp(name, "blocktime") == 0)
cmd->blockTime = time_atoi(tok);
else if (strcmp(name, "loopdelay") == 0)
cmd->loopDelay = time_atoi(tok);
else if (strcmp(name, "checkmailinterval") == 0) /* BACK COMPAT */
cmd->loopDelay = time_atoi(tok);
else
return 0; /* no match */
return 1; /* matched it */
}
/*
* count_num_commands()
* given a commandsfile string, count the valid command for us.
TODO Dynamically load the protocols found
*/
static int
count_num_commands(char *commands)
{
char *cmdptr = commands;
int num_comms = 0;
char line[LINE_BUFSIZE];
/*
* parse through the string line-by-line,strip out comments
*/
/*D_PRINTF(stderr, "count_num_commands[%s]\n", commands);*/
while (NULL != (cmdptr = get_line_from_buffer (cmdptr, line, NULL, 0))) {
/* increment count if we've hit a open tag (e.g. <SMTP...) and
it's not the <Default> tag, or <Graph> tag */
if (line[0] != '<') continue; /* not an open */
if (line[1] == '/') continue; /* a close */
if (0 == strnicmp (line+1, "default", 7)) continue; /* default */
/* should already be filtered out */
if (0 == strnicmp (line+1, "graph", 5)) continue; /* graph */
/* Section open, check if for us */
if (check_hostname_attribute (line) < 0) {
D_PRINTF (stderr, "count_num_commands: section not for us '%s'\n",
line);
continue;
}
/* find protocol */
if (NULL == protocol_get (line+1)) {
/* TODO load handler */
/* TODO add to protocol list */
D_PRINTF (stderr, "count_num_commands: No handler for '%s'\n",
line);
continue;
}
D_PRINTF(stderr, "count_num_commands: Found section '%s'\n", line);
num_comms++;
}
return (num_comms);
}
char *
string_tolower(char *string)
{
if (string == NULL)
return NULL;
/* convert to lower case */
for (; *string != '\0'; ++string) {
*string = tolower (*string);
}
return string;
}
char *
string_unquote(char *string)
{
int len, num;
char *from, *to;
if (string == NULL)
return NULL;
len = strlen(string);
if (string[0] == '"' && string[len-1] == '"') {
/* remove matching double-quotes */
string[len-1] = '\0';
++string;
}
/* replace quoted characters (and decimal codes) */
/* assuming line-continuation already happened */
from = to = string;
while (*from) {
if (*from == '\\') {
++from;
if (IS_NUM(*from)) {
num = *from++ - '0';
if (IS_NUM(*from))
num = num*10 + (*from++ - '0');
if (IS_NUM(*from))
num = num*10 + (*from++ - '0');
*to++ = num;
} else {
switch (*from) {
case '\0': continue;
case 'n': *to++ = '\n'; break;
case 'r': *to++ = '\r'; break;
case 't': *to++ = '\t'; break;
default: *to++ = *from; break;
}
++from;
}
} else {
*to++ = *from++;
}
}
*to = '\0';
return string;
}
/*
* load_commands()
* Parse the commlist file again, this time getting the commands, filenames
* and weights and reading the message files into memory.
*/
int
load_commands(char *commands)
{
char *cmdptr = commands;
int total_weight = 0;
char line[LINE_BUFSIZE];
int lineNumber = 0;
int commIndex = 0;
int inCommand = 0; /* 0 none, -1 ignore, 1 default, 2 other */
string_list_t *param_list = NULL;
g_default_params = paramListInit (); /* create default section list */
/* set built in defaults. always use lower case names */
paramListAdd (g_default_params, "numloops", "1");
paramListAdd (g_default_params, "numrecipients", "1");
paramListAdd (g_default_params, "numlogins", "1");
paramListAdd (g_default_params, "numaddresses", "1");
paramListAdd (g_default_params, "weight", "100");
gn_number_of_commands = count_num_commands(commands);
D_PRINTF(stderr, "number_of_commands = %d\n", gn_number_of_commands);
if (gn_number_of_commands <= 0) { /* no mail msgs - exit */
return returnerr (stderr, "No commands found\n");
}
/* allocate structure to hold command list (command filename weight) */
g_loaded_comm_list =
(mail_command_t *) mycalloc(gn_number_of_commands
* sizeof(mail_command_t));
while (NULL
!= (cmdptr = get_line_from_buffer (cmdptr, line, &lineNumber, 0))) {
/* The pre-process step does lots of checking, keep this simple */
/* check for close tag */
if ((line[0] == '<') && (line[1] == '/')) {
/* default or ignored command */
if (inCommand < 2) {
assert (param_list == NULL);
inCommand = 0;
continue;
}
stringListAdd (param_list, line); /* store last line */
if (g_loaded_comm_list[commIndex].proto->parseEnd) {
int ret;
ret = (g_loaded_comm_list[commIndex].proto->parseEnd)
(g_loaded_comm_list+commIndex,
param_list, g_default_params);
if (ret < 0) {
D_PRINTF (stderr, "Error finalizing section for '%s'\n",
line);
continue;
}
}
g_loaded_comm_list[commIndex].proto->cmdCount++;
D_PRINTF (stderr, "Section done: '%s' weight=%d\n\n",
line, g_loaded_comm_list[commIndex].weight);
/* update total weight */
total_weight += g_loaded_comm_list[commIndex].weight;
commIndex++;
inCommand = 0;
if (param_list) {
stringListFree (param_list);
param_list = NULL;
}
continue;
}
/* open tag */
if (line[0] == '<') {
protocol_t *pp;
if (check_hostname_attribute (line) < 0) { /* not for us */
D_PRINTF (stderr, "Section not for us %s\n", line);
inCommand = -1;
continue;
}
/* Check if default special case */
if (0 == strnicmp (line+1, "default", 7)) { /* default */
D_PRINTF (stderr, "DEFAULT section\n");
inCommand = 1;
continue;
}
/* Check if we should ignore it */
if (0 == strnicmp (line+1, "graph", 5)) { /* ignore graph */
D_PRINTF (stderr, "GRAPH section (ignored)\n");
inCommand = -1;
continue;
}
pp = protocol_get (line+1);
if (NULL == pp) { /* protocol not found */
d_printf (stderr,
"Warning: Skipping section with no protocol handler '%s'\n",
line);
continue;
}
if (pp->parseStart) {
int ret;
ret = (pp->parseStart) (g_loaded_comm_list+commIndex,
line, g_default_params);
if (ret < 0) {
D_PRINTF (stderr, "Error Initializing section for '%s'\n",
line);
continue;
} else if (ret == 0) {
D_PRINTF (stderr, "Ignoring section for '%s'\n",
line);
continue;
}
}
/* start a command */
D_PRINTF (stderr, "New Section: %s\n", line);
g_loaded_comm_list[commIndex].proto = pp;
inCommand = 2;
param_list = stringListInit (line); /* store first line */
/* ignoring rest of line */
continue;
}
/* If we're not inside a command tag or not for us, ignore the line */
if (inCommand <= 0) {
continue;
}
/* attr value */
if (1 == inCommand) { /* default, always name value pairs */
char *value;
value = line + strcspn (line, " \t=");
if (value != line) {
*value++ = 0; /* terminate name */
value += strspn(value, " \t=");
string_tolower(line);
value = string_unquote(value);
/*D_PRINTF (stderr, "DEFAULT: name='%s' value='%s'\n",
line, value);*/
paramListAdd (g_default_params, line, value);
} else {
D_PRINTF (stderr, "DEFAULT: Cound not find 'NAME VALUE...', line %d\n",
lineNumber);
}
continue;
}
/* store body for protocol parsing */
stringListAdd (param_list, line);
}
return (total_weight);
}

Просмотреть файл

@ -1,92 +0,0 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/* these are protocol dependent timers for Pop, Imap, Smtp, Http*/
typedef struct pish_stats {
event_timer_t connect;
event_timer_t banner;
event_timer_t login;
event_timer_t cmd;
event_timer_t msgread;
event_timer_t msgwrite;
event_timer_t logout;
/* protocol dependent local storage */
/* should have local ranges too */
range_t loginRange; /* login range for this thread */
unsigned long lastLogin;
range_t domainRange; /* domain range for this thread */
unsigned long lastDomain;
range_t addressRange; /* address range for this thread */
unsigned long lastAddress;
} pish_stats_t;
/* These are common to POP, IMAP, SMTP, HTTP */
typedef struct pish_command {
resolved_addr_t hostInfo; /* should be a read only cache */
/* These are common to SMTP, POP, IMAP */
char * loginFormat;
range_t loginRange; /* login range for all threads */
range_t domainRange; /* domain range for all threads */
char * passwdFormat;
/* SMTP command attrs */
char * addressFormat;
range_t addressRange; /* address range for all threads */
char * smtpMailFrom;
char * filename;
int numRecipients; /* recpients per message */
int msgsize; /* message size without trailing CRLF.CRLF */
char * msgMailFrom; /* message mail from (envelope sender) */
char * msgdata; /* cache the file in mem */
int useEHLO; /* use EHLO instead of HELO */
int useAUTHLOGIN; /* use AUTH LOGIN to authenticate */
int useAUTHPLAIN; /* use AUTH PLAIN to authenticate */
/* POP/IMAP flag to leave mail on server */
int leaveMailOnServer; /* IMAP > 2: leave unseen */
/* IMAP command attrs */
char * imapSearchFolder;
char * imapSearchPattern;
int imapSearchRate;
} pish_command_t;
/* TRANSITION functions */
extern int pishParseNameValue (pmail_command_t cmd, char *name, char *tok);

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -44,6 +44,9 @@ typedef struct _doPOP3_state {
int msgCounter; /* count in download */
} doPOP3_state_t;
/* POP3 flags definitions */
#define leaveMailOnServer 0x01
static void doPop3Exit (ptcx_t ptcx, doPOP3_state_t *me);
@ -58,7 +61,11 @@ PopParseNameValue (pmail_command_t cmd,
if (pishParseNameValue(cmd, name, tok) == 0)
; /* done */
else if (strcmp(name, "leavemailonserver") == 0)
pish->leaveMailOnServer = atoi(tok);
if (atoi(tok) > 0) {
pish->flags |= leaveMailOnServer;
} else {
pish->flags &= ~leaveMailOnServer;
}
else {
return -1;
}
@ -365,7 +372,7 @@ doPop3Loop(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
}
/* if we're not told to leave mail on server, delete the message */
if (!pish->leaveMailOnServer) {
if (!(pish->flags & leaveMailOnServer)) {
/* send the DELE command */
sprintf(command, "DELE %d%s", me->msgCounter, CRLF);
event_start(ptcx, &stats->cmd);

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@ -37,15 +37,320 @@
#include "bench.h"
#include "pish.h"
#include <glob.h> /* for glob, globfree */
#define MAXCOMMANDLEN 256
#define MAXCOMMANDLEN 256 /* parse buffer length */
/* SMTP protocol line to send after a message */
#define MSG_TRAILER CRLF "." CRLF
/* run time state */
typedef struct _doSMTP_state {
int nothing;
} doSMTP_state_t;
/* info on files/messages to send */
typedef struct {
char * filename; /* file name */
int offset; /* where to start sending from */
char * msgMailFrom; /* message mail from (envelope sender) */
} smtp_file_t;
/* flags definitions */
#define useEHLO 0x01 /* use EHLO instead of HELO */
#define useAUTHLOGIN 0x02 /* use AUTH LOGIN to authenticate */
#define useAUTHPLAIN 0x04 /* use AUTH PLAIN to authenticate */
static void doSMTPExit (ptcx_t ptcx, doSMTP_state_t *me);
/* ================ Support routines ================ */
/*
Handle the initial look at the specified file
*/
static int
SmtpFileInit (pmail_command_t cmd, /* command being checked */
param_list_t *defparm, /* default parameters */
smtp_file_t *fileEntry) /* file entry to fill in */
{
/*pish_command_t *pish = (pish_command_t *)cmd->data;*/
int fd;
int bytesRead;
struct stat statbuf;
char *msgdata; /* temp buffer */
int msgsize; /* message size without trailing CRLF.CRLF */
/* Handle multiple files. This means that the file contents
(starting from an offset) are read when the block is executed.
The start of the file is scanned here for special commands. */
D_PRINTF (stderr, "SmtpFileInit: %s\n", fileEntry->filename);
/* read the contents of file into struct */
memset(&statbuf, 0, sizeof(statbuf));
if (stat(fileEntry->filename, &statbuf) != 0) {
return returnerr(stderr,"Couldn't stat file %s: errno=%d: %s\n",
fileEntry->filename, errno, strerror(errno));
}
/* open file */
if ((fd = open(fileEntry->filename, O_RDONLY)) <= 0) {
return returnerr(stderr, "Cannot open file %s: errno=%d: %s\n",
fileEntry->filename, errno, strerror(errno));
}
/* We don't really need much of the file, but it warms up the
* cache. Limit at 1Mb */
msgsize = MIN (statbuf.st_size, 1024*1024);
msgdata = (char *) mycalloc(msgsize+strlen(MSG_TRAILER)+1);
if ((bytesRead = read(fd, msgdata, msgsize)) <= 0) {
close(fd);
return returnerr(stderr, "Cannot read file %s: errno=%d: %s\n",
fileEntry->filename, errno, strerror(errno));
}
if (bytesRead != msgsize) {
returnerr(stderr, "Error reading file %s, got %d expected %d\n",
fileEntry->filename, bytesRead, msgsize);
close(fd);
return -1;
}
msgdata[msgsize] = 0;
/* If the file starts with SMTP, then it has extra info in it */
/* clean up message to rfc822 style */
#define PROTO_HEADER "SMTP"
#define PROTO_MAIL_FROM "\nMAIL FROM:"
#define PROTO_DATA "\nDATA\n"
if (strncmp(msgdata, PROTO_HEADER, strlen(PROTO_HEADER)) == 0) {
char *cp, *cp2;
int off;
D_PRINTF(stderr, "found PROTO_HEADER [%s]\n", PROTO_HEADER);
cp = strstr(msgdata, PROTO_MAIL_FROM);
if (cp != NULL) { /* copy out FROM field */
cp += strlen(PROTO_MAIL_FROM);
cp2 = strchr(cp, '\n');
off = cp2 - cp;
fileEntry->msgMailFrom = (char *) mycalloc(off+1);
memcpy(fileEntry->msgMailFrom, cp, off);
fileEntry->msgMailFrom[off] = 0;
D_PRINTF(stderr, "got PROTO_MAIL_FROM:%s\n",
fileEntry->msgMailFrom);
}
cp = strstr(msgdata, PROTO_DATA);
if (cp != NULL) { /* DATA marks the real message, copy up */
off = cp - msgdata;
off += strlen(PROTO_DATA);
fileEntry->offset = off;
D_PRINTF(stderr, "found PROTO_DATA at off=%d\n", off);
} else {
D_PRINTF(stderr,
"WARNING: PROTO_HEADER [%s] given, but PROTO_DATA [%s] never found\n",
PROTO_HEADER, PROTO_DATA);
}
}
myfree (msgdata);
close(fd);
return 0;
}
/*
Handle file expansion for the given file pattern
*/
static int
SmtpFilePrep (pmail_command_t cmd, /* command being checked */
param_list_t *defparm) /* default parameters */
{
pish_command_t *pish = (pish_command_t *)cmd->data;
int ii;
glob_t globs;
smtp_file_t *fileEntry;
/* We randomly pick files, so dont bother to sort them */
if (glob (pish->filePattern, GLOB_NOSORT | GLOB_MARK, NULL, &globs) < 0) {
globfree (&globs);
return returnerr(stderr,"Error globbing '%s': errno=%d: %s\n",
pish->filePattern, errno, strerror(errno));
}
pish->fileCount = globs.gl_pathc;
D_PRINTF (stderr, "SmtpFilePrep: filePattern='%s' entries=%d\n",
pish->filePattern, pish->fileCount);
pish->files = mycalloc (pish->fileCount * sizeof (smtp_file_t));
fileEntry = pish->files;
for (ii = 0; ii < pish->fileCount; ++ii, ++fileEntry) {
fileEntry->filename = mystrdup (globs.gl_pathv[ii]);
if (SmtpFileInit (cmd, defparm, fileEntry) < 0) {
globfree (&globs);
return -1;
}
}
globfree (&globs);
return 0;
}
/*
Send a file with leading and trailing text.
Currently only used by SMTP.
The leading and trailing text may be NULL.
For SMTP, put the <CRLF>.<CRLF> in the trailing text.
*/
static int
sendFile (
ptcx_t ptcx, /* timer context */
SOCKET sock, /* socket to send on */
char *leading, /* initial text/headers or NULL */
char *fileName, /* filename */
int offset, /* offset into file */
char *trailing) /* trailing text or NULL */
{
int leadLen = 0, trailLen = 0;
int sentbytes = 0;
int sent, todo, done, fd;
char buff[16*1024];
fd = open (fileName, O_RDONLY);
if (fd < 0) {
snprintf (buff, sizeof (buff),
"<sendfile: Error opening '%s' (%s)",
fileName, strerror (errno));
strcat (ptcx->errMsg, buff);
return -1;
}
if (NULL != leading) leadLen = strlen(leading);
if (NULL != trailing) trailLen = strlen(trailing);
D_PRINTF(debugfile, "Writing file '%s' to server: leadLen=%d trailLen=%d offset=%d\n",
fileName, leadLen, trailLen, offset);
/* Send leading text */
todo = leadLen;
done = 0;
while (todo > 0) {
if ((sent = retryWrite(ptcx, sock, leading + done,
todo - done)) == -1) {
strcat (ptcx->errMsg, "<sendFile");
return -1;
}
done += sent;
todo -= sent;
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"sendFile() Time expired.\n");
sentbytes += done;
goto exitFast;
}
}
sentbytes += done;
/* Send the file */
if (offset > 0) { /* skip an initial offset */
if (lseek (fd, offset, SEEK_SET) < 0) {
strcat (ptcx->errMsg, "<sendFile() seek failed.\n");
return -1;
}
}
while ((todo = read (fd, buff, sizeof (buff))) > 0) {
done = 0;
while (todo > 0) {
if ((sent = retryWrite(ptcx, sock, buff + done,
todo - done)) == -1) {
strcat (ptcx->errMsg, "<sendFile");
return -1;
}
done += sent;
todo -= sent;
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"sendFile() Time expired.\n");
sentbytes += done;
goto exitFast;
}
}
sentbytes += done;
}
if (todo < 0) {
D_PRINTF(debugfile,"sendFile() File read.\n");
}
close (fd);
/* Send trailing text */
todo = trailLen;
done = 0;
while (todo > 0) {
if ((sent = retryWrite(ptcx, sock, trailing + done,
todo - done)) == -1) {
strcat (ptcx->errMsg, "<sendFile");
return -1;
}
done += sent;
todo -= sent;
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"sendFile() Time expired.\n");
sentbytes += done;
goto exitFast;
}
}
sentbytes += done;
exitFast:
ptcx->byteswritten += sentbytes;
return sentbytes;
}
#if 0 /* not currently used */
/*
Send a message from memory. Currently only used by SMTP.
Assumes we already included the <CRLF>.<CRLF> at the end of message
*/
static int
sendMessage(ptcx_t ptcx, SOCKET sock, char *message)
{
int writelen;
int sentbytes = 0;
int sent;
writelen = strlen(message);
D_PRINTF(debugfile, "Writing message to server: len=%d\n", writelen );
while (sentbytes < writelen) {
if ((sent = retryWrite(ptcx, sock, message + sentbytes,
writelen - sentbytes)) == -1) {
strcat (ptcx->errMsg, "<sendMessage");
return -1;
}
sentbytes += sent;
if (gf_timeexpired >= EXIT_FAST) {
D_PRINTF(debugfile,"sendMessage() Time expired.\n");
break;
}
}
ptcx->byteswritten += sentbytes;
return sentbytes;
}
#endif
/* ================ SMTP protocol entry points ================ */
/*
Set defaults in command structure
*/
@ -80,9 +385,6 @@ SmtpParseEnd (pmail_command_t cmd,
param_list_t *defparm)
{
string_list_t *sp;
int fd;
int bytesRead;
struct stat statbuf;
pish_command_t *pish = (pish_command_t *)cmd->data;
/* Now parse section lines */
@ -126,88 +428,12 @@ SmtpParseEnd (pmail_command_t cmd,
}
/* check for required attrs */
if (!pish->filename) {
if (!pish->filePattern) {
D_PRINTF(stderr,"missing file for SMTP command");
return returnerr(stderr,"missing file for SMTP command\n");
}
/* read the contents of file into struct */
memset(&statbuf, 0, sizeof(statbuf));
if (stat(pish->filename, &statbuf) != 0) {
return returnerr(stderr,"Couldn't stat file %s: errno=%d: %s\n",
pish->filename, errno, strerror(errno));
}
/* open file */
if ((fd = open(pish->filename, O_RDONLY)) <= 0) {
return returnerr(stderr, "Cannot open file %s: errno=%d: %s\n",
pish->filename, errno, strerror(errno));
}
/* read into loaded_comm_list */
#define MSG_TRAILER CRLF "." CRLF
pish->msgsize = statbuf.st_size;
pish->msgMailFrom = NULL;
pish->msgdata = (char *) mycalloc(pish->msgsize+strlen(MSG_TRAILER)+1);
if ((bytesRead = read(fd, pish->msgdata, pish->msgsize)) <= 0) {
close(fd);
return returnerr(stderr, "Cannot read file %s: errno=%d: %s\n",
pish->filename, errno, strerror(errno));
}
if (bytesRead != pish->msgsize) {
returnerr(stderr, "Error reading file %s, got %d expected %d\n",
pish->filename, bytesRead, pish->msgsize);
close(fd);
return -1;
}
pish->msgdata[pish->msgsize] = 0;
/* clean up message to rfc822 style */
#define PROTO_HEADER "SMTP"
#define PROTO_MAIL_FROM "\nMAIL FROM:"
#define PROTO_DATA "\nDATA\n"
D_PRINTF (stderr, "checking for PROTO_HEADER [%s]\n", PROTO_HEADER);
if (strncmp(pish->msgdata, PROTO_HEADER, strlen(PROTO_HEADER)) == 0) {
char *cp, *cp2;
int off;
D_PRINTF(stderr, "got PROTO_HEADER\n");
D_PRINTF(stderr, "find PROTO_MAIL_FROM...\n");
cp = strstr(pish->msgdata, PROTO_MAIL_FROM);
if (cp != NULL) {
cp += strlen(PROTO_MAIL_FROM);
cp2 = strchr(cp, '\n');
off = cp2 - cp;
pish->msgMailFrom = (char *) mycalloc(off+1);
memcpy(pish->msgMailFrom, cp, off);
pish->msgMailFrom[off] = 0;
D_PRINTF(stderr, "got PROTO_MAIL_FROM:%s\n",pish->msgMailFrom);
}
D_PRINTF(stderr, "find PROTO_DATA...\n");
cp = strstr(pish->msgdata, PROTO_DATA);
if (cp != NULL) {
off = cp - pish->msgdata;
off += strlen(PROTO_DATA);
D_PRINTF(stderr, "got past PROTO_DATA at off=%d\n", off);
char *newmsg = (char *) mycalloc(pish->msgsize+strlen(MSG_TRAILER)+1-off);
memcpy(newmsg, pish->msgdata+off, pish->msgsize-off+1);
myfree(pish->msgdata);
pish->msgdata = newmsg;
D_PRINTF(stderr, "done msg shrink\n");
}
}
strcat(pish->msgdata, MSG_TRAILER);
close(fd);
SmtpFilePrep (cmd, defparm);
/* see if we can resolve the mailserver addr */
if (resolve_addrs(pish->hostInfo.hostName, "tcp",
@ -283,7 +509,7 @@ pishParseNameValue (pmail_command_t cmd,
else if (strcmp(name, "numrecipients") == 0)
pish->numRecipients = atoi(tok);
else if (strcmp(name, "file") == 0)
pish->filename= mystrdup (tok);
pish->filePattern = mystrdup (tok);
else if (strcmp(name, "passwdformat") == 0)
pish->passwdFormat = mystrdup (tok);
else if (strcmp(name, "searchfolder") == 0)
@ -293,11 +519,23 @@ pishParseNameValue (pmail_command_t cmd,
else if (strcmp(name, "searchrate") == 0)
pish->imapSearchRate = atoi(tok);
else if (strcmp(name, "useehlo") == 0)
pish->useEHLO = atoi(tok);
if (atoi(tok)) {
pish->flags |= useEHLO;
} else {
pish->flags &= ~useEHLO;
}
else if (strcmp(name, "useauthlogin") == 0)
pish->useAUTHLOGIN = atoi(tok);
if (atoi(tok) > 0) {
pish->flags |= useAUTHLOGIN;
} else {
pish->flags &= ~useAUTHLOGIN;
}
else if (strcmp(name, "useauthplain") == 0)
pish->useAUTHPLAIN = atoi(tok);
if (atoi(tok) > 0) {
pish->flags |= useAUTHPLAIN;
} else {
pish->flags &= ~useAUTHPLAIN;
}
else {
return -1;
}
@ -774,7 +1012,7 @@ sendSMTPStart(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
D_PRINTF(debugfile,"read connect response\n");
if (pish->useEHLO != 0) {
if (pish->flags & useEHLO) {
/* send extended EHLO */
sprintf(command, "EHLO %s" CRLF, gs_thishostname);
} else {
@ -795,7 +1033,7 @@ sendSMTPStart(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
return NULL;
}
if (pish->useAUTHPLAIN) {
if (pish->flags & useAUTHPLAIN) {
/* look for AUTH PLAIN LOGIN in respBuffer */
if (strstr(respBuffer, "AUTH PLAIN LOGIN") != NULL) {
/* FIX: time get base64 time and multiple round trips */
@ -805,7 +1043,7 @@ sendSMTPStart(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
return NULL;
}
}
} else if (pish->useAUTHLOGIN) {
} else if (pish->flags & useAUTHLOGIN) {
/* look for AUTH LOGIN in respBuffer */
if (strstr(respBuffer, "AUTH=LOGIN") != NULL) {
/* FIX: time get base64 time and multiple round trips */
@ -836,13 +1074,23 @@ sendSMTPLoop(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystat
int numBytes;
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
pish_command_t *pish = (pish_command_t *)cmd->data;
smtp_file_t *fileEntry;
/* send MAIL FROM:<username> */
if (pish->msgMailFrom != NULL) {
sprintf(command, "MAIL FROM:%s%s", pish->msgMailFrom, CRLF);
if (pish->fileCount > 1) { /* randomly pick file */
int ff;
ff = (RANDOM() % pish->fileCount);
/*D_PRINTF(debugfile,"random file<%d=%d\n", pish->fileCount, ff);*/
fileEntry = ((smtp_file_t *)pish->files) + ff;
} else {
fileEntry = (smtp_file_t *)pish->files;
}
if (fileEntry->msgMailFrom != NULL) {
sprintf(command, "MAIL FROM:%s%s", fileEntry->msgMailFrom, CRLF);
} else {
sprintf(command, "MAIL FROM:<%s>%s", pish->smtpMailFrom, CRLF);
}
/*D_PRINTF(debugfile,"%s\n", command);*/
event_start(ptcx, &stats->cmd);
rc = doSmtpCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->cmd);
@ -901,9 +1149,12 @@ sendSMTPLoop(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystat
D_PRINTF(debugfile, "data response %s\n", respBuffer);
/* send data as message (we already added the CRLF.CRLF) */
/* send message */
event_start(ptcx, &stats->msgwrite);
numBytes = sendMessage(ptcx, ptcx->sock, pish->msgdata);
numBytes = sendFile(ptcx, ptcx->sock,
NULL,
fileEntry->filename, fileEntry->offset,
MSG_TRAILER);
if (numBytes == -1) {
event_stop(ptcx, &stats->msgwrite);
if (gf_timeexpired < EXIT_FAST) {

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file

Просмотреть файл

@ -1,202 +0,0 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
* David Shak
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
#ifndef __SYSDEP_H__
#define __SYSDEP_H__
/* include config.h, output from autoconf */
#ifdef HAVE_CONFIG_H
#ifndef __CONFIG_H__
#define __CONFIG_H__
/* borrow config.h from gnuplot. Should build our own */
#include "gnuplot/config.h"
#endif
#else
/* Modern OSes have these */
#define HAVE_SNPRINTF 1
#define HAVE_STRERROR 1
#endif
#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#endif /* _WIN32 */
#ifdef __OSF1__
#include <sys/sysinfo.h> /* for setsysinfo() */
#endif
/* MAXHOSTNAMELEN is undefined on some systems */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* SunOS doesn't define NULL */
#ifndef NULL
#define NULL 0
#endif
/* encapsulation of minor UNIX/WIN NT differences */
#ifdef _WIN32
#define NETREAD(sock, buf, len) recv(sock, buf, len, 0)
#define NETWRITE(sock, buf, len) send(sock, buf, len, 0)
#define NETCLOSE(sock) closesocket(sock)
#define OUTPUT_WRITE(sock, buf, len) write(sock, buf, len)
#define BADSOCKET(sock) ((sock) == INVALID_SOCKET)
#define BADSOCKET_ERRNO(sock) BADSOCKET(sock)
#define BADSOCKET_VALUE INVALID_SOCKET
#define S_ADDR S_un.S_addr
#define GET_ERROR WSAGetLastError()
#define SET_ERROR(err) WSASetLastError(err)
/* NT gettimeofday() doesn't support USE_TIMEZONE (yet) */
#include <time.h>
#define GETTIMEOFDAY(timeval, tz) gettimeofday(timeval)
typedef unsigned short NETPORT;
#define SRANDOM srand
#define RANDOM rand
#define PROGPATH "c:\\mailstone\\mailclient"
#define FILENAME_SIZE 256
#define HAVE_VPRINTF 1
#define SIGCHLD 0 /* dummy value */
#define SIGALRM 0 /* dummy value */
typedef int pid_t;
typedef unsigned short ushort;
#define MAXPATHLEN 512
extern void sock_cleanup(void);
#define THREAD_RET void
#define THREAD_ID int
#else /* not _WIN32 */
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#define NETREAD(sock, buf, len) read(sock, buf, len)
#define NETWRITE(sock, buf, len) write(sock, buf, len)
#define NETCLOSE(sock) close(sock)
#define OUTPUT_WRITE(sock, buf, len) write(sock, buf, len)
#define BADSOCKET(sock) ((sock) < 0)
#define BADSOCKET_ERRNO(sock) (BADSOCKET(sock) || errno)
#define BADSOCKET_VALUE (-1)
#define S_ADDR s_addr
#define GET_ERROR errno
#define SET_ERROR(err) (errno = (err))
#define GETTIMEOFDAY(timeval,tz) gettimeofday(timeval, NULL)
typedef unsigned short NETPORT;
#if defined (USE_LRAND48_R)
extern void osf_srand48_r(unsigned int seed);
extern long osf_lrand48_r(void);
#define SRANDOM osf_srand48_r
#define RANDOM osf_lrand48_r
#elif defined (USE_LRAND48)
#define SRANDOM srand48
#define RANDOM lrand48
#else /* !USE_LRAND48 */
#define SRANDOM srandom
#define RANDOM random
#endif /* USE_LRAND48_R */
#define PROGPATH "/mailstone/mailclient"
#define FILENAME_SIZE 1024
#define HAVE_VPRINTF 1
typedef int SOCKET;
#define min(a,b) (((a) < (b)) ? a : b)
#define max(a,b) (((a) > (b)) ? a : b)
#define THREAD_RET void *
#ifdef USE_PTHREADS
#define THREAD_ID pthread_t
#else
#define THREAD_ID int
#endif
#endif /* _WIN32 */
typedef THREAD_RET (*thread_fn_t)(void *);
/* function prototypes */
extern void crank_limits(void);
extern int sysdep_thread_create(THREAD_ID *id, thread_fn_t tfn, void *arg);
extern int sysdep_thread_join(THREAD_ID id, int *pstatus);
extern void setup_signal_handlers (void);
#ifdef _WIN32
int getopt(int argc, char ** argv, char *opts);
int getpid(void);
int gettimeofday(struct timeval *curTimeP);
int random_number(int max);
SOCKET rexec(const char **hostname, NETPORT port, char *username, char *password,
char *command, SOCKET *sockerr);
#else
#ifdef NO_REXEC
extern int rexec(char **, int, char *, char *, char *, int *);
#endif
#endif /* _WIN32 */
#ifndef HAVE_STRERROR
/* strerror() is not available on SunOS 4.x and others */
char *strerror(int errnum);
#endif
/* strerror() */
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
#endif /* !__SYSDEP_H__ */

Просмотреть файл

@ -1,73 +0,0 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/*
Stuff that deals with timevals.
*/
#include "bench.h"
double
timevaldouble(struct timeval *tin)
{
return ((double)tin->tv_sec + ((double)tin->tv_usec / USECINSEC));
}
void
doubletimeval(const double tin, struct timeval *tout)
{
tout->tv_sec = (long)floor(tin);
tout->tv_usec = (long)((tin - tout->tv_sec) * USECINSEC );
}
/* Difference two timevals and return as a double (in seconds) */
/* Could be a macro */
double
compdifftime_double(struct timeval *EndTime, struct timeval *StartTime)
{
/* doing the integeger differences first is supposed to prevent
any loss in resolution (more important if we returned float instead) */
double d = (EndTime->tv_sec - StartTime->tv_sec)
+ ((double)(EndTime->tv_usec - StartTime->tv_usec)*(1.0/USECINSEC));
if (d < 0.0) {
D_PRINTF (stderr, "Woa! compdifftime negative start %lu.%06lu end %lu.%06lu\n",
StartTime->tv_sec, StartTime->tv_usec,
EndTime->tv_sec, EndTime->tv_usec);
return 0.0;
}
return d;
}

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C; c-file-style: "bsd"; comment-column: 40 -*- */
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file