/*
* Main source module for the client program.
*
- * Copyright (c) 1987-2009 by the citadel.org team
+ * Copyright (c) 1987-2012 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 open source software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * 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"
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];
-int screenwidth;
-int screenheight;
unsigned room_flags;
unsigned room_flags2;
int entmsg_ok = 0;
long highest_msg_read; /* used for <A>bandon room cmd */
long maxmsgnum; /* used for <G>oto */
char sigcaught = 0;
-char have_xterm = 0; /* are we running on an xterm? */
char rc_username[USERNAME_SIZE];
char rc_password[32];
char hostbuf[SIZ];
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
*/
char *pop_march(int desired_floor, struct march *_march)
{
static char TheRoom[ROOMNAMELEN];
- int TheFloor = 0;
- int TheOrder = 32767;
int TheWeight = 0;
int weight;
struct march *mptr = NULL;
if (weight > TheWeight) {
TheWeight = weight;
strcpy(TheRoom, mptr->march_name);
- TheFloor = mptr->march_floor;
- TheOrder = mptr->march_order;
}
}
return (TheRoom);
color(DIM_WHITE);
if (!IsEmptyStr(rc_gotmail_cmd)) {
rv = system(rc_gotmail_cmd);
+ if (rv)
+ scr_printf("*** failed to check for mail calling %s Reason %d.\n",
+ rc_gotmail_cmd, rv);
}
}
free(room);
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 (marchptr == NULL) {
- r = CtdlIPCKnownRooms(ipc, SubscribedRoomsWithNewMessages,
- AllFloors, &marchptr, buf);
+ 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
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) {
if (mode == 0) { /* not skipping */
updatels(ipc);
- } else {
- if (rc_alt_semantics) {
- updatelsa(ipc);
- }
}
/* Free the room list */
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])) {
+ if (!IsEmptyStr(editor_path)) {
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);
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);
+ 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);
resp = NULL;
/* get high message# */
- ret = CtdlIPCGenericCommand(ipc, "MRTG|messages", NULL, 0, &resp, &bytes, buf);
+ CtdlIPCGenericCommand(ipc, "MRTG|messages", NULL, 0, &resp, &bytes, buf);
mrtg_himessage = extract_long(resp, 0);
free(resp);
resp = NULL;
}
-/*
- * Figure out the physical screen dimensions, if we can
- * WARNING: this is now called from a signal handler!
- */
-void check_screen_dims(void)
-{
-#ifdef TIOCGWINSZ
- struct {
- unsigned short height; /* rows */
- unsigned short width; /* columns */
- unsigned short xpixels;
- unsigned short ypixels; /* pixels */
- } xwinsz;
-
- if (have_xterm) { /* dynamically size screen if on an xterm */
- if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) {
- if (xwinsz.height)
- screenheight = (int) xwinsz.height;
- if (xwinsz.width)
- screenwidth = (int) xwinsz.width;
- }
- }
-#endif
-}
-
-
/*
* set floor mode depending on client, server, and user settings
*/
/*
- * Record compare function for SortOnlineUsers()
+ * Session username compare function for SortOnlineUsers()
+ */
+int rwho_username_cmp(const void *rec1, const void *rec2) {
+ char *u1, *u2;
+
+ u1 = strchr(rec1, '|');
+ u2 = strchr(rec2, '|');
+
+ return strcasecmp( (u1?++u1:"") , (u2?++u2:"") );
+}
+
+
+/*
+ * Idle time compare function for SortOnlineUsers()
*/
int idlecmp(const void *rec1, const void *rec2) {
time_t i1, i2;
* 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.
+ *
+ * If 'condense' is nonzero, multiple sessions for the same user will be
+ * combined into one for brevity.
*/
-char *SortOnlineUsers(char *listing) {
+char *SortOnlineUsers(char *listing, int condense) {
int rows;
char *sortbuf;
char *retbuf;
memcpy(&sortbuf[i*SIZ], buf, (size_t)SIZ);
}
- /* Do the sort */
+ /* Sort by idle time */
qsort(sortbuf, rows, SIZ, idlecmp);
+ /* Combine multiple sessions for the same user */
+ if (condense) {
+ qsort(sortbuf, rows, SIZ, rwho_username_cmp);
+ if (rows > 1) for (i=1; i<rows; ++i) if (i>0) {
+ char u1[USERNAME_SIZE];
+ char u2[USERNAME_SIZE];
+ extract_token(u1, &sortbuf[(i-1)*SIZ], 1, '|', sizeof u1);
+ extract_token(u2, &sortbuf[i*SIZ], 1, '|', sizeof u2);
+ if (!strcasecmp(u1, u2)) {
+ memcpy(&sortbuf[i*SIZ], &sortbuf[(i+1)*SIZ], (rows-i-1)*SIZ);
+ --rows;
+ --i;
+ }
+ }
+
+ qsort(sortbuf, rows, SIZ, idlecmp); /* idle sort again */
+ }
+
/* Copy back to a \n delimited list */
strcpy(retbuf, "");
for (i=0; i<rows; ++i) {
- strcat(retbuf, &sortbuf[i*SIZ]);
- if (i<(rows-1)) strcat(retbuf, "\n");
+ if (!IsEmptyStr(&sortbuf[i*SIZ])) {
+ strcat(retbuf, &sortbuf[i*SIZ]);
+ if (i<(rows-1)) strcat(retbuf, "\n");
+ }
}
- free(listing);
- free(sortbuf);
+ free(listing);
+ free(sortbuf);
return(retbuf);
}
scr_printf("\n");
}
r = CtdlIPCOnlineUsers(ipc, &listing, &timenow, buf);
- listing = SortOnlineUsers(listing);
+ listing = SortOnlineUsers(listing, (!longlist));
if (r / 100 == 1) {
while (!IsEmptyStr(listing)) {
int isidle = 0;
static void statusHook(char *s) {
scr_printf(s);
- scr_flush();
}
/*
char *telnet_client_host = NULL;
char *sptr, *sptr2; /* USed to extract the nonce */
char hexstring[MD5_HEXSTRING_SIZE];
- int stored_password = 0;
char password[SIZ];
struct ctdlipcmisc chek;
struct ctdluser *myself = NULL;
screen_new();
+ /* Get screen dimensions. First we go to a default of 80x24.
+ * Then attempt to read the actual screen size from the terminal.
+ */
+ check_screen_dims();
+
#ifdef __CYGWIN__
newprompt("Connect to (return for local server): ", hostbuf, 64);
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();
- 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 */
if (r / 100 == 2) {
load_user_info(aaa);
- stored_password = 1;
goto PWOK;
} else {
set_stored_password(hostbuf, portbuf, "", "");
if (!IsEmptyStr(rc_password)) {
strcpy(password, rc_password);
} else {
- newprompt("\rPlease enter your password: ", password, -19);
+ newprompt("\rPlease enter your password: ", password, -(SIZ-1));
}
if (*nonce) {
color(DIM_WHITE);
if (!IsEmptyStr(rc_gotmail_cmd)) {
rv = system(rc_gotmail_cmd);
+ if (rv)
+ scr_printf("*** failed to check for mail calling %s Reason %d.\n",
+ rc_gotmail_cmd, rv);
+
}
}
if ((axlevel >= AxAideU) && (chek.needvalid > 0)) {
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.
- * However, if we're running on an xterm, all this stuff is
- * irrelevant because we're going to dynamically size the screen
- * during the session.
- */
- screenwidth = 80;
- screenheight = 24;
r = CtdlIPCGetConfig(ipc, &myself, aaa);
- if (getenv("TERM") != NULL)
- if (!strcmp(getenv("TERM"), "xterm")) {
- have_xterm = 1;
- }
- check_screen_dims();
-
set_floor_mode(ipc);
/* Enter the lobby */
mcmd = getcmd(ipc, argbuf); /* Get keyboard command */
#ifdef TIOCGWINSZ
- check_screen_dims(); /* if xterm, get screen size */
+ check_screen_dims(); /* get screen size */
#endif
if (termn8 == 0)
gotonext(ipc);
break;
case 47: /* <A>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: /* <M>ail */
break;
case 52:
if (!IsEmptyStr(argbuf)) {
- if (rc_alt_semantics) {
- updatelsa(ipc);
- }
dotgoto(ipc, argbuf, 0, 0);
}
break;
break;
case 29:
case 30:
- if (!rc_alt_semantics) {
- updatels(ipc);
- }
+ updatels(ipc);
termn8 = 1;
break;
case 48:
case 15:
scr_printf("Are you sure (y/n)? ");
if (yesno() == 1) {
- if (!rc_alt_semantics)
- updatels(ipc);
+ updatels(ipc);
a = 0;
termn8 = 1;
}
scr_printf("All users will be disconnected! "
"Really terminate the server? ");
if (yesno() == 1) {
- if (!rc_alt_semantics)
- updatels(ipc);
+ updatels(ipc);
r = CtdlIPCTerminateServerNow(ipc, aaa);
scr_printf("%s\n", aaa);
if (r / 100 == 2) {
break;
case 6:
- if (rc_alt_semantics) {
- updatelsa(ipc);
- }
gotonext(ipc);
break;
do_internet_configuration(ipc);
break;
- case 83:
- check_message_base(ipc);
- break;
-
case 84:
quiet_mode(ipc);
break;
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;
- }
+ default:
+ break;
} /* end switch */
} while (termn8 == 0);