From: Art Cancro Date: Tue, 13 Nov 2018 21:36:22 +0000 (-0500) Subject: Merge branch 'master' of ssh://git.citadel.org/appl/gitroot/citadel X-Git-Tag: v939~334 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=421c6e0bce6917ae9d09ae066c77fb58b964c399;hp=ccf70a1258a8cbb81b66e0e1cea7b5049a8efa07 Merge branch 'master' of ssh://git.citadel.org/appl/gitroot/citadel --- diff --git a/citadel/COPYING b/citadel/COPYING index 44b6007e8..4d0a56b1f 100644 --- a/citadel/COPYING +++ b/citadel/COPYING @@ -1,5 +1,5 @@ -Copyright: (C) 1987-2017 Citadel development team; GPL V3 +Copyright: (C) 1987-2018 Citadel development team; GPL V3 Copyright for CRC16: (C) 2002-2003 Indigo Systems Corporation; Artistic license + Non advertising clause @@ -9,8 +9,7 @@ Copyright for MD5 implementation: (C) 1993 Colin Plumb; Public Domain * In addition, as a special exception, we hereby declare that our favorite type of software is called "open source" -- NOT "free software" -- and that our favorite operating system is called - "Linux" -- NOT "GNU/Linux." We officially reject and denounce - Richard Stallman's linguistic fascism. + "Linux" -- NOT "GNU/Linux". * In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the @@ -680,30 +679,5 @@ MD5 license: This code was written by Colin Plumb in 1993, no copyright is claimed. This code is in the public domain; do with it what you wish. -RFC 2739 openldap schema license: - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. diff --git a/citadel/Makefile.in b/citadel/Makefile.in index f1b1407bc..16ca85fd3 100644 --- a/citadel/Makefile.in +++ b/citadel/Makefile.in @@ -36,12 +36,10 @@ include Make_modules UTIL_TARGETS=citmail$(EXEEXT) sendcommand$(EXEEXT) -UTILBIN_TARGETS= base64$(EXEEXT) setup$(EXEEXT) \ +UTILBIN_TARGETS= setup$(EXEEXT) \ chkpw$(EXEEXT) chkpwd$(EXEEXT) \ - msgform$(EXEEXT) \ ctdlmigrate$(EXEEXT) - ACLOCAL=@ACLOCAL@ AUTOCONF=@AUTOCONF@ chkpwd_LIBS=@chkpwd_LIBS@ @@ -71,9 +69,9 @@ LOCALEDIR=@LOCALEDIR@ SOURCES=utils/citmail.c \ - utils/setup.c utils/msgform.c utils/chkpw.c \ + utils/setup.c utils/chkpw.c \ utils/sendcommand.c \ - utils/ctdlmigrate.c utils/base64.c utils/chkpwd.c \ + utils/ctdlmigrate.c utils/chkpwd.c \ utillib/citadel_dirs.c \ citserver.c clientsocket.c config.c control.c $(DATABASE) \ domain.c serv_extensions.c genstamp.c \ @@ -169,12 +167,6 @@ sendcommand$(EXEEXT): utils/sendcommand.o utillib/citadel_dirs.o $(LIBOBJS) $(CC) utils/sendcommand.o utillib/citadel_dirs.o \ $(LIBOBJS) $(LDFLAGS) -o sendcommand$(EXEEXT) $(LIBS) -base64$(EXEEXT): utils/base64.o - $(CC) utils/base64.o $(LDFLAGS) -o base64$(EXEEXT) - -msgform$(EXEEXT): utils/msgform.o - $(CC) utils/msgform.o $(LDFLAGS) -o msgform$(EXEEXT) - .PHONY: install-data install-doc install-exec clean cleaner distclean install-locale: diff --git a/citadel/docs/developers.txt b/citadel/docs/developers.txt deleted file mode 100644 index 81d2a5464..000000000 --- a/citadel/docs/developers.txt +++ /dev/null @@ -1,63 +0,0 @@ -Every client for the Citadel system is capable of identifying itself with -a developer code, client code, and client version. Here are the known values -for these fields. - - -Developer codes (and where known, client codes) - - 0 The Citadel core development team - (See copyright.txt for the list of people involved in the project) - Here are the client ID's we've used: - - Client Name Status Description - 0 Citadel deployed Citadel text based client - 1 lcit dead Curses-based text client - 2 WinCit legacy Visual Basic client for Win16 - 4 WebCit deployed Web-based access to Citadel - 5 Shaggy dead Java-powered client - 6 Daphne dead wx multiplatform "fat" client - 7 Shaggy (new) unknown Java-powered client - - 8 ctdlphp deployed PHP interface to Citadel - 9 z-push in development Citadel backend for Z-Push - - 1 Brian Ledbetter - - Client Name Status Description - 0 libCxClient deployed Client-side API library - 1 Infusion deployed Groupware for Citadel - - 2 OST Systems, Inc. - Matthew Scott - - Client Name Status Description - 0 CivisLink development Python Citadel protocol library - - 3 Jesse Vincent - - 4 Brian Costello - - 5 Robert Abatecola - - 6 Bastille - - 7 Walden Leverich - - 8 Michael Hampton - - Client Name Status Description - 0 libcitadel in development Client-side API library - 1 D.O.C. dead Dave's Own Citadel look-alike - 8 stress deployed Citadel server stress tester - 16 Courier in development GTK+ Unix/Win32 Client - - 31 Stuart Cianos - - 69 Anticlimactic Teleservices - Don Kimberlin (err head) - - 71 Robert Barta - - 177 Kevin Fisher - - 226 David Given diff --git a/citadel/include/citadel_dirs.h b/citadel/include/citadel_dirs.h index 6956a2810..161ab943f 100644 --- a/citadel/include/citadel_dirs.h +++ b/citadel/include/citadel_dirs.h @@ -46,7 +46,6 @@ extern char file_crpt_file_key[PATH_MAX]; extern char file_crpt_file_csr[PATH_MAX]; extern char file_crpt_file_cer[PATH_MAX]; extern char file_chkpwd[PATH_MAX]; -extern char file_base64[PATH_MAX]; extern char file_guesstimezone[PATH_MAX]; extern void calc_dirs_n_files(int relh, int home, const char *relhome, char *ctdldir, int dbg); diff --git a/citadel/modules/instmsg/serv_instmsg.c b/citadel/modules/instmsg/serv_instmsg.c index 5915ab6c7..1bf8c728a 100644 --- a/citadel/modules/instmsg/serv_instmsg.c +++ b/citadel/modules/instmsg/serv_instmsg.c @@ -110,12 +110,9 @@ void log_instant_message(struct CitContext *me, struct CitContext *them, char *m this_im->conversation = NewStrBuf(); this_im->next = imlist; imlist = this_im; - StrBufAppendBufPlain(this_im->conversation, HKEY( - "\r\n" - ), 0); + StrBufAppendBufPlain(this_im->conversation, HKEY("\r\n"), 0); } - /* Since it's possible for this function to get called more than once if a user is logged * in on multiple sessions, we use the message's serial number to keep track of whether * we've already logged it. @@ -152,7 +149,6 @@ void delete_instant_messages(void) { } - /* * Retrieve instant messages */ @@ -188,6 +184,7 @@ void cmd_gexp(char *argbuf) { free(ptr); } + /* * Asynchronously deliver instant messages */ @@ -202,6 +199,7 @@ void cmd_gexp_async(void) { cprintf("%d instant msg\n", ASYNC_MSG + ASYNC_GEXP); } + /* * Back end support function for send_instant_message() and company */ @@ -227,8 +225,6 @@ void add_xmsg_to_context(struct CitContext *ccptr, struct ExpressMessage *newmsg } - - /* * This is the back end to the instant message sending function. * Returns the number of users to which the message was sent. @@ -289,6 +285,7 @@ int send_instant_message(char *lun, char *lem, char *x_user, char *x_msg) return (message_sent); } + /* * send instant messages */ @@ -305,10 +302,12 @@ void cmd_sexp(char *argbuf) cprintf("%d Not logged in.\n", ERROR + NOT_LOGGED_IN); return; } - if (CC->fake_username[0]) + if (CC->fake_username[0]) { lun = CC->fake_username; - else + } + else { lun = CC->user.fullname; + } lem = CC->cs_inet_email; @@ -358,21 +357,24 @@ void cmd_sexp(char *argbuf) message_sent = PerformXmsgHooks(lun, lem, x_user, x_msg); if (message_sent > 0) { - if (!IsEmptyStr(x_msg)) + if (!IsEmptyStr(x_msg)) { cprintf("%d Message sent", CIT_OK); - else + } + else { cprintf("%d Ok to send message", CIT_OK); - if (message_sent > 1) + } + if (message_sent > 1) { cprintf(" to %d users", message_sent); + } cprintf(".\n"); } else { - if (CtdlGetUser(NULL, x_user)) - cprintf("%d '%s' does not exist.\n", - ERROR + NO_SUCH_USER, x_user); - else - cprintf("%d '%s' is not logged in " - "or is not accepting pages.\n", + if (CtdlGetUser(NULL, x_user)) { + cprintf("%d '%s' does not exist.\n", ERROR + NO_SUCH_USER, x_user); + } + else { + cprintf("%d '%s' is not logged in or is not accepting instant messages.\n", ERROR + RESOURCE_NOT_OPEN, x_user); + } } @@ -380,7 +382,6 @@ void cmd_sexp(char *argbuf) } - /* * Enter or exit paging-disabled mode */ @@ -457,10 +458,11 @@ void flush_individual_conversation(struct imlog *im) { FullMsgBuf = NewStrBufPlain(NULL, StrLength(im->conversation) + 100); StrBufAppendBufPlain(FullMsgBuf, HKEY( - "Content-type: text/html; charset=UTF-8\r\n" - "Content-Transfer-Encoding: quoted-printable\r\n" - "\r\n" - ), 0); + "Content-type: text/html; charset=UTF-8\r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "\r\n" + ), 0 + ); StrBufAppendBuf (FullMsgBuf, MsgBuf, 0); FreeStrBuf(&MsgBuf); diff --git a/citadel/utillib/citadel_dirs.c b/citadel/utillib/citadel_dirs.c index afb2b5441..c7407c4a2 100644 --- a/citadel/utillib/citadel_dirs.c +++ b/citadel/utillib/citadel_dirs.c @@ -63,7 +63,6 @@ char file_crpt_file_key[PATH_MAX]=""; char file_crpt_file_csr[PATH_MAX]=""; char file_crpt_file_cer[PATH_MAX]=""; char file_chkpwd[PATH_MAX]=""; -char file_base64[PATH_MAX]=""; char file_guesstimezone[PATH_MAX]=""; @@ -247,11 +246,6 @@ void calc_dirs_n_files(int relh, int home, const char *relhome, char *ctdldir, "%schkpwd", ctdl_utilbin_dir); StripSlashes(file_chkpwd, 0); - snprintf(file_base64, - sizeof file_base64, - "%sbase64", - ctdl_utilbin_dir); - StripSlashes(file_base64, 0); snprintf(file_guesstimezone, sizeof file_guesstimezone, "%sguesstimezone.sh", @@ -303,7 +297,6 @@ void calc_dirs_n_files(int relh, int home, const char *relhome, char *ctdldir, DBG_PRINT(file_crpt_file_csr); DBG_PRINT(file_crpt_file_cer); DBG_PRINT(file_chkpwd); - DBG_PRINT(file_base64); DBG_PRINT(file_guesstimezone); } diff --git a/citadel/utils/base64.c b/citadel/utils/base64.c deleted file mode 100644 index f3614d02d..000000000 --- a/citadel/utils/base64.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Encode or decode file as MIME base64 (RFC 1341) - * Public domain by John Walker, August 11 1997 - * Modified slightly for the Citadel system, June 1999 - * - * This program is open source software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - -#include -#include -#include -#include - -#define TRUE 1 -#define FALSE 0 - -#define LINELEN 72 /* Encoded line length (max 76) */ - -typedef unsigned char byte; /* Byte type */ - -FILE *fi; /* Input file */ -FILE *fo; /* Output file */ -static byte iobuf[256]; /* I/O buffer */ -static int iolen = 0; /* Bytes left in I/O buffer */ -static int iocp = 256; /* Character removal pointer */ -static int ateof = FALSE; /* EOF encountered */ -static byte dtable[256]; /* Encode / decode table */ -static int linelength = 0; /* Length of encoded output line */ -static char eol[] = "\r\n"; /* End of line sequence */ -static int errcheck = TRUE; /* Check decode input for errors ? */ - -/* INBUF -- Fill input buffer with data */ - -static int inbuf(void) -{ - int l; - - if (ateof) { - return FALSE; - } - l = fread(iobuf, 1, sizeof iobuf, fi); /* Read input buffer */ - if (l <= 0) { - if (ferror(fi)) { - exit(1); - } - ateof = TRUE; - return FALSE; - } - iolen = l; - iocp = 0; - return TRUE; -} - -/* INCHAR -- Return next character from input */ - -static int inchar(void) -{ - if (iocp >= iolen) { - if (!inbuf()) { - return EOF; - } - } - - return iobuf[iocp++]; -} - -/* OCHAR -- Output an encoded character, inserting line breaks - where required. */ - -static void ochar(int c) -{ - if (linelength >= LINELEN) { - if (fputs(eol, fo) == EOF) { - exit(1); - } - linelength = 0; - } - if (putc(((byte) c), fo) == EOF) { - exit(1); - } - linelength++; -} - -/* ENCODE -- Encode binary file into base64. */ - -static void encode(void) -{ - int i, hiteof = FALSE; - - /* Fill dtable with character encodings. */ - - for (i = 0; i < 26; i++) { - dtable[i] = 'A' + i; - dtable[26 + i] = 'a' + i; - } - for (i = 0; i < 10; i++) { - dtable[52 + i] = '0' + i; - } - dtable[62] = '+'; - dtable[63] = '/'; - - while (!hiteof) { - byte igroup[3], ogroup[4]; - int c, n; - - igroup[0] = igroup[1] = igroup[2] = 0; - for (n = 0; n < 3; n++) { - c = inchar(); - if (c == EOF) { - hiteof = TRUE; - break; - } - igroup[n] = (byte) c; - } - if (n > 0) { - ogroup[0] = dtable[igroup[0] >> 2]; - ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; - ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; - ogroup[3] = dtable[igroup[2] & 0x3F]; - - /* Replace characters in output stream with "=" pad - characters if fewer than three characters were - read from the end of the input stream. */ - - if (n < 3) { - ogroup[3] = '='; - if (n < 2) { - ogroup[2] = '='; - } - } - for (i = 0; i < 4; i++) { - ochar(ogroup[i]); - } - } - } - if (fputs(eol, fo) == EOF) { - exit(1); - } -} - -/* INSIG -- Return next significant input */ - -static int insig(void) -{ - int c; - - /*CONSTANTCONDITION*/ - while (TRUE) { - c = inchar(); - if (c == EOF || (c > ' ')) { - return c; - } - } - /*NOTREACHED*/ -} - -/* DECODE -- Decode base64. */ - -static void decode(void) -{ - int i; - - for (i = 0; i < 255; i++) { - dtable[i] = 0x80; - } - for (i = 'A'; i <= 'Z'; i++) { - dtable[i] = 0 + (i - 'A'); - } - for (i = 'a'; i <= 'z'; i++) { - dtable[i] = 26 + (i - 'a'); - } - for (i = '0'; i <= '9'; i++) { - dtable[i] = 52 + (i - '0'); - } - dtable['+'] = 62; - dtable['/'] = 63; - dtable['='] = 0; - - /*CONSTANTCONDITION*/ - while (TRUE) { - byte a[4], b[4], o[3]; - - for (i = 0; i < 4; i++) { - int c = insig(); - - if (c == EOF) { - if (errcheck && (i > 0)) { - fprintf(stderr, "Input file incomplete.\n"); - exit(1); - } - return; - } - if (dtable[c] & 0x80) { - if (errcheck) { - fprintf(stderr, "Illegal character '%c' in input file.\n", c); - exit(1); - } - /* Ignoring errors: discard invalid character. */ - i--; - continue; - } - a[i] = (byte) c; - b[i] = (byte) dtable[c]; - } - o[0] = (b[0] << 2) | (b[1] >> 4); - o[1] = (b[1] << 4) | (b[2] >> 2); - o[2] = (b[2] << 6) | b[3]; - i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3); - if (fwrite(o, i, 1, fo) == EOF) { - exit(1); - } - if (i < 3) { - return; - } - } -} - -/* USAGE -- Print how-to-call information. */ - -static void usage(char *pname) -{ - fprintf(stderr, "%s -- Encode/decode file as base64. Call:\n", pname); - fprintf(stderr, - " %s [-e[ncode] / -d[ecode]] [-n] [infile] [outfile]\n", pname); - fprintf(stderr, "\n"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -D Decode base64 encoded file\n"); - fprintf(stderr, " -E Encode file into base64\n"); - fprintf(stderr, " -N Ignore errors when decoding\n"); - fprintf(stderr, " -U Print this message\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "by John Walker\n"); - fprintf(stderr, " WWW: http://www.fourmilab.ch/\n"); -} - -/* Main program */ - -int main(int argc, char *argv[]) -{ - int i, f = 0, decoding = FALSE; - char *cp, opt; - - fi = stdin; - fo = stdout; - - for (i = 1; i < argc; i++) { - cp = argv[i]; - if (*cp == '-') { - opt = *(++cp); - if (islower(opt)) { - opt = toupper(opt); - } - switch (opt) { - - case 'D': /* -D Decode */ - decoding = TRUE; - break; - - case 'E': /* -E Encode */ - decoding = FALSE; - break; - - case 'N': /* -N Suppress error checking */ - errcheck = FALSE; - break; - - case 'U': /* -U Print how-to-call information */ - case '?': - usage(argv[0]); - return 0; - } - } else { - switch (f) { - - /** Warning! On systems which distinguish text mode and - binary I/O (MS-DOS, Macintosh, etc.) the modes in these - open statements will have to be made conditional based - upon whether an encode or decode is being done, which - will have to be specified earlier. But it's worse: if - input or output is from standard input or output, the - mode will have to be changed on the fly, which is - generally system and compiler dependent. 'Twasn't me - who couldn't conform to Unix CR/LF convention, so - don't ask me to write the code to work around - Apple and Microsoft's incompatible standards. **/ - - case 0: - if (strcmp(cp, "-") != 0) { - if ((fi = fopen(cp, "r")) == NULL) { - fprintf(stderr, "Cannot open input file %s\n", cp); - return 2; - } - } - f++; - break; - - case 1: - if (strcmp(cp, "-") != 0) { - if ((fo = fopen(cp, "w")) == NULL) { - fprintf(stderr, "Cannot open output file %s\n", cp); - return 2; - } - } - f++; - break; - - default: - fprintf(stderr, "Too many file names specified.\n"); - usage(argv[0]); - return 2; - } - } - } - - if (decoding) { - decode(); - } else { - encode(); - } - return 0; -} diff --git a/citadel/utils/msgform.c b/citadel/utils/msgform.c deleted file mode 100644 index 03d94c2c7..000000000 --- a/citadel/utils/msgform.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This is simply a filter that converts Citadel binary message format - * to readable, formatted output. - * - * If the -q (quiet or qwk) flag is used, only the message text prints, and - * then it stops at the end of the first message it prints. - * - * This utility isn't very useful anymore. - * - */ - -#include "sysdep.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int qwk = 0; - -int fpgetfield(FILE * fp, char *string); -int fmout(int width, FILE * fp); - - - -int main(int argc, char **argv) -{ - struct tm tm; - int a, b, e, aflag; - char bbb[1024]; - char subject[1024]; - FILE *fp; - time_t now; - - if (argc == 2) - if (!strcmp(argv[1], "-q")) - qwk = 1; - fp = stdin; - if (argc == 2) - if (strcmp(argv[1], "-q")) { - fp = fopen(argv[1], "r"); - if (fp == NULL) { - fprintf(stderr, "%s: cannot open %s: %s\n", - argv[0], argv[1], strerror(errno)); - exit(errno); - } - } - -TOP: do { - e = getc(fp); - if (e < 0) - exit(0); - } while (e != 255); - strcpy(subject, ""); - getc(fp); - aflag = getc(fp); - if (qwk == 0) - printf(" "); - - do { - b = getc(fp); - if (b == 'M') { - if (qwk == 0) { - printf("\n"); - if (!IsEmptyStr(subject)) - printf("Subject: %s\n", subject); - } - if (aflag != 1) - fmout(80, fp); - else - while (a = getc(fp), a > 0) { - if (a == 13) - putc(10, stdout); - else - putc(a, stdout); - } - } - if ((b != 'M') && (b > 0)) - fpgetfield(fp, bbb); - if (b == 'U') - strcpy(subject, bbb); - if (qwk == 0) { - if (b == 'A') - printf("from %s ", bbb); - if (b == 'N') - printf("@%s ", bbb); - if (b == 'O') - printf("in %s> ", bbb); - if (b == 'R') - printf("to %s ", bbb); - if (b == 'T') { - now = atol(bbb); - localtime_r(&now, &tm); - strcpy(bbb, asctime(&tm)); - bbb[strlen(bbb) - 1] = 0; - printf("%s ", &bbb[4]); - } - } - } while ((b != 'M') && (b > 0)); - if (qwk == 0) - printf("\n"); - if (qwk == 1) - exit(0); - goto TOP; -} - -int fpgetfield(FILE * fp, char *string) - -{ /* level-2 break out next null-terminated string */ - int a, b; - strcpy(string, ""); - a = 0; - do { - b = getc(fp); - if (b < 1) { - string[a] = 0; - return (0); - } - string[a] = b; - ++a; - } while (b != 0); - return (0); -} - -int fmout(int width, FILE * fp) -{ - int a, b, c; - int real = 0; - int old = 0; - char aaa[140]; - - strcpy(aaa, ""); - old = 255; - c = 1; /* c is the current pos */ -FMTA: old = real; - a = getc(fp); - real = a; - if (a <= 0) - goto FMTEND; - - if (((a == 13) || (a == 10)) && (old != 13) && (old != 10)) - a = 32; - if (((old == 13) || (old == 10)) && (isspace(real))) { - printf("\n"); - c = 1; - } - if (a > 126) - goto FMTA; - - if (a > 32) { - if (((strlen(aaa) + c) > (width - 5)) - && (strlen(aaa) > (width - 5))) { - printf("\n%s", aaa); - c = strlen(aaa); - aaa[0] = 0; - } - b = strlen(aaa); - aaa[b] = a; - aaa[b + 1] = 0; - } - if (a == 32) { - if ((strlen(aaa) + c) > (width - 5)) { - printf("\n"); - c = 1; - } - printf("%s ", aaa); - ++c; - c = c + strlen(aaa); - strcpy(aaa, ""); - goto FMTA; - } - if ((a == 13) || (a == 10)) { - printf("%s\n", aaa); - c = 1; - strcpy(aaa, ""); - goto FMTA; - } - goto FMTA; - -FMTEND: printf("\n"); - return (0); -} diff --git a/citadel/utils/stress.c b/citadel/utils/stress.c deleted file mode 100644 index 2655b11c9..000000000 --- a/citadel/utils/stress.c +++ /dev/null @@ -1,362 +0,0 @@ - -/* This message is exactly 1024 bytes */ -char* const message = -"The point of this little file is to stress test a Citadel server.\n" -"It spawns n threads, where n is a command line parameter, each of\n" -"which writes 1000 messages total to the server.\n" -"\n" -"-n is a command line parameter indicating how many users to simulate\n" -"(default 100). WARNING: Your system must be capable of creating this\n" -"many threads!\n" -"\n" -"-w is a command line parameter indicating how long to wait in seconds\n" -"between posting each message (default 10). The actual interval\n" -"will be randomized between w / 3 and w * 3.\n" -"\n" -"A run is expected to take approximately three hours, given default\n" -"values, and assuming the server can keep up. If the run takes much\n" -"longer than this, there may be a performance problem with the server.\n" -"For best results, the test should be run from a different machine than\n" -"the server, but connected via a fast network link (e.g. 100Base-T).\n" -"\n" -"To get baseline results, run the test with -n 1 (simulating 1 user)\n" -"on a machine with no other users logged in.\n" -"\n" -"Example:\n" -"stress -n 500 -w 25 myserver > stress.csv\n"; - -/* The program tries to be as small and as fast as possible. Wherever - * possible, we avoid allocating memory on the heap. We do not pass data - * between threads. We do only a minimal amount of calculation. In - * particular, we only output raw timing data for the run; we do not - * collate it, average it, or do anything else with it. See below. - * The program does, however, use the same CtdlIPC functions as the - * standard Citadel text client, and incurs the same overhead as that - * program, using those functions. - * - * The program first creates a new user with a randomized username which - * begins with "testuser". It then creates 100 rooms named test0 through - * test99. If they already exist, this condition is ignored. - * - * The program then creates n threads, all of which wait on a conditional - * before they do anything. Once all of the threads have been created, - * they are signaled, and begin execution. Each thread logs in to the - * Citadel server separately, simulating a user login, then takes a - * timestamp from the operating system. - * - * Each thread selects a room from 0-99 randomly, then writes a small - * (1KB) test message to that room. 1K was chosen because it seems to - * represent an average message size for messages we expect to see. - * After writing the message, the thread sleeps for w seconds (sleep(w);) - * and repeats the process, until it has written 1,000 messages. The - * program provides a status display to standard error, unless w <= 2, in - * which case status display is disabled. - * - * After posting all messages, each thread takes a second timestamp, and - * subtracts the first timestamp. The resulting value (in seconds) is - * sent to standard output, followed by the minimum, average, and maximum - * amounts of time (in milliseconds) it took to post a message. The - * thread then exits. - * - * Once all threads have exited, the program exits. - */ - -#include -#include -#include -#include -#include -#include -#include "sysdep.h" -#include -#include "citadel_ipc.h" - -#ifndef HAVE_PTHREAD_H -#error This program requires threads -#endif - -static int w = 10; /* see above */ -static int n = 100; /* see above */ -static int m = 1000; /* Number of messages to send; see above */ -static volatile int count = 0; /* Total count of messages posted */ -static volatile int total = 0; /* Total messages to be posted */ -static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t arg_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t output_mutex = PTHREAD_MUTEX_INITIALIZER; - -static char username[12]; -static char password[12]; - -/* - * Mutex for the random number generator - * We don't assume that rand_r() is present, so we have to - * provide our own locking for rand() - */ -static pthread_mutex_t rand_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* - * Conditional. All the threads wait for this signal to actually - * start bombarding the server. - */ -static pthread_mutex_t start_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t start_cond = PTHREAD_COND_INITIALIZER; - - -/* - * This is the worker thread. It logs in and creates the 1,000 messages - * as described above. - */ -void* worker(void* data) -{ - CtdlIPC* ipc; /* My connection to the server */ - void** args; /* Args sent in */ - int r; /* IPC return code */ - char aaa[SIZ]; /* Generic buffer */ - int c; /* Message count */ - time_t start, end; /* Timestamps */ - struct ctdlipcmessage msg; /* The message we will post */ - int argc_; - char** argv_; - long tmin = LONG_MAX, trun = 0, tmax = LONG_MIN; - - args = (void*)data; - argc_ = (int)args[0]; - argv_ = (char**)args[1]; - - /* Setup the message we will be posting */ - msg.text = message; - msg.anonymous = 0; - msg.type = 1; - strcpy(msg.recipient, ""); - strcpy(msg.subject, "Test message; ignore"); - strcpy(msg.author, username); - - pthread_mutex_lock(&arg_mutex); - ipc = CtdlIPC_new(argc_, argv_, NULL, NULL); - pthread_mutex_unlock(&arg_mutex); - if (!ipc) - return NULL; /* oops, something happened... */ - - CtdlIPC_chat_recv(ipc, aaa); - if (aaa[0] != '2') { - fprintf(stderr, "Citadel refused me: %s\n", &aaa[4]); - return NULL; /* server ran out of connections maybe? */ - } - - CtdlIPCIdentifySoftware(ipc, 8, 8, REV_LEVEL, "Citadel stress tester", - "localhost", aaa); /* we're lying, the server knows */ - - r = CtdlIPCQueryUsername(ipc, username, aaa); - if (r / 100 == 2) { - /* testuser already exists (from previous run?) */ - r = CtdlIPCTryLogin(ipc, username, aaa); - if (r / 100 != 3) { - fprintf(stderr, "Citadel refused username: %s\n", aaa); - CtdlIPC_delete_ptr(&ipc); - return NULL; /* Gawd only knows what went wrong */ - } - r = CtdlIPCTryPassword(ipc, password, aaa); - if (r / 100 != 2) { - fprintf(stderr, "Citadel refused password: %s\n", aaa); - CtdlIPC_delete_ptr(&ipc); - return NULL; /* Gawd only knows what went wrong */ - } - } else { - /* testuser doesn't yet exist */ - r = CtdlIPCCreateUser(ipc, username, 1, aaa); - if (r / 100 != 2) { - fprintf(stderr, "Citadel refused create user: %s\n", aaa); - CtdlIPC_delete_ptr(&ipc); - return NULL; /* Gawd only knows what went wrong */ - } - r = CtdlIPCChangePassword(ipc, password, aaa); - if (r / 100 != 2) { - fprintf(stderr, "Citadel refused change password: %s\n", aaa); - CtdlIPC_delete_ptr(&ipc); - return NULL; /* Gawd only knows what went wrong */ - } - } - - /* Wait for the rest of the threads */ - pthread_mutex_lock(&start_mutex); - pthread_cond_wait(&start_cond, &start_mutex); - pthread_mutex_unlock(&start_mutex); - - /* And now the fun begins! Send out a whole shitload of messages */ - start = time(NULL); - for (c = 0; c < m; c++) { - int rm; - char room[7]; - struct ctdlipcroom *rret; - struct timeval tv; - long tstart, tend; - int wait; - - /* Wait for a while */ - pthread_mutex_lock(&rand_mutex); - /* See Numerical Recipes in C or Knuth vol. 2 ch. 3 */ - /* Randomize between w/3 to w*3 (yes, it's complicated) */ - wait = (int)((1.0+2.7*(float)w)*rand()/(RAND_MAX+(float)w/3.0)); /* range 0-99 */ - pthread_mutex_unlock(&rand_mutex); - sleep(wait); - - /* Select the room to goto */ - pthread_mutex_lock(&rand_mutex); - /* See Numerical Recipes in C or Knuth vol. 2 ch. 3 */ - rm = (int)(100.0*rand()/(RAND_MAX+1.0)); /* range 0-99 */ - pthread_mutex_unlock(&rand_mutex); - - /* Goto the selected room */ - sprintf(room, "test%d", rm); - /* Create the room if not existing. Ignore the return */ - r = CtdlIPCCreateRoom(ipc, 1, room, 0, NULL, 0, aaa); - if (r / 100 != 2 && r != 574) { /* Already exists */ - fprintf(stderr, "Citadel refused room create: %s\n", aaa); - pthread_mutex_lock(&count_mutex); - total -= m - c; - pthread_mutex_unlock(&count_mutex); - CtdlIPC_delete_ptr(&ipc); - return NULL; - } - gettimeofday(&tv, NULL); - tstart = tv.tv_sec * 1000 + tv.tv_usec / 1000; /* cvt to msec */ - r = CtdlIPCGotoRoom(ipc, room, "", &rret, aaa); - if (r / 100 != 2) { - fprintf(stderr, "Citadel refused room change: %s\n", aaa); - pthread_mutex_lock(&count_mutex); - total -= m - c; - pthread_mutex_unlock(&count_mutex); - CtdlIPC_delete_ptr(&ipc); - return NULL; - } - - /* Post the message */ - r = CtdlIPCPostMessage(ipc, 1, NULL, &msg, aaa); - if (r / 100 != 4) { - fprintf(stderr, "Citadel refused message entry: %s\n", aaa); - pthread_mutex_lock(&count_mutex); - total -= m - c; - pthread_mutex_unlock(&count_mutex); - CtdlIPC_delete_ptr(&ipc); - return NULL; - } - - /* Do a status update */ - pthread_mutex_lock(&count_mutex); - count++; - pthread_mutex_unlock(&count_mutex); - fprintf(stderr, " %d/%d=%d%% \r", - count, total, - (int)(100 * count / total)); - gettimeofday(&tv, NULL); - tend = tv.tv_sec * 1000 + tv.tv_usec / 1000; /* cvt to msec */ - tend -= tstart; - if (tend < tmin) tmin = tend; - if (tend > tmax) tmax = tend; - trun += tend; - } - end = time(NULL); - pthread_mutex_lock(&output_mutex); - fprintf(stderr, " \r"); - printf("%ld %ld %ld %ld\n", end - start, tmin, trun / c, tmax); - pthread_mutex_unlock(&output_mutex); - return (void*)(end - start); -} - - -/* - * Shift argument list - */ -int shift(int argc, char **argv, int start, int count) -{ - int i; - - for (i = start; i < argc - count; ++i) - argv[i] = argv[i + count]; - return argc - count; -} - - -/* - * Main loop. Start a shitload of threads, all of which will attempt to - * kick a Citadel server square in the nuts. - */ -int main(int argc, char** argv) -{ - void* data[2]; /* pass args to worker thread */ - pthread_t* threads; /* A shitload of threads */ - pthread_attr_t attr; /* Thread attributes (we use defaults) */ - int i; /* Counters */ - long runtime; /* Run time for each thread */ - - /* Read argument list */ - for (i = 0; i < argc; i++) { - if (!strcmp(argv[i], "-n")) { - n = atoi(argv[i + 1]); - argc = shift(argc, argv, i, 2); - } - if (!strcmp(argv[i], "-w")) { - w = atoi(argv[i + 1]); - argc = shift(argc, argv, i, 2); - } - if (!strcmp(argv[i], "-m")) { - m = atoi(argv[i + 1]); - argc = shift(argc, argv, i, 2); - } - if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { - fprintf(stderr, "Read stress.c for usage info\n"); - return 1; - } - } - - data[0] = (void*)argc; /* pass args to worker thread */ - data[1] = (void*)argv; /* pass args to worker thread */ - - /* This is how many total messages will be posted */ - total = n * m; - - /* Pick a randomized username */ - pthread_mutex_lock(&rand_mutex); - /* See Numerical Recipes in C or Knuth vol. 2 ch. 3 */ - i = (int)(100.0*rand()/(RAND_MAX+1.0)); /* range 0-99 */ - pthread_mutex_unlock(&rand_mutex); - sprintf(username, "testuser%d", i); - strcpy(password, username); - - /* First, memory for our shitload of threads */ - threads = calloc(n, sizeof(pthread_t)); - if (!threads) { - perror("Not enough memory"); - return 1; - } - - /* Then thread attributes (all defaults for now) */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - /* Then, create some threads */ - fprintf(stderr, "Creating threads \r"); - for (i = 0; i < n; ++i) { - pthread_create(&threads[i], &attr, worker, (void*)data); - - /* Give thread #0 time to create the user account */ - if (i == 0) sleep(3); - } - - //fprintf(stderr, "Starting in %d seconds\r", n); - //sleep(n); - fprintf(stderr, " \r"); - - /* Then, signal the conditional they all are waiting on */ - pthread_mutex_lock(&start_mutex); - pthread_cond_broadcast(&start_cond); - pthread_mutex_unlock(&start_mutex); - - /* Then wait for them to exit */ - for (i = 0; i < n; i++) { - pthread_join(threads[i], (void*)&runtime); - /* We're ignoring this value for now... TODO */ - } - fprintf(stderr, "\r \r"); - return 0; -}