home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
archiver
/
zoossr06
/
zooshell.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-08
|
15KB
|
625 lines
/*
* ZOOSHELL.C
* A GEM-based shell for painlessly invoking the ZOO archiver
* Author: Steve Yelvington
* Internet <steve@thelake.mn.org>
* GEnie S.YELVINGTO2
* This program is hereby released to the public domain.
* You are solely responsible for any use you make of it.
*/
#define VERSION "ZOOSHELL Version 0.6 beta"
#ifdef APSTART /* If using APSTART.O instead of DSTART.O, */
/* some kludgery to get around peculiarities of dLibs */
#define NULL (void *)(0)
#define exit Pterm
#define FALSE (0)
#define TRUE (!FALSE)
#define ERROR (-1)
int errno;
#else
#include <stdio.h>
#endif
#include <osbind.h> /* Atari operating system bindings */
#include <gemfast.h> /* you may prefer gemdefs.h and obdefs.h */
#include <macros.h> /* abs, loword/hiword, etc. */
#include <limits.h> /* standard limits such as PATHSIZ */
#include <string.h> /* values returned by string functions */
#include "zooshell.h" /* file generated by resource editor */
#define RESOURCE_FILE "zooshell.rsc"
#define STDOUT 1 /* GEMDOS handle */
#define STDPRN 3 /* GEMDOS handle */
#define CON 2 /* BIOS device number */
OBJECT *menubar; /* pointer for resource menu */
char cwd[PATHSIZE]; /* current working directory */
char zoottp[PATHSIZE]; /* name of ZOO program */
int m_hidden; /* mouse hidden flag */
char mycmd[256]; /* command buffer for launching ZOO */
char myargs[256]; /* argument buffer for launching ZOO */
int confh,outfh; /* file handles for redirection */
extern char *h_ex[], /* help screens from zoohelp.c */
*h_rest[], *h_view[],
*h_spec[], *h_buttons[];
/*
* Function: g_clrscr()
* Returns: void
* Description: Instructs GEM to redraw the workspace
*/
void g_clrscr()
{
int x,y,w,h;
wind_get(0,WF_FULLXYWH,&x,&y,&w,&h); /* get desktop dimensions */
form_dial(FMD_START,1,1,1,1,x,y,w,h); /* this may be unnecessary */
form_dial(FMD_FINISH,1,1,1,1,x,y,w,h); /* generate redraw msg */
}
/*
* Function: hide_mouse
* Returns: void
* Description: hide the mouse and set the m_hidden flag
*/
void hide_mouse()
{
if (m_hidden) return;
graf_mouse(M_OFF,NULL);
m_hidden = TRUE;
}
/*
* Function: show_mouse
* Returns: void
* Description: if the mouse is hidden, show the mouse and set the flag
*/
void show_mouse()
{
if (m_hidden)
{
graf_mouse(M_ON,NULL);
m_hidden = FALSE;
}
}
/*
* Function: show_about()
* Returns: void
* Description: Shows the ABOUTBOX until 4-second timeout or mouse click
* Note: This function uses the GEMFAST evnx_multi function, which is
* available in C source code if you don't have GEMFAST.
*/
void show_about()
{
OBJECT *aboutbox;
XMULTI xm;
int x,y,w,h;
static long delay;
delay = 4*1000L;
rsrc_gaddr(0,ABOUTBOX, &aboutbox);
hide_mouse();
form_center(aboutbox, &x, &y, &w, &h);
form_dial(FMD_START,1,1,1,1,x,y,w,h);
form_dial(FMD_GROW,1,1,1,1,x,y,w,h);
objc_draw(aboutbox, 0, 10, x, y, w, h);
show_mouse();
/* now wait for timer, keyboard or button activity */
xm.mflags = MU_TIMER|MU_KEYBD|MU_BUTTON;
xm.mtlocount = loword(delay);
xm.mthicount = hiword(delay);
xm.mbclicks = 1; /* wait for single */
xm.mbmask = 1; /* click of left */
xm.mbstate = 1; /* button */
evnx_multi(&xm);
form_dial(FMD_SHRINK,1,1,1,1,x,y,w,h);
form_dial(FMD_FINISH,1,1,1,1,x,y,w,h);
}
/*
* Function: do_dialog
* Returns: index of exit object
* Description: This smart wrapper for form_dial handles centering, etc.
*/
int do_dialog(ind)
int ind;
{
OBJECT *form;
int exit_obj;
int x,y,w,h;
rsrc_gaddr(0,ind,&form);
hide_mouse();
form_center(form, &x, &y, &w, &h);
form_dial(FMD_START,1,1,1,1,x,y,w,h);
form_dial(FMD_GROW,1,1,1,1,x,y,w,h);
objc_draw(form, 0, 10, x, y, w, h);
show_mouse();
exit_obj = form_do(form, 0);
hide_mouse();
form_dial(FMD_SHRINK,1,1,1,1,x,y,w,h);
form_dial(FMD_FINISH,1,1,1,1,x,y,w,h);
form[exit_obj].ob_state = NORMAL;
show_mouse();
return(exit_obj);
}
/*
* Function: forcedir
* Returns: void
* Description: combines set-drive and set-path functions into one call
*/
void forcedir(d)
char *d;
{
Dsetdrv(((int)d[0]) - 'A');
Dsetpath(&d[2]);
}
/*
* Function: change_dir
* Returns: void
* Description: Prompt user with a file selector and change directories
* as appropriate
*/
void change_dir()
{
char file[14];
int status;
char *p;
file[0] = '\0';
getcwd(cwd,PATHSIZE);
strupr(cwd);
status = fsel_exinput(cwd,file, &status, "Select directory for output");
if (p=strrchr(cwd,'\\'))
*p = '\0';
if (status)
forcedir(cwd);
}
/*
* Function: fsel
* Returns: 0 if [CANCEL], 1 if [OK]
* Description: Display the GEM file selector, including a prompt if
* one is supplied. The path and default filename will
* be shown, if supplied. Convert the user's input into
* a complete filename and copy the result into the
* supplied buffer.
*
* Side effects: fsel remembers the previous values of inpath and default
* filename and uses them if those args are NULL
*/
int fsel(prompt, path, insel, filename)
char *prompt, /* message to user, or NULL */
*path, /* initial path, or NULL */
*insel, /* initial filename, or NULL */
*filename; /* 128-byte buffer for full selected name */
{
static char xpath[128], xinsel[14];
char *p;
int button;
if (!prompt)
prompt = "Please choose a file";
if (!path)
{
xpath[0] = Dgetdrv() + 'A';
xpath[1] = ':';
Dgetpath(&xpath[2],(int)(xpath[0]-'A'+1));
strcat(xpath,"\\*.*");
path = xpath;
}
if (!strchr(path,':')) /* nonabsolute path */
{
xpath[0] = Dgetdrv() + 'A';
xpath[1] = ':';
Dgetpath(&xpath[2],(int)(xpath[0]-'A'+1));
strcat(xpath,"\\");
strcat(xpath,path);
}
else if (path != xpath)
strcpy(xpath,path);
if (insel)
strcpy(xinsel,insel);
fsel_exinput(xpath,xinsel,&button,prompt);
if (!button)
return button;
strcpy(filename,xpath);
if (p = strrchr(filename,'\\'))
*++p = '\0';
else if (p = strrchr(filename,':'))
*++p = '\0';
else if (p = strchr(filename,'*'))
*p = '\0';
else
{
strcat(filename,"\\");
p = filename + strlen(filename);
}
strcpy(p,xinsel);
return button;
}
/*
* Function: Bconws
* Returns: void
* Description: Like Cconws, but to redirection-proof BIOS device
*/
void Bconws(dev,s)
int dev;
char *s;
{
while (*s)
Bconout(dev,*s++);
}
/*
* Function: xparse_args
* Returns: void
* Description: Parse a command line into an argv array
* (modified from dlibs)
*/
void xparse_args(cmdln, argv)
char *cmdln;
register char *argv[];
{
register char *p;
static char delim[] = " \t\r\n";
if(p = strtok(cmdln, delim))
{
do
{
*argv++ = p;
}
while(p = strtok(NULL, delim));
}
}
/*
* Function: xsystem
* Returns: the value returned by a child process
* Description: this is a simple, system()-like interface to
* invoke fork/wait in a palatable fashion. It's
* modified from dlibs; basically this is system()
* without the _shell_p support. I don't want to
* pass commands to a shell because I don't want
* to give it the opportunity to mangle the args
* ... this lets me control exactly what ZOO sees.
*/
int xsystem(command)
register char *command;
{
register char *p;
char rv[2];
char cmdln[1024];
char *args[64];
if(!command)
return(ERROR);
strcpy(cmdln, command);
xparse_args(cmdln, args);
p = args[0];
forkvpe(p, args, NULL);
wait(rv);
return((rv[1] == 0) ? rv[0] : rv[1]);
}
/*
* Function: exzoo
* Returns: void
* Description: Prompt the user for a ZOO file name. Then, if flag is
* true, prompt the user for a file to process. Build
* a command line including the cmd argument, and then
* clear the screen and invoke xsystem. Restore the
* GEM screen afterward.
*/
void exzoo(cmd,flag,prompt)
char *cmd;
int flag;
char *prompt;
{
char insel[14];
int rv;
insel[0] = '\0';
strcpy(mycmd,zoottp);
strcat(mycmd,cmd);
if (!fsel("Choose ZOO file to process","*.ZOO",insel,myargs))
return;
strcat(mycmd," ");
strcat(mycmd,myargs);
if (strcmp(cmd,"-backup") ==0)
strcat(mycmd," *");
if (flag) /* get more args */
{
myargs[0] = '\0';
if (!fsel(prompt,"*.*",insel,myargs))
return;
strcat(mycmd," ");
strcat(mycmd,myargs);
}
/* now clear the screen, run ZOO, and restore the screen */
menu_bar(menubar,FALSE);
hide_mouse();
Bconws(CON,"\033E\033e"); /* cls, home, cursor on */
Bconws(CON,"Setting current directory: ");
Bconws(CON,cwd);
Bconws(CON,"\r\n");
forcedir(cwd);
Bconws(CON,"Current directory set to: ");
Bconout(CON,Dgetdrv() + 'A');
Bconout(CON,':');
{
char buf[PATHSIZE];
Dgetpath(buf, Dgetdrv()+1);
Bconws(CON,buf);
}
Bconws(CON,"\r\n");
Bconws(CON,"Executing command xsystem( ");
Bconws(CON,mycmd);
Bconws(CON," )\r\n");
if ((rv = xsystem(mycmd)) < 0)
{
show_mouse();
form_error(abs(rv));
}
else
{
Bconws(CON,"\a**** Strike any key to continue ****");
Bconin(CON);
}
Bconws(CON,"\033E\033f"); /* cls, home, cursor off */
g_clrscr();
menu_bar(menubar,TRUE);
show_mouse();
}
/*
* Function: notimpl
* Returns: void
* Description: Displays informative message for unimplemented features
*/
void notimpl()
{
form_alert(1,"[0][That option is|not yet|implemented][Sorry]");
}
/*
* Function: load_resource
* Returns: TRUE if the resource was loaded, else FALSE.
* Description: This is just a standard wrapper.
*/
int load_resource(rfile)
char *rfile;
{
if (!rsrc_load(rfile))
{
form_alert(1,"[0][Can't find|resource file][EXIT]");
return(FALSE);
}
return(TRUE);
}
/*
* Function: prt_output
* Returns: TRUE or FALSE depending on whether redirection succeeded.
* Description: Redirects GEMDOS console output to the printer device.
* If the printer is not ready, redirection is considered
* to have failed.
*/
int prt_output()
{
if (!Cprnos())
{
form_alert(1,"[0][Printer not ready!][Oops]");
return FALSE;
}
confh = Fdup(STDOUT);
if (confh < 0)
{
form_alert(1,"[0][Fdup() failed!][Oops]");
form_error(abs(confh));
return FALSE;
}
outfh = Fopen("PRN:",1);
if (outfh < -3)
{
form_alert(1,"[0][Fopen() failed!][Oops]");
form_error(abs(outfh));
return FALSE;
}
if (Fforce(STDOUT,outfh))
{
form_alert(1,"[0][Fforce() failed!][Oops]");
return FALSE;
}
return TRUE;
}
/*
* Function: restore_output
* Returns: void
* Description: Close redirected file handles and restore the originals.
*/
void restore_output()
{
if (outfh)
{
Fclose(outfh);
outfh = 0;
}
Fforce(STDOUT,confh);
}
/*
* Function: do_menuitem
* Returns: void
* Description: Respond to a user's menu action; dispatch appropriately.
*/
void do_menuitem(title,item)
int title, item;
{
menu_tnormal(menubar,title,TRUE);
menu_tnormal(menubar,item,TRUE);
switch (item)
{
case MNABOUT :
do_dialog(ABOUTBOX);
return;
case QUIT :
g_clrscr();
rsrc_free();
appl_exit();
exit(0);
case CHDIR :
change_dir();
return;
/* the help functions */
case WHATIS :
do_dialog(FWHATIS);
return;
case HELPEX :
frm_dsdial(h_ex, h_buttons, TRUE);
return;
case HELPREST :
frm_dsdial(h_rest, h_buttons, TRUE);
return;
case HELPVIEW :
frm_dsdial(h_view, h_buttons, TRUE);
return;
case HELPSPEC :
frm_dsdial(h_spec, h_buttons, TRUE);
return;
/* the rest of the cases will spawn ZOO */
/* here are the adds */
case ADD :
exzoo("-add",TRUE,"Choose file to add");
break;
case MOVE :
exzoo("-move",TRUE,"Choose file to move");
break;
case BACKUP :
exzoo("-backup",FALSE,NULL);
break;
case COMMENT :
exzoo("-comment",FALSE,NULL);
break;
/* here are the extracts */
case EXTRACT :
exzoo("x",FALSE,NULL);
break;
case PRINT :
notimpl();
break;
case PRINTPRN :
notimpl();
break;
case RESTORE :
exzoo("x//",FALSE,NULL);
break;
case RELATIVE :
exzoo("x.//",FALSE,NULL);
break;
case LIST :
exzoo("-list",FALSE,NULL);
break;
case LISTPRN :
if (prt_output())
{
exzoo("-list",FALSE,NULL);
restore_output();
}
break;
case TEST :
exzoo("-test",FALSE,NULL);
break;
default:
notimpl();
break;
}
}
/*
* Function: maintevent
* Returns: void
* Description: Call the GEMFAST evnx_multi function and wait for
* a menu message. Pass the results to do_menuitem.
* Note: This function uses the GEMFAST evnx_multi function, which is
* available in C source code if you don't have GEMFAST.
*/
void mainevent()
{
XMULTI xm;
int events;
xm.mflags = MU_MESAG;
while (1)
{
events = evnx_multi(&xm);
if (events & MU_MESAG)
if (xm.msgbuf[0] == MN_SELECTED)
do_menuitem(xm.msgbuf[3], xm.msgbuf[4]);
}
}
/*
* Function: main
* Returns: Only returns on failure, in which case an error value is set.
* Description: Initialize GEM, load the resource, find ZOO, and otherwise
* prepare for mainevent.
*/
main()
{
void g_clrscr();
char *pfindfile();
char *fullpath();
char *p;
appl_init();
g_clrscr();
if (!load_resource(RESOURCE_FILE))
{
appl_exit();
exit(-1);
}
rsrc_gaddr(0,MENUBAR, &menubar);
menu_bar(menubar,TRUE);
graf_mouse(ARROW,NULL);
show_about();
cwd[0] = Dgetdrv() + 'A';
cwd[1] = ':';
Dgetpath(&cwd[2],(int)(cwd[0]-'A'+1));
if (access("ZOO.TTP",0))
p = fullpath(NULL,"ZOO.TTP");
else if (!(p = pfindfile(NULL,"ZOO.TTP",NULL)))
{
if (!fsel("Where is the ZOO program?","ZOO*.TTP",NULL,zoottp))
{
form_alert(1,"[0][ZOO.TTP must be available][Exit]");
appl_exit();
exit(-1);
}
}
strcpy(zoottp,p);
strcat(zoottp," ");
mainevent();
/* There should be no path to this, but just to be safe ... */
g_clrscr();
rsrc_free();
appl_exit();
}
/* EOF */