500 lines
12 KiB
C++
500 lines
12 KiB
C++
|
|
// ------------------------------------------------------------------
|
|
// GoldED+
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
|
// ------------------------------------------------------------------
|
|
// 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.
|
|
//
|
|
// 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
|
|
// ------------------------------------------------------------------
|
|
// $Id$
|
|
// ------------------------------------------------------------------
|
|
// DOS Shell, cleanup, errorhandling etc.
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
#include <golded.h>
|
|
#include <gutlos.h>
|
|
#include <gmoprot.h>
|
|
#ifdef __UNIX__
|
|
#include <gkbdunix.h>
|
|
#endif
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
extern GPickArealist* PickArealist;
|
|
extern bool in_arealist;
|
|
|
|
// ------------------------------------------------------------------
|
|
// Clean up the screen, memory and files before exiting to DOS
|
|
|
|
void Cleanup(void) {
|
|
|
|
if(CFG) {
|
|
|
|
if(CFG->switches.get(areakeeplast) and startupscan_success)
|
|
AL.WriteGoldLast();
|
|
|
|
#ifndef GMB_NOXBBS
|
|
if(AL.msgbases & MT_ADEPTXBBS)
|
|
XbbsExit();
|
|
#endif
|
|
#ifndef GMB_NOEZY
|
|
if(AL.msgbases & MT_EZYCOM)
|
|
EzycomExit();
|
|
#endif
|
|
if(AL.msgbases & MT_FIDO)
|
|
FidoExit();
|
|
#ifndef GMB_NOGOLD
|
|
if(AL.msgbases & MT_GOLDBASE)
|
|
GoldExit();
|
|
#endif
|
|
#ifndef GMB_NOHUDS
|
|
if(AL.msgbases & MT_HUDSON)
|
|
HudsExit();
|
|
#endif
|
|
#ifndef GMB_NOJAM
|
|
if(AL.msgbases & MT_JAM)
|
|
JamExit();
|
|
#endif
|
|
#ifndef GMB_NOPCB
|
|
if(AL.msgbases & MT_PCBOARD)
|
|
PcbExit();
|
|
#endif
|
|
#ifndef GMB_NOSQSH
|
|
if(AL.msgbases & MT_SQUISH)
|
|
SquishExit();
|
|
#endif
|
|
#ifndef GMB_NOWCAT
|
|
if(AL.msgbases & MT_WILDCAT)
|
|
WCatExit();
|
|
#endif
|
|
#ifndef GMB_NOSMB
|
|
if(AL.msgbases & MT_SMB)
|
|
SMBExit();
|
|
#endif
|
|
|
|
SearchExit();
|
|
|
|
// Free area data
|
|
AL.Reset();
|
|
|
|
// Free various lists
|
|
CFG->addressmacro.clear();
|
|
CFG->aka.clear();
|
|
CFG->akamatch.clear();
|
|
CFG->event.clear();
|
|
CFG->externutil.clear();
|
|
CFG->filealias.clear();
|
|
CFG->frqext.clear();
|
|
CFG->frqnodemap.clear();
|
|
CFG->kludge.clear();
|
|
CFG->mailinglist.clear();
|
|
CFG->mappath.clear();
|
|
CFG->origin.clear();
|
|
CFG->robotname.clear();
|
|
CFG->tagline.clear();
|
|
CFG->tpl.clear();
|
|
CFG->twitname.clear();
|
|
CFG->twitsubj.clear();
|
|
CFG->username.clear();
|
|
CFG->xlatcharset.clear();
|
|
CFG->xlatescset.clear();
|
|
CFG->cmdkey.clear();
|
|
CFG->macro.clear();
|
|
|
|
// Free misc data
|
|
throw_xrelease(CharTable);
|
|
throw_xrelease(CompTable);
|
|
throw_xrelease(MNETable);
|
|
throw_xrelease(I51Table);
|
|
|
|
throw_delete(QWK);
|
|
|
|
if(errorlevel != EXIT_CFGERR) {
|
|
if(netpost)
|
|
TouchFile(AddPath(CFG->areapath, CFG->semaphore.netscan));
|
|
if(echopost)
|
|
TouchFile(AddPath(CFG->areapath, CFG->semaphore.echoscan));
|
|
}
|
|
|
|
// Reset border color
|
|
if(C_BACKB != 0)
|
|
gvid->setoverscan(gvid->orig.color.overscan);
|
|
|
|
wcloseall(); // Close all windows
|
|
if(in_arealist)
|
|
PickArealist->close_all(); // Unlink hidden area windows
|
|
whelpundef(); // Disengage the help system
|
|
kbclear(); // Clear CXL keyboard buffer
|
|
freonkey(); // Free all onkeys (macros)
|
|
FreePastebuf(); // Free the internal editor cut'n'paste buffer
|
|
|
|
#if not defined(__UNIX__) and not defined(__USE_NCURSES__)
|
|
if(CFG->screenpalette[16])
|
|
gvid->setpalette(gvid->orig.color.palette);
|
|
|
|
if(gvid->curr.screen.mode != gvid->orig.screen.mode)
|
|
gvid->setmode(gvid->orig.screen.mode);
|
|
if(gvid->curr.screen.rows != gvid->orig.screen.rows)
|
|
gvid->setrows(gvid->orig.screen.rows);
|
|
|
|
if(oldscreen) {
|
|
vrestore(oldscreen);
|
|
throw_xrelease(oldscreen);
|
|
}
|
|
if(CFG->intensecolors)
|
|
gvid->setintensity(gvid->orig.color.intensity);
|
|
vcurset(gvid->orig.cursor.start, gvid->orig.cursor.end);
|
|
#endif
|
|
|
|
#ifndef __WIN32__
|
|
vposset(gvid->orig.cursor.row, 0);
|
|
vputx(gvid->orig.cursor.row, 0, gvid->orig.color.textattr, ' ', gvid->orig.screen.columns);
|
|
#endif
|
|
|
|
vposset(gvid->orig.cursor.row-1, 0);
|
|
vcurshow();
|
|
}
|
|
throw_xdelete(BodyView);
|
|
throw_xdelete(HeaderView);
|
|
throw_xdelete(gvid);
|
|
|
|
int smax = MinV((int)GLOG_STORELINES, LOG.storelines);
|
|
for(int s=0; s<smax; s++)
|
|
cout << LOG.storeline[s] << endl;
|
|
if(LOG.storelines > GLOG_STORELINES)
|
|
cout << "(See also " << CFG->logfile << ")" << endl;
|
|
if(errorlevel > EXIT_NONAME)
|
|
MakeNoise(SND_S_O_S);
|
|
|
|
#if defined(GUTLOS_FUNCS)
|
|
g_deinit_os();
|
|
#endif
|
|
|
|
// Back to default Ctrl-Break handler
|
|
signal(SIGINT, SIG_DFL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Multipurpose DOS shell function
|
|
|
|
int ShellToDos(char* command, char* message, int cls, int cursor, int swap, int pause) {
|
|
|
|
NW(swap);
|
|
|
|
int error = 0;
|
|
|
|
#if defined(GUTLOS_FUNCS)
|
|
char ge_temptitle[GMAXTITLE];
|
|
#endif
|
|
|
|
#ifndef __UNIX__
|
|
if(strlen(command) > 125) {
|
|
w_info(" Warning: Command line longer than 125 characters! ");
|
|
waitkeyt(10000);
|
|
w_info(NULL);
|
|
}
|
|
#endif
|
|
|
|
// Put up a wait window
|
|
if(shellvid)
|
|
w_info(LNG->Wait);
|
|
|
|
#if defined(GUTLOS_FUNCS)
|
|
g_get_ostitle_name(ge_temptitle);
|
|
g_set_ostitle_name("OS Shell",0);
|
|
#endif
|
|
|
|
// Close msgbase files
|
|
int _wasopen = AA->isopen();
|
|
if(_wasopen)
|
|
AA->Suspend();
|
|
|
|
HandleGEvent(EVTT_DOSSHELL);
|
|
|
|
// Change the prompt
|
|
#ifndef __UNIX__
|
|
static char prompt[256];
|
|
static char oldprompt[256];
|
|
|
|
if(CFG->switches.get(dosprompt)) {
|
|
#ifdef __DJGPP__
|
|
const char* p = getenv("PROMPT");
|
|
if(p) {
|
|
strcpy(oldprompt, p);
|
|
strcpy(stpcpy(prompt, LNG->Prompt), p);
|
|
setenv("PROMPT", prompt, true);
|
|
}
|
|
#else
|
|
int envn = 0;
|
|
while(environ[envn] and *environ[envn]) {
|
|
if(strnieql(environ[envn], "PROMPT=", 7)) {
|
|
strcpy(oldprompt, environ[envn]);
|
|
sprintf(prompt, "PROMPT=%s%s", LNG->Prompt, *oldprompt ? oldprompt+7 : "");
|
|
environ[envn] = prompt;
|
|
break;
|
|
}
|
|
envn++;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
// Store the screen
|
|
vatch* scrnbuf = vsave();
|
|
|
|
// Store current drive/dir
|
|
Path orgdir;
|
|
getcwd(orgdir, sizeof(Path));
|
|
|
|
// Set cursor position
|
|
if(gvid->curr.screen.rows != gvid->orig.screen.rows)
|
|
gvid->setrows(gvid->orig.screen.rows);
|
|
if(gvid->curr.screen.mode != gvid->orig.screen.mode)
|
|
gvid->setmode(gvid->orig.screen.mode);
|
|
|
|
// Clear screen
|
|
if(cls)
|
|
vclrscr(cls);
|
|
|
|
// Reset border color
|
|
if(C_BACKB != 0)
|
|
gvid->setoverscan(gvid->orig.color.overscan);
|
|
|
|
// Turn on the blinking attributes
|
|
gvid->setintensity(gvid->orig.color.intensity);
|
|
|
|
// Restore original palette during the shell
|
|
if(CFG->screenpalette[16])
|
|
gvid->setpalette(gvid->orig.color.palette);
|
|
|
|
#if defined(__UNIX__) and not defined(__USE_NCURSES__)
|
|
gkbd_tty_reset();
|
|
#endif
|
|
|
|
#ifdef __USE_NCURSES__
|
|
savetty();
|
|
reset_shell_mode();
|
|
#endif
|
|
|
|
// Write message on screen
|
|
if(*message)
|
|
puts(message);
|
|
|
|
// Turn on cursor
|
|
int yy, xx;
|
|
if(cursor) {
|
|
vposget(&yy, &xx);
|
|
vcurset(gvid->orig.cursor.start, gvid->orig.cursor.end);
|
|
vcurshow();
|
|
}
|
|
|
|
HandleGEvent(EVTT_BREAKLOOP);
|
|
|
|
// Shell return value
|
|
int status = -1;
|
|
|
|
// Shell using the regular RTL function
|
|
#ifndef __CYGWIN__
|
|
status = system(command);
|
|
#else
|
|
// Get executable and parameters
|
|
char* _arg_v[3];
|
|
|
|
char* _pars = "";
|
|
char _xfn[256] = ""; // Call command interpreter
|
|
if(strnieql(command, "/c", 2))
|
|
_pars = strskip_wht(command+2);
|
|
else {
|
|
_pars = strpbrk(command, " \t");
|
|
if(_pars) {
|
|
++_pars++;
|
|
strxcpy(_xfn, command, _pars-command);
|
|
_pars = strskip_wht(_pars);
|
|
}
|
|
else
|
|
_xfn = command;
|
|
}
|
|
_arg_v[0] = _xfn;
|
|
_arg_v[1] = _pars;
|
|
_arg_v[2] = NULL;
|
|
status = spawnvpe(P_WAIT, _xfn, _arg_v, environ);
|
|
#endif
|
|
|
|
if(status == -1)
|
|
error = errno;
|
|
|
|
if(status != -1)
|
|
status = 0;
|
|
|
|
// Restore keyboard settings
|
|
#ifdef __USE_NCURSES__
|
|
clearok(stdscr, TRUE);
|
|
resetty();
|
|
#else
|
|
gkbd.Init();
|
|
#endif
|
|
|
|
// Pause if needed
|
|
if(pause) {
|
|
if((pause > 0) or (status != 0))
|
|
kbxget();
|
|
}
|
|
|
|
// Restore current directory
|
|
gchdir(orgdir);
|
|
|
|
// Restore video mode and rows
|
|
if(CFG->screensize > 0xFF)
|
|
gvid->setmode(CFG->screensize >> 8);
|
|
else if(CFG->screensize)
|
|
gvid->setrows(CFG->screensize);
|
|
|
|
// Restore cursor position and form
|
|
if(cursor) {
|
|
vposset(yy+1, xx);
|
|
vcurhide();
|
|
}
|
|
|
|
// Restore screen
|
|
if(scrnbuf) {
|
|
vrestore(scrnbuf);
|
|
throw_xrelease(scrnbuf);
|
|
} else
|
|
vclrscr();
|
|
|
|
// Restore screen intensity
|
|
gvid->setintensity(CFG->intensecolors);
|
|
|
|
// Restore border color
|
|
if(C_BACKB != 0)
|
|
gvid->setoverscan(C_BACKB);
|
|
|
|
// Set palette if changes were specified
|
|
if(CFG->screenpalette[16])
|
|
gvid->setpalette(CFG->screenpalette);
|
|
|
|
// Restore prompt
|
|
#ifndef __UNIX__
|
|
if(CFG->switches.get(dosprompt)) {
|
|
#ifdef __DJGPP__
|
|
setenv("PROMPT", oldprompt, true);
|
|
#else
|
|
int envn = 0;
|
|
while(environ[envn] and *environ[envn]) {
|
|
if(strnieql(environ[envn], "PROMPT=", 7)) {
|
|
environ[envn] = oldprompt;
|
|
break;
|
|
}
|
|
envn++;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
// Re-open msgbase
|
|
if(_wasopen)
|
|
AA->Resume();
|
|
|
|
// Remove the wait window
|
|
if(shellvid)
|
|
w_info(NULL);
|
|
|
|
// Popup error message
|
|
if(error) {
|
|
switch(errno) {
|
|
case E2BIG: w_info("Argument list too long!"); break;
|
|
case EACCES: w_info("Permission denied!"); break;
|
|
case EAGAIN: w_info("Ressource temporarily unavailable!"); break;
|
|
case EBADF: w_info("Bad file descriptor!"); break;
|
|
case EBUSY: w_info("Resource busy!"); break;
|
|
case ECHILD: w_info("No child processes!"); break;
|
|
case EEXIST: w_info("File exists!"); break;
|
|
case EFAULT: w_info("Bad address!"); break;
|
|
case EFBIG: w_info("File too large!"); break;
|
|
case EINTR: w_info("Interrupted system call!"); break;
|
|
case EINVAL: w_info("Invalid argument!"); break;
|
|
case EISDIR: w_info("Is a directory!"); break;
|
|
case EMFILE: w_info("Too many open files!"); break;
|
|
case ENFILE: w_info("Too many open files in system!"); break;
|
|
case ENOENT: w_info("No such file or directory!"); break;
|
|
case ENOEXEC: w_info("Unable to execute file!"); break;
|
|
case ENOMEM: w_info("Not enough memory!"); break;
|
|
default:
|
|
w_info("error during shelling");
|
|
}
|
|
waitkeyt(10000);
|
|
w_info(NULL);
|
|
}
|
|
|
|
// Reset tick values to avoid triggering screenblanker or timeout
|
|
gkbdtickpressreset();
|
|
gkbdtickvaluereset();
|
|
|
|
#if defined(GUTLOS_FUNCS)
|
|
g_set_ostitle_name(ge_temptitle, 1);
|
|
g_set_osicon();
|
|
#endif
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Error exit function
|
|
|
|
void ErrorExit(int type) {
|
|
|
|
static int in_error_exit = false;
|
|
|
|
if(not in_error_exit++) {
|
|
|
|
error_exit = type;
|
|
|
|
if(type) {
|
|
|
|
HandleGEvent(EVTT_ERRORFATAL);
|
|
|
|
if(_in_editor) {
|
|
LOG.printf("+ TIP: If you were writing a msg and want to recover it,");
|
|
LOG.printf("+ try looking in the %s file.", AddPath(CFG->goldpath, EDIT->File()));
|
|
}
|
|
|
|
// Dump the function tracker log
|
|
#if defined(GFTRK_ENABLE)
|
|
__gftrk_log();
|
|
#endif
|
|
|
|
if(type != 9)
|
|
errorlevel = EXIT_ERRORS;
|
|
else if(type == 5)
|
|
errorlevel = 100;
|
|
else
|
|
errorlevel = EXIT_CFGERR;
|
|
|
|
exit(errorlevel);
|
|
}
|
|
|
|
exit(EXIT_OK);
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|