home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 */
-