home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CDPD Public Domain Collection for CDTV 3
/
CDPDIII.bin
/
pd
/
utilities
/
dirutils
/
visualshell
/
src
/
main_vsh.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-28
|
9KB
|
324 lines
/*********************************
* *
* Visual Shell v1.17 10/92 *
* *
* by Torsten Jürgeleit *
* *
* vsh main part *
* *
*********************************/
/* Includes */
#include "includes.h"
/* Defines */
#define MAX_ARGUMENTS 4
#define ARGUMENT_LEFT 0
#define ARGUMENT_RIGHT 1
#define ARGUMENT_HIDE 2
#define ARGUMENT_REMOVE 3
#define CTOB(cptr) ((BPTR)((ULONG)cptr >> 2)) /* Convert C ptr to BCPL ptr */
#define BTOC(bptr) ((VOID *)((ULONG)bptr << 2)) /* Convert BCPL ptr to C ptr */
#define MIN_VSH_WIDTH (USHORT)640 /* NTSC resolution */
#define MIN_VSH_HEIGHT (USHORT)200
#define VSH_PROCESS_NAME "VSh v1.17 for CLI %ld"
#define VSH_PROCESS_NAME_LEN 25
#define VSH_PROCESS_STACK_SIZE 4096
#define VSH_PROCESS_PRIORITY 0
/* Structures */
struct StartupMsg {
struct Message sm_Message;
struct Process *sm_CLIProcess;
struct Window *sm_ConWindow;
struct Device *sm_ConDevice;
struct ConUnit *sm_ConUnit;
BYTE *sm_LeftPath; /* path for left file requester */
BYTE *sm_RightPath; /* path for right file requester */
USHORT sm_Flags; /* used for HIDE flag */
};
/* Globals */
struct ArpBase *ArpBase;
/* Statics */
STATIC struct ProcessControlBlock seg_pcb;
STATIC struct StartupMsg seg_sm;
STATIC BYTE process_name[VSH_PROCESS_NAME_LEN + 1],
*vsh_segment = "l:VShSegment",
*template = "Left,Right,HIDE/S,REMOVE/S",
*xtra_help = "\nVSh v1.17 - Copyright © 1992 Torsten Jürgeleit\n\n"
"Usage: VSh [Left] [Right] [REMOVE] [HIDE]\n"
"\t[Left] = path for left file requester\n"
"\t[Right] = path for right file requester\n"
"\t[HIDE] = start VSh in hide mode\n"
"\t[REMOVE] = remove VSh segment from resident list\n";
/* Prototypes */
LONG _main(BYTE *arg_line, LONG arg_len);
BYTE *check_path(BYTE *path);
BOOL check_valid_start(struct Process *proc, struct StartupMsg *sm);
struct Window *get_con_window(struct Process *proc, struct StartupMsg *sm);
LONG start_vsh_segment(struct Process *proc, struct StartupMsg *sm);
/* Pragmas */
#pragma regcall(_main(a0,d0))
#pragma regcall(check_path(a0))
#pragma regcall(check_valid_start(a0,a1))
#pragma regcall(get_con_window(a0,a1))
#pragma regcall(start_vsh_segment(a0,a1))
/* Main - parses arguments and starts main segment */
LONG
_main(BYTE *arg_line, LONG arg_len)
{
LONG return_code = RETURN_FAIL;
/* First open ARP library */
if (!(ArpBase = OpenLibrary(ArpName, ArpVersion))) {
Write(Output(), "Need arp.library v39+\n", 22L);
} else {
BYTE *argv[MAX_ARGUMENTS];
USHORT i;
/* Clear argument array */
for (i = 0; i < MAX_ARGUMENTS; i++) {
argv[i] = NULL;
}
/* Parse command line arguments */
if (GADS(arg_line, arg_len, xtra_help, &argv[0], template) < 0) {
Puts(argv[0]);
} else {
/* Check arguments */
if (argv[ARGUMENT_REMOVE]) {
LONG usage;
/* Remove VSh segment from ARP resident list */
if (usage = RemResidentPrg(vsh_segment)) {
Printf("%s is [%ld] in use\n", vsh_segment, usage);
} else {
return_code = RETURN_OK;
}
} else {
struct StartupMsg *sm = &seg_sm;
BOOL error = FALSE;
if (argv[ARGUMENT_HIDE]) {
/* Set HIDE flag */
sm->sm_Flags = 1;
}
if (argv[ARGUMENT_LEFT]) {
/* Check given path for left file requester */
if (!(sm->sm_LeftPath = check_path(argv[ARGUMENT_LEFT]))) {
error = TRUE;
}
} else {
sm->sm_LeftPath = NULL;
}
if (argv[ARGUMENT_RIGHT]) {
/* Check given path for right file requester */
if (!(sm->sm_RightPath = check_path(argv[ARGUMENT_RIGHT]))) {
error = TRUE;
}
} else {
sm->sm_RightPath = NULL;
}
if (error == FALSE) {
struct ResidentProgramNode *rpn;
BPTR seg;
/* Check if VSh segment is already in ARP resident list */
if (rpn = ObtainResidentPrg(vsh_segment)) {
ReleaseResidentPrg(rpn->rpn_Segment);
} else {
/* Add VSh segment to ARP resident list */
if (!(seg = LoadPrg(vsh_segment + 2)) &&
!(seg = LoadPrg(vsh_segment))) {
Printf("Can't load '%s'\n", vsh_segment);
} else {
if (!(rpn = AddResidentPrg(seg, vsh_segment))) {
Printf("Can't add '%s' to ARP resident list\n",
vsh_segment);
UnLoadPrg(seg);
}
}
}
/* If VSh segment found then start it */
if (rpn) {
struct Process *proc = (struct Process *)FindTask(NULL);
if (check_valid_start(proc, sm) == TRUE) {
return_code = start_vsh_segment(proc, sm);
}
}
}
}
}
CloseLibrary(ArpBase);
}
return(return_code);
}
/* Check path for file requester */
STATIC BYTE *
check_path(BYTE *path)
{
struct FileInfoBlock *fib;
BPTR lock;
BYTE *error_msg = NULL;
if (!(lock = Lock(path, (LONG)SHARED_LOCK))) {
error_msg = "Can't lock path '%s'\n";
} else {
if (!(fib = AllocMem((LONG)sizeof(struct FileInfoBlock), (LONG)
MEMF_PUBLIC))) {
error_msg = "Out of memory\n";
} else {
if (Examine(lock, fib) == DOSFALSE) {
error_msg = "Examine() failed\n";
} else {
if (fib->fib_DirEntryType < 0) {
error_msg = "'%s' isn't a directory\n";
}
}
FreeMem(fib, (LONG)sizeof(struct FileInfoBlock));
}
UnLock(lock);
}
if (error_msg) {
Printf(error_msg, path);
path = NULL;
}
return(path);
}
/* Check for a valid start of VSh */
STATIC BOOL
check_valid_start(struct Process *proc, struct StartupMsg *sm)
{
struct CommandLineInterface *con_cli;
struct Window *con_win;
BYTE *error_msg = NULL;
BOOL success = FALSE;
/* VSh startet from CLI ? */
if (con_cli = BTOC(proc->pr_CLI)) {
/* VSh started with RUN ? */
if (con_cli->cli_Background == DOSTRUE) {
error_msg = "Don't start VSh with RUN !";
} else {
struct FileHandle *con_output_fh = BTOC(proc->pr_COS);
/* VSh startet from ConMan console window ? */
if ((struct FileHandle *)con_output_fh->fh_Arg1 != con_output_fh) {
error_msg = "Need a ConMan console window !";
} else {
if (!(con_win = get_con_window(proc, sm))) {
error_msg = "Can't find console window !";
} else {
/* Check window dimension */
if (con_win->WScreen->Width < MIN_VSH_WIDTH) {
error_msg = "Workbench screen to small (min. 640) !";
} else {
struct TextFont *con_tf = con_win->RPort->Font;
/* Check text font used by this CLI */
if (con_tf->tf_XSize != 8 || con_tf->tf_YSize != 8 ||
(con_tf->tf_Flags & FPF_PROPORTIONAL)) {
error_msg = "Only 8x8 nonproportional fonts allowed !";
} else {
/* Check if VSh already started for this CLI */
SPrintf(&process_name[0], VSH_PROCESS_NAME,
proc->pr_TaskNum);
if (FindPort(&process_name[0])) {
error_msg = "Can't start VSh for this CLI twice !";
} else {
success = TRUE;
}
}
}
}
}
}
if (error_msg) {
Puts(error_msg);
}
}
return(success);
}
/* Get pointer to the console window our process started from */
STATIC struct Window *
get_con_window(struct Process *proc, struct StartupMsg *sm)
{
struct Window *win = NULL;
struct IOStdReq *req;
struct InfoData *id;
if (((struct Task *)proc)->tc_Node.ln_Type == NT_PROCESS) {
if (id = AllocMem((LONG)sizeof(struct InfoData), (LONG)MEMF_PUBLIC)) {
if (dos_packet((struct MsgPort *)proc->pr_ConsoleTask, (LONG)
ACTION_DISK_INFO, CTOB(id)) == DOSTRUE) {
win = (struct Window *)id->id_VolumeNode;
req = (struct IOStdReq *)id->id_InUse;
sm->sm_ConWindow = win;
sm->sm_ConDevice = req->io_Device;
sm->sm_ConUnit = (struct ConUnit *)req->io_Unit;
}
FreeMem(id, (LONG)sizeof(struct InfoData));
}
}
return(win);
}
/* Start VSh segment */
STATIC LONG
start_vsh_segment(struct Process *proc, struct StartupMsg *sm)
{
struct ProcessControlBlock *pcb = &seg_pcb;
LONG return_code = RETURN_FAIL;
/* Init process control block and start VSh segment */
pcb->pcb_StackSize = VSH_PROCESS_STACK_SIZE;
pcb->pcb_Pri = VSH_PROCESS_PRIORITY;
pcb->pcb_Control = PRF_NOCLI;
if (ASyncRun(vsh_segment, NULL, pcb) < 0) {
Printf("Can't run '%s'\n", vsh_segment);
} else {
struct MsgPort *mp = &proc->pr_MsgPort;
/* Init startup msg and send it to VSh segment */
sm->sm_Message.mn_ReplyPort = mp;
sm->sm_Message.mn_Length = sizeof(struct StartupMsg);
sm->sm_CLIProcess = proc;
PutMsg(pcb->pcb_WBProcess, &sm->sm_Message);
/* Wait for reply of startup msg */
WaitPort(mp);
GetMsg(mp);
return_code = RETURN_OK;
}
return(return_code);
}