#include <sys/ioctl.h>
#include <signal.h>
#include <pwd.h>
-#include <setjmp.h>
#include <stdarg.h>
+#include <errno.h>
#include "citadel.h"
#include "citadel_ipc.h"
#include "citadel_decls.h"
#include "tools.h"
#include "acconfig.h"
-#include "client_crypto.h"
#ifndef HAVE_SNPRINTF
#include "snprintf.h"
#endif
struct march *march = NULL;
/* globals associated with the client program */
-char temp[PATH_MAX]; /* Name of general temp file */
-char temp2[PATH_MAX]; /* Name of general temp file */
-char tempdir[PATH_MAX]; /* Name of general temp dir */
-char editor_path[SIZ]; /* path to external editor */
+char temp[PATH_MAX]; /* Name of general-purpose temp file */
+char temp2[PATH_MAX]; /* Name of general-purpose temp file */
+char tempdir[PATH_MAX]; /* Name of general-purpose temp directory */
+char editor_paths[MAX_EDITORS][SIZ]; /* paths to external editors */
char printcmd[SIZ]; /* print command */
int editor_pid = (-1);
-char fullname[32];
-jmp_buf nextbuf;
+char fullname[USERNAME_SIZE];
struct CtdlServInfo serv_info; /* Info on the server connected */
int screenwidth;
int screenheight;
long maxmsgnum; /* used for <G>oto */
char sigcaught = 0;
char have_xterm = 0; /* are we running on an xterm? */
-char rc_username[32];
+char rc_username[USERNAME_SIZE];
char rc_password[32];
char hostbuf[SIZ];
char portbuf[SIZ];
*/
void logoff(CtdlIPC *ipc, int code)
{
- int lp;
+ int lp;
+
if (editor_pid > 0) { /* kill the editor if it's running */
kill(editor_pid, SIGHUP);
}
- /* Free the ungoto list */
- for (lp = 0; lp < uglistsize; lp++)
- free (uglist[lp]);
+ /* Free the ungoto list */
+ for (lp = 0; lp < uglistsize; lp++) {
+ free(uglist[lp]);
+ }
-/* shut down the server... but not if the logoff code is 3, because
- * that means we're exiting because we already lost the server
+/* Shut down the server connection ... but not if the logoff code is 3,
+ * because that means we're exiting because we already lost the server.
*/
- if (code != 3)
+ if (code != 3) {
CtdlIPCQuit(ipc);
+ }
/*
* now clean up various things
*/
-
screen_delete();
unlink(temp);
}
-
/* general purpose routines */
+
/* display a file */
void formout(CtdlIPC *ipc, char *name)
{
*/
void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto)
{
- char aaa[SIZ], bbb[SIZ], psearch[SIZ];
+ char aaa[SIZ], bbb[SIZ];
static long ls = 0L;
int newmailcount = 0;
int partial_match, best_match;
uglistlsn[lp] = uglistlsn[lp+1];
}
ugpos--;
- } else
+ } else {
uglistsize++;
+ }
uglist[ugpos] = malloc(strlen(room_name)+1);
strcpy(uglist[ugpos], room_name);
* has the highest-weighted match.
*/
if (r / 100 != 2) {
+ struct march *march = NULL;
+
best_match = 0;
strcpy(bbb, "");
- CtdlIPC_putline(ipc, "LKRA");
- CtdlIPC_getline(ipc, aaa);
- if (aaa[0] == '1')
- while (CtdlIPC_getline(ipc, aaa), strcmp(aaa, "000")) {
- extract(psearch, aaa, 0);
+
+ r = CtdlIPCKnownRooms(ipc, AllAccessibleRooms, AllFloors, &march, aaa);
+ if (r / 100 == 1) {
+ /* Run the roomlist; free the data as we go */
+ struct march *mp = march; /* Current */
+
+ while (mp) {
partial_match = 0;
- if (pattern(psearch, towhere) >= 0) {
+ if (pattern(mp->march_name, towhere) >= 0) {
partial_match = 1;
}
- if (!strncasecmp(towhere, psearch, strlen(towhere))) {
+ if (!strncasecmp(mp->march_name, towhere, strlen(towhere))) {
partial_match = 2;
}
if (partial_match > best_match) {
- strcpy(bbb, psearch);
+ strcpy(bbb, mp->march_name);
best_match = partial_match;
}
+ /* Both pointers are NULL at end of list */
+ march = mp->next;
+ free(mp);
+ mp = march;
}
+ }
+
if (strlen(bbb) == 0) {
scr_printf("No room '%s'.\n", towhere);
return;
roomrec = NULL;
r = CtdlIPCGotoRoom(ipc, bbb, "", &roomrec, aaa);
}
- if (r / 100 != 2) {
+ if (r / 100 != 1 && r / 100 != 2) {
scr_printf("%s\n", aaa);
return;
}
* If it is, pop the first room off the list and go there.
*/
if (march == NULL) {
- r = CtdlIPCKnownRooms(ipc, 1, -1, &march, buf);
+ r = CtdlIPCKnownRooms(ipc, SubscribedRoomsWithNewMessages, AllFloors, &march, buf);
/* add _BASEROOM_ to the end of the march list, so the user will end up
* in the system base room (usually the Lobby>) at the end of the loop
*/
scr_printf("Forgetting all rooms on %s...\r", &floorlist[ffloor][0]);
scr_flush();
- snprintf(buf, sizeof buf, "LKRA %d", ffloor);
- CtdlIPC_putline(ipc, buf);
- CtdlIPC_getline(ipc, buf);
- if (buf[0] != '1') {
- scr_printf("%-72s\n", &buf[4]);
+ r = CtdlIPCKnownRooms(ipc, AllAccessibleRooms, ffloor, &flist, buf);
+ if (r / 100 != 1) {
+ scr_printf("%-72s\n", buf);
return;
}
- flist = NULL;
- while (CtdlIPC_getline(ipc, buf), strcmp(buf, "000")) {
- fptr = (struct march *) malloc(sizeof(struct march));
- fptr->next = flist;
- flist = fptr;
- extract(fptr->march_name, buf, 0);
- }
- while (flist != NULL) {
+ while (flist) {
r = CtdlIPCGotoRoom(ipc, flist->march_name, "", &roomrec, buf);
if (r / 100 == 2) {
r = CtdlIPCForgetRoom(ipc, buf);
void gotofloor(CtdlIPC *ipc, char *towhere, int mode)
{
int a, tofloor;
+ int r; /* IPC response code */
struct march *mptr;
char buf[SIZ], targ[SIZ];
}
strcpy(targ, "");
- snprintf(buf, sizeof buf, "LKRA %d", tofloor);
- CtdlIPC_putline(ipc, buf);
- CtdlIPC_getline(ipc, buf);
- if (buf[0] == '1')
- while (CtdlIPC_getline(ipc, buf), strcmp(buf, "000")) {
- if ((extract_int(buf, 2) == tofloor) && (strlen(targ) == 0))
- extract(targ, buf, 0);
+ mptr = NULL;
+ r = CtdlIPCKnownRooms(ipc, AllAccessibleRooms, tofloor, &mptr, buf);
+ if (r / 100 == 1) {
+ struct march *tmp = mptr;
+
+ /* TODO: room order is being ignored? */
+ if (mptr)
+ strncpy(targ, mptr->march_name, ROOMNAMELEN);
+ while (mptr) {
+ tmp = mptr->next;
+ free(mptr);
+ mptr = tmp;
}
+ }
if (strlen(targ) > 0) {
gf_toroom(ipc, targ, mode);
} else {
if (!strcasecmp(pass1, pass2)) {
CtdlIPCChangePassword(ipc, pass1, buf);
scr_printf("%s\n", buf);
- offer_to_remember_password(hostbuf, portbuf, fullname, pass1);
+ offer_to_remember_password(ipc, hostbuf, portbuf, fullname, pass1);
return (0);
} else {
scr_printf("*** They don't match... try again.\n");
/* be nice and identify ourself to the server */
CtdlIPCIdentifySoftware(ipc, SERVER_TYPE, 0, REV_LEVEL,
(ipc->isLocal ? "local" : CITADEL),
- (supplied_hostname) ? supplied_hostname : "", buf);
- /* (locate_host(buf), buf)); */
+ (supplied_hostname) ? supplied_hostname :
+ /* Look up the , in the bible if you're confused */
+ (locate_host(buf), buf), buf);
/* Tell the server what our preferred content formats are */
if ((CtdlIPCSpecifyPreferredFormats(ipc, buf, "text/html|text/plain") / 100 )== 2) {
#ifdef HAVE_OPENSSL
arg_encrypt = RC_DEFAULT;
#endif
-#ifdef HAVE_CURSES_H
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
arg_screen = RC_DEFAULT;
#endif
if (!strcmp(argv[a], "-X")) {
#ifdef HAVE_OPENSSL
arg_encrypt = RC_YES;
- argc = shift(argc, argv, a, 1);
+ argc = shift(argc, argv, a, 1);
#else
fprintf(stderr, "Not compiled with encryption support");
return 1;
#endif
}
if (!strcmp(argv[a], "-s")) {
-#ifdef HAVE_CURSES_H
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
arg_screen = RC_NO;
#endif
argc = shift(argc, argv, a, 1);
}
if (!strcmp(argv[a], "-S")) {
-#ifdef HAVE_CURSES_H
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
arg_screen = RC_YES;
#endif
argc = shift(argc, argv, a, 1);
logoff(NULL, 3);
}
/*
- scr_printf("Privileges changed to uid %d gid %d\n",
- getuid(), getgid());
+ scr_printf("Privileges changed to uid %d gid %d\n",
+ getuid(), getgid());
*/
}
argc = shift(argc, argv, a, 1);
sln_printf("Attaching to server... \r");
sln_flush();
ipc = CtdlIPC_new(argc, argv, hostbuf, portbuf);
+ if (!ipc) {
+ screen_delete();
+ error_printf("Can't connect: %s\n", strerror(errno));
+ logoff(NULL, 3);
+ }
+#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES)
+ CtdlIPC_SetNetworkStatusCallback(ipc, wait_indicator);
+#endif
ipc_for_signal_handlers = ipc; /* KLUDGE cover your eyes */
CtdlIPC_getline(ipc, aaa);
logoff(ipc, atoi(aaa));
}
-/* If there is a [nonce] at the end, put the nonce in <nonce>, else nonce
- * is zeroized.
- */
+ /* If there is a [nonce] at the end, put the nonce in <nonce>, else nonce
+ * is zeroized.
+ */
if ((sptr = strchr(aaa, '<')) == NULL)
- {
- nonce[0] = '\0';
- }
+ {
+ nonce[0] = '\0';
+ }
else
- {
- if ((sptr2 = strchr(sptr, '>')) == NULL)
- {
- nonce[0] = '\0';
- }
- else
- {
- sptr2++;
- *sptr2 = '\0';
- strncpy(nonce, sptr, NONCE_SIZE);
- }
+ {
+ if ((sptr2 = strchr(sptr, '>')) == NULL)
+ {
+ nonce[0] = '\0';
+ }
+ else
+ {
+ sptr2++;
+ *sptr2 = '\0';
+ strncpy(nonce, sptr, NONCE_SIZE);
+ }
+ }
+
+#ifdef HAVE_OPENSSL
+ /* Evaluate encryption preferences */
+ if (arg_encrypt != RC_NO && rc_encrypt != RC_NO) {
+ if (!ipc->isLocal || arg_encrypt == RC_YES || rc_encrypt == RC_YES) {
+ secure = (CtdlIPCStartEncryption(ipc, aaa) / 100 == 2) ? 1 : 0;
+ if (!secure)
+ error_printf("Can't encrypt: %s\n", aaa);
+ }
}
+#endif
get_serv_info(ipc, telnet_client_host);
-
scr_printf("%-24s\n%s\n%s\n", serv_info.serv_software, serv_info.serv_humannode,
- serv_info.serv_bbs_city);
+ serv_info.serv_bbs_city);
scr_flush();
- secure = starttls(ipc);
status_line(serv_info.serv_humannode, serv_info.serv_bbs_city, NULL,
- secure, -1);
+ secure, -1);
screenwidth = 80; /* default screen dimensions */
screenheight = 24;
formout(ipc, "hello"); /* print the opening greeting */
scr_printf("\n");
-GSTA: /* See if we have a username and password on disk */
+ GSTA: /* See if we have a username and password on disk */
if (rc_remember_passwords) {
get_stored_password(hostbuf, portbuf, fullname, password);
if (strlen(fullname) > 0) {
- snprintf(aaa, sizeof(aaa)-1, "USER %s", fullname);
- CtdlIPC_putline(ipc, aaa);
- CtdlIPC_getline(ipc, aaa);
- if (nonce[0])
- {
- snprintf(aaa, sizeof aaa, "PAS2 %s", make_apop_string(password, nonce, hexstring, sizeof hexstring));
+ r = CtdlIPCTryLogin(ipc, fullname, aaa);
+ if (r / 100 == 3) {
+ if (*nonce) {
+ r = CtdlIPCTryApopPassword(ipc, make_apop_string(password, nonce, hexstring, sizeof hexstring), aaa);
+ } else {
+ r = CtdlIPCTryPassword(ipc, password, aaa);
+ }
}
- else /* Else no APOP */
- {
- snprintf(aaa, sizeof(aaa)-1, "PASS %s", password);
- }
-
- CtdlIPC_putline(ipc, aaa);
- CtdlIPC_getline(ipc, aaa);
- if (aaa[0] == '2') {
- load_user_info(&aaa[4]);
+
+ if (r / 100 == 2) {
+ load_user_info(aaa);
stored_password = 1;
goto PWOK;
- }
- else {
+ } else {
set_stored_password(hostbuf, portbuf, "", "");
}
}
scr_printf("Please enter the name you wish to log in with.\n");
}
} while (
- (!strcasecmp(fullname, "bbs"))
- || (!strcasecmp(fullname, "new"))
- || (strlen(fullname) == 0));
+ (!strcasecmp(fullname, "bbs"))
+ || (!strcasecmp(fullname, "new"))
+ || (strlen(fullname) == 0));
if (!strcasecmp(fullname, "off")) {
mcmd = 29;
}
strproc(password);
- if (nonce[0])
- {
- snprintf(aaa, sizeof aaa, "PAS2 %s", make_apop_string(password, nonce, hexstring, sizeof hexstring));
- }
- else /* Else no APOP */
- {
- snprintf(aaa, sizeof aaa, "PASS %s", password);
+ if (*nonce) {
+ r = CtdlIPCTryApopPassword(ipc, make_apop_string(password, nonce, hexstring, sizeof hexstring), aaa);
+ } else {
+ r = CtdlIPCTryPassword(ipc, password, aaa);
}
- CtdlIPC_putline(ipc, aaa);
- CtdlIPC_getline(ipc, aaa);
- if (aaa[0] == '2') {
- load_user_info(&aaa[4]);
- offer_to_remember_password(hostbuf, portbuf,
- fullname, password);
+ if (r / 100 == 2) {
+ load_user_info(aaa);
+ offer_to_remember_password(ipc, hostbuf, portbuf,
+ fullname, password);
goto PWOK;
}
scr_printf("<< wrong password >>\n");
if (strlen(rc_password) > 0)
- logoff(ipc, 0);
+ logoff(ipc, 2);
goto GSTA;
NEWUSR: if (strlen(rc_password) == 0) {
if (yesno() == 0)
goto GSTA;
}
- snprintf(aaa, sizeof aaa, "NEWU %s", fullname);
- CtdlIPC_putline(ipc, aaa);
- CtdlIPC_getline(ipc, aaa);
- if (aaa[0] != '2') {
+
+ r = CtdlIPCCreateUser(ipc, fullname, 1, aaa);
+ if (r / 100 != 2) {
scr_printf("%s\n", aaa);
goto GSTA;
}
- load_user_info(&aaa[4]);
+ load_user_info(aaa);
- while (set_password(ipc) != 0);;
+ while (set_password(ipc) != 0);
newnow = 1;
enter_config(ipc, 1);
-PWOK:
+ PWOK:
/* Switch color support on or off if we're in user mode */
if (rc_ansi_color == 3) {
if (userflags & US_COLOR)
enable_color = 0;
}
- scr_printf("%s\nAccess level: %d (%s)\n"
- "User #%ld / Login #%d",
- fullname, axlevel, axdefs[(int) axlevel],
- usernum, timescalled);
+ color(BRIGHT_WHITE);
+ scr_printf("\n%s\nAccess level: %d (%s)\n"
+ "User #%ld / Login #%d",
+ fullname, axlevel, axdefs[(int) axlevel],
+ usernum, timescalled);
if (lastcall > 0L) {
- scr_printf(" / Last login: %s\n",
- asctime(localtime(&lastcall)) );
+ scr_printf(" / Last login: %s",
+ asctime(localtime(&lastcall)));
}
scr_printf("\n");
/* Enter the lobby */
dotgoto(ipc, "_BASEROOM_", 1, 0);
-/* Main loop for the system... user is logged in. */
- uglistsize = 0;
+ /* Main loop for the system... user is logged in. */
+ uglistsize = 0;
if (newnow == 1)
- readmsgs(ipc, 3, 1, 5);
+ readmsgs(ipc, LastMessages, ReadForward, 5);
else
- readmsgs(ipc, 1, 1, 0);
+ readmsgs(ipc, NewMessages, ReadForward, 0);
/* MAIN COMMAND LOOP */
do {
dotgoto(ipc, "_MAIL_", 1, 0);
break;
case 20:
- updatels(ipc);
- dotgoto(ipc, argbuf, 0, 0);
+ if (strlen(argbuf) > 0) {
+ updatels(ipc);
+ dotgoto(ipc, argbuf, 0, 0);
+ }
break;
case 52:
- if (rc_alt_semantics)
- updatelsa(ipc);
- dotgoto(ipc, argbuf, 0, 0);
+ if (strlen(argbuf) > 0) {
+ if (rc_alt_semantics) {
+ updatelsa(ipc);
+ }
+ dotgoto(ipc, argbuf, 0, 0);
+ }
+ break;
+ case 95: /* what exactly is the numbering scheme supposed to be anyway? */
+ dotungoto(ipc, argbuf);
break;
case 10:
- readmsgs(ipc, 0, 1, 0);
+ readmsgs(ipc, AllMessages, ReadForward, 0);
break;
case 9:
- readmsgs(ipc, 3, 1, 5);
+ readmsgs(ipc, LastMessages, ReadForward, 5);
break;
case 13:
- readmsgs(ipc, 1, 1, 0);
+ readmsgs(ipc, NewMessages, ReadForward, 0);
break;
case 11:
- readmsgs(ipc, 0, (-1), 0);
+ readmsgs(ipc, AllMessages, ReadReverse, 0);
break;
case 12:
- readmsgs(ipc, 2, (-1), 0);
+ readmsgs(ipc, OldMessages, ReadReverse, 0);
break;
case 71:
- readmsgs(ipc, 3, 1, atoi(argbuf));
+ readmsgs(ipc, LastMessages, ReadForward,
+ atoi(argbuf));
break;
case 7:
forget(ipc);
validate(ipc);
break;
case 29:
- if (!rc_alt_semantics)
- updatels(ipc);
- termn8 = 1;
- break;
case 30:
- if (!rc_alt_semantics)
+ if (!rc_alt_semantics) {
updatels(ipc);
+ }
termn8 = 1;
break;
case 48:
case 15:
scr_printf("Are you sure (y/n)? ");
if (yesno() == 1) {
- updatels(ipc);
+ if (!rc_alt_semantics)
+ updatels(ipc);
a = 0;
termn8 = 1;
}
case 85:
scr_printf("All users will be disconnected! "
- "Really terminate the server? ");
+ "Really terminate the server? ");
if (yesno() == 1) {
+ if (!rc_alt_semantics)
+ updatels(ipc);
r = CtdlIPCTerminateServerNow(ipc, aaa);
scr_printf("%s\n", aaa);
if (r / 100 == 2) {
- updatels(ipc);
a = 0;
termn8 = 1;
}
case 86:
scr_printf("Do you really want to schedule a "
- "server shutdown? ");
+ "server shutdown? ");
if (yesno() == 1) {
r = CtdlIPCTerminateServerScheduled(ipc, 1, aaa);
if (r / 100 == 2) {
if (atoi(aaa)) {
scr_printf(
-"The Citadel server will terminate when all users are logged off.\n"
- );
+ "The Citadel server will terminate when all users are logged off.\n"
+ );
} else {
scr_printf(
-"The Citadel server will not terminate.\n"
- );
+ "The Citadel server will not terminate.\n"
+ );
}
}
}
case 87:
network_config_management(ipc, "listrecp",
- "Message-by-message mailing list recipients");
+ "Message-by-message mailing list recipients");
break;
case 94:
network_config_management(ipc, "digestrecp",
- "Digest mailing list recipients");
+ "Digest mailing list recipients");
break;
case 89:
network_config_management(ipc, "ignet_push_share",
- "Nodes with which we share this room");
+ "Nodes with which we share this room");
break;
case 88:
sttybbs(SB_RESTORE);
snprintf(aaa, sizeof aaa, "USERNAME=\042%s\042; export USERNAME;"
"exec ./subsystem %ld %d %d", fullname,
- usernum, screenwidth, axlevel);
+ usernum, screenwidth, axlevel);
ka_system(aaa);
sttybbs(SB_NO_INTR);
screen_set();
who_is_online(ipc, 1);
break;
- case 91:
- who_is_online(ipc, 2);
- break;
+ case 91:
+ who_is_online(ipc, 2);
+ break;
case 80:
do_system_configuration(ipc);
break;
case 70:
- edit_system_message(argbuf);
+ edit_system_message(ipc, argbuf);
break;
case 19:
page_user(ipc);
break;
+ default: /* allow some math on the command */
+ /* commands 100... to 100+MAX_EDITORS-1 will
+ call the appropriate editor... in other
+ words, command numbers 100+ will match
+ the citadel.rc keys editor0, editor1, etc.*/
+ if (mcmd >= 100 && mcmd < (100+MAX_EDITORS))
+ {
+ /* entmsg mode >=2 select editor */
+ entmsg(ipc, 0, mcmd - 100 + 2);
+ break;
+ }
} /* end switch */
} while (termn8 == 0);
-TERMN8: scr_printf("%s logged out.\n", fullname);
+TERMN8: scr_printf("%s logged out.", fullname);
+ termn8 = 0;
+ color(ORIGINAL_PAIR);
+ scr_printf("\n");
while (march != NULL) {
remove_march(march->march_name, 0);
}