X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fcitadel.c;h=7e5ef874a2351bf2233c80e1a4b657bdce81c01f;hb=3f28c1900103b2a18628c9fc19f07adb86d87264;hp=62a79774b08b4cd601633d0424a3f8bed6b9b167;hpb=e63c8562afab456400dbea6fc528edbfc2074d21;p=citadel.git diff --git a/citadel/citadel.c b/citadel/citadel.c index 62a79774b..7e5ef874a 100644 --- a/citadel/citadel.c +++ b/citadel/citadel.c @@ -2,6 +2,22 @@ * $Id$ * * Main source module for the client program. + * + * Copyright (c) 1987-2009 by the citadel.org team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sysdep.h" @@ -30,28 +46,29 @@ #include #include #include -#include #include #include - +#include #include "citadel.h" #include "citadel_ipc.h" #include "axdefs.h" #include "routines.h" #include "routines2.h" +#include "tuiconfig.h" #include "rooms.h" #include "messages.h" #include "commands.h" #include "client_chat.h" #include "client_passwords.h" #include "citadel_decls.h" -#include "tools.h" -#include "acconfig.h" +#include "sysdep.h" #ifndef HAVE_SNPRINTF #include "snprintf.h" #endif #include "screen.h" +#include "citadel_dirs.h" +#include "ecrash.h" #include "md5.h" #define IFEXPERT if (userflags&US_EXPERT) @@ -59,21 +76,22 @@ #define IFAIDE if (axlevel>=6) #define IFNAIDE if (axlevel<6) -struct march *march = NULL; +int rordercmp(struct ctdlroomlisting *r1, struct ctdlroomlisting *r2); + +march *marchptr = 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[USERNAME_SIZE]; -jmp_buf nextbuf; -struct CtdlServInfo serv_info; /* Info on the server connected */ int screenwidth; int screenheight; unsigned room_flags; +unsigned room_flags2; char room_name[ROOMNAMELEN]; 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. */ @@ -101,38 +119,56 @@ char curr_floor = 0; /* number of current floor */ char floorlist[128][SIZ]; /* names of floors */ 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 express_msgs; /* express messages waiting! */ +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 */ +int enable_syslog = 0; + + +/* + * CtdlLogPrintf() ... Write logging information; + * simple here to have the same + * symbols in the client. + */ + +void CtdlLogPrintf(enum LogLevel loglevel, const char *format, ...) { + va_list arg_ptr; + + va_start(arg_ptr, format); + vfprintf(stderr, format, arg_ptr); + va_end(arg_ptr); + fflush(stderr); +} /* * here is our 'clean up gracefully and exit' routine */ -void logoff(CtdlIPC *ipc, int code) +void ctdl_logoff(char *file, int line, 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); @@ -148,7 +184,12 @@ void logoff(CtdlIPC *ipc, int code) kill(0 - getpgrp(), SIGKILL); } color(ORIGINAL_PAIR); /* Restore the old color settings */ - sttybbs(SB_RESTORE); /* return the old terminal 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 */ } @@ -170,13 +211,13 @@ void dropcarr(int signum) */ void catch_sigcont(int signum) { - sttybbs(SB_LAST); + stty_ctdl(SB_LAST); signal(SIGCONT, catch_sigcont); } - /* general purpose routines */ + /* display a file */ void formout(CtdlIPC *ipc, char *name) { @@ -190,7 +231,7 @@ void formout(CtdlIPC *ipc, char *name) return; } if (text) { - fmout2(screenwidth, NULL, text, NULL, + fmout(screenwidth, NULL, text, NULL, ((userflags & US_PAGINATOR) ? 1 : 0), screenheight, 1, 1); free(text); @@ -202,36 +243,36 @@ 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; - r = CtdlIPCUserListing(ipc, &listing, buf); + 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 (strlen(listing) > 0) { - extract_token(buf, listing, 0, '\n'); + pprintf(" User Name Num L Last Visit Logins Messages\n"); + pprintf("------------------------- ----- - ---------- ------ --------\n"); + if (listing != NULL) while (!IsEmptyStr(listing)) { + 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)); - pprintf("%5ld %5ld\n", extract_long(buf, 4), extract_long(buf, 5)); + (tmbuf.tm_mon + 1), + tmbuf.tm_mday, + (tmbuf.tm_year + 1900)); + pprintf("%6ld %8ld\n", extract_long(buf, 4), extract_long(buf, 5)); } } @@ -246,7 +287,7 @@ void userlist(CtdlIPC *ipc, 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); @@ -265,18 +306,18 @@ void remove_march(char *roomname, int floornum) { struct march *mptr, *mptr2; - if (march == NULL) + if (marchptr == NULL) return; - if ((!strcasecmp(march->march_name, roomname)) - || ((!strcasecmp(roomname, "_FLOOR_")) && (march->march_floor == floornum))) { - mptr = march->next; - free(march); - march = mptr; + if ((!strcasecmp(marchptr->march_name, roomname)) + || ((!strcasecmp(roomname, "_FLOOR_")) && (marchptr->march_floor == floornum))) { + mptr = marchptr->next; + free(marchptr); + marchptr = mptr; return; } - mptr2 = march; - for (mptr = march; mptr != NULL; mptr = mptr->next) { + mptr2 = marchptr; + for (mptr = marchptr; mptr != NULL; mptr = mptr->next) { if ((!strcasecmp(mptr->march_name, roomname)) || ((!strcasecmp(roomname, "_FLOOR_")) @@ -296,7 +337,7 @@ void remove_march(char *roomname, int floornum) * Locate the room on the march list which we most want to go to. Each room * is measured given a "weight" of preference based on various factors. */ -char *pop_march(int desired_floor) +char *pop_march(int desired_floor, struct march *_march) { static char TheRoom[ROOMNAMELEN]; int TheFloor = 0; @@ -306,10 +347,10 @@ char *pop_march(int desired_floor) struct march *mptr = NULL; strcpy(TheRoom, "_BASEROOM_"); - if (march == NULL) + if (_march == NULL) return (TheRoom); - for (mptr = march; mptr != NULL; mptr = mptr->next) { + for (mptr = _march; mptr != NULL; mptr = mptr->next) { weight = 0; if ((strcasecmp(mptr->march_name, "_BASEROOM_"))) weight = weight + 10000; @@ -342,7 +383,8 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) char from_floor; int ugpos = uglistsize; int r; /* IPC result code */ - struct ctdlipcroom *roomrec = NULL; + struct ctdlipcroom *room = NULL; + int rv = 0; /* store ungoto information */ if (fromungoto == 0) { @@ -355,8 +397,9 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) uglistlsn[lp] = uglistlsn[lp+1]; } ugpos--; - } else + } else { uglistsize++; + } uglist[ugpos] = malloc(strlen(room_name)+1); strcpy(uglist[ugpos], room_name); @@ -364,10 +407,10 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) } /* first try an exact match */ - r = CtdlIPCGotoRoom(ipc, towhere, "", &roomrec, aaa); + r = CtdlIPCGotoRoom(ipc, towhere, "", &room, aaa); if (r / 10 == 54) { newprompt("Enter room password: ", bbb, 9); - r = CtdlIPCGotoRoom(ipc, towhere, bbb, &roomrec, aaa); + r = CtdlIPCGotoRoom(ipc, towhere, bbb, &room, aaa); if (r / 10 == 54) { scr_printf("Wrong password.\n"); return; @@ -378,7 +421,8 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) * 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 (r / 100 != 2) { struct march *march = NULL; @@ -386,7 +430,7 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) best_match = 0; strcpy(bbb, ""); - r = CtdlIPCKnownRooms(ipc, AllAccessibleRooms, -1, &march, aaa); + 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 */ @@ -410,26 +454,26 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) } } - if (strlen(bbb) == 0) { + if (IsEmptyStr(bbb)) { scr_printf("No room '%s'.\n", towhere); return; } - roomrec = NULL; - r = CtdlIPCGotoRoom(ipc, bbb, "", &roomrec, aaa); + r = CtdlIPCGotoRoom(ipc, bbb, "", &room, aaa); } if (r / 100 != 1 && r / 100 != 2) { scr_printf("%s\n", aaa); return; } - safestrncpy(room_name, roomrec->RRname, ROOMNAMELEN); - room_flags = roomrec->RRflags; + safestrncpy(room_name, room->RRname, ROOMNAMELEN); + room_flags = room->RRflags; + room_flags2 = room->RRflags2; from_floor = curr_floor; - curr_floor = roomrec->RRfloor; + curr_floor = room->RRfloor; remove_march(room_name, 0); if (!strcasecmp(towhere, "_BASEROOM_")) remove_march(towhere, 0); - if (!roomrec->RRunread) + 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) @@ -444,26 +488,26 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) } if (display_name != 2) { color(BRIGHT_YELLOW); - scr_printf("%d ", roomrec->RRunread); + scr_printf("%d ", room->RRunread); color(DIM_WHITE); scr_printf("new of "); color(BRIGHT_YELLOW); - scr_printf("%d ", roomrec->RRtotal); + scr_printf("%d ", room->RRtotal); color(DIM_WHITE); scr_printf("messages.\n"); } - highest_msg_read = roomrec->RRlastread; - maxmsgnum = roomrec->RRhighest; - is_mail = roomrec->RRismailbox; - is_room_aide = roomrec->RRaide; - ls = roomrec->RRlastread; + 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 (roomrec->RRinfoupdated > 0) + if (room->RRinfoupdated > 0) readinfo(ipc); /* check for newly arrived mail if we can */ - newmailcount = roomrec->RRnewmail; + newmailcount = room->RRnewmail; if (newmailcount > 0) { color(BRIGHT_RED); if (newmailcount == 1) { @@ -474,12 +518,13 @@ void dotgoto(CtdlIPC *ipc, char *towhere, int display_name, int fromungoto) newmailcount); } color(DIM_WHITE); - if (strlen(rc_gotmail_cmd) > 0) { - system(rc_gotmail_cmd); + if (!IsEmptyStr(rc_gotmail_cmd)) { + rv = system(rc_gotmail_cmd); } } - status_line(serv_info.serv_humannode, serv_info.serv_bbs_city, + status_line(ipc->ServInfo.humannode, ipc->ServInfo.site_location, room_name, secure, newmailcount); + free(room); } /* Goto next room having unread messages. @@ -497,18 +542,22 @@ void gotonext(CtdlIPC *ipc) /* 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) { - r = CtdlIPCKnownRooms(ipc, SubscribedRoomsWithNewMessages, -1, &march, buf); + if (marchptr == NULL) { + r = CtdlIPCKnownRooms(ipc, SubscribedRoomsWithNewMessages, + AllFloors, &marchptr, 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 */ mptr = (struct march *) malloc(sizeof(struct march)); mptr->next = NULL; + mptr->march_order = 0; + mptr->march_floor = 0; strcpy(mptr->march_name, "_BASEROOM_"); - if (march == NULL) { - march = mptr; + if (marchptr == NULL) { + marchptr = mptr; } else { - mptr2 = march; + mptr2 = marchptr; while (mptr2->next != NULL) mptr2 = mptr2->next; mptr2->next = mptr; @@ -519,8 +568,8 @@ void gotonext(CtdlIPC *ipc) */ remove_march(room_name, 0); } - if (march != NULL) { - strcpy(next_room, pop_march(curr_floor)); + if (marchptr != NULL) { + strcpy(next_room, pop_march(curr_floor, marchptr)); } else { strcpy(next_room, "_BASEROOM_"); } @@ -534,27 +583,33 @@ void gotonext(CtdlIPC *ipc) void forget_all_rooms_on(CtdlIPC *ipc, int ffloor) { char buf[SIZ]; - struct march *flist, *fptr; - struct ctdlipcroom *roomrec; /* Ignored */ + struct march *flist = NULL; + struct march *fptr = NULL; + struct ctdlipcroom *room = NULL; int r; /* IPC response code */ - scr_printf("Forgetting all rooms on %s...\r", &floorlist[ffloor][0]); + 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("%-72s\n", buf); + scr_printf("Error %d: %s\n", r, buf); return; } while (flist) { - r = CtdlIPCGotoRoom(ipc, flist->march_name, "", &roomrec, buf); + 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); } - scr_printf("%-72s\r", ""); + if (room) free(room); } @@ -567,15 +622,15 @@ void gf_toroom(CtdlIPC *ipc, char *towhere, int mode) floor_being_left = curr_floor; - if (mode == GF_GOTO) { /* <;G>oto mode */ + if (mode == GF_GOTO) { /* <;G>oto mode */ updatels(ipc); dotgoto(ipc, towhere, 1, 0); } - if (mode == GF_SKIP) { /* <;S>kip mode */ + 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 */ + else if (mode == GF_ZAP) { /* <;Z>ap mode */ dotgoto(ipc, towhere, 1, 0); remove_march("_FLOOR_", floor_being_left); forget_all_rooms_on(ipc, floor_being_left); @@ -616,51 +671,386 @@ void gotofloor(CtdlIPC *ipc, char *towhere, int mode) scr_printf("No floor '%s'.\n", towhere); return; } - for (mptr = march; mptr != NULL; mptr = mptr->next) { - if ((mptr->march_floor) == tofloor) + for (mptr = marchptr; mptr != NULL; mptr = mptr->next) { + 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; + + /*. . . according to room order */ + if (mptr) + strcpy(targ, pop_march(tofloor, mptr)); + while (mptr) { + tmp = mptr->next; + free(mptr); + mptr = tmp; + } + } + if (!IsEmptyStr(targ)) { + gf_toroom(ipc, targ, mode); return; } + /* No known rooms on the floor; unzap the first one then */ + strcpy(targ, ""); mptr = NULL; r = CtdlIPCKnownRooms(ipc, AllAccessibleRooms, tofloor, &mptr, buf); if (r / 100 == 1) { struct march *tmp = mptr; - - /* TODO: room order is being ignored? */ + + /*. . . according to room order */ if (mptr) - strncpy(targ, mptr->march_name, ROOMNAMELEN); + strcpy(targ, pop_march(tofloor, mptr)); while (mptr) { tmp = mptr->next; free(mptr); mptr = tmp; } } - if (strlen(targ) > 0) { + if (!IsEmptyStr(targ)) { gf_toroom(ipc, targ, mode); } else { scr_printf("There are no rooms on '%s'.\n", &floorlist[tofloor][0]); } } +/* + * Indexing mechanism for a room list, called by gotoroomstep() + */ +void room_tree_list_query(struct ctdlroomlisting *rp, char *findrmname, int findrmslot, char *rmname, int *rmslot, int *rmtotal) +{ + char roomname[ROOMNAMELEN]; + static int cur_rmslot = 0; + + if (rp == NULL) { + cur_rmslot = 0; + return; + } + + if (rp->lnext != NULL) { + room_tree_list_query(rp->lnext, findrmname, findrmslot, rmname, rmslot, rmtotal); + } + + if (sigcaught == 0) { + strcpy(roomname, rp->rlname); + + if (rmname != NULL) { + if (cur_rmslot == findrmslot) { + strcpy(rmname, roomname); + } + } + if (rmslot != NULL) { + if (!strcmp(roomname, findrmname)) { + *rmslot = cur_rmslot; + } + } + cur_rmslot++; + } + + if (rp->rnext != NULL) { + room_tree_list_query(rp->rnext, findrmname, findrmslot, rmname, rmslot, rmtotal); + } + + if ((rmname == NULL) && (rmslot == NULL)) + free(rp); + + if (rmtotal != NULL) { + *rmtotal = cur_rmslot; + } +} + +/* + * step through rooms on current floor + */ +void gotoroomstep(CtdlIPC *ipc, int direction, int mode) +{ + struct march *listing = NULL; + struct march *mptr; + int r; /* IPC response code */ + char buf[SIZ]; + struct ctdlroomlisting *rl = NULL; + struct ctdlroomlisting *rp; + struct ctdlroomlisting *rs; + int list_it; + char rmname[ROOMNAMELEN]; + int rmslot = 0; + int rmtotal; + + /* Ask the server for a room list */ + r = CtdlIPCKnownRooms(ipc, SubscribedRooms, (-1), &listing, buf); + if (r / 100 != 1) { + listing = NULL; + } + + load_floorlist(ipc); + + for (mptr = listing; mptr != NULL; mptr = mptr->next) { + list_it = 1; + + if ( floor_mode + && (mptr->march_floor != curr_floor)) + list_it = 0; + + if (list_it) { + rp = malloc(sizeof(struct ctdlroomlisting)); + strncpy(rp->rlname, mptr->march_name, ROOMNAMELEN); + rp->rlflags = mptr->march_flags; + rp->rlfloor = mptr->march_floor; + rp->rlorder = mptr->march_order; + rp->lnext = NULL; + rp->rnext = NULL; + + rs = rl; + if (rl == NULL) { + rl = rp; + } else { + while (rp != NULL) { + if (rordercmp(rp, rs) < 0) { + if (rs->lnext == NULL) { + rs->lnext = rp; + rp = NULL; + } else { + rs = rs->lnext; + } + } else { + if (rs->rnext == NULL) { + rs->rnext = rp; + rp = NULL; + } else { + rs = rs->rnext; + } + } + } + } + } + } + + /* Find position of current room */ + room_tree_list_query(NULL, NULL, 0, NULL, NULL, NULL); + room_tree_list_query(rl, room_name, 0, NULL, &rmslot, &rmtotal); + + if (direction == 0) { /* Previous room */ + /* If we're at the first room, wrap to the last room */ + if (rmslot == 0) { + rmslot = rmtotal - 1; + } else { + rmslot--; + } + } else { /* Next room */ + /* If we're at the last room, wrap to the first room */ + if (rmslot == rmtotal - 1) { + rmslot = 0; + } else { + rmslot++; + } + } + + /* Get name of next/previous room */ + room_tree_list_query(NULL, NULL, 0, NULL, NULL, NULL); + room_tree_list_query(rl, NULL, rmslot, rmname, NULL, NULL); + + /* Free the tree */ + room_tree_list_query(rl, NULL, 0, NULL, NULL, NULL); + + if (mode == 0) { /* not skipping */ + updatels(ipc); + } else { + if (rc_alt_semantics) { + updatelsa(ipc); + } + } + + /* Free the room list */ + while (listing) { + mptr = listing->next; + free(listing); + listing = mptr; + }; + + dotgoto(ipc, rmname, 1, 0); +} + + +/* + * step through floors on system + */ +void gotofloorstep(CtdlIPC *ipc, int direction, int mode) +{ + int tofloor; + + if (floorlist[0][0] == 0) + load_floorlist(ipc); + + empty_keep_going: + + if (direction == 0) { /* Previous floor */ + if (curr_floor) tofloor = curr_floor - 1; + else tofloor = 127; + + while (!floorlist[tofloor][0]) tofloor--; + } else { /* Next floor */ + if (curr_floor < 127) tofloor = curr_floor + 1; + else tofloor = 0; + + while (!floorlist[tofloor][0] && tofloor < 127) tofloor++; + if (!floorlist[tofloor][0]) tofloor = 0; + } + /* ;g works when not in floor mode so . . . */ + if (!floor_mode) { + scr_printf("(%s)\n", floorlist[tofloor] ); + } + + gotofloor(ipc, floorlist[tofloor], mode); + if (curr_floor != tofloor) { /* gotofloor failed */ + curr_floor = tofloor; + goto empty_keep_going; + } +} + +/* + * Display user 'preferences'. + */ +extern int rc_prompt_control; +void read_config(CtdlIPC *ipc) +{ + char buf[SIZ]; + char *resp = NULL; + int r; /* IPC response code */ + char _fullname[USERNAME_SIZE]; + long _usernum; + int _axlevel, _timescalled, _posted; + time_t _lastcall; + struct ctdluser *user = NULL; + + /* get misc user info */ + r = CtdlIPCGetBio(ipc, fullname, &resp, buf); + if (r / 100 != 1) { + pprintf("%s\n", buf); + return; + } + extract_token(_fullname, buf, 1, '|', sizeof fullname); + _usernum = extract_long(buf, 2); + _axlevel = extract_int(buf, 3); + _lastcall = extract_long(buf, 4); + _timescalled = extract_int(buf, 5); + _posted = extract_int(buf, 6); + free(resp); + resp = NULL; + + /* get preferences */ + r = CtdlIPCGetConfig(ipc, &user, buf); + if (r / 100 != 2) { + scr_printf("%s\n", buf); + free(user); + return; + } + + /* show misc user info */ + scr_printf("%s\nAccess level: %d (%s)\n" + "User #%ld / %d Calls / %d Posts", + _fullname, _axlevel, axdefs[(int) _axlevel], + _usernum, _timescalled, _posted); + if (_lastcall > 0L) { + scr_printf(" / Curr login: %s", + asctime(localtime(&_lastcall))); + } + scr_printf("\n"); + + /* show preferences */ + scr_printf("Your screen width: "); color(BRIGHT_CYAN); scr_printf("%d", /*user->USscreenwidth*/ screenwidth); color(DIM_WHITE); + scr_printf(", height: "); color(BRIGHT_CYAN); scr_printf("%d\n", /*user->USscreenheight*/ screenheight); color(DIM_WHITE); + scr_printf("Are you an experienced Citadel user: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_EXPERT) ? "Yes" : "No"); color(DIM_WHITE); + scr_printf("Print last old message on New message request: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_LASTOLD)? "Yes" : "No"); color(DIM_WHITE); + scr_printf("Prompt after each message: "); color(BRIGHT_CYAN); scr_printf("%s\n", (!(user->flags & US_NOPROMPT))? "Yes" : "No"); color(DIM_WHITE); + if ((user->flags & US_NOPROMPT) == 0) { + scr_printf("Use 'disappearing' prompts: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_DISAPPEAR)? "Yes" : "No"); color(DIM_WHITE); + } + scr_printf("Pause after each screenful of text: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_PAGINATOR)? "Yes" : "No"); color(DIM_WHITE); + if (rc_prompt_control == 3 && (user->flags & US_PAGINATOR)) { + scr_printf("ext and top work at paginator prompt: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_PROMPTCTL)? "Yes" : "No"); color(DIM_WHITE); + } + if (rc_floor_mode == RC_DEFAULT) { + scr_printf("View rooms by floor: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_FLOORS)? "Yes" : "No"); color(DIM_WHITE); + } + if (rc_ansi_color == 3) { + scr_printf("Enable color support: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_COLOR)? "Yes" : "No"); color(DIM_WHITE); + } + scr_printf("Be unlisted in userlog: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_UNLISTED)? "Yes" : "No"); color(DIM_WHITE); + if (!IsEmptyStr(editor_paths[0])) { + scr_printf("Always enter messages with the full-screen editor: "); color(BRIGHT_CYAN); scr_printf("%s\n", (user->flags & US_EXTEDIT)? "Yes" : "No"); color(DIM_WHITE); + } + free(user); +} + +/* + * Display system statistics. + */ +void system_info(CtdlIPC *ipc) +{ + char buf[SIZ]; + char *resp = NULL; + size_t bytes; + int mrtg_users, mrtg_active_users; + char mrtg_server_uptime[40]; + long mrtg_himessage; + int ret; /* IPC response code */ + + /* get #users, #active & server uptime */ + ret = CtdlIPCGenericCommand(ipc, "MRTG|users", NULL, 0, &resp, &bytes, buf); + mrtg_users = extract_int(resp, 0); + remove_token(resp, 0, '\n'); + mrtg_active_users = extract_int(resp, 0); + remove_token(resp, 0, '\n'); + extract_token(mrtg_server_uptime, resp, 0, '\n', sizeof mrtg_server_uptime); + free(resp); + resp = NULL; + + /* get high message# */ + ret = CtdlIPCGenericCommand(ipc, "MRTG|messages", NULL, 0, &resp, &bytes, buf); + mrtg_himessage = extract_long(resp, 0); + free(resp); + resp = NULL; + + /* refresh server info just in case */ + CtdlIPCServerInfo(ipc, buf); + + scr_printf("You are connected to %s (%s) @%s\n", ipc->ServInfo.nodename, ipc->ServInfo.humannode, ipc->ServInfo.fqdn); + scr_printf("running %s with text client v%.2f,\n", ipc->ServInfo.software, (float)REV_LEVEL/100); + scr_printf("server build %s,\n", ipc->ServInfo.svn_revision, (float)REV_LEVEL/100); + scr_printf("and located in %s.\n", ipc->ServInfo.site_location); + scr_printf("Connected users %d / Active users %d / Highest message #%ld\n", mrtg_users, mrtg_active_users, mrtg_himessage); + scr_printf("Server uptime: %s\n", mrtg_server_uptime); + scr_printf("Your system administrator is %s.\n", ipc->ServInfo.sysadm); + scr_printf("Copyright (C)1987-2009 by the Citadel development team\n"); +} /* * forget all rooms on current floor */ void forget_this_floor(CtdlIPC *ipc) { - if (curr_floor == 0) { scr_printf("Can't forget this floor.\n"); return; } - if (floorlist[0][0] == 0) + 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(ipc, "_BASEROOM_", GF_ZAP); } @@ -695,9 +1085,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! */ @@ -723,7 +1113,7 @@ int set_password(CtdlIPC *ipc) char pass2[20]; char buf[SIZ]; - if (strlen(rc_password) > 0) { + if (!IsEmptyStr(rc_password)) { strcpy(pass1, rc_password); strcpy(pass2, rc_password); } else { @@ -753,22 +1143,96 @@ void get_serv_info(CtdlIPC *ipc, char *supplied_hostname) { char buf[SIZ]; - CtdlIPCServerInfo(ipc, &serv_info, buf); + CtdlIPCServerInfo(ipc, buf); /* 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(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; + /* Indicate to the server that we prefer to decode Base64 and + * quoted-printable on the client side. + */ + if ((CtdlIPCSpecifyPreferredFormats(ipc, buf, "dont_decode") / 100 ) != 2) { + scr_printf("ERROR: Extremely old server; MSG4 framework not supported.\n"); + logoff(ipc, 0); + } + + /* + * Tell the server what our preferred content formats are. + * + * Originally we preferred HTML over plain text because we can format + * it to the reader's screen width, but since our HTML-to-text parser + * isn't really all that great, it's probably better to just go with + * the plain text when we have it available. + */ + if ((CtdlIPCSpecifyPreferredFormats(ipc, buf, "text/plain|text/html") / 100 ) != 2) { + scr_printf("ERROR: Extremely old server; MSG4 framework not supported.\n"); + logoff(ipc, 0); } } +/* + * 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= 80) pprintf(" Idle From host"); + pprintf("\n"); color(DIM_WHITE); - pprintf("--- --- ------------------------- -------------------- ------------------------\n"); + pprintf(" ------------------------- --------------------"); + if (screenwidth >= 80) pprintf(" ---- ------------------------"); + pprintf("\n"); } r = CtdlIPCOnlineUsers(ipc, &listing, &timenow, buf); + listing = SortOnlineUsers(listing); if (r / 100 == 1) { - while (strlen(listing) > 0) { + while (!IsEmptyStr(listing)) { int isidle = 0; /* Get another line */ - extract_token(buf, listing, 0, '\n'); + extract_token(buf, listing, 0, '\n', sizeof buf); remove_token(listing, 0, '\n'); - extract(username, buf, 1); - extract(roomname, buf, 2); - extract(fromhost, buf, 3); - extract(clientsoft, buf, 4); - extract(flags, buf, 7); + 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; @@ -819,18 +1288,15 @@ void who_is_online(CtdlIPC *ipc, int longlist) idlesecs = (idletime - (idlehours * 3600) - (idlemins * 60)); if (idletime > rc_idle_threshold) { - while (strlen(roomname) < 20) { - strcat(roomname, " "); - } - strcpy(&roomname[14], "[idle]"); - if (skipidle) + 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)); @@ -843,36 +1309,64 @@ void who_is_online(CtdlIPC *ipc, int longlist) (long) idlemins, (long) idlesecs); - if ( (strlen(actual_user)+strlen(actual_room)+strlen(actual_host)) > 0) { + if ( (!IsEmptyStr(actual_user)&& + !IsEmptyStr(actual_room)&& + !IsEmptyStr(actual_host))) { pprintf("(really "); - if (strlen(actual_user)>0) pprintf("<%s> ", actual_user); - if (strlen(actual_room)>0) pprintf("in <%s> ", actual_room); - if (strlen(actual_host)>0) pprintf("from <%s> ", actual_host); + if (!IsEmptyStr(actual_user)) pprintf("<%s> ", actual_user); + if (!IsEmptyStr(actual_room)) pprintf("in <%s> ", actual_room); + if (!IsEmptyStr(actual_host)) pprintf("from <%s> ", actual_host); pprintf(")\n"); } pprintf("\n"); } else { - if (isidle == 0) { - if (extract_int(buf, 0) == last_session) { - pprintf(" "); - } else { + 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); - pprintf("%-3s ", flags); + roomname[20] = 0; + pprintf("%-20s", roomname); + + if (screenwidth >= 80) { + pprintf(" "); + 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); + } + } + else { + pprintf(" "); + } + pprintf(" "); + color(BRIGHT_CYAN); + fromhost[24] = '\0'; + pprintf("%-24s", fromhost); + } + pprintf("\n"); color(DIM_WHITE); - pprintf("%-3d ", extract_int(buf, 0)); - } - 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); - } + } } } } @@ -910,7 +1404,7 @@ int main(int argc, char **argv) { int a, b, mcmd; char aaa[100], bbb[100];/* general purpose variables */ - char argbuf[32]; /* command line buf */ + char argbuf[64]; /* command line buf */ char nonce[NONCE_SIZE]; char *telnet_client_host = NULL; char *sptr, *sptr2; /* USed to extract the nonce */ @@ -918,10 +1412,39 @@ int main(int argc, char **argv) int stored_password = 0; char password[SIZ]; struct ctdlipcmisc chek; - struct usersupp *myself = NULL; + struct ctdluser *myself = NULL; CtdlIPC* ipc; /* Our server connection */ int r; /* IPC result code */ - + int rv = 0; /* fetch but ignore syscall return value to suppress warnings */ + + int relh=0; + int home=0; + char relhome[PATH_MAX]=""; + char ctdldir[PATH_MAX]=CTDLDIR; + int lp; +#ifdef HAVE_BACKTRACE + eCrashParameters params; +// eCrashSymbolTable symbol_table; +#endif + calc_dirs_n_files(relh, home, relhome, ctdldir, 0); + +#ifdef HAVE_BACKTRACE + bzero(¶ms, sizeof(params)); + params.filename = file_pid_paniclog; +// panic_fd=open(file_pid_paniclog, O_APPEND|O_CREAT|O_DIRECT); + params.filep = fopen(file_pid_paniclog, "a+"); + params.debugLevel = ECRASH_DEBUG_VERBOSE; + params.dumpAllThreads = TRUE; + params.useBacktraceSymbols = 1; +/// BuildSymbolTable(&symbol_table); +// params.symbolTable = &symbol_table; + params.signals[0]=SIGSEGV; + params.signals[1]=SIGILL; + params.signals[2]=SIGBUS; + params.signals[3]=SIGABRT; + + eCrash_Init(¶ms); +#endif setIPCDeathHook(screen_delete); setIPCErrorPrintf(err_printf); setCryptoStatusHook(statusHook); @@ -935,10 +1458,11 @@ int main(int argc, char **argv) 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 */ #ifdef SIGWINCH @@ -991,8 +1515,8 @@ int main(int argc, char **argv) if (!strcmp(argv[a], "-p")) { struct stat st; - if (chdir(BBSDIR) < 0) { - perror("can't change to " BBSDIR); + if (chdir(CTDLDIR) < 0) { + perror("can't change to " CTDLDIR); logoff(NULL, 3); } @@ -1002,7 +1526,7 @@ 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(file_citadel_config, &st) < 0) { perror("couldn't stat citadel.config"); logoff(NULL, 3); } @@ -1022,9 +1546,14 @@ int main(int argc, char **argv) argc = shift(argc, argv, a, 1); } } + screen_new(); +#ifdef __CYGWIN__ + newprompt("Connect to (return for local server): ", hostbuf, 64); +#endif + sln_printf("Attaching to server... \r"); sln_flush(); ipc = CtdlIPC_new(argc, argv, hostbuf, portbuf); @@ -1038,7 +1567,7 @@ int main(int argc, char **argv) #endif ipc_for_signal_handlers = ipc; /* KLUDGE cover your eyes */ - CtdlIPC_getline(ipc, aaa); + CtdlIPC_chat_recv(ipc, aaa); if (aaa[0] != '2') { scr_printf("%s\n", &aaa[4]); logoff(ipc, atoi(aaa)); @@ -1062,7 +1591,7 @@ int main(int argc, char **argv) { sptr2++; *sptr2 = '\0'; - strncpy(nonce, sptr, NONCE_SIZE); + strncpy(nonce, sptr, (size_t)NONCE_SIZE); } } @@ -1078,11 +1607,11 @@ int main(int argc, char **argv) #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); + scr_printf("%-24s\n%s\n%s\n", ipc->ServInfo.software, ipc->ServInfo.humannode, + ipc->ServInfo.site_location); scr_flush(); - status_line(serv_info.serv_humannode, serv_info.serv_bbs_city, NULL, + status_line(ipc->ServInfo.humannode, ipc->ServInfo.site_location, NULL, secure, -1); screenwidth = 80; /* default screen dimensions */ @@ -1096,7 +1625,7 @@ int main(int argc, char **argv) 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) { + if (!IsEmptyStr(fullname)) { r = CtdlIPCTryLogin(ipc, fullname, aaa); if (r / 100 == 3) { if (*nonce) { @@ -1119,7 +1648,7 @@ int main(int argc, char **argv) termn8 = 0; newnow = 0; do { - if (strlen(rc_username) > 0) { + if (!IsEmptyStr(rc_username)) { strcpy(fullname, rc_username); } else { newprompt("Enter your name: ", fullname, 29); @@ -1131,7 +1660,7 @@ int main(int argc, char **argv) } while ( (!strcasecmp(fullname, "bbs")) || (!strcasecmp(fullname, "new")) - || (strlen(fullname) == 0)); + || (IsEmptyStr(fullname))); if (!strcasecmp(fullname, "off")) { mcmd = 29; @@ -1143,7 +1672,7 @@ int main(int argc, char **argv) goto NEWUSR; /* password authentication */ - if (strlen(rc_password) > 0) { + if (!IsEmptyStr(rc_password)) { strcpy(password, rc_password); } else { newprompt("\rPlease enter your password: ", password, -19); @@ -1163,14 +1692,21 @@ int main(int argc, char **argv) goto PWOK; } scr_printf("<< wrong password >>\n"); - if (strlen(rc_password) > 0) - logoff(ipc, 0); + if (!IsEmptyStr(rc_password)) + logoff(ipc, 2); goto GSTA; -NEWUSR: if (strlen(rc_password) == 0) { - scr_printf("No record. Enter as new user? "); - if (yesno() == 0) +NEWUSR: if (IsEmptyStr(rc_password)) { + scr_printf("'%s' not found.\n", fullname); + scr_printf("Type 'off' if you would like to exit.\n"); + if (ipc->ServInfo.newuser_disabled == 1) { goto GSTA; + } + scr_printf("Do you want to create a new user account called '%s'? ", + fullname); + if (yesno() == 0) { + goto GSTA; + } } r = CtdlIPCCreateUser(ipc, fullname, 1, aaa); @@ -1215,8 +1751,8 @@ NEWUSR: if (strlen(rc_password) == 0) { if (b > 1) 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 (!IsEmptyStr(rc_gotmail_cmd)) { + rv = system(rc_gotmail_cmd); } } if ((axlevel >= 6) && (chek.needvalid > 0)) { @@ -1232,9 +1768,9 @@ NEWUSR: if (strlen(rc_password) == 0) { * 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. @@ -1257,19 +1793,19 @@ NEWUSR: if (strlen(rc_password) == 0) { check_screen_dims(); #endif - set_floor_mode(); - + set_floor_mode(ipc); /* Enter the lobby */ dotgoto(ipc, "_BASEROOM_", 1, 0); /* Main loop for the system... user is logged in. */ + free(uglist[0]); 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 { @@ -1285,71 +1821,71 @@ NEWUSR: if (strlen(rc_password) == 0) { formout(ipc, "help"); break; case 4: - entmsg(ipc, 0, 0); + entmsg(ipc, 0, ((userflags & US_EXTEDIT) ? 2 : 0), 0); break; case 36: - entmsg(ipc, 0, 1); + entmsg(ipc, 0, 1, 0); break; case 46: - entmsg(ipc, 0, 2); + entmsg(ipc, 0, 2, 0); 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); - CtdlIPC_putline(ipc, bbb); - CtdlIPC_getline(ipc, aaa); - if (strncmp("200", aaa, 3)) - scr_printf("\n%s\n", aaa); - else - entmsg(ipc, 0, 0); - break; - case 5: + entmsg(ipc, 0, ((userflags & US_EXTEDIT) ? 2 : 0), 1); + break; + case 5: /* oto */ updatels(ipc); gotonext(ipc); break; - case 47: - if (!rc_alt_semantics) + case 47: /* bandon */ + if (!rc_alt_semantics) { updatelsa(ipc); + } gotonext(ipc); break; - case 90: + case 90: /* <.A>bandon */ if (!rc_alt_semantics) updatelsa(ipc); dotgoto(ipc, argbuf, 0, 0); break; - case 58: + case 58: /* ail */ updatelsa(ipc); dotgoto(ipc, "_MAIL_", 1, 0); break; case 20: - updatels(ipc); - dotgoto(ipc, argbuf, 0, 0); + if (!IsEmptyStr(argbuf)) { + updatels(ipc); + dotgoto(ipc, argbuf, 0, 0); + } break; case 52: - if (rc_alt_semantics) - updatelsa(ipc); - dotgoto(ipc, argbuf, 0, 0); + if (!IsEmptyStr(argbuf)) { + if (rc_alt_semantics) { + updatelsa(ipc); + } + dotgoto(ipc, argbuf, 0, 0); + } break; - case 95: /* what exactly is the numbering scheme supposed to be anyway? */ + 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(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); @@ -1423,8 +1959,9 @@ NEWUSR: if (strlen(rc_password) == 0) { break; case 29: case 30: - if (!rc_alt_semantics) + if (!rc_alt_semantics) { updatels(ipc); + } termn8 = 1; break; case 48: @@ -1449,19 +1986,19 @@ NEWUSR: if (strlen(rc_password) == 0) { enternew(ipc, "roomname", aaa, 20); r = CtdlIPCChangeRoomname(ipc, aaa, bbb); if (r / 100 != 2) - scr_printf("\n%s\n", aaa); + scr_printf("\n%s\n", bbb); break; case 76: enternew(ipc, "hostname", aaa, 25); r = CtdlIPCChangeHostname(ipc, aaa, bbb); if (r / 100 != 2) - scr_printf("\n%s\n", aaa); + scr_printf("\n%s\n", bbb); break; case 77: enternew(ipc, "username", aaa, 32); r = CtdlIPCChangeUsername(ipc, aaa, bbb); if (r / 100 != 2) - scr_printf("\n%s\n", aaa); + scr_printf("\n%s\n", bbb); break; case 35: @@ -1547,8 +2084,9 @@ NEWUSR: if (strlen(rc_password) == 0) { break; case 6: - if (rc_alt_semantics) + if (rc_alt_semantics) { updatelsa(ipc); + } gotonext(ipc); break; @@ -1559,12 +2097,12 @@ NEWUSR: if (strlen(rc_password) == 0) { case 2: if (ipc->isLocal) { screen_reset(); - sttybbs(SB_RESTORE); + stty_ctdl(SB_RESTORE); snprintf(aaa, sizeof aaa, "USERNAME=\042%s\042; export USERNAME;" "exec ./subsystem %ld %d %d", fullname, usernum, screenwidth, axlevel); ka_system(aaa); - sttybbs(SB_NO_INTR); + stty_ctdl(SB_NO_INTR); screen_set(); } else { scr_printf("*** Can't run doors when server is not local.\n"); @@ -1609,12 +2147,12 @@ NEWUSR: if (strlen(rc_password) == 0) { case 37: enter_config(ipc, 0); - set_floor_mode(); + set_floor_mode(ipc); break; case 59: enter_config(ipc, 3); - set_floor_mode(); + set_floor_mode(ipc); break; case 60: @@ -1650,7 +2188,11 @@ NEWUSR: if (strlen(rc_password) == 0) { break; case 25: - edituser(ipc); + edituser(ipc, 25); + break; + + case 96: + edituser(ipc, 96); break; case 8: @@ -1680,10 +2222,6 @@ NEWUSR: if (strlen(rc_password) == 0) { deletefile(ipc); break; - case 53: - netsendfile(ipc); - break; - case 54: movefile(ipc); break; @@ -1692,14 +2230,102 @@ NEWUSR: if (strlen(rc_password) == 0) { page_user(ipc); break; + case 110: /* <+> Next room */ + gotoroomstep(ipc, 1, 0); + break; + + case 111: /* <-> Previous room */ + gotoroomstep(ipc, 0, 0); + break; + + case 112: /* <>> Next floor */ + gotofloorstep(ipc, 1, GF_GOTO); + break; + + case 113: /* <<> Previous floor */ + gotofloorstep(ipc, 0, GF_GOTO); + break; + + case 116: /* <.> skip to <+> Next room */ + gotoroomstep(ipc, 1, 1); + break; + + case 117: /* <.> skip to <-> Previous room */ + gotoroomstep(ipc, 0, 1); + break; + + case 118: /* <.> skip to <>> Next floor */ + gotofloorstep(ipc, 1, GF_SKIP); + break; + + case 119: /* <.> skip to <<> Previous floor */ + gotofloorstep(ipc, 0, GF_SKIP); + break; + + case 114: + read_config(ipc); + break; + + case 115: + system_info(ipc); + break; + + case 120: /* .KAnonymous */ + dotknown(ipc, 0, NULL); + break; + + case 121: /* .KDirectory */ + dotknown(ipc, 1, NULL); + break; + + case 122: /* .KMatch */ + dotknown(ipc, 2, argbuf); + break; + + case 123: /* .KpreferredOnly */ + dotknown(ipc, 3, NULL); + break; + + case 124: /* .KPrivate */ + dotknown(ipc, 4, NULL); + break; + + case 125: /* .KRead only */ + dotknown(ipc, 5, NULL); + break; + + case 126: /* .KShared */ + dotknown(ipc, 6, NULL); + break; + + case 127: /* Configure POP3 aggregation */ + do_pop3client_configuration(ipc); + break; + + case 128: /* Configure XML/RSS feed retrieval */ + do_rssclient_configuration(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, 0); + break; + } } /* end switch */ } while (termn8 == 0); TERMN8: scr_printf("%s logged out.", fullname); + termn8 = 0; color(ORIGINAL_PAIR); scr_printf("\n"); - while (march != NULL) { - remove_march(march->march_name, 0); + while (marchptr != NULL) { + remove_march(marchptr->march_name, 0); } if (mcmd == 30) { sln_printf("\n\nType 'off' to disconnect, or next user...\n"); @@ -1707,10 +2333,16 @@ TERMN8: scr_printf("%s logged out.", fullname); CtdlIPCLogout(ipc); if ((mcmd == 29) || (mcmd == 15)) { screen_delete(); - sttybbs(SB_RESTORE); + stty_ctdl(SB_RESTORE); formout(ipc, "goodbye"); logoff(ipc, 0); } + /* Free the ungoto list */ + for (lp = 0; lp < uglistsize; lp++) { + free(uglist[lp]); + } + uglistsize = 0; goto GSTA; } /* end main() */ +