uedit.c 57.1 KB
Newer Older
1 2 3 4 5 6
/* Synchronet for *nix user editor */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
rswindell's avatar
rswindell committed
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *																			*
 * 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 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include <sys/types.h>
#include <time.h>
#ifdef __QNX__
#include <string.h>
#endif
#include <stdio.h>
28
#ifdef __unix__
29
#include <unistd.h>
30
#include <sys/time.h>
deuce's avatar
deuce committed
31
#include <signal.h>
32
#endif
deuce's avatar
deuce committed
33

34
#include "ciolib.h"
35 36
#include "curs_cio.h"
#undef OK
37 38
#include "sbbs.h"

39 40 41 42 43 44 45 46 47 48 49 50 51
#include "genwrap.h"
#include "uifc.h"
#include "sbbsdefs.h"
#include "genwrap.h"	/* stricmp */
#include "dirwrap.h"	/* lock/unlock/sopen */
#include "filewrap.h"	/* lock/unlock/sopen */
#include "sbbs_ini.h"	/* INI parsing */
#include "scfglib.h"	/* SCFG files */
#include "ars_defs.h"	/* needed for SCFG files */
#include "userdat.h"	/* getnodedat() */

#define CTRL(x) (x&037)

deuce's avatar
deuce committed
52 53 54 55 56
struct user_list {
	char	info[MAX_OPLN];
	int		usernum;
};

57 58 59 60
/********************/
/* Global Variables */
/********************/
uifcapi_t uifc; /* User Interface (UIFC) Library API */
deuce's avatar
deuce committed
61 62
char YesStr[]="Yes";
char NoStr[]="No";
63

64 65
#define GETUSERDAT(cfg, user)	if (getuserdat(cfg, user) != 0) { uifc.msg("Error reading user database!"); return -1; }

66 67 68 69 70
/*
 * Find the first occurrence of find in s, ignore case.
 * From FreeBSD src/lib/libc/string/strcasestr.c
 */
char *
71
strcasestr(const char *s, const char *find)
72 73 74 75 76 77 78 79 80 81 82 83
{
	char c, sc;
	size_t len;

	if ((c = *find++) != 0) {
		c = tolower((unsigned char)c);
		len = strlen(find);
		do {
			do {
				if ((sc = *s++) == 0)
					return (NULL);
			} while ((char)tolower((unsigned char)sc) != c);
84
		} while (strnicmp(s, find, len) != 0);
85 86 87 88 89
		s--;
	}
	return ((char *)s);
}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
int lprintf(char *fmt, ...)
{
	va_list argptr;
	char sbuf[1024];
	int	len;

	va_start(argptr,fmt);
	len=vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
	sbuf[sizeof(sbuf)-1]=0;
	va_end(argptr);
	uifc.msg(sbuf);
	return(len);
}

void bail(int code)
{
    if(code) {
        puts("\nHit a key...");
deuce's avatar
deuce committed
108
        getch();
109 110 111 112 113 114 115 116 117 118 119 120
	}
    uifc.bail();

    exit(code);
}

void allocfail(uint size)
{
    printf("\7Error allocating %u bytes of memory.\n",size);
    bail(1);
}

deuce's avatar
deuce committed
121 122 123 124 125 126 127 128 129
int confirm(char *prompt)
{
	int i=0;
	char *opt[3]={
		 YesStr
		,NoStr
		,""
	};

deuce's avatar
deuce committed
130
	i=uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&i,0,prompt,opt);
deuce's avatar
deuce committed
131 132
	if(i==0)
		return(1);
133 134 135
	if(i==-1)
		return(-1);
	return(0);
deuce's avatar
deuce committed
136 137
}

deuce's avatar
deuce committed
138 139 140
/****************************************************************************/
/* Takes a string in the format HH:MM:SS and returns in seconds             */
/****************************************************************************/
Rob Swindell's avatar
Rob Swindell committed
141
time_t strtosec(char *str)
deuce's avatar
deuce committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
{
	char *p1;
	char *p2;
	long int hour=0;
	long int min=0;
	long int sec2=0;
	time_t	sec=0;

	hour=strtol(str,&p1,10);
	if(hour<0 || hour > 24)
		return(-1);
	if(*p1==':') {
		p1++;
		min=strtol(p1,&p2,10);
		if(min<0 || min > 59)
			return(-1);
		if(*p2==':') {
			p2++;
			sec2=strtol(p2,&p1,10);
			if(sec2 < 0 || sec2 > 59)
				return(-1);
		}
	}

	sec=hour*60*60;
	sec+=min*60;
	sec+=sec2;
	return(sec);
}

deuce's avatar
deuce committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
char *geteditor(char *edit)
{
	if(getenv("EDITOR")==NULL && (getenv("VISUAL")==NULL || getenv("DISPLAY")==NULL))
#ifdef __unix__
		strcpy(edit,"vi");
#else
		strcpy(edit,"notepad");
#endif
	else {
		if(getenv("DISPLAY")!=NULL && getenv("VISUAL")!=NULL)
			strcpy(edit,getenv("VISUAL"));
		else
			strcpy(edit,getenv("EDITOR"));
	}
	return(edit);
}

int do_cmd(char *cmd)
{
	int i;

193 194 195
#ifdef HAS_CURSES
	if(cio_api.mode == CIOLIB_MODE_CURSES || cio_api.mode == CIOLIB_MODE_CURSES_IBM)
		endwin();
deuce's avatar
deuce committed
196 197
#endif
	i=system(cmd);
198 199 200
#ifdef HAS_CURSES
	if(cio_api.mode == CIOLIB_MODE_CURSES || cio_api.mode == CIOLIB_MODE_CURSES_IBM)
		refresh();
deuce's avatar
deuce committed
201 202 203 204
#endif
	return(i);
}

deuce's avatar
deuce committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218
/* Edit terminal settings
 *       Auto-Detect
 *       Extended ASCII
 *       ANSI
 *       Color
 *       RIP
 *       WIP
 *       Pause
 *       Hot Keys
 *       Spinning Cursor
 *       Number of Rows
 */
int edit_terminal(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
219 220 221 222
	int 	i,j;
	char 	**opt;
	char	str[256];

223 224 225
	if((opt=(char **)alloca(sizeof(char *)*(11+1)))==NULL)
		allocfail(sizeof(char *)*(11+1));
	for(i=0;i<11;i++)
226
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
227 228 229 230
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
231
		GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
232
		i=0;
233 234 235 236 237 238 239 240 241
		sprintf(opt[i++],"Auto-detect      %s",user->misc & AUTOTERM?"Yes":"No");
		sprintf(opt[i++],"Extended ASCII   %s",user->misc & NO_EXASCII?"No":"Yes");
		sprintf(opt[i++],"ANSI             %s",user->misc & ANSI?"Yes":"No");
		sprintf(opt[i++],"Color            %s",user->misc & COLOR?"Yes":"No");
		sprintf(opt[i++],"RIP              %s",user->misc & RIP?"Yes":"No");
		sprintf(opt[i++],"WIP              %s",user->misc & WIP?"Yes":"No");
		sprintf(opt[i++],"Pause            %s",user->misc & UPAUSE?"Yes":"No");
		sprintf(opt[i++],"Hot Keys         %s",user->misc & COLDKEYS?"No":"Yes");
		sprintf(opt[i++],"Spinning Cursor  %s",user->misc & SPIN?"Yes":"No");
242 243
		sprintf(str,"%u",user->cols);
		sprintf(opt[i++],"Screen Columns   %s",user->cols?str:"Auto");
deuce's avatar
deuce committed
244
		sprintf(str,"%u",user->rows);
245
		sprintf(opt[i++],"Screen Rows      %s",user->rows?str:"Auto");
246
		opt[i] = NULL;
deuce's avatar
deuce committed
247 248 249 250 251 252 253
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Terminal Settings",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* Auto-detect */
				user->misc ^= AUTOTERM;
deuce's avatar
deuce committed
254
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
255 256 257 258
				break;
			case 1:
				/* EX-ASCII */
				user->misc ^= NO_EXASCII;
deuce's avatar
deuce committed
259
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
260 261 262 263
				break;
			case 2:
				/* ANSI */
				user->misc ^= ANSI;
deuce's avatar
deuce committed
264
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
265 266 267 268
				break;
			case 3:
				/* Colour */
				user->misc ^= COLOR;
deuce's avatar
deuce committed
269
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
270 271 272 273
				break;
			case 4:
				/* RIP */
				user->misc ^= RIP;
deuce's avatar
deuce committed
274
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
275 276 277 278
				break;
			case 5:
				/* WIP */
				user->misc ^= WIP;
deuce's avatar
deuce committed
279
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
280 281 282 283
				break;
			case 6:
				/* Pause */
				user->misc ^= UPAUSE;
deuce's avatar
deuce committed
284
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
285 286 287 288
				break;
			case 7:
				/* Hot Keys */
				user->misc ^= COLDKEYS;
deuce's avatar
deuce committed
289
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
290 291 292 293
				break;
			case 8:
				/* Spinning Cursor */
				user->misc ^= SPIN;
deuce's avatar
deuce committed
294
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
295 296
				break;
			case 9:
297 298 299 300 301 302 303 304 305
				/* Columns */
				SAFEPRINTF(str,"%u",user->cols);
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0, "Columns (0=auto-detect)", str, LEN_COLS, K_EDIT|K_NUMBER);
				if(uifc.changes) {
					user->cols=strtoul(str,NULL,10);
					putuserrec(cfg,user->number,U_COLS,0,ultoa(user->cols,str,10));
				}
				break;
			case 10:
deuce's avatar
deuce committed
306
				/* Rows */
307 308
				SAFEPRINTF(str,"%u",user->rows);
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0, "Rows (0=auto-detect)", str, LEN_ROWS, K_EDIT|K_NUMBER);
deuce's avatar
deuce committed
309 310
				if(uifc.changes) {
					user->rows=strtoul(str,NULL,10);
311
					putuserrec(cfg,user->number,U_ROWS,0,ultoa(user->rows,str,10));
deuce's avatar
deuce committed
312 313 314
				}
				break;
		}
deuce's avatar
deuce committed
315
	}
deuce's avatar
deuce committed
316 317 318 319 320 321 322 323 324 325 326 327
	return(0);
}

/* Edit Logon settings
 *       Ask for New Message Scan
 *       Ask for Your Message Scan
 *       Remember Current Sub-board
 *       Quiet Mode (Q exempt)
 *       Auto-Login via IP (V exempt)
 */
int edit_logon(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
328 329
	int 	i,j;
	char 	**opt;
deuce's avatar
deuce committed
330
	char	str[256];
deuce's avatar
deuce committed
331

332 333 334
	if((opt=(char **)alloca(sizeof(char *)*(5+1)))==NULL)
		allocfail(sizeof(char *)*(5+1));
	for(i=0;i<(5+1);i++)
335
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
336 337 338 339 340
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
		i=0;
341
		GETUSERDAT(cfg,user);
342 343 344 345
		sprintf(opt[i++],"Ask for New Message Scan     %s",user->misc & ASK_NSCAN?"Yes":"No");
		sprintf(opt[i++],"Ask for Your Message Scan    %s",user->misc & ASK_SSCAN?"Yes":"No");
		sprintf(opt[i++],"Remember Current Sub         %s",user->misc & CURSUB?"Yes":"No");
		sprintf(opt[i++],"Quiet Mode  (Q exempt)       %s",user->misc & QUIET?"Yes":"No");
deuce's avatar
deuce committed
346 347 348 349 350 351 352 353 354
		sprintf(opt[i++],"Auto-Login via IP (V exempt) %s",user->misc & AUTOLOGON?"Yes":"No");
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Logon Settings",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* Ask New MSG Scan */
				user->misc ^= ASK_NSCAN;
deuce's avatar
deuce committed
355
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
356 357 358 359
				break;
			case 1:
				/* Ask YOUR MSG scan */
				user->misc ^= ASK_SSCAN;
deuce's avatar
deuce committed
360
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
361 362 363 364
				break;
			case 2:
				/* Remember Curr Sub */
				user->misc ^= CURSUB;
deuce's avatar
deuce committed
365
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
366 367 368 369
				break;
			case 3:
				/* Quiet Mode */
				user->misc ^= QUIET;
deuce's avatar
deuce committed
370
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
371 372 373 374
				break;
			case 4:
				/* Auto-Login by IP */
				user->misc ^= AUTOLOGON;
deuce's avatar
deuce committed
375
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
376 377 378
				break;
		}
	}
deuce's avatar
deuce committed
379 380 381 382 383 384 385 386 387 388 389 390
	return(0);
}

/* Edit Chat Settings
 *       Multinode Chat Echo
 *       Multinode Chat Actions
 *       Available for Internode chat
 *       Multinode Activity Alerts
 *       Split-screen Private Chat
 */
int edit_chat(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
391 392
	int 	i,j;
	char 	**opt;
deuce's avatar
deuce committed
393
	char	str[256];
deuce's avatar
deuce committed
394

395 396 397
	if((opt=(char **)alloca(sizeof(char *)*(5+1)))==NULL)
		allocfail(sizeof(char *)*(5+1));
	for(i=0;i<(5+1);i++)
398
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
399 400 401 402 403
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
		i=0;
404
		GETUSERDAT(cfg,user);
405 406 407
		sprintf(opt[i++],"Chat Echo                  %s",user->chat & CHAT_ECHO?"Yes":"No");
		sprintf(opt[i++],"Chat Actions               %s",user->chat & CHAT_ACTION?"Yes":"No");
		sprintf(opt[i++],"Available for Chat         %s",user->chat & CHAT_NOPAGE?"No":"Yes");
deuce's avatar
deuce committed
408
		sprintf(opt[i++],"Activity Alerts            %s",user->chat & CHAT_NOACT?"No":"Yes");
409
		sprintf(opt[i++],"Split-Screen Private Chat  %s",user->chat & CHAT_SPLITP?"Yes":"No");
deuce's avatar
deuce committed
410 411 412 413 414 415 416 417
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Chat Settings",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* Chat Echo */
				user->chat ^= CHAT_ECHO;
deuce's avatar
deuce committed
418
				putuserrec(cfg,user->number,U_CHAT,8,ultoa(user->chat,str,16));
deuce's avatar
deuce committed
419 420 421 422
				break;
			case 1:
				/* Chat Actions */
				user->chat ^= CHAT_ACTION;
deuce's avatar
deuce committed
423
				putuserrec(cfg,user->number,U_CHAT,8,ultoa(user->chat,str,16));
deuce's avatar
deuce committed
424 425 426 427
				break;
			case 2:
				/* Availabe for Chat */
				user->chat ^= CHAT_NOPAGE;
deuce's avatar
deuce committed
428
				putuserrec(cfg,user->number,U_CHAT,8,ultoa(user->chat,str,16));
deuce's avatar
deuce committed
429 430 431 432
				break;
			case 3:
				/* Activity Alerts */
				user->chat ^= CHAT_NOACT;
deuce's avatar
deuce committed
433
				putuserrec(cfg,user->number,U_CHAT,8,ultoa(user->chat,str,16));
deuce's avatar
deuce committed
434 435 436 437
				break;
			case 4:
				/* Split-Screen Priv Chat */
				user->chat ^= CHAT_SPLITP;
deuce's avatar
deuce committed
438
				putuserrec(cfg,user->number,U_CHAT,8,ultoa(user->chat,str,16));
deuce's avatar
deuce committed
439 440 441 442 443 444 445
				break;
		}
	}
	return(0);
}

/* Pick Command Shell */
deuce's avatar
deuce committed
446

deuce's avatar
deuce committed
447 448 449 450 451
int edit_shell(scfg_t *cfg, user_t *user)
{
	int 	i,j;
	char 	**opt;

452 453
	if((opt=(char **)alloca(sizeof(char *)*(cfg->total_shells+1)))==NULL)
		allocfail(sizeof(char *)*(cfg->total_shells+1));
deuce's avatar
deuce committed
454 455 456 457 458

	for(i=0;i<cfg->total_shells;i++) {
		opt[i]=cfg->shell[i]->name;
	}
	opt[i]="";
deuce's avatar
deuce committed
459 460
	j=user->shell;
	switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Command Shell",opt)) {
deuce's avatar
deuce committed
461 462 463
		case -1:
			break;
		default:
deuce's avatar
deuce committed
464 465 466
			if(user->shell != j) {
				user->shell=j;
				putuserrec(cfg,user->number,U_SHELL,8,cfg->shell[j]->code);
deuce's avatar
deuce committed
467
			}
deuce's avatar
deuce committed
468 469
			break;
	}
470

deuce's avatar
deuce committed
471 472 473 474 475 476 477 478 479
	return(0);
}

/* Edit Command Shell
 *       Name
 *       Expert Mode
 */
int edit_cmd(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
480 481
	int 	i,j;
	char 	**opt;
deuce's avatar
deuce committed
482
	char	str[256];
deuce's avatar
deuce committed
483

484 485 486
	if((opt=(char **)alloca(sizeof(char *)*(2+1)))==NULL)
		allocfail(sizeof(char *)*(2+1));
	for(i=0;i<(2+1);i++)
487
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
488 489 490 491 492
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
		i=0;
493
		GETUSERDAT(cfg,user);
494 495
		sprintf(opt[i++],"Command Shell  %s",cfg->shell[user->shell]->name);
		sprintf(opt[i++],"Expert Mode    %s",user->misc & EXPERT?"Yes":"No");
deuce's avatar
deuce committed
496 497 498 499 500 501 502 503 504 505
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Command Shell",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* Command Shell */
				edit_shell(cfg,user);
				break;
			case 1:
deuce's avatar
deuce committed
506
				/* Expert Mode */
deuce's avatar
deuce committed
507
				user->misc ^= EXPERT;
deuce's avatar
deuce committed
508
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
509 510 511 512
				break;
		}
	}

deuce's avatar
deuce committed
513 514 515
	return(0);
}

deuce's avatar
deuce committed
516 517 518 519 520 521
/* Pick External Editor */
int edit_xedit(scfg_t *cfg, user_t *user)
{
	int 	i,j;
	char 	**opt;

522 523
	if((opt=(char **)alloca(sizeof(char *)*(cfg->total_xedits+1)))==NULL)
		allocfail(sizeof(char *)*(cfg->total_xedits+1));
deuce's avatar
deuce committed
524

525
	GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
526 527 528 529 530 531
	opt[0]="None";
	for(i=1;i<=cfg->total_xedits;i++) {
		opt[i]=cfg->xedit[i-1]->name;
	}
	opt[i]="";
	j=user->xedit;
deuce's avatar
deuce committed
532
	switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"External Editor",opt)) {
deuce's avatar
deuce committed
533 534 535
		case -1:
			break;
		default:
deuce's avatar
deuce committed
536 537
			if(user->xedit != j) {
				user->xedit=j;
deuce's avatar
deuce committed
538 539 540
				if(j > 0)
				    putuserrec(cfg,user->number,U_XEDIT,8,cfg->xedit[j-1]->code);
				else
541
				    putuserrec(cfg,user->number,U_XEDIT,8,"");
deuce's avatar
deuce committed
542
			}
deuce's avatar
deuce committed
543 544 545 546 547 548 549 550 551 552 553
			break;
	}
	return(0);
}

/* Edit Message Options
 *       Forward Email to NetMail
 *       Clear Screen Between Messages
 *       External Editor
 */
int edit_msgopts(scfg_t *cfg, user_t *user)
deuce's avatar
deuce committed
554
{
deuce's avatar
deuce committed
555 556
	int 	i,j;
	char 	**opt;
deuce's avatar
deuce committed
557
	char	str[256];
deuce's avatar
deuce committed
558

559 560 561
	if((opt=(char **)alloca(sizeof(char *)*(3+1)))==NULL)
		allocfail(sizeof(char *)*(3+1));
	for(i=0;i<(3+1);i++)
562
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
563 564 565 566
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
567
		GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
568
		i=0;
569 570 571
		sprintf(opt[i++],"Forward Email to NetMail       %s",user->misc & NETMAIL?"Yes":"No");
		sprintf(opt[i++],"Clear Screen Between Messages  %s",user->misc & CLRSCRN?"Yes":"No");
		sprintf(opt[i++],"External Editor                %s",user->xedit?cfg->xedit[user->xedit-1]->name:"None");
deuce's avatar
deuce committed
572 573 574 575 576 577 578 579
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Message Options",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* FWD Email */
				user->misc ^= NETMAIL;
deuce's avatar
deuce committed
580
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
581 582 583 584
				break;
			case 1:
				/* Clear Between MSGS */
				user->misc ^=CLRSCRN;
deuce's avatar
deuce committed
585
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
				break;
			case 2:
				/* External Editor */
				edit_xedit(cfg,user);
				break;
		}
	}
	return(0);
}

/* Pick Tmp/QWK File Type */
int edit_tmpqwktype(scfg_t *cfg, user_t *user)
{
	int 	i;
	int		j=0;
	char 	**opt;

603 604
	if((opt=(char **)alloca(sizeof(char *)*(cfg->total_fcomps+1)))==NULL)
		allocfail(sizeof(char *)*(cfg->total_fcomps+1));
deuce's avatar
deuce committed
605

606
	GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
607 608 609 610 611 612 613 614 615 616
	for(i=0;i<cfg->total_fcomps;i++) {
		opt[i]=cfg->fcomp[i]->ext;
		if(!strcmp(cfg->fcomp[i]->ext,user->tmpext))
			j=i;
	}
	opt[i]="";
	switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Temp/QWK File Type",opt)) {
		case -1:
			break;
		default:
deuce's avatar
deuce committed
617 618 619 620
			if(strcmp(cfg->fcomp[j]->ext,user->tmpext)) {
				strcpy(user->tmpext,cfg->fcomp[j]->ext);
				putuserrec(cfg,user->number,U_TMPEXT,3,user->tmpext);
			}
deuce's avatar
deuce committed
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
			break;
	}
	return(0);
}

/* Edit QWK Packet Options
 *       Include New Files List
 *       Include Unread Email
 *       Delete Email After Download
 *       Include Messages From Self
 *       Expand CTRL-A Codes to ANSI
 *       Strip CTRL-A Codes
 *       Include File Attachments
 *       Include Index Files
 *       Include Time Zone (@TZ)
 *       Include Seen-Bys (@VIA)
 *       Extraneous Control Files
 */
int edit_qwk(scfg_t *cfg, user_t *user)
{
	int 	i,j;
	char 	**opt;
deuce's avatar
deuce committed
643
	char	str[256];
deuce's avatar
deuce committed
644

645 646 647
	if((opt=(char **)alloca(sizeof(char *)*(15+1)))==NULL)
		allocfail(sizeof(char *)*(15+1));
	for(i=0;i<(15+1);i++)
648
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
649 650 651 652 653
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
		i=0;
654
		GETUSERDAT(cfg,user);
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
		sprintf(opt[i++],"Include New Files List        %s",user->qwk & QWK_FILES?"Yes":"No");
		sprintf(opt[i++],"Include Unread Email          %s",user->qwk & QWK_EMAIL?"Yes":"No");
		sprintf(opt[i++],"Include ALL Email             %s",user->qwk & QWK_ALLMAIL?"Yes":"No");
		sprintf(opt[i++],"Delete Email After Download   %s",user->qwk & QWK_DELMAIL?"Yes":"No");
		sprintf(opt[i++],"Include Messages from Self    %s",user->qwk & QWK_BYSELF?"Yes":"No");
		sprintf(opt[i++],"Expand CTRL-A to ANSI         %s",user->qwk & QWK_EXPCTLA?"Yes":"No");
		sprintf(opt[i++],"Strip CTRL-A Codes            %s",user->qwk & QWK_RETCTLA?"No":"Yes");
		sprintf(opt[i++],"Include File Attachments      %s",user->qwk & QWK_ATTACH?"Yes":"No");
		sprintf(opt[i++],"Include Index Files           %s",user->qwk & QWK_NOINDEX?"No":"Yes");
		sprintf(opt[i++],"Include Time Zone (@TZ)       %s",user->qwk & QWK_TZ?"Yes":"No");
		sprintf(opt[i++],"Include Seen-Bys (@VIA)       %s",user->qwk & QWK_VIA?"Yes":"No");
		sprintf(opt[i++],"Extraneous Control Files      %s",user->qwk & QWK_NOCTRL?"No":"Yes");
		sprintf(opt[i++],"Extended (QWKE) Format        %s",user->qwk & QWK_EXT?"Yes":"No");
		sprintf(opt[i++],"Include Message IDs (@MSGID)  %s",user->qwk & QWK_MSGID?"Yes":"No");
		sprintf(opt[i++],"Temp/QWK File Type            %s",user->tmpext);
deuce's avatar
deuce committed
670 671 672 673 674 675 676 677
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Command Shell",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* New Files List */
				user->qwk ^= QWK_FILES;
deuce's avatar
deuce committed
678
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
679 680 681 682
				break;
			case 1:
				/* Unread Email */
				user->qwk ^= QWK_EMAIL;
deuce's avatar
deuce committed
683
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
684 685 686 687
				break;
			case 2:
				/* ALL Email */
				user->qwk ^= QWK_ALLMAIL;
deuce's avatar
deuce committed
688
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
689 690 691 692
				break;
			case 3:
				/* Del Email after Download */
				user->qwk ^= QWK_DELMAIL;
deuce's avatar
deuce committed
693
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
694 695 696 697
				break;
			case 4:
				/* Include From Self */
				user->qwk ^= QWK_BYSELF;
deuce's avatar
deuce committed
698
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
699 700 701 702
				break;
			case 5:
				/* Expand CTRL-A */
				user->qwk ^= QWK_EXPCTLA;
deuce's avatar
deuce committed
703
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
704 705 706 707
				break;
			case 6:
				/* Strip CTRL-A */
				user->qwk ^= QWK_RETCTLA;
deuce's avatar
deuce committed
708
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
709 710 711 712
				break;
			case 7:
				/* Include Attach */
				user->qwk ^= QWK_ATTACH;
deuce's avatar
deuce committed
713
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
714 715 716 717
				break;
			case 8:
				/* Include Indexes */
				user->qwk ^= QWK_NOINDEX;
deuce's avatar
deuce committed
718
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
719 720 721 722
				break;
			case 9:
				/* Include TZ */
				user->qwk ^= QWK_TZ;
deuce's avatar
deuce committed
723
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
724 725 726 727
				break;
			case 10:
				/* Include VIA */
				user->qwk ^= QWK_VIA;
deuce's avatar
deuce committed
728
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
729 730 731 732
				break;
			case 11:
				/* Extra CTRL Files */
				user->qwk ^= QWK_NOCTRL;
deuce's avatar
deuce committed
733
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
734 735 736 737
				break;
			case 12:
				/* Extended QWKE */
				user->qwk ^= QWK_EXT;
deuce's avatar
deuce committed
738
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
739 740 741 742
				break;
			case 13:
				/* Include MSGID */
				user->qwk ^= QWK_MSGID;
deuce's avatar
deuce committed
743
				putuserrec(cfg,user->number,U_QWK,8,ultoa(user->qwk,str,16));
deuce's avatar
deuce committed
744 745 746 747 748 749 750 751 752 753 754
				break;
			case 14:
				/* Temp/QWK Type */
				edit_tmpqwktype(cfg,user);
				break;
		}
	}
	return(0);
}

/* Pick Protocol */
deuce's avatar
deuce committed
755

deuce's avatar
deuce committed
756 757 758 759 760 761
int edit_proto(scfg_t *cfg, user_t *user)
{
	int 	i;
	int		j=0;
	char 	**opt;

762 763
	if((opt=(char **)alloca(sizeof(char *)*(cfg->total_prots+1)))==NULL)
		allocfail(sizeof(char *)*(cfg->total_prots+1));
deuce's avatar
deuce committed
764

765
	GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
766 767 768 769 770 771 772 773 774 775 776 777
	opt[0]="None";
	for(i=1;i<=cfg->total_prots;i++) {
		opt[i]=cfg->prot[i-1]->name;
		if(cfg->prot[i-1]->mnemonic == user->prot)
			j=i;
	}
	opt[i]="";
	switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Default Protcol",opt)) {
		case -1:
			break;
		case 0:
			if(user->prot != ' ')
deuce's avatar
deuce committed
778
				putuserrec(cfg,user->number,U_PROT,1," ");
deuce's avatar
deuce committed
779 780 781
			user->prot=' ';
			break;
		default:
deuce's avatar
deuce committed
782 783
			if(user->prot != cfg->prot[j-1]->mnemonic) {
				user->prot=cfg->prot[j-1]->mnemonic;
784
				putuserrec(cfg,user->number,U_PROT,1,(char*)&user->prot);
deuce's avatar
deuce committed
785
			}
deuce's avatar
deuce committed
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
			break;
	}
	return(0);
}

/* Edit File Options
 *       Auto-New Scan
 *       Extended Descriptions
 *       Batch Flagging
 *       Auto-Hangup After Transfer
 *       Default download Protocol
 *       Temp/QWK File Type
 */
int edit_fileopts(scfg_t *cfg, user_t *user)
{
	int 	i,j;
	int		k;
	char 	**opt;
	char 	str[256];

806 807 808
	if((opt=(char **)alloca(sizeof(char *)*(6+1)))==NULL)
		allocfail(sizeof(char *)*(6+1));
	for(i=0;i<(6+1);i++)
809
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
810 811 812 813
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
814
		GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
815
		i=0;
816 817 818 819
		sprintf(opt[i++],"Auto-New Scan              %s",user->misc & ANFSCAN?"Yes":"No");
		sprintf(opt[i++],"Extended Descriptions      %s",user->misc & EXTDESC?"Yes":"No");
		sprintf(opt[i++],"Batch Flagging             %s",user->misc & BATCHFLAG?"Yes":"No");
		sprintf(opt[i++],"Auto Transfer Hangup       %s",user->misc & AUTOHANG?"Yes":"No");
deuce's avatar
deuce committed
820 821 822 823
		strcpy(str,"None");
		for(k=0;k<cfg->total_prots;k++)
			if(cfg->prot[k]->mnemonic==user->prot)
				strcpy(str,cfg->prot[k]->name);
824 825
		sprintf(opt[i++],"Default Download Protocol  %s",str);
		sprintf(opt[i++],"Temp/QWK File Type         %s",user->tmpext);
deuce's avatar
deuce committed
826 827 828 829 830 831 832 833
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"File Options",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* Auto-New Scan */
				user->misc ^= ANFSCAN;
deuce's avatar
deuce committed
834
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
835 836 837 838
				break;
			case 1:
				/* Extended Descs */
				user->misc ^= EXTDESC;
deuce's avatar
deuce committed
839
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
840 841 842 843
				break;
			case 2:
				/* Batch Flagging */
				user->misc ^= BATCHFLAG;
deuce's avatar
deuce committed
844
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
845 846
				break;
			case 3:
deuce's avatar
deuce committed
847
				/* Auto-Hangup */
deuce's avatar
deuce committed
848
				user->misc ^= AUTOHANG;
deuce's avatar
deuce committed
849
				putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16));
deuce's avatar
deuce committed
850 851 852 853 854 855 856 857 858 859 860 861 862 863
				break;
			case 4:
				/* Default Download Protocol */
				edit_proto(cfg,user);
				break;
			case 5:
				/* Temp/QWK File Type */
				edit_tmpqwktype(cfg,user);
				break;
		}
	}
	return(0);
}

deuce's avatar
deuce committed
864 865
/* Edit "Extended Comment" */

deuce's avatar
deuce committed
866 867
int edit_comment(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
868 869 870
	char str[1024];
	char editor[1024];

deuce's avatar
deuce committed
871
	sprintf(str,"%s %suser/%04u.msg",geteditor(editor),cfg->data_dir,user->number);
deuce's avatar
deuce committed
872
	do_cmd(str);
deuce's avatar
deuce committed
873 874 875 876 877 878 879 880 881 882
	return(0);
}

/* MSG and File settings
 *      - Message Options
 *      - QWK Message Packet
 *      - File Options
 */
int edit_msgfile(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
	char *opt[4]={
		 "Message Options"
		,"QWK Message Packet"
		,"File Options"
		,""};
	int i=0;
	while(1) {
		switch(uifc.list(WIN_BOT|WIN_RHT|WIN_ACT,0,0,0,&i,0,"Settings",opt)) {
			case -1:
				return(0);
				break;
			case 0:
				/* Message Options */
				edit_msgopts(cfg,user);
				break;
			case 1:
				/* QWK Message Packet */
				edit_qwk(cfg,user);
				break;
			case 2:
				/* File Options */
				edit_fileopts(cfg,user);
				break;
		}
	}
deuce's avatar
deuce committed
908 909 910 911 912 913 914 915 916 917 918
	return(0);
}

/* Settings
 *     - Terminal Settings
 *     - Logon Toggles
 *     - Chat Toggles
 *     - Command Shell
 */
int edit_settings(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
919 920 921 922 923 924 925 926 927
	char *opt[5]={
		 "Terminal Settings"
		,"Logon Toggles"
		,"Chat Toggles"
		,"Command Shell"
		,""};
	int i=0;

	while(1) {
deuce's avatar
deuce committed
928
		switch(uifc.list(WIN_BOT|WIN_RHT|WIN_ACT,0,0,0,&i,0,"Settings",opt)) {
deuce's avatar
deuce committed
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
			case -1:
				return(0);
				break;
			case 0:
				/* Terminal Settings */
				edit_terminal(cfg,user);
				break;
			case 1:
				/* Logon Toggles */
				edit_logon(cfg,user);
				break;
			case 2:
				/* Chat Toggles */
				edit_chat(cfg,user);
				break;
			case 3:
				/* Command Shell */
				edit_cmd(cfg,user);
				break;
		}
	}
deuce's avatar
deuce committed
950 951 952 953 954 955 956 957 958 959 960 961 962 963
	return(0);
}

/* Statistics
 *     First On
 *     Last On
 *     Total Logons
 *     Todays Logons
 *     Total Posts
 *     Todays Posts
 *     Total Uploads
 *     Todays Uploads
 *     Total Time On
 *     Todays Time On
deuce's avatar
deuce committed
964
 *     Last Call Time On
deuce's avatar
deuce committed
965 966 967 968 969 970 971 972 973 974
 *     Extra
 *     Total Downloads
 *     Bytes
 *     Leech
 *     Total Email
 *     Todays Email
 *     Email to Sysop
 */
int edit_stats(scfg_t *cfg, user_t *user)
{
deuce's avatar
deuce committed
975 976 977 978 979
	int 	i,j;
	char 	**opt;
	char	str[256];
	time_t	temptime,temptime2;

980 981 982
	if((opt=(char **)alloca(sizeof(char *)*(20+1)))==NULL)
		allocfail(sizeof(char *)*(20+1));
	for(i=0;i<(20+1);i++)
983
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
deuce's avatar
deuce committed
984 985 986 987
			allocfail(MAX_OPLN);

	j=0;
	while(1) {
988
		GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
989
		i=0;
990 991 992
		sprintf(opt[i++],"First On           %s",user->firston?timestr(cfg, user->firston, str):"Never");
		sprintf(opt[i++],"Last On            %s",user->laston?timestr(cfg, user->laston, str):"Never");
		sprintf(opt[i++],"Logon Time         %s",user->laston?timestr(cfg, user->logontime, str):"Not On");
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
		sprintf(opt[i++],"Total Logons       %hu",user->logons);
		sprintf(opt[i++],"Todays Logons      %hu",user->ltoday);
		sprintf(opt[i++],"Total Posts        %hu",user->posts);
		sprintf(opt[i++],"Todays Posts       %hu",user->ptoday);
		sprintf(opt[i++],"Total Email        %hu",user->emails);
		sprintf(opt[i++],"Todays Email       %hu",user->etoday);
		sprintf(opt[i++],"Email To Sysop     %hu",user->fbacks);
		sprintf(opt[i++],"Total Time On      %hu",user->timeon);
		sprintf(opt[i++],"Time On Today      %hu",user->ttoday);
		sprintf(opt[i++],"Time On Last Call  %hu",user->tlast);
		sprintf(opt[i++],"Extra Time Today   %hu",user->textra);
		sprintf(opt[i++],"Total Downloads    %hu",user->dls);
		sprintf(opt[i++],"Downloaded Bytes   %lu",user->dlb);
		sprintf(opt[i++],"Total Uploads      %hu",user->uls);
		sprintf(opt[i++],"Uploaded Bytes     %lu",user->ulb);
		sprintf(opt[i++],"Leech Downloads    %u",user->leech);
1009
		sprintf(opt[i++],"Password Modified  %s",user->pwmod?timestr(cfg, user->pwmod, str):"Never");
deuce's avatar
deuce committed
1010
		opt[i][0]=0;
deuce's avatar
deuce committed
1011
		switch(uifc.list(WIN_MID|WIN_ACT,0,0,0,&j,0,"Statistics",opt)) {
deuce's avatar
deuce committed
1012 1013 1014 1015 1016
			case -1:
				return(0);
				break;
			case 0:
				/* First On */
1017
				GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
1018 1019
				temptime=user->firston;
				unixtodstr(cfg,temptime,str);
deuce's avatar
deuce committed
1020
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"First On Date",str,8,K_EDIT);
deuce's avatar
deuce committed
1021 1022 1023
				user->firston=dstrtounix(cfg, str);
				temptime2=temptime-user->firston;
				sectostr(temptime2,str);
deuce's avatar
deuce committed
1024
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"First On Time",str,8,K_EDIT);
deuce's avatar
deuce committed
1025 1026 1027 1028
				temptime2=strtosec(str);
				if(temptime2!=-1)
					user->firston += temptime2;
				if(temptime!=user->firston)
deuce's avatar
deuce committed
1029
					putuserrec(cfg,user->number,U_FIRSTON,8,ultoa(user->firston,str,16));
deuce's avatar
deuce committed
1030 1031 1032
				break;
			case 1:
				/* Last On */
1033
				GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
1034 1035
				temptime=user->laston;
				unixtodstr(cfg,temptime,str);
deuce's avatar
deuce committed
1036
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Last On Date",str,8,K_EDIT);
deuce's avatar
deuce committed
1037 1038 1039
				user->laston=dstrtounix(cfg, str);
				temptime2=temptime-user->laston;
				sectostr(temptime2,str);
deuce's avatar
deuce committed
1040
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Last On Time",str,8,K_EDIT);
deuce's avatar
deuce committed
1041 1042 1043 1044
				temptime2=strtosec(str);
				if(temptime2!=-1)
					user->laston += temptime2;
				if(temptime!=user->laston)
deuce's avatar
deuce committed
1045
					putuserrec(cfg,user->number,U_LASTON,8,ultoa(user->laston,str,16));
deuce's avatar
deuce committed
1046 1047 1048
				break;
			case 2:
				/* Logon Time */
1049
				GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
1050 1051
				temptime=user->logontime;
				unixtodstr(cfg,temptime,str);
deuce's avatar
deuce committed
1052
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Logon Date",str,8,K_EDIT);
deuce's avatar
deuce committed
1053 1054 1055
				user->logontime=dstrtounix(cfg, str);
				temptime2=temptime-user->logontime;
				sectostr(temptime2,str);
deuce's avatar
deuce committed
1056
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Logon Time",str,8,K_EDIT);
deuce's avatar
deuce committed
1057 1058 1059 1060
				temptime2=strtosec(str);
				if(temptime2!=-1)
					user->logontime += temptime2;
				if(temptime!=user->logontime)
deuce's avatar
deuce committed
1061
					putuserrec(cfg,user->number,U_LOGONTIME,8,ultoa(user->logontime,str,16));
deuce's avatar
deuce committed
1062 1063 1064
				break;
			case 3:
				/* Total Logons */
1065
				GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
1066
				sprintf(str,"%hu",user->logons);
deuce's avatar
deuce committed
1067
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Total Logons",str,5,K_EDIT|K_NUMBER);
deuce's avatar
deuce committed
1068 1069
				if(uifc.changes) {
					user->logons=strtoul(str,NULL,10);
deuce's avatar
deuce committed
1070
					putuserrec(cfg,user->number,U_LOGONS,5,ultoa(user->logons,str,10));
deuce's avatar
deuce committed
1071 1072 1073 1074
				}
				break;
			case 4:
				/* Todays Logons */
1075
				GETUSERDAT(cfg,user);
deuce's avatar
deuce committed
1076
				sprintf(str,"%hu",user->ltoday);
deuce's avatar
deuce committed
1077
				uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Todays Logons",str,5,K_EDIT|K_NUMBER);
deuce's avatar
deuce committed
1078 1079
				if(uifc.changes) {
					user->ltoday=strtoul(str,NULL,10);
deuce's avatar
deuce committed
1080
					putuserrec(cfg,user->number,U_LTODAY,5,ultoa(user->ltoday,str,10));
deuce's avatar
deuce committed
1081 1082 1083 1084
				}
				break;
			case 5:
				/* Total Posts */
1085
				GETUSERDAT(cfg,user);
deuce's avatar