/*-- AutoRev header do NOT edit! * * Program : dcback.c * Copyright : © 1991 Jaba Development * Author : Jan van den Baard * Creation Date : 16-Nov-91 * Current version : 1.2 * Translator : DICE v2.6. * * REVISION HISTORY * * Date Version Comment * --------- ------- ------------------------------------------ * 29-Feb-92 1.2 Now uses "SetArgStr()". * 23-Nov-91 1.1 Command line promting now allowed. * 16-Nov-91 1.0 Auto detach 2.0 argument parsing startup. * *-- REV_END --*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * --- These globals MUST be defined somewhere in your source! */ extern UBYTE *_procname; /* process name */ extern UBYTE *_template; /* commandline template */ extern UBYTE *_exthelp; /* extended command line help */ extern LONG _stack; /* process stack */ extern LONG _priority; /* process priority */ extern LONG _BackGroundIO; /* open background io channel */ /* * --- externally referenced structures. */ extern struct ExecBase *SysBase; /* to check for V36 minimum */ extern struct WBStartup *_WBMsg; /* guess what.... */ /* * --- This is how both main() and wbmain() are called. */ extern long main( long, long * ); extern long wbmain( struct WBStartup * ); /* * --- Proto for the exit routine */ long exit( long ); /* * --- Data that isn't chucked in the BSS section. */ BPTR _DetachDir = 0l; /* process current dir */ BPTR _Backstdout = 0l; /* io channel */ UBYTE _IsDetached = FALSE; /* detached flag */ ULONG *_DosArray = 0l; /* commandline array */ UWORD _NumArgs = 0l; /* max # of args */ UBYTE *_Arguments = 0l; /* argument line */ struct RDArgs *_DosSource = 0l; /* for the arguments */ /* * --- New _main() which checks if it is run from the shell or * --- the workbench. */ __stkargs long _main( long len, char *lin ) { struct Process *ThisTask; struct CommandLineInterface *cli; struct MemList *mlist; BPTR *SegList, *TmpSeg, StdOut; ULONG SegCount = 0l, ArgCount = 0l; BYTE DetachRun = FALSE; UBYTE *Tmp; ULONG alert; /* * --- First we must see wether we are running * --- under 2.0 or not. We need 2.0 for the * --- commandline parsing! */ if ((( struct Library *)SysBase)->lib_Version < 36 ) return( RETURN_FAIL ); /* * --- Get a pointer to our Task (Process) */ ThisTask = ( struct Process * )SysBase->ThisTask; /* * --- When run from the shell the process has * --- a CLI structure. If this is the case * --- the 'DetachRun' flag is set to TRUE so we * --- we know that the program still has to be * --- detached. */ if ( ThisTask->pr_CLI ) DetachRun = TRUE; /* * --- When either the 'DetachRun' or '_IsDetached' flag * --- is TRUE it means that we are run from the shell. */ if ( DetachRun || _IsDetached ) { /* * --- Check if we are detached yet... */ if ( ! _IsDetached ) { /* * --- We arn't detached yet so we must parse * --- the arguments given to us by the shell. */ if ( Tmp = _template ) { /* * --- There is a template string supplied */ if ( *Tmp ) { /* * --- The template string even got characters in it! * --- Now we must count the maximum number of arguments * --- we can expect. This is done by counting the * --- commas in the template string and then adding * --- one to the result */ while ( *Tmp ) { if ( *Tmp == ',' ) ArgCount++; Tmp++; } ArgCount++; } } /* * --- Allocate and parse the arguments. */ if ( ArgCount ) { /* * --- There are arguments to be expected. */ _NumArgs = ArgCount; /* save argument count */ _Arguments = lin; /* save the argument line pointer */ /* * --- Allocate our RDArgs structure. */ if ( ! ( _DosSource = ( struct RDArgs * )AllocVec((long)sizeof( struct RDArgs ), MEMF_PUBLIC | MEMF_CLEAR ))) { alert = AT_Recovery | AG_NoMemory | AO_Unknown; goto suError; } /* * --- Setup the RDArgs structure for extended help. */ _DosSource->RDA_ExtHelp = _exthelp; /* * --- Try to allocate the array that will hold * --- the result of the parse. */ if ( ! (_DosArray = (ULONG *)AllocVec( ArgCount * sizeof( LONG ), MEMF_PUBLIC | MEMF_CLEAR ))) { alert = AT_Recovery | AG_NoMemory | AO_Unknown; goto suError; } /* * --- Try to parse the arguments from STDIN. */ if ( ! ReadArgs( _template, _DosArray, _DosSource )) { if ( StdOut = Output()) Write( StdOut, "Bad Args\n", 9l ); alert = 0l; goto suError; } } } /* * --- This code only get's executed when the program * --- was started from the shell and isn't detached yet. */ if ( cli = ( struct CommandLineInterface * )BADDR( ThisTask->pr_CLI )) { /* * --- Get a copy of the lock to the current directory */ CurrentDir( _DetachDir = CurrentDir( 0l )); _DetachDir = DupLock( _DetachDir ); /* * --- Mark us as detached ( a little premature but so what.. ) */ _IsDetached = TRUE; /* * --- Open a io channel if requested */ if ( _BackGroundIO ) _Backstdout = Open( "*", MODE_OLDFILE ); /* * --- Sanity check. If the stack is 0 then make the stack 4096 */ if ( ! _stack ) _stack = 4096l; /* * --- Try to launch us as a non-cli process */ if ( CreateProc( _procname, _priority, cli->cli_Module, _stack )) { /* * --- Don't rip the code out from under us */ cli->cli_Module = 0l; /* * --- We must make sure that dos doesn't deallocate * --- our arguments before we get a chance to use * --- them. */ SetArgStr( 0l ); return ( RETURN_OK ); } else { alert = AT_Recovery | AG_ProcCreate | AO_Unknown; goto suError; } } else { /* * --- Getting here means that we now run as a non-cli * --- process initially started from a shell. */ if ( ! strcmp( ThisTask->pr_Task.tc_Node.ln_Name, _procname )) { /* * --- Now we are running detached we must make sure that * --- dos deallocates the commandline (if there) when * --- we exit. */ SetArgStr( _Arguments ); /* * --- Now we must make sure that we get deallocated * --- when the program exits. This is done by creating * --- a MemList with pointers to all our segments in * --- it and then AddTail'ing this to the Task it's * --- MemList which automatically get's deallocated * --- by the system. */ SegList = ( BPTR * )BADDR( ThisTask->pr_SegList ); SegList = ( BPTR * )BADDR( SegList[3] ); TmpSeg = SegList; /* * --- Count the number of segments we have. */ while ( SegList ) { SegList = ( BPTR * )BADDR( *SegList ); SegCount++; } /* * --- Try to allocate a MemList with enough MemEntry's * --- I didn't use AllocVec because the system deallocates * --- this structure itself with FreeMem() and not FreeVec() * --- (I think........) */ if ( mlist = ( struct MemList * )AllocMem( sizeof( struct MemList ) + sizeof( struct MemEntry ) * ( SegCount - 1 ), MEMF_PUBLIC | MEMF_CLEAR )) { SegList = TmpSeg; mlist->ml_NumEntries = SegCount; SegCount = 0l; /* * --- Initialize all MemEntries */ while ( SegList ) { mlist->ml_me[ SegCount ].me_Addr = (APTR)&SegList[ -1 ]; mlist->ml_me[ SegCount ].me_Length = SegList[ -1 ]; SegList = ( BPTR * )BADDR( *SegList ); SegCount++; } /* * --- Add our MemList to the Task it's MemList. */ AddTail( &ThisTask->pr_Task.tc_MemEntry, &mlist->ml_Node ); /* * --- Set our current dir */ CurrentDir( _DetachDir ); /* * --- If an io channel was requested we must * --- initialize the proper stdio structures */ if ( _BackGroundIO ) { ThisTask->pr_COS = _Backstdout; _IoStaticFD[1].fd_Fh = _Backstdout; _IoStaticFD[1].fd_Flags = O_RDWR | O_NOCLOSE | O_ISOPEN; _IoStaticFD[2].fd_Fh = _Backstdout; _IoStaticFD[2].fd_Flags = O_RDWR | O_NOCLOSE | O_ISOPEN; _finitdesc( stdout, 1, __SIF_WRITE | __SIF_NOFREE ); _finitdesc( stderr, 2, __SIF_WRITE | __SIF_NOFREE ); } /* * --- Now we just exit with whatever main() * --- returns to us. */ exit( main( (long)_NumArgs, _DosArray )); } else { alert = AT_Recovery | AG_NoMemory | AO_Unknown; goto suError; } } } } else { /* * --- Getting here means we have been started from the workbench. */ if ( _WBMsg->sm_ArgList ) /* * --- CurrentDir to the directory we are started from */ CurrentDir( _WBMsg->sm_ArgList->wa_Lock ); /* * --- Now we just exit with whatever wbmain() * --- returns to us. */ exit( wbmain( _WBMsg )); } /* * --- This is never called! It just brings in the code that * --- waits for the Workbench message for when we are started * --- from the workbench! See wbmain.a! */ _waitwbmsg(); /* * --- Here's where we land when something failed. * --- This cleans up the mess we made except when we * --- got here because the MemList could not be * --- allocated! If that's the case the segments wont * --- be deallocated. This shouldn't be a problem * --- because when the MemList cannot be allocated anymore * --- your system is really fuc#@$$##@ up! */ suError: if ( _DosSource ) { FreeArgs( _DosSource ); FreeVec( _DosSource ); } if ( _DosArray ) FreeVec( _DosArray ); if ( _DetachDir ) UnLock( _DetachDir ); if ( alert ) Alert( alert ); return( RETURN_FAIL ); } #include typedef struct Process Process; AtExit *_ExitBase; /* * --- A New exit which cleans up the mess we made. */ long exit( long code ) { AtExit *eb; /* * --- If opened, close the io channel */ if ( _Backstdout ) Close( _Backstdout ); /* * --- UnLock our current dir */ if ( _DetachDir ) UnLock( _DetachDir ); /* * --- Deallocate our argument array */ if ( _DosArray ) FreeVec( _DosArray ); /* * --- Cleanup our RDArgs structure */ if ( _DosSource ) { FreeArgs( _DosSource ); FreeVec( _DosSource ); } /* * --- Ask Matthew...... I don't know! */ for (eb = _ExitBase; eb; eb = eb->Next) (*eb->Func)(); /* * --- Low level exit */ _exit(code); }