proboard/SHELL.CPP

823 lines
20 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define Use_MsgBase
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <tswin.hpp>
#include "proboard.hpp"
extern "C" int swapshell(char *command);
static void write_dorinfo(int node,bool write_handle,bool write_avatar);
static void write_exitinfo1();
static void read_exitinfo1();
static void write_exitinfo2();
static void read_exitinfo2();
static void write_doorsys();
unsigned shell_windowed = 0;
unsigned shell_updateline = 0;
unsigned shell_swap = 0;
char shell_swapname[13];
static bool use_underscore;
inline void
test_ems()
{
char far *ptr = (char far *) MK_FP(*((word *)MK_FP(0,0x67*4+2)),10);
if(strncmp(ptr,"EMMXXXX0",8)) use_ems = 0;
}
static void
set_environment()
{
static char _far *alloc_ptr = NULL;
int envlen = 1; // Start with 1 (extra zero byte at end of table)
for(int i=0;environ[i];i++) envlen += strlen(environ[i])+1;
if(alloc_ptr != NULL) free(alloc_ptr);
char far *eptr = (char far *)malloc(envlen+16);
alloc_ptr = eptr;
if(eptr == NULL) return;
eptr = (char far *)normalize_ptr(eptr); // Normalize pointer
eptr = (char far *)MK_FP(FP_SEG(eptr)+1,0); // Make zero-offset pointer
char _far *p = eptr;
for(i=0;environ[i];i++)
{
memcpy(p,environ[i],strlen(environ[i])+1);
p += strlen(environ[i]) + 1;
}
*p = 0;
*((word _far *)MK_FP(_psp,0x2C)) = FP_SEG(eptr);
}
void
shell(char *data)
{
bool hotfossil = FALSE;
bool log = TRUE;
bool message = TRUE;
bool old_exitinfo = FALSE;
bool do_door_sys = FALSE;
bool suspend = FALSE;
bool sysop = FALSE;
bool no_io = FALSE;
bool doscmd = FALSE;
bool write_handle = FALSE;
bool write_avatar = TRUE;
#ifdef DEBUG_EFL
LOG("EFLDEBUG: [SP=%04X] shell() entry",_SP);
#endif
use_underscore = TRUE;
int dorinfo_node = node_number;
test_ems();
shell_swap = cfg.doswap;
String commandline;
shell_windowed = 0;
shell_updateline = 0;
bool flag = FALSE;
for(;*data;data++)
{
if(*data=='*' && !flag)
{
flag = TRUE;
continue;
}
if(flag)
{ // free: J,K,U
switch(toupper(*data))
{
case '*': commandline << '*'; break;
case '#': commandline << node_number; break;
case 'A': write_handle = TRUE; break;
case 'B': commandline << io.baud; break;
case 'C': commandline << getenv("COMSPEC"); break;
case 'D': do_door_sys = TRUE; break;
case 'E': old_exitinfo = TRUE; break;
case 'F': commandline << user_firstname; break;
case 'G': commandline << ((ansi_mode)?1:0); break;
case 'H': hotfossil = TRUE; break;
case 'I': commandline << cfg.inactivity_time; break;
// case 'J': break;
// case 'K': break;
case 'L': {
String s(user.name);
for(int i=0;i<s.len();i++) if(s[i]==' ') break;
commandline << (char *)(&s[i+1]);
} break;
case 'M': commandline << mypath; break;
case 'N': log = FALSE; break;
case 'O': {
FileArea fa;
if(!fa.read(user.fileArea))
{
user.fileArea = 1;
fa.read(1);
}
commandline << fa.filepath;
} break;
case 'P': commandline << (io.port+1); break;
case 'Q': message = FALSE; break;
case 'R': commandline << user_recnr; break;
case 'S': commandline << syspath; break;
case 'T': commandline << timer.left(); break;
// case 'U':
case 'V': write_avatar = FALSE; break;
case 'W': shell_windowed=1; break;
case 'X': shell_swap=1; break;
case 'Y': shell_swap=0; break;
case 'Z': doscmd = TRUE; break;
case '0': dorinfo_node = 1; break;
case '1': shell_updateline=1; break;
case '2': shell_updateline=tsw_vsize; break;
case '!': suspend = TRUE; break;
case '\\': sysop = TRUE; break;
case '=': no_io = TRUE; break;
case '_': use_underscore = FALSE; break;
}
flag = FALSE;
}
else
{
if(*data!=' ' || commandline.len()) commandline << *data;
}
}
if(doscmd)
{
commandline.insert(0," /C ");
commandline.insert(0,getenv("COMSPEC"));
}
if(log) LOG(1,"DOS SHELL: %s",(char *)commandline);
if(sysop) io << '\n' << S_SYSOP_SHELLING << char(255);
if(message) io << "\n\f" << S_LOADING << "\n\xFF";
user_online uo;
uo.setstatus(UO_SHELLING);
if(user_recnr >= 0) user.write(FALSE);
write_taglist();
FileArea::close();
msgbase.close();
/*
f_users .close();
f_usersxi .close();
f_usersidx.close();
f_userspb .close();
*/
display_mode = 1;
word *screenbuf=new word[tsw_hsize*tsw_vsize];
tsw_gettext(screenbuf,1,1,tsw_hsize,tsw_vsize);
if(!hotfossil && !no_io) io.cooldown();
sprintf(shell_swapname,"PB$$$%03.3d.SWP",node_number);
byte videomode = getvideomode();
unsigned old_vsize = tsw_vsize;
unsigned old_hsize = tsw_hsize;
write_dorinfo(dorinfo_node,write_handle,write_avatar);
if(old_exitinfo)
write_exitinfo1();
else
write_exitinfo2();
if(do_door_sys) write_doorsys();
if(suspend) timer.suspend();
set_environment();
#ifdef DEBUG_EFL
LOG("EFLDEBUG: [SP=%04X] Before swapshell()",_SP);
#endif
returnvalue=swapshell(commandline);
#ifdef DEBUG_EFL
LOG("EFLDEBUG: [SP=%04X] After swapshell()",_SP);
#endif
if(suspend) timer.restart();
timer.clearinactivity();
if(old_exitinfo)
read_exitinfo1();
else
read_exitinfo2();
if(tsw_videocard==EGA) tsw_vsize = *((byte _far *)0x484)+1;
tsw_hsize = *((byte far *)0x44A);
if((old_vsize != tsw_vsize) || (old_hsize != tsw_hsize))
{
setvideomode(videomode);
if((videomode == 3) && (old_vsize>25)) set43();
if(tsw_videocard==EGA) tsw_vsize=*((byte _far *)0x484)+1;
tsw_hsize = *((byte far *)0x44A);
}
SCREEN.moveCursor(0,0);
if(!hotfossil && !no_io) io.heatup();
read_taglist();
msgbase.open();
uo.setstatus(UO_BROWSING);
tsw_puttext(screenbuf,1,1,tsw_hsize,tsw_vsize);
timer.clearinactivity();
if(rip_mode) io << "\r\r[2!";
if(sysop) io << S_SYSOP_RETURNED_FROM_DOS << char(255);
unlink(form("%sDORINFO%d.DEF",mypath,dorinfo_node));
unlink(form("%sDOOR.SYS",mypath));
unlink(form("%sEXITINFO.BBS",mypath));
delete [] screenbuf;
updatemenu = TRUE;
}
static void
write_dorinfo(int node,bool write_handle,bool write_avt)
{
int i;
File f(form("%sDORINFO%d.DEF",mypath,node),fmode_create | fmode_text);
String sysopname (cfg.sysopname);
String username (user.name);
String usercity (user.city);
String boardname (cfg.bbsname);
if(write_handle) if(user.alias[0]) username = user.alias;
sysopname.upperCase();
username.upperCase();
usercity.upperCase();
boardname.upperCase();
f << boardname << '\n';
for(i=0;i<sysopname.len();i++)
if(sysopname[i]==' ')
{
sysopname[i++] = '\0';
break;
}
f << sysopname << '\n';
if(sysopname[i])
for(int j=0;j<strlen(&sysopname[i]);j++)
f << char((sysopname[i+j]==' ' && use_underscore)? '_' : sysopname[i+j]);
f << form("\nCOM%d\n%ld BAUD,N,8,1\n0\n",(io.baud)?(io.port+1):0,io.baud);
for(i=0;i<username.len();i++)
if(username[i]==' ')
{
username[i++] = '\0';
break;
}
f << username << '\n';
if(username[i])
for(int j=0;j<strlen(&username[i]);j++)
f << char((username[i+j]==' ' && use_underscore)? '_' : username[i+j]);
f << form("\n%s\n",(char *)usercity);
int graphics = (ansi_mode)?1:0;
if(write_avt && (avatar || avtplus)) graphics += 2;
f << form("%d\n%u\n%d\n",graphics,user.level,timer.left());
}
static void
write_doorsys()
{
File f(form("%sDOOR.SYS",mypath),fmode_create | fmode_text);
f << form("COM%d:\n",(io.baud)?(io.port+1):0);
f << form("%ld\n8\n",io.baud);
f << form("%d\n",node_number);
f << form("%ld\nY\nN\nN\nN\n",io.baud);
f << user.name << '\n';
f << user.city << '\n';
f << user.voicePhone << '\n';
f << user.dataPhone << '\n';
f << '\n';
f << form("%u\n",user.level);
f << form("%lu\n",user.timesCalled);
f << user.lastDate.format("MM-DD-YY") << '\n'; // Y2K BUG!
f << form("%ld\n",60L*timer.left());
f << form("%d\n",timer.left());
if(ansi_mode)
f << "GR\n";
else
f << "NG\n";
f << form("%d\nN\n\n\n",user.screenLength);
f << user.expDate.format("MM-DD-YY") << '\n'; // Y2K BUG!
f << form("%d\n",user_recnr);
f << (user.defaultProtocol ? form("%c\n",user.defaultProtocol) : "\n");
f << form("%ld\n",user.numUploads);
f << form("%ld\n",user.numDownloads);
f << form("%ld\n",user.kbToday);
f << form("%d\n",download_limit);
f << user.birthDate.format("MM-DD-YY") << '\n'; // Y2K BUG!
f << cfg.msgpath << '\n';
f << cfg.msgpath << '\n';
f << cfg.sysopname << '\n';
f << user.alias << '\n';
f << nextevent.start.format("HH:MM") << '\n';
f << "N\nN\nY\n7\n0\n";
f << user.lastDate.format("MM-DD-YY") << '\n'; // Y2K BUG!
f << login_time.format("HH:MM") << '\n';
f << user.lastTime.format("HH:MM") << '\n';
f << "32768\n";
f << "0\n";
f << form("%ld\n",user.kbUploaded);
f << form("%ld\n",user.kbDownloaded);
f << user.comment << "\n0\n";
f << form("%lu\n",user.msgsPosted);
}
static long
swapbits(long x)
{
long y = 0;
for(int i=0;i<32;i++) if(TESTBIT(x,long(i))) SETBIT(y,long(31-i));
return y;
}
struct exitinfo2
{
unsigned BaudRate;
long CallCount; // Sysinfo record
char LastCaller[36];
byte Extra1[128];
char StartDate[9]; // Timelog record
int BusyPerHour[24];
int BusyPerDay[7];
RA2_UsersBBS users_bbs; //*// User record
byte EventStatus; // Event record
char EventRunTime[6];
byte EventErrorLevel;
byte EventDays;
byte EventForced;
char EventLastTimeRun[9];
bool NetMailEntered;
bool EchoMailEntered;
char LoginTime[6];
char LoginDate[9];
int TmLimit;
long LoginSec;
// long dummy; // ???
int UserRecNum;
int ReadThru;
int PageTimes;
int DownLimit;
char TimeOfCreation[6];
/*
char LogonPassword[16]; //*
*/
dword LogonPasswordCRC; //*
byte WantChat;
int DeductedTime;
char MenuStack[50][9];
byte MenuPointer;
RA2_UsersXiBBS usersxi_bbs; //*// UsersXI record
bool ErrorFreeConnect;
bool SysopNext;
byte Extra4[209];
char PageReason[81];
byte StatusLine;
char LastCostMenu[9];
word MenuCostPerMin;
bool DoesAVT;
bool RIPmode;
byte extra5[86];
};
struct exitinfo1
{
unsigned BaudRate;
long CallCount;
char LastCaller[36];
byte Extra1[128];
char StartDate[9];
int BusyPerHour[24];
int BusyPerDay[7];
RA1_UsersBBS users_bbs;
byte EventStatus;
char EventRunTime[6];
byte EventErrorLevel;
byte EventDays;
byte EventForced;
char EventLastTimeRun[9];
byte NetMailEntered;
byte EchoMailEntered;
char LoginTime[6];
char LoginDate[9];
int TmLimit;
long LoginSec;
long dummy;
int UserRecNum;
int ReadThru;
int PageTimes;
int DownLimit;
char TimeOfCreation[6];
char LogonPassword[16];
byte WantChat;
int DeductedTime;
char MenuStack[50][9];
byte MenuPointer;
RA1_UsersXiBBS usersxi_bbs;
byte ErrorFreeConnect;
byte SysopNext;
byte Extra4[309];
};
static int time_adj;
static
void write_exitinfo2()
{
struct exitinfo2 *ei = new exitinfo2;
memset( ei,
0,
sizeof( exitinfo2 ) );
RA2_UsersPbBBS upb;
time_adj = timer.used();
user.timeUsed += time_adj;
user.toRa( ei->users_bbs,
ei->usersxi_bbs,
upb );
ei->BaudRate = io.baud;
ei->CallCount = totalcalls;
strcpy( ei->LastCaller, lastcaller.name );
c2pas( ei->LastCaller );
strcpy( ei->StartDate, "01-01-80" );
c2pas( ei->StartDate );
ei->TmLimit = timer.left();
ei->DownLimit = int( download_limit - user.kbToday );
ei->UserRecNum = user_recnr;
ei->LoginSec = 3600L * login_time[ 0 ] +
60L * login_time[ 1 ] +
login_time[ 0 ];
Date now(NOW);
sprintf( ei->TimeOfCreation,
"%02d:%02d",
now[ 0 ],
now[ 1 ] );
c2pas( ei->TimeOfCreation );
sprintf( ei->LoginTime,
"%02d:%02d",
login_time[ 0 ],
login_time[ 1 ] );
c2pas( ei->LoginTime );
sprintf( ei->LoginDate,
"%02d-%02d-%02d",
login_date[ 0 ],
login_date[ 1 ],
login_date[ 2 ] % 100 ); // Y2K FIXED!
// login_date[ 2 ] ); // Y2K BUG!
c2pas( ei->LoginDate );
ei->PageTimes = num_yells;
sprintf( ei->EventRunTime,
"%02d:%02d",
nextevent.start[ 0 ],
nextevent.start[ 1 ] );
c2pas( ei->EventRunTime );
if ( nextevent.enabled )
{
ei->EventStatus = 1;
}
else
{
ei->EventStatus = 2;
}
ei->EventErrorLevel = nextevent.errorlevel;
if ( nextevent.enabled )
{
ei->EventDays = nextevent.days;
}
else
{
ei->EventDays = 0;
}
strcpy( ei->EventLastTimeRun, "01-01-80" );
c2pas( ei->EventLastTimeRun );
ei->NetMailEntered = ( net_entered ) ? TRUE : FALSE;
ei->EchoMailEntered = ( echo_entered ) ? TRUE : FALSE;
ei->RIPmode = ! ! rip_mode;
ei->DoesAVT = ! ! avatar;
File f( form( "%sEXITINFO.BBS", mypath ),
fmode_create );
f.write( ei, sizeof( exitinfo2 ) );
delete ei;
}
static void
write_exitinfo1()
{
struct exitinfo1 *ei = new exitinfo1;
memset(ei,0,sizeof(exitinfo1));
ei->BaudRate = io.baud;
ei->CallCount = totalcalls;
strcpy(ei->LastCaller,lastcaller.name);
c2pas(ei->LastCaller);
strcpy(ei->StartDate,"01-01-80");
c2pas(ei->StartDate);
ei->TmLimit = timer.left();
ei->LoginSec = 3600L*login_time[0]+60L*login_time[1]+login_time[0];
ei->DownLimit = int(download_limit-user.kbToday);
ei->UserRecNum = user_recnr;
Date now(NOW);
sprintf(ei->TimeOfCreation,"%02d:%02d",now[0],now[1]);
c2pas(ei->TimeOfCreation);
sprintf(ei->LoginTime,"%02d:%02d",login_time[0],login_time[1]);
c2pas(ei->LoginTime);
sprintf(ei->LoginDate,"%02d-%02d-%02d",login_date[0],login_date[1],login_date[2]);
c2pas(ei->LoginDate);
ei->PageTimes=num_yells;
sprintf(ei->EventRunTime,"%02d:%02d",nextevent.start[0],nextevent.start[1]);
c2pas(ei->EventRunTime);
if(nextevent.enabled) ei->EventStatus = 1;
else ei->EventStatus = 2;
ei->EventErrorLevel = nextevent.errorlevel;
if(nextevent.enabled) ei->EventDays = nextevent.days;
else ei->EventDays = 0;
strcpy(ei->EventLastTimeRun,"01-01-80");
c2pas(ei->EventLastTimeRun);
ei->NetMailEntered = (net_entered) ? TRUE : FALSE;
ei->EchoMailEntered = (echo_entered) ? TRUE : FALSE;
strcpy(ei->users_bbs.Name,user.name);
strcpy(ei->users_bbs.Location,user.city);
strcpy(ei->users_bbs.Password,user.passWord);
strncpy(ei->users_bbs.DataPhone,user.dataPhone,12);
ei->users_bbs.DataPhone[12]='\0';
strncpy(ei->users_bbs.VoicePhone,user.voicePhone,12);
ei->users_bbs.VoicePhone[12]='\0';
strcpy(ei->usersxi_bbs.Handle,user.alias);
strcpy(ei->usersxi_bbs.Comment,user.comment);
strcpy(ei->usersxi_bbs.ForwardFor,user.forwardTo);
sprintf(ei->usersxi_bbs.BirthDate,"%02d-%02d-%02d",user.birthDate[1],user.birthDate[0],user.birthDate[2]);
sprintf(ei->usersxi_bbs.FirstDate,"%02d-%02d-%02d",user.firstDate[1],user.firstDate[0],user.firstDate[2]);
sprintf(ei->usersxi_bbs.SubDate ,"%02d-%02d-%02d",user.expDate[1],user.expDate[0],user.expDate[2]);
sprintf(ei->users_bbs .LastDate ,"%02d-%02d-%02d",user.lastDate[1],user.lastDate[0],user.lastDate[2]);
sprintf(ei->users_bbs .LastTime ,"%02d:%02d" ,user.lastTime[0],user.lastTime[1]);
ei->users_bbs.Security = user.level ;
ei->users_bbs.NoCalls = user.timesCalled ;
ei->users_bbs.Elapsed = user.timeUsed ;
ei->users_bbs.Downloads = user.numDownloads ;
ei->users_bbs.DownloadsK = user.kbDownloaded ;
ei->users_bbs.Uploads = user.numUploads ;
ei->users_bbs.UploadsK = user.kbUploaded ;
ei->users_bbs.MsgsPosted = user.msgsPosted ;
ei->users_bbs.TodayK = user.kbToday ;
ei->users_bbs.ScreenLength = user.screenLength ;
ei->users_bbs.Credit = user.credit ;
ei->users_bbs.Pending = user.pending ;
ei->users_bbs.LastRead = user.highMsgRead ;
for(int z=0;z<25;z++) ei->usersxi_bbs.CombinedInfo[z] = ((byte *)(&user.combinedBoards))[z];
ei->users_bbs.Flags = swapbits(*((long *)&user.aFlags));
if(user.uFlags & UFLAG_DELETED) ei->users_bbs.Attribute |= RA1_UFLAG_DELETED;
if(user.uFlags & UFLAG_CLEAR) ei->users_bbs.Attribute |= RA1_UFLAG_CLRSCR;
if(user.uFlags & UFLAG_PAUSE) ei->users_bbs.Attribute |= RA1_UFLAG_MORE;
if(user.uFlags & UFLAG_ANSI) ei->users_bbs.Attribute |= RA1_UFLAG_ANSI;
if(user.uFlags & UFLAG_NOKILL) ei->users_bbs.Attribute |= RA1_UFLAG_NOKILL;
if(user.uFlags & UFLAG_IGNORE) ei->users_bbs.Attribute |= RA1_UFLAG_IGNORE;
if(user.uFlags & UFLAG_FSED) ei->users_bbs.Attribute |= RA1_UFLAG_FSE;
// if(uflags & UFLAG_QUIET) ei->users_bbs.Attribute |= RA_UFLAG_QUIET;
if(user.uFlags & UFLAG_HIDDEN) ei->users_bbs.Attribute2 |= RA1_UFLAG2_HIDDEN;
if(user.uFlags & UFLAG_AVATAR) ei->users_bbs.Attribute2 |= RA1_UFLAG2_AVATAR;
if(user.uFlags & UFLAG_HOTKEYS) ei->users_bbs.Attribute2 |= RA1_UFLAG2_HOTKEYS;
ei->usersxi_bbs.MsgArea = user.msgArea & 0xFF;
ei->usersxi_bbs.FileArea = user.fileArea & 0xFF;
c2pas(ei->users_bbs.Name);
c2pas(ei->users_bbs.Location);
c2pas(ei->users_bbs.Password);
c2pas(ei->users_bbs.DataPhone);
c2pas(ei->users_bbs.VoicePhone);
c2pas(ei->users_bbs.LastTime);
c2pas(ei->users_bbs.LastDate);
c2pas(ei->usersxi_bbs.Handle);
c2pas(ei->usersxi_bbs.Comment);
c2pas(ei->usersxi_bbs.BirthDate);
c2pas(ei->usersxi_bbs.SubDate);
c2pas(ei->usersxi_bbs.FirstDate);
c2pas(ei->usersxi_bbs.ForwardFor);
File f(form("%sEXITINFO.BBS",mypath),fmode_create);
f.write(ei,sizeof(exitinfo1));
delete ei;
}
static void
read_exitinfo2()
{
struct exitinfo2 *ei = new exitinfo2;
RA2_UsersPbBBS upb;
user.toRa(ei->users_bbs,ei->usersxi_bbs,upb);
memset(ei,0,sizeof(exitinfo2));
File f(form("%sEXITINFO.BBS",mypath));
if(f.read(ei,sizeof(exitinfo2)) != sizeof(exitinfo2))
{
delete ei;
return;
}
f.close();
num_yells = ei->PageTimes;
unsigned oldlevel = user.level;
user.fromRa(ei->users_bbs,ei->usersxi_bbs,upb);
user.timeUsed -= time_adj;
timer.changeleft(int(time_limit-timer.used()-user.timeUsed-time_removed));
net_entered = ei->NetMailEntered;
net_entered = ei->EchoMailEntered;
if(user.level != oldlevel) adjust_limits();
delete ei;
}
static void
read_exitinfo1()
{
struct exitinfo1 *ei = new exitinfo1;
memset(ei,0,sizeof(exitinfo1));
File f(form("%sEXITINFO.BBS",mypath));
if(f.read(ei,sizeof(exitinfo1)) != sizeof(exitinfo1))
{
delete ei;
return;
}
f.close();
num_yells = ei->PageTimes;
unsigned oldlevel = user.level;
user.level = ei->users_bbs.Security;
net_entered = ei->NetMailEntered;
net_entered = ei->EchoMailEntered;
if(user.level != oldlevel) adjust_limits();
delete ei;
}