X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fcitadel.c;h=ac21ebc9011695c8482d6569f899762181fd6207;hb=44bdabdda4dc6e9823e0464c37157c960abac9f7;hp=6845b46123fc7c470013f3833f3d9a430da0a5d6;hpb=d11ca042dded59c097edcb2dad3ace0103230ce6;p=citadel.git diff --git a/citadel/citadel.c b/citadel/citadel.c index 6845b4612..ac21ebc90 100644 --- a/citadel/citadel.c +++ b/citadel/citadel.c @@ -30,37 +30,29 @@ #include #include #include -#include #include +#include #include "citadel.h" +#include "citadel_ipc.h" #include "axdefs.h" -#include "serv_info.h" #include "routines.h" #include "routines2.h" #include "rooms.h" #include "messages.h" #include "commands.h" -#include "ipc.h" #include "client_chat.h" #include "client_passwords.h" #include "citadel_decls.h" #include "tools.h" #include "acconfig.h" -#include "client_crypto.h" #ifndef HAVE_SNPRINTF #include "snprintf.h" #endif +#include "screen.h" #include "md5.h" -struct march { - struct march *next; - char march_name[ROOMNAMELEN]; - char march_floor; - char march_order; - }; - #define IFEXPERT if (userflags&US_EXPERT) #define IFNEXPERT if ((userflags&US_EXPERT)==0) #define IFAIDE if (axlevel>=6) @@ -69,21 +61,20 @@ struct march { 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; -struct CtdlServInfo serv_info; /* Info on the server connected */ +char fullname[USERNAME_SIZE]; int screenwidth; int screenheight; unsigned room_flags; char room_name[ROOMNAMELEN]; -char ugname[ROOMNAMELEN]; -long uglsn; /* holds ngoto info */ +char *uglist[UGLISTLEN]; /* size of the ungoto list */ +long uglistlsn[UGLISTLEN]; /* current read position for all the ungoto's. Not going to make any friends with this one. */ +int uglistsize = 0; char is_mail = 0; /* nonzero when we're in a mail room */ char axlevel = 0; /* access level */ char is_room_aide = 0; /* boolean flag, 1 if room aide */ @@ -97,7 +88,7 @@ long highest_msg_read; /* used for bandon room cmd */ long maxmsgnum; /* used for 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]; @@ -105,28 +96,43 @@ char rc_floor_mode; char floor_mode; char curr_floor = 0; /* number of current floor */ char floorlist[128][SIZ]; /* names of floors */ -char express_msgs = 0; /* express messages waiting! */ int termn8 = 0; /* Set to nonzero to cause a logoff */ +int secure; /* Set to nonzero when wire is encrypted */ +int can_do_msg4 = 0; /* Set to nonzero if the server can handle MSG4 commands */ +extern char instant_msgs; /* instant messages waiting! */ extern int rc_ansi_color; /* ansi color value from citadel.rc */ +extern int next_lazy_cmd; + +CtdlIPC *ipc_for_signal_handlers; /* KLUDGE cover your eyes */ /* * here is our 'clean up gracefully and exit' routine */ -void logoff(int code) +void ctdl_logoff(char *file, int line, CtdlIPC *ipc, int code) { + int lp; + if (editor_pid > 0) { /* kill the editor if it's running */ kill(editor_pid, SIGHUP); } -/* shut down the server... but not if the logoff code is 3, because - * that means we're exiting because we already lost the server + + /* Free the ungoto list */ + for (lp = 0; lp < uglistsize; lp++) { + free(uglist[lp]); + } + +/* 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) - serv_puts("QUIT"); + if (code != 3) { + CtdlIPCQuit(ipc); + } /* * now clean up various things */ + screen_delete(); unlink(temp); unlink(temp2); @@ -140,7 +146,13 @@ void logoff(int code) sleep(1); kill(0 - getpgrp(), SIGKILL); } - sttybbs(SB_RESTORE); /* return the old terminal settings */ + color(ORIGINAL_PAIR); /* Restore the old color settings */ + stty_ctdl(SB_RESTORE); /* return the old terminal settings */ + /* + * uncomment the following if you need to know why Citadel exited + printf("*** Exit code %d at %s:%d\n", code, file, line); + sleep(2); + */ exit(code); /* exit with the proper exit code */ } @@ -151,7 +163,7 @@ void logoff(int code) */ void dropcarr(int signum) { - logoff(SIGHUP); + logoff(NULL, 3); /* No IPC when server's already gone! */ } @@ -162,63 +174,73 @@ void dropcarr(int signum) */ void catch_sigcont(int signum) { - sttybbs(SB_LAST); + stty_ctdl(SB_LAST); signal(SIGCONT, catch_sigcont); } - /* general purpose routines */ -void formout(char *name) -{ /* display a file */ - char cmd[SIZ]; - snprintf(cmd, sizeof cmd, "MESG %s", name); - serv_puts(cmd); - serv_gets(cmd); - if (cmd[0] != '1') { - printf("%s\n", &cmd[4]); +/* display a file */ +void formout(CtdlIPC *ipc, char *name) +{ + int r; /* IPC return code */ + char buf[SIZ]; + char *text = NULL; + + r = CtdlIPCSystemMessage(ipc, name, &text, buf); + if (r / 100 != 1) { + scr_printf("%s\n", buf); return; } - fmout(screenwidth, NULL, - ((userflags & US_PAGINATOR) ? 1 : 0), - screenheight, 1, 1); + if (text) { + fmout(screenwidth, NULL, text, NULL, + ((userflags & US_PAGINATOR) ? 1 : 0), + screenheight, 1, 1); + free(text); + } } -void userlist(char *patn) +void userlist(CtdlIPC *ipc, char *patn) { char buf[SIZ]; char fl[SIZ]; - struct tm *tmbuf; + struct tm tmbuf; time_t lc; + int r; /* IPC response code */ + char *listing = NULL; - serv_puts("LIST"); - serv_gets(buf); - if (buf[0] != '1') { - pprintf("%s\n", &buf[4]); + r = CtdlIPCUserListing(ipc, patn, &listing, buf); + if (r / 100 != 1) { + pprintf("%s\n", buf); return; } + pprintf(" User Name Num L LastCall Calls Posts\n"); pprintf("------------------------- ----- - ---------- ----- -----\n"); - while (serv_gets(buf), strcmp(buf, "000")) { + if (listing != NULL) while (strlen(listing) > 0) { + extract_token(buf, listing, 0, '\n', sizeof buf); + remove_token(listing, 0, '\n'); + if (sigcaught == 0) { - extract(fl, buf, 0); + extract_token(fl, buf, 0, '|', sizeof fl); if (pattern(fl, patn) >= 0) { pprintf("%-25s ", fl); pprintf("%5ld %d ", extract_long(buf, 2), extract_int(buf, 1)); lc = extract_long(buf, 3); - tmbuf = (struct tm *) localtime(&lc); + localtime_r(&lc, &tmbuf); pprintf("%02d/%02d/%04d ", - (tmbuf->tm_mon + 1), - tmbuf->tm_mday, - (tmbuf->tm_year + 1900)); + (tmbuf.tm_mon + 1), + tmbuf.tm_mday, + (tmbuf.tm_year + 1900)); pprintf("%5ld %5ld\n", extract_long(buf, 4), extract_long(buf, 5)); } } } + free(listing); pprintf("\n"); } @@ -228,7 +250,7 @@ void userlist(char *patn) */ void load_user_info(char *params) { - extract(fullname, params, 0); + extract_token(fullname, params, 0, '|', sizeof fullname); axlevel = extract_int(params, 1); timescalled = extract_int(params, 2); posted = extract_int(params, 3); @@ -315,126 +337,155 @@ char *pop_march(int desired_floor) /* * jump directly to a room */ -void dotgoto(char *towhere, int display_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; - static int oldmailcount = (-1); + int newmailcount = 0; int partial_match, best_match; char from_floor; + int ugpos = uglistsize; + int r; /* IPC result code */ + struct ctdlipcroom *room = NULL; /* store ungoto information */ - strcpy(ugname, room_name); - uglsn = ls; - + if (fromungoto == 0) { + /* sloppy slide them all down, hey it's the client, who cares. :-) */ + if (uglistsize >= (UGLISTLEN-1)) { + int lp; + free (uglist[0]); + for (lp = 0; lp < (UGLISTLEN-1); lp++) { + uglist[lp] = uglist[lp+1]; + uglistlsn[lp] = uglistlsn[lp+1]; + } + ugpos--; + } else { + uglistsize++; + } + + uglist[ugpos] = malloc(strlen(room_name)+1); + strcpy(uglist[ugpos], room_name); + uglistlsn[ugpos] = ls; + } + /* first try an exact match */ - snprintf(aaa, sizeof aaa, "GOTO %s", towhere); - serv_puts(aaa); - serv_gets(aaa); - if (aaa[3] == '*') - express_msgs = 1; - if (!strncmp(aaa, "54", 2)) { + r = CtdlIPCGotoRoom(ipc, towhere, "", &room, aaa); + if (r / 10 == 54) { newprompt("Enter room password: ", bbb, 9); - snprintf(aaa, sizeof aaa, "GOTO %s|%s", towhere, bbb); - serv_puts(aaa); - serv_gets(aaa); - if (aaa[3] == '*') - express_msgs = 1; - } - if (!strncmp(aaa, "54", 2)) { - printf("Wrong password.\n"); - return; - } + r = CtdlIPCGotoRoom(ipc, towhere, bbb, &room, aaa); + if (r / 10 == 54) { + scr_printf("Wrong password.\n"); + return; + } + } + /* * If a match is not found, try a partial match. * Partial matches anywhere in the string carry a weight of 1, * left-aligned matches carry a weight of 2. Pick the room that - * has the highest-weighted match. + * has the highest-weighted match. Do not match on forgotten + * rooms. */ - if (aaa[0] != '2') { + if (r / 100 != 2) { + struct march *march = NULL; + best_match = 0; strcpy(bbb, ""); - serv_puts("LKRA"); - serv_gets(aaa); - if (aaa[0] == '1') - while (serv_gets(aaa), strcmp(aaa, "000")) { - extract(psearch, aaa, 0); + + r = CtdlIPCKnownRooms(ipc, SubscribedRooms, 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) { - printf("No room '%s'.\n", towhere); + scr_printf("No room '%s'.\n", towhere); return; } - snprintf(aaa, sizeof aaa, "GOTO %s", bbb); - serv_puts(aaa); - serv_gets(aaa); - if (aaa[3] == '*') - express_msgs = 1; + room = NULL; + r = CtdlIPCGotoRoom(ipc, bbb, "", &room, aaa); } - if (aaa[0] != '2') { - printf("%s\n", aaa); + if (r / 100 != 1 && r / 100 != 2) { + scr_printf("%s\n", aaa); return; } - extract(room_name, &aaa[4], 0); - room_flags = extract_int(&aaa[4], 4); + safestrncpy(room_name, room->RRname, ROOMNAMELEN); + room_flags = room->RRflags; from_floor = curr_floor; - curr_floor = extract_int(&aaa[4], 10); + curr_floor = room->RRfloor; remove_march(room_name, 0); if (!strcasecmp(towhere, "_BASEROOM_")) remove_march(towhere, 0); + if (!room->RRunread) + next_lazy_cmd = 5; /* Don't read new if no new msgs */ if ((from_floor != curr_floor) && (display_name > 0) && (floor_mode == 1)) { if (floorlist[(int) curr_floor][0] == 0) - load_floorlist(); - printf("(Entering floor: %s)\n", &floorlist[(int) curr_floor][0]); + load_floorlist(ipc); + scr_printf("(Entering floor: %s)\n", &floorlist[(int) curr_floor][0]); } if (display_name == 1) { color(BRIGHT_WHITE); - printf("%s ", room_name); + scr_printf("%s ", room_name); color(DIM_WHITE); - printf("- "); + scr_printf("- "); } if (display_name != 2) { color(BRIGHT_YELLOW); - printf("%d ", extract_int(&aaa[4], 1)); + scr_printf("%d ", room->RRunread); color(DIM_WHITE); - printf("new of "); + scr_printf("new of "); color(BRIGHT_YELLOW); - printf("%d ", extract_int(&aaa[4], 2)); + scr_printf("%d ", room->RRtotal); color(DIM_WHITE); - printf("messages.\n"); + scr_printf("messages.\n"); } - highest_msg_read = extract_int(&aaa[4], 6); - maxmsgnum = extract_int(&aaa[4], 5); - is_mail = (char) extract_int(&aaa[4], 7); - is_room_aide = (char) extract_int(&aaa[4], 8); - ls = extract_long(&aaa[4], 6); + highest_msg_read = room->RRlastread; + maxmsgnum = room->RRhighest; + is_mail = room->RRismailbox; + is_room_aide = room->RRaide; + ls = room->RRlastread; /* read info file if necessary */ - if (extract_int(&aaa[4], 3) > 0) - readinfo(); + if (room->RRinfoupdated > 0) + readinfo(ipc); /* check for newly arrived mail if we can */ - if (num_parms(&aaa[4]) >= 10) { - newmailcount = extract_int(&aaa[4], 9); - if ((oldmailcount >= 0) && (newmailcount > oldmailcount)) { - color(BRIGHT_RED); - printf("*** You have new mail\n"); - color(DIM_WHITE); + newmailcount = room->RRnewmail; + if (newmailcount > 0) { + color(BRIGHT_RED); + if (newmailcount == 1) { + scr_printf("*** A new mail message has arrived.\n"); + } + else { + scr_printf("*** %d new mail messages have arrived.\n", + newmailcount); + } + color(DIM_WHITE); + if (strlen(rc_gotmail_cmd) > 0) { + system(rc_gotmail_cmd); } - oldmailcount = newmailcount; } + status_line(ipc->ServInfo.humannode, ipc->ServInfo.site_location, + room_name, secure, newmailcount); } /* Goto next room having unread messages. @@ -442,34 +493,20 @@ void dotgoto(char *towhere, int display_name) * user back to the lobby when done. The room we end up in is placed in * newroom - which is set to 0 (the lobby) initially. */ -void gotonext(void) +void gotonext(CtdlIPC *ipc) { char buf[SIZ]; struct march *mptr, *mptr2; char next_room[ROOMNAMELEN]; + int r; /* IPC response code */ /* Check to see if the march-mode list is already allocated. * If it is, pop the first room off the list and go there. */ if (march == NULL) { - serv_puts("LKRN"); - serv_gets(buf); - if (buf[0] == '1') - while (serv_gets(buf), strcmp(buf, "000")) { - mptr = (struct march *) malloc(sizeof(struct march)); - mptr->next = NULL; - extract(mptr->march_name, buf, 0); - mptr->march_floor = (char) (extract_int(buf, 2) & 0x7F); - mptr->march_order = (char) (extract_int(buf, 3) & 0x7F); - if (march == NULL) { - march = mptr; - } else { - mptr2 = march; - while (mptr2->next != NULL) - mptr2 = mptr2->next; - mptr2->next = mptr; - } - } + 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 */ @@ -496,70 +533,65 @@ void gotonext(void) strcpy(next_room, "_BASEROOM_"); } remove_march(next_room, 0); - dotgoto(next_room, 1); + dotgoto(ipc, next_room, 1, 0); } /* * forget all rooms on a given floor */ -void forget_all_rooms_on(int ffloor) +void forget_all_rooms_on(CtdlIPC *ipc, int ffloor) { char buf[SIZ]; - struct march *flist, *fptr; - - printf("Forgetting all rooms on %s...\r", &floorlist[ffloor][0]); - fflush(stdout); - snprintf(buf, sizeof buf, "LKRA %d", ffloor); - serv_puts(buf); - serv_gets(buf); - if (buf[0] != '1') { - printf("%-72s\n", &buf[4]); + struct march *flist = NULL; + struct march *fptr = NULL; + struct ctdlipcroom *room = NULL; + int r; /* IPC response code */ + + scr_printf("Forgetting all rooms on %s...\n", &floorlist[ffloor][0]); + scr_flush(); + remove_march("_FLOOR_", ffloor); + r = CtdlIPCKnownRooms(ipc, AllAccessibleRooms, ffloor, &flist, buf); + if (r / 100 != 1) { + scr_printf("Error %d: %s\n", r, buf); return; } - flist = NULL; - while (serv_gets(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) { - snprintf(buf, sizeof buf, "GOTO %s", flist->march_name); - serv_puts(buf); - serv_gets(buf); - if (buf[0] == '2') { - serv_puts("FORG"); - serv_gets(buf); + while (flist) { + r = CtdlIPCGotoRoom(ipc, flist->march_name, "", &room, buf); + if (r / 100 == 2) { + r = CtdlIPCForgetRoom(ipc, buf); + if (r / 100 != 2) { + scr_printf("Error %d: %s\n", r, buf); + } + } fptr = flist; flist = flist->next; free(fptr); } - printf("%-72s\r", ""); } /* * routine called by gotofloor() to move to a new room on a new floor */ -void gf_toroom(char *towhere, int mode) +void gf_toroom(CtdlIPC *ipc, char *towhere, int mode) { int floor_being_left; floor_being_left = curr_floor; - if (mode == GF_GOTO) { /* <;G>oto mode */ - updatels(); - dotgoto(towhere, 1); + if (mode == GF_GOTO) { /* <;G>oto mode */ + updatels(ipc); + dotgoto(ipc, towhere, 1, 0); } - if (mode == GF_SKIP) { /* <;S>kip mode */ - dotgoto(towhere, 1); + else if (mode == GF_SKIP) { /* <;S>kip mode */ + dotgoto(ipc, towhere, 1, 0); remove_march("_FLOOR_", floor_being_left); } - if (mode == GF_ZAP) { /* <;Z>ap mode */ - dotgoto(towhere, 1); + else if (mode == GF_ZAP) { /* <;Z>ap mode */ + dotgoto(ipc, towhere, 1, 0); remove_march("_FLOOR_", floor_being_left); - forget_all_rooms_on(floor_being_left); + forget_all_rooms_on(ipc, floor_being_left); } } @@ -567,14 +599,15 @@ void gf_toroom(char *towhere, int mode) /* * go to a new floor */ -void gotofloor(char *towhere, int mode) +void gotofloor(CtdlIPC *ipc, char *towhere, int mode) { int a, tofloor; + int r; /* IPC response code */ struct march *mptr; char buf[SIZ], targ[SIZ]; if (floorlist[0][0] == 0) - load_floorlist(); + load_floorlist(ipc); tofloor = (-1); for (a = 0; a < 128; ++a) if (!strcasecmp(&floorlist[a][0], towhere)) @@ -593,28 +626,59 @@ void gotofloor(char *towhere, int mode) tofloor = a; } if (tofloor < 0) { - printf("No floor '%s'.\n", towhere); + scr_printf("No floor '%s'.\n", towhere); return; } for (mptr = march; mptr != NULL; mptr = mptr->next) { - if ((mptr->march_floor) == tofloor) - gf_toroom(mptr->march_name, mode); + if ((mptr->march_floor) == tofloor) { + gf_toroom(ipc, mptr->march_name, mode); + return; + } + } + + /* Find first known room on the floor */ + + strcpy(targ, ""); + mptr = NULL; + r = CtdlIPCKnownRooms(ipc, SubscribedRooms, 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); return; } + /* No known rooms on the floor; unzap the first one then */ + strcpy(targ, ""); - snprintf(buf, sizeof buf, "LKRA %d", tofloor); - serv_puts(buf); - serv_gets(buf); - if (buf[0] == '1') - while (serv_gets(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(targ, mode); + gf_toroom(ipc, targ, mode); } else { - printf("There are no rooms on '%s'.\n", &floorlist[tofloor][0]); + scr_printf("There are no rooms on '%s'.\n", &floorlist[tofloor][0]); } } @@ -622,26 +686,28 @@ void gotofloor(char *towhere, int mode) /* * forget all rooms on current floor */ -void forget_this_floor(void) +void forget_this_floor(CtdlIPC *ipc) { - if (curr_floor == 0) { - printf("Can't forget this floor.\n"); + scr_printf("Can't forget this floor.\n"); return; } - if (floorlist[0][0] == 0) - load_floorlist(); - printf("Are you sure you want to forget all rooms on %s? ", + if (floorlist[0][0] == 0) { + load_floorlist(ipc); + } + scr_printf("Are you sure you want to forget all rooms on %s? ", &floorlist[(int) curr_floor][0]); - if (yesno() == 0) + if (yesno() == 0) { return; + } - gf_toroom("_BASEROOM_", GF_ZAP); + gf_toroom(ipc, "_BASEROOM_", GF_ZAP); } /* * Figure out the physical screen dimensions, if we can + * WARNING: this is now called from a signal handler! */ void check_screen_dims(void) { @@ -656,7 +722,7 @@ void check_screen_dims(void) if (have_xterm) { /* dynamically size screen if on an xterm */ if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) { if (xwinsz.height) - screenheight = (int) xwinsz.height; + screenheight = is_curses_enabled() ? (int)xwinsz.height - 1 : (int) xwinsz.height; if (xwinsz.width) screenwidth = (int) xwinsz.width; } @@ -668,9 +734,9 @@ void check_screen_dims(void) /* * set floor mode depending on client, server, and user settings */ -void set_floor_mode(void) +void set_floor_mode(CtdlIPC* ipc) { - if (serv_info.serv_ok_floors == 0) { + if (ipc->ServInfo.ok_floors == 0) { floor_mode = 0; /* Don't use floors if the server */ } /* doesn't support them! */ @@ -690,7 +756,7 @@ void set_floor_mode(void) /* * Set or change the user's password */ -int set_password(void) +int set_password(CtdlIPC *ipc) { char pass1[20]; char pass2[20]; @@ -700,21 +766,19 @@ int set_password(void) strcpy(pass1, rc_password); strcpy(pass2, rc_password); } else { - IFNEXPERT formout("changepw"); + IFNEXPERT formout(ipc, "changepw"); newprompt("Enter a new password: ", pass1, -19); newprompt("Enter it again to confirm: ", pass2, -19); } strproc(pass1); strproc(pass2); if (!strcasecmp(pass1, pass2)) { - snprintf(buf, sizeof buf, "SETP %s", pass1); - serv_puts(buf); - serv_gets(buf); - printf("%s\n", &buf[4]); - offer_to_remember_password(hostbuf, portbuf, fullname, pass1); + CtdlIPCChangePassword(ipc, pass1, buf); + scr_printf("%s\n", buf); + offer_to_remember_password(ipc, hostbuf, portbuf, fullname, pass1); return (0); } else { - printf("*** They don't match... try again.\n"); + scr_printf("*** They don't match... try again.\n"); return (1); } } @@ -724,88 +788,147 @@ int set_password(void) /* * get info about the server we've connected to */ -void get_serv_info(char *supplied_hostname) +void get_serv_info(CtdlIPC *ipc, char *supplied_hostname) { - char buf[512]; + char buf[SIZ]; - CtdlInternalGetServInfo(&serv_info); + CtdlIPCServerInfo(ipc, buf); /* be nice and identify ourself to the server */ - snprintf(buf, sizeof buf, "IDEN %d|%d|%d|%s|", - SERVER_TYPE, 0, REV_LEVEL, - (server_is_local ? "local" : CITADEL)); - - /* Append a hostname */ - if (supplied_hostname != NULL) { - strcat(buf, supplied_hostname); - } - else { - locate_host(&buf[strlen(buf)]); /* append to the end */ + CtdlIPCIdentifySoftware(ipc, SERVER_TYPE, 0, REV_LEVEL, + (ipc->isLocal ? "local" : CITADEL), + (supplied_hostname) ? supplied_hostname : + /* Look up the , in the bible if you're confused */ + (locate_host(ipc, buf), buf), buf); + + /* Tell the server what our preferred content formats are */ + if ((CtdlIPCSpecifyPreferredFormats(ipc, buf, "text/html|text/plain") / 100 )== 2) { + can_do_msg4 = 1; } +} - serv_puts(buf); - serv_gets(buf); /* we don't care about the result code */ + + +/* + * Record compare function for SortOnlineUsers() + */ +int idlecmp(const void *rec1, const void *rec2) { + time_t i1, i2; + + i1 = extract_long(rec1, 5); + i2 = extract_long(rec2, 5); + + if (i1 < i2) return(1); + if (i1 > i2) return(-1); + return(0); } +/* + * Sort the list of online users by idle time. + * This function frees the supplied buffer, and returns a new one + * to the caller. The caller is responsible for freeing the returned buffer. + */ +char *SortOnlineUsers(char *listing) { + int rows; + char *sortbuf; + char *retbuf; + char buf[SIZ]; + int i; + + rows = num_tokens(listing, '\n'); + sortbuf = malloc(rows * SIZ); + if (sortbuf == NULL) return(listing); + retbuf = malloc(rows * SIZ); + if (retbuf == NULL) { + free(sortbuf); + return(listing); + } + + /* Copy the list into a fixed-record-size array for sorting */ + for (i=0; i 0) { + int isidle = 0; + + /* Get another line */ + extract_token(buf, listing, 0, '\n', sizeof buf); + remove_token(listing, 0, '\n'); + + extract_token(username, buf, 1, '|', sizeof username); + extract_token(roomname, buf, 2, '|', sizeof roomname); + extract_token(fromhost, buf, 3, '|', sizeof fromhost); + extract_token(clientsoft, buf, 4, '|', sizeof clientsoft); + extract_token(flags, buf, 7, '|', sizeof flags); idletime = timenow - extract_long(buf, 5); idlehours = idletime / 3600; idlemins = (idletime - (idlehours * 3600)) / 60; idlesecs = (idletime - (idlehours * 3600) - (idlemins * 60)); - if (idletime > 900) { + if (idletime > rc_idle_threshold) { + /* while (strlen(roomname) < 20) { strcat(roomname, " "); } strcpy(&roomname[14], "[idle]"); + */ + if (skipidle) + isidle = 1; } if (longlist) { - - extract(actual_user, buf, 8); - extract(actual_room, buf, 9); - extract(actual_host, buf, 10); + extract_token(actual_user, buf, 8, '|', sizeof actual_user); + extract_token(actual_room, buf, 9, '|', sizeof actual_room); + extract_token(actual_host, buf, 10, '|', sizeof actual_host); pprintf(" Flags: %s\n", flags); pprintf("Session: %d\n", extract_int(buf, 0)); @@ -828,30 +951,54 @@ void who_is_online(int longlist) pprintf("\n"); } else { - if (extract_int(buf, 0) == last_session) { - pprintf(" "); - } else { - color(BRIGHT_MAGENTA); - pprintf("%-3s ", flags); - color(DIM_WHITE); - pprintf("%-3d ", extract_int(buf, 0)); + if (isidle == 0) { + if (extract_int(buf, 0) == last_session) { + pprintf(" "); + } else { + color(BRIGHT_MAGENTA); + pprintf("%-3s", flags); + } + last_session = extract_int(buf, 0); + color(BRIGHT_CYAN); + pprintf("%-25s ", username); + color(BRIGHT_MAGENTA); + roomname[20] = 0; + pprintf("%-20s ", roomname); + if (idletime > rc_idle_threshold) { + /* over 1000d, must be gone fishing */ + if (idlehours > 23999) { + pprintf("fish"); + /* over 10 days */ + } else if (idlehours > 239) { + pprintf("%3ldd", + idlehours / 24); + /* over 10 hours */ + } else if (idlehours > 9) { + pprintf("%1ldd%02ld", + idlehours / 24, + idlehours % 24); + /* less than 10 hours */ + } else { + pprintf("%1ld:%02ld", + idlehours, idlemins); + } } - last_session = extract_int(buf, 0); - color(BRIGHT_CYAN); - pprintf("%-25s ", username); - color(BRIGHT_MAGENTA); - roomname[20] = 0; - pprintf("%-20s ", roomname); - color(BRIGHT_CYAN); - fromhost[24] = '\0'; - pprintf("%-24s\n", fromhost); - color(DIM_WHITE); + else { + pprintf(" "); + } + pprintf(" "); + color(BRIGHT_CYAN); + fromhost[24] = '\0'; + pprintf("%-24s\n", fromhost); + color(DIM_WHITE); + } } } } + free(listing); } -void enternew(char *desc, char *buf, int maxlen) +void enternew(CtdlIPC *ipc, char *desc, char *buf, int maxlen) { char bbb[128]; snprintf(bbb, sizeof bbb, "Enter in your new %s: ", desc); @@ -870,6 +1017,11 @@ int shift(int argc, char **argv, int start, int count) { return argc; } +static void statusHook(char *s) { + sln_printf(s); + sln_flush(); +} + /* * main */ @@ -884,24 +1036,41 @@ int main(int argc, char **argv) char hexstring[MD5_HEXSTRING_SIZE]; int stored_password = 0; char password[SIZ]; + struct ctdlipcmisc chek; + struct ctdluser *myself = NULL; + CtdlIPC* ipc; /* Our server connection */ + int r; /* IPC result code */ + + setIPCDeathHook(screen_delete); + setIPCErrorPrintf(err_printf); + setCryptoStatusHook(statusHook); /* Permissions sanity check - don't run citadel setuid/setgid */ if (getuid() != geteuid()) { - fprintf(stderr, "Please do not run citadel setuid!\n"); - logoff(3); + err_printf("Please do not run citadel setuid!\n"); + logoff(NULL, 3); } else if (getgid() != getegid()) { - fprintf(stderr, "Please do not run citadel setgid!\n"); - logoff(3); + err_printf("Please do not run citadel setgid!\n"); + logoff(NULL, 3); } - sttybbs(SB_SAVE); /* Store the old terminal parameters */ + stty_ctdl(SB_SAVE); /* Store the old terminal parameters */ load_command_set(); /* parse the citadel.rc file */ - sttybbs(SB_NO_INTR); /* Install the new ones */ - signal(SIGHUP, dropcarr); /* Cleanup gracefully if carrier is dropped */ + stty_ctdl(SB_NO_INTR); /* Install the new ones */ + /* signal(SIGHUP, dropcarr);FIXME */ /* Cleanup gracefully if carrier is dropped */ + signal(SIGPIPE, dropcarr); /* Cleanup gracefully if local conn. dropped */ signal(SIGTERM, dropcarr); /* Cleanup gracefully if terminated */ - signal(SIGCONT, catch_sigcont); /* Catch SIGCONT so we can reset terminal */ + signal(SIGCONT, catch_sigcont); /* Catch SIGCONT so we can reset terminal */ +#ifdef SIGWINCH + signal(SIGWINCH, scr_winch); /* Window resize signal */ +#endif +#ifdef HAVE_OPENSSL arg_encrypt = RC_DEFAULT; +#endif +#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES) + arg_screen = RC_DEFAULT; +#endif /* * Handle command line options as if we were called like /bin/login @@ -913,19 +1082,38 @@ int main(int argc, char **argv) argc = shift(argc, argv, a, 2); } if (!strcmp(argv[a], "-x")) { +#ifdef HAVE_OPENSSL arg_encrypt = RC_NO; +#endif argc = shift(argc, argv, a, 1); } if (!strcmp(argv[a], "-X")) { +#ifdef HAVE_OPENSSL arg_encrypt = RC_YES; argc = shift(argc, argv, a, 1); +#else + fprintf(stderr, "Not compiled with encryption support"); + return 1; +#endif + } + if (!strcmp(argv[a], "-s")) { +#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES) + arg_screen = RC_NO; +#endif + argc = shift(argc, argv, a, 1); + } + if (!strcmp(argv[a], "-S")) { +#if defined(HAVE_CURSES_H) && !defined(DISABLE_CURSES) + arg_screen = RC_YES; +#endif + argc = shift(argc, argv, a, 1); } if (!strcmp(argv[a], "-p")) { struct stat st; - if (chdir(BBSDIR) < 0) { - perror("can't change to " BBSDIR); - logoff(3); + if (chdir(CTDLDIR) < 0) { + perror("can't change to " CTDLDIR); + logoff(NULL, 3); } /* @@ -934,105 +1122,125 @@ int main(int argc, char **argv) * guaranteed to have the uid/gid we want. */ if (!getuid() || !getgid()) { - if (stat(BBSDIR "/citadel.config", &st) < 0) { + if (stat( +#ifndef HAVE_ETC_DIR + CTDLDIR +#else + ETC_DIR +#endif + "/citadel.config", &st) < 0) { perror("couldn't stat citadel.config"); - logoff(3); + logoff(NULL, 3); } if (!getgid() && (setgid(st.st_gid) < 0)) { perror("couldn't change gid"); - logoff(3); + logoff(NULL, 3); } if (!getuid() && (setuid(st.st_uid) < 0)) { perror("couldn't change uid"); - logoff(3); + logoff(NULL, 3); } /* - 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); } } - printf("Attaching to server... \r"); - fflush(stdout); - attach_to_server(argc, argv, hostbuf, portbuf); + screen_new(); - send_ansi_detect(); +#ifdef __CYGWIN__ + newprompt("Connect to (return for local server): ", hostbuf, 64); +#endif - serv_gets(aaa); + 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_chat_recv(ipc, aaa); if (aaa[0] != '2') { - printf("%s\n", &aaa[4]); - logoff(atoi(aaa)); + scr_printf("%s\n", &aaa[4]); + logoff(ipc, atoi(aaa)); } -/* If there is a [nonce] at the end, put the nonce in , else nonce - * is zeroized. - */ + /* If there is a [nonce] at the end, put the nonce in , 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, (size_t)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(telnet_client_host); + get_serv_info(ipc, telnet_client_host); + scr_printf("%-24s\n%s\n%s\n", ipc->ServInfo.software, ipc->ServInfo.humannode, + ipc->ServInfo.site_location); + scr_flush(); - if (!starttls()) { - printf("Session will not be encrypted.\n"); - } - - look_for_ansi(); - cls(0); - color(7); + status_line(ipc->ServInfo.humannode, ipc->ServInfo.site_location, NULL, + secure, -1); - printf("%-24s\n%s\n%s\n", serv_info.serv_software, serv_info.serv_humannode, - serv_info.serv_bbs_city); screenwidth = 80; /* default screen dimensions */ screenheight = 24; + + scr_printf(" pause next stop\n"); + scr_printf(" ctrl-s ctrl-o ctrl-c\n\n"); + formout(ipc, "hello"); /* print the opening greeting */ + scr_printf("\n"); - printf(" pause next stop\n"); - printf(" ctrl-s ctrl-o ctrl-c\n\n"); - formout("hello"); /* print the opening greeting */ - 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); - serv_puts(aaa); - serv_gets(aaa); - if (nonce[0]) - { - sprintf(aaa, "PAS2 %s", make_apop_string(password, nonce, 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); - } - - serv_puts(aaa); - serv_gets(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, "", ""); } } @@ -1048,22 +1256,20 @@ GSTA: /* See if we have a username and password on disk */ } strproc(fullname); if (!strcasecmp(fullname, "new")) { /* just in case */ - printf("Please enter the name you wish to log in with.\n"); + 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; goto TERMN8; } /* sign on to the server */ - snprintf(aaa, sizeof aaa, "USER %s", fullname); - serv_puts(aaa); - serv_gets(aaa); - if (aaa[0] != '3') + r = CtdlIPCTryLogin(ipc, fullname, aaa); + if (r / 100 != 3) goto NEWUSR; /* password authentication */ @@ -1074,48 +1280,44 @@ GSTA: /* See if we have a username and password on disk */ } strproc(password); - if (nonce[0]) - { - sprintf(aaa, "PAS2 %s", make_apop_string(password, nonce, hexstring)); - } - else /* Else no APOP */ - { - snprintf(aaa, sizeof(aaa)-1, "PASS %s", password); + if (*nonce) { + r = CtdlIPCTryApopPassword(ipc, make_apop_string(password, nonce, hexstring, sizeof hexstring), aaa); + } else { + r = CtdlIPCTryPassword(ipc, password, aaa); } - serv_puts(aaa); - serv_gets(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; } - printf("<< wrong password >>\n"); + scr_printf("<< wrong password >>\n"); if (strlen(rc_password) > 0) - logoff(0); + logoff(ipc, 2); goto GSTA; NEWUSR: if (strlen(rc_password) == 0) { - printf("No record. Enter as new user? "); + scr_printf("'%s' not found.\n" + "Do you want to create a new account with this name? ", + fullname); if (yesno() == 0) goto GSTA; } - snprintf(aaa, sizeof aaa, "NEWU %s", fullname); - serv_puts(aaa); - serv_gets(aaa); - if (aaa[0] != '2') { - printf("%s\n", aaa); + + 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() != 0);; + while (set_password(ipc) != 0); newnow = 1; - enter_config(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) @@ -1124,44 +1326,47 @@ PWOK: enable_color = 0; } - 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) { - printf(" / Last login: %s\n", - asctime(localtime(&lastcall)) ); + scr_printf(" / Last login: %s", + asctime(localtime(&lastcall))); } - printf("\n"); + scr_printf("\n"); - serv_puts("CHEK"); - serv_gets(aaa); - if (aaa[0] == '2') { - b = extract_int(&aaa[4], 0); + r = CtdlIPCMiscCheck(ipc, &chek, aaa); + if (r / 100 == 2) { + b = chek.newmail; if (b > 0) { color(BRIGHT_RED); if (b == 1) - printf("*** You have a new private message in Mail>\n"); + scr_printf("*** You have a new private message in Mail>\n"); if (b > 1) - printf("*** You have %d new private messages in Mail>\n", b); + scr_printf("*** You have %d new private messages in Mail>\n", b); color(DIM_WHITE); + if (strlen(rc_gotmail_cmd) > 0) { + system(rc_gotmail_cmd); + } } - if ((axlevel >= 6) && (extract_int(&aaa[4], 2) > 0)) { - printf("*** Users need validation\n"); + if ((axlevel >= 6) && (chek.needvalid > 0)) { + scr_printf("*** Users need validation\n"); } - if (extract_int(&aaa[4], 1) > 0) { - printf("*** Please register.\n"); - formout("register"); - entregis(); + if (chek.needregis > 0) { + scr_printf("*** Please register.\n"); + formout(ipc, "register"); + entregis(ipc); } } /* Make up some temporary filenames for use in various parts of the * program. Don't mess with these once they've been set, because we * will be unlinking them later on in the program and we don't * want to delete something that we didn't create. */ - snprintf(temp, sizeof temp, tmpnam(NULL)); - snprintf(temp2, sizeof temp2, tmpnam(NULL)); - snprintf(tempdir, sizeof tempdir, tmpnam(NULL)); + CtdlMakeTempFileName(temp, sizeof temp); + CtdlMakeTempFileName(temp2, sizeof temp2); + CtdlMakeTempFileName(tempdir, sizeof tempdir); /* Get screen dimensions. First we go to a default of 80x24. Then * we try to get the user's actual screen dimensions off the server. @@ -1171,11 +1376,10 @@ PWOK: */ screenwidth = 80; screenheight = 24; - serv_puts("GETU"); - serv_gets(aaa); - if (aaa[0] == '2') { - screenwidth = extract_int(&aaa[4], 0); - screenheight = extract_int(&aaa[4], 1); + r = CtdlIPCGetConfig(ipc, &myself, aaa); + if (r == 2) { + screenwidth = myself->USscreenwidth; + screenheight = myself->USscreenheight; } if (getenv("TERM") != NULL) if (!strcmp(getenv("TERM"), "xterm")) { @@ -1185,24 +1389,22 @@ PWOK: check_screen_dims(); #endif - set_floor_mode(); - + set_floor_mode(ipc); /* Enter the lobby */ - dotgoto("_BASEROOM_", 1); + dotgoto(ipc, "_BASEROOM_", 1, 0); -/* Main loop for the system... user is logged in. */ - strcpy(ugname, ""); - uglsn = 0L; + /* Main loop for the system... user is logged in. */ + uglistsize = 0; if (newnow == 1) - readmsgs(3, 1, 5); + readmsgs(ipc, LastMessages, ReadForward, 5); else - readmsgs(1, 1, 0); + readmsgs(ipc, NewMessages, ReadForward, 0); /* MAIN COMMAND LOOP */ do { - mcmd = getcmd(argbuf); /* Get keyboard command */ + mcmd = getcmd(ipc, argbuf); /* Get keyboard command */ #ifdef TIOCGWINSZ check_screen_dims(); /* if xterm, get screen size */ @@ -1211,216 +1413,234 @@ PWOK: if (termn8 == 0) switch (mcmd) { case 1: - formout("help"); + formout(ipc, "help"); break; case 4: - entmsg(0, 0); + entmsg(ipc, 0, ((userflags & US_EXTEDIT) ? 2 : 0)); break; case 36: - entmsg(0, 1); + entmsg(ipc, 0, 1); break; case 46: - entmsg(0, 2); + entmsg(ipc, 0, 2); break; case 78: - newprompt("What do you want your username to be? ", aaa, 32); - snprintf(bbb, sizeof bbb, "ENT0 2|0|0|0|%s", aaa); - serv_puts(bbb); - serv_gets(aaa); - if (strncmp("200", aaa, 3)) - printf("\n%s\n", aaa); - else - entmsg(0, 0); - break; - case 5: - updatels(); - gotonext(); - break; - case 47: - updatelsa(); - gotonext(); - break; - case 58: - updatelsa(); - dotgoto("_MAIL_", 1); + { + /* Only m.author is used */ + struct ctdlipcmessage m; + newprompt("What do you want your username to be? ", + m.author, USERNAME_SIZE - 1); + m.text = ""; + r = CtdlIPCPostMessage(ipc, 2, &m, aaa); + if (r / 100 != 2) + scr_printf("%s\n", aaa); + else + entmsg(ipc, 0, 0); + } + break; + case 5: /* oto */ + updatels(ipc); + gotonext(ipc); + break; + case 47: /* bandon */ + if (!rc_alt_semantics) { + updatelsa(ipc); + } + gotonext(ipc); + break; + case 90: /* <.A>bandon */ + if (!rc_alt_semantics) + updatelsa(ipc); + dotgoto(ipc, argbuf, 0, 0); + break; + case 58: /* ail */ + updatelsa(ipc); + dotgoto(ipc, "_MAIL_", 1, 0); break; case 20: - updatels(); + if (strlen(argbuf) > 0) { + updatels(ipc); + dotgoto(ipc, argbuf, 0, 0); + } + break; case 52: - dotgoto(argbuf, 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? --Ford, there isn't one. -IO */ + dotungoto(ipc, argbuf); break; case 10: - readmsgs(0, 1, 0); + readmsgs(ipc, AllMessages, ReadForward, 0); break; case 9: - readmsgs(3, 1, 5); + readmsgs(ipc, LastMessages, ReadForward, 5); break; case 13: - readmsgs(1, 1, 0); + readmsgs(ipc, NewMessages, ReadForward, 0); break; case 11: - readmsgs(0, (-1), 0); + readmsgs(ipc, AllMessages, ReadReverse, 0); break; case 12: - readmsgs(2, (-1), 0); + readmsgs(ipc, OldMessages, ReadReverse, 0); break; case 71: - readmsgs(3, 1, atoi(argbuf)); + readmsgs(ipc, LastMessages, ReadForward, + atoi(argbuf)); break; case 7: - forget(); + forget(ipc); break; case 18: subshell(); break; case 38: - updatels(); - entroom(); + updatels(ipc); + entroom(ipc); break; case 22: - killroom(); + killroom(ipc); break; case 32: - userlist(argbuf); + userlist(ipc, argbuf); break; case 27: - invite(); + invite(ipc); break; case 28: - kickout(); + kickout(ipc); break; case 23: - editthisroom(); + editthisroom(ipc); break; case 14: - roomdir(); + roomdir(ipc); break; case 33: - download(0); + download(ipc, 0); break; case 34: - download(1); + download(ipc, 1); break; case 31: - download(2); + download(ipc, 2); break; case 43: - download(3); + download(ipc, 3); break; case 45: - download(4); + download(ipc, 4); break; case 55: - download(5); + download(ipc, 5); break; case 39: - upload(0); + upload(ipc, 0); break; case 40: - upload(1); + upload(ipc, 1); break; case 42: - upload(2); + upload(ipc, 2); break; case 44: - upload(3); + upload(ipc, 3); break; case 57: - cli_upload(); + cli_upload(ipc); break; case 16: - ungoto(); + ungoto(ipc); break; case 24: - whoknows(); + whoknows(ipc); break; case 26: - validate(); + validate(ipc); break; case 29: - updatels(); - termn8 = 1; - break; case 30: - updatels(); + if (!rc_alt_semantics) { + updatels(ipc); + } termn8 = 1; break; case 48: - enterinfo(); + enterinfo(ipc); break; case 49: - readinfo(); + readinfo(ipc); break; case 72: - cli_image_upload("_userpic_"); + cli_image_upload(ipc, "_userpic_"); break; case 73: - cli_image_upload("_roompic_"); + cli_image_upload(ipc, "_roompic_"); break; case 74: snprintf(aaa, sizeof aaa, "_floorpic_|%d", curr_floor); - cli_image_upload(aaa); + cli_image_upload(ipc, aaa); break; case 75: - enternew("roomname", aaa, 20); - snprintf(bbb, sizeof bbb, "RCHG %s", aaa); - serv_puts(bbb); - serv_gets(aaa); - if (strncmp("200", aaa, 3)) - printf("\n%s\n", aaa); + enternew(ipc, "roomname", aaa, 20); + r = CtdlIPCChangeRoomname(ipc, aaa, bbb); + if (r / 100 != 2) + scr_printf("\n%s\n", bbb); break; case 76: - enternew("hostname", aaa, 25); - snprintf(bbb, sizeof bbb, "HCHG %s", aaa); - serv_puts(bbb); - serv_gets(aaa); - if (strncmp("200", aaa, 3)) - printf("\n%s\n", aaa); + enternew(ipc, "hostname", aaa, 25); + r = CtdlIPCChangeHostname(ipc, aaa, bbb); + if (r / 100 != 2) + scr_printf("\n%s\n", bbb); break; case 77: - enternew("username", aaa, 32); - snprintf(bbb, sizeof bbb, "UCHG %s", aaa); - serv_puts(bbb); - serv_gets(aaa); - if (strncmp("200", aaa, 3)) - printf("\n%s\n", aaa); + enternew(ipc, "username", aaa, 32); + r = CtdlIPCChangeUsername(ipc, aaa, bbb); + if (r / 100 != 2) + scr_printf("\n%s\n", bbb); break; case 35: - set_password(); + set_password(ipc); break; case 21: if (argbuf[0] == 0) strcpy(aaa, "?"); - display_help(argbuf); + display_help(ipc, argbuf); break; case 41: - formout("register"); - entregis(); + formout(ipc, "register"); + entregis(ipc); break; case 15: - printf("Are you sure (y/n)? "); + scr_printf("Are you sure (y/n)? "); if (yesno() == 1) { - updatels(); + if (!rc_alt_semantics) + updatels(ipc); a = 0; termn8 = 1; } break; case 85: - printf("All users will be disconnected! " - "Really terminate the server? "); + scr_printf("All users will be disconnected! " + "Really terminate the server? "); if (yesno() == 1) { - serv_puts("DOWN"); - serv_gets(aaa); - printf("%s\n", &aaa[4]); - if (aaa[0]=='2') { - updatels(); + if (!rc_alt_semantics) + updatels(ipc); + r = CtdlIPCTerminateServerNow(ipc, aaa); + scr_printf("%s\n", aaa); + if (r / 100 == 2) { a = 0; termn8 = 1; } @@ -1428,190 +1648,228 @@ PWOK: break; case 86: - printf("Do you really want to schedule a " - "server shutdown? "); + scr_printf("Do you really want to schedule a " + "server shutdown? "); if (yesno() == 1) { - serv_puts("SCDN 1"); - serv_gets(aaa); - if (aaa[0]=='2') { - if (atoi(&aaa[4])) { - printf( -"The Citadel server will terminate when all users are logged off.\n" - ); - } - else { - printf( -"The Citadel server will not terminate.\n" - ); + 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" + ); + } else { + scr_printf( + "The Citadel server will not terminate.\n" + ); } } } break; case 87: - network_config_management("listrecp", - "Mailing list recipients"); + network_config_management(ipc, "listrecp", + "Message-by-message mailing list recipients"); + break; + + case 94: + network_config_management(ipc, "digestrecp", + "Digest mailing list recipients"); break; case 89: - network_config_management("ignet_push_share", - "Nodes with which we share this room"); + network_config_management(ipc, "ignet_push_share", + "Nodes with which we share this room"); break; case 88: - do_ignet_configuration(); + do_ignet_configuration(ipc); + break; + + case 92: + do_filterlist_configuration(ipc); break; case 6: - gotonext(); + if (rc_alt_semantics) { + updatelsa(ipc); + } + gotonext(ipc); break; case 3: - chatmode(); + chatmode(ipc); break; case 2: - if (server_is_local) { - sttybbs(SB_RESTORE); + if (ipc->isLocal) { + screen_reset(); + stty_ctdl(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); + stty_ctdl(SB_NO_INTR); + screen_set(); } else { - printf("*** Can't run doors when server is not local.\n"); + scr_printf("*** Can't run doors when server is not local.\n"); } break; case 17: - who_is_online(0); + who_is_online(ipc, 0); break; case 79: - who_is_online(1); + who_is_online(ipc, 1); break; + case 91: + who_is_online(ipc, 2); + break; + case 80: - do_system_configuration(); + do_system_configuration(ipc); break; case 82: - do_internet_configuration(); + do_internet_configuration(ipc); break; case 83: - check_message_base(); + check_message_base(ipc); break; case 84: - quiet_mode(); + quiet_mode(ipc); + break; + + case 93: + stealth_mode(ipc); break; case 50: - enter_config(2); + enter_config(ipc, 2); break; case 37: - enter_config(0); - set_floor_mode(); + enter_config(ipc, 0); + set_floor_mode(ipc); break; case 59: - enter_config(3); - set_floor_mode(); + enter_config(ipc, 3); + set_floor_mode(ipc); break; case 60: - gotofloor(argbuf, GF_GOTO); + gotofloor(ipc, argbuf, GF_GOTO); break; case 61: - gotofloor(argbuf, GF_SKIP); + gotofloor(ipc, argbuf, GF_SKIP); break; case 62: - forget_this_floor(); + forget_this_floor(ipc); break; case 63: - create_floor(); + create_floor(ipc); break; case 64: - edit_floor(); + edit_floor(ipc); break; case 65: - kill_floor(); + kill_floor(ipc); break; case 66: - enter_bio(); + enter_bio(ipc); break; case 67: - read_bio(); + read_bio(ipc); break; case 25: - edituser(); + edituser(ipc, 25); + break; + + case 96: + edituser(ipc, 96); break; case 8: - knrooms(floor_mode); - printf("\n"); + knrooms(ipc, floor_mode); + scr_printf("\n"); break; case 68: - knrooms(2); - printf("\n"); + knrooms(ipc, 2); + scr_printf("\n"); break; case 69: - misc_server_cmd(argbuf); + misc_server_cmd(ipc, argbuf); break; case 70: - edit_system_message(argbuf); + edit_system_message(ipc, argbuf); break; case 19: - listzrooms(); - printf("\n"); + listzrooms(ipc); + scr_printf("\n"); break; case 51: - deletefile(); + deletefile(ipc); break; case 53: - netsendfile(); + netsendfile(ipc); break; case 54: - movefile(); + movefile(ipc); break; case 56: - page_user(); - break; - + 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: 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); } if (mcmd == 30) { - printf("\n\nType 'off' to disconnect, or next user...\n"); + sln_printf("\n\nType 'off' to disconnect, or next user...\n"); } - snprintf(aaa, sizeof aaa, "LOUT"); - serv_puts(aaa); - serv_gets(aaa); + CtdlIPCLogout(ipc); if ((mcmd == 29) || (mcmd == 15)) { - formout("goodbye"); - logoff(0); + screen_delete(); + stty_ctdl(SB_RESTORE); + formout(ipc, "goodbye"); + logoff(ipc, 0); } goto GSTA;