/* * "Roadshow" Amiga TCP/IP stack * * :ts=4 * * Copyright © 2001-2019 by Olaf Barthel. All Rights Reserved. */ #include #include #include #include #include #include #include #include #include /****************************************************************************/ #if defined(__amigaos4__) #include #endif /* __amigaos4__ */ /****************************************************************************/ #if !defined(__amigaos4__) #define NO_INLINE_STDARG #endif /* __amigaos4__ */ #define __NOLIBBASE__ #define __NOGLOBALIFACE__ #define __USE_INLINE__ /****************************************************************************/ #include #include #include #include /****************************************************************************/ #include #include /****************************************************************************/ #include "macros.h" /****************************************************************************/ #include "RemoveNetInterface_rev.h" /****************************************************************************/ #ifndef AbsExecBase #define AbsExecBase (*(struct ExecBase **)4) #endif /* AbsExecBase */ /****************************************************************************/ typedef LONG * NUMBER; typedef LONG SWITCH; typedef STRPTR KEY; /****************************************************************************/ struct CommandContext { struct Library * cc_SysBase; struct Library * cc_DOSBase; struct Library * cc_SocketBase; struct Library * cc_LocaleBase; #if defined(__amigaos4__) /************************************************************************/ struct ExecIFace * cc_IExec; struct DOSIFace * cc_IDOS; struct SocketIFace * cc_ISocket; struct LocaleIFace * cc_ILocale; /************************************************************************/ #endif /* __amigaos4__ */ struct Catalog * cc_Catalog; UBYTE cc_ProgramName[256]; }; /****************************************************************************/ #if defined(__amigaos4__) /****************************************************************************/ #define DECLARE_SYSBASE(cc) \ struct ExecIFace * IExec = cc->cc_IExec; \ struct Library * SysBase = cc->cc_SysBase #define DECLARE_DOSBASE(cc) \ struct DOSIFace * IDOS = cc->cc_IDOS; \ struct Library * DOSBase = cc->cc_DOSBase #define DECLARE_LOCALEBASE(cc) \ struct LocaleIFace * ILocale = cc->cc_ILocale; \ struct Library * LocaleBase = cc->cc_LocaleBase #define DECLARE_SOCKETBASE(cc) \ struct SocketIFace * ISocket = cc->cc_ISocket; \ struct Library * SocketBase = cc->cc_SocketBase /****************************************************************************/ #else /****************************************************************************/ #define DECLARE_SYSBASE(cc) \ struct Library * SysBase = cc->cc_SysBase #define DECLARE_DOSBASE(cc) \ struct Library * DOSBase = cc->cc_DOSBase #define DECLARE_LOCALEBASE(cc) \ struct Library * LocaleBase = cc->cc_LocaleBase #define DECLARE_SOCKETBASE(cc) \ struct Library * SocketBase = cc->cc_SocketBase /****************************************************************************/ #endif /* __amigaos4__ */ /****************************************************************************/ LONG _start(VOID); /****************************************************************************/ STATIC VOID close_libs(struct CommandContext *cc); STATIC LONG open_libs(struct CommandContext *cc, struct Library *SysBase); STATIC LONG cmd(struct CommandContext *cc); STATIC LONG VARARGS68K Local_Printf(struct CommandContext *cc, STRPTR format, ...); STATIC LONG VARARGS68K Local_ErrorPrintf(struct CommandContext *cc, STRPTR format, ...); STATIC STRPTR get_builtin_str(LONG id); STATIC STRPTR get_str(struct CommandContext *cc, LONG id); STATIC LONG VARARGS68K Local_SocketBaseTags(struct CommandContext *cc, ...); /****************************************************************************/ LONG _start(VOID) { struct Library *SysBase = (struct Library *)AbsExecBase; #if defined(__amigaos4__) struct ExecIFace * IExec = (struct ExecIFace *)((struct ExecBase *)SysBase)->MainInterface; #endif /* __amigaos4__ */ struct CommandContext _cc,*cc = &_cc; LONG result = RETURN_FAIL; struct Process * pr; LONG error; memset(cc,0,sizeof(*cc)); pr = (struct Process *)FindTask(NULL); if(pr->pr_CLI == ZERO) { struct MsgPort * mp = &pr->pr_MsgPort; struct Message * mn; WaitPort(mp); mn = GetMsg(mp); Forbid(); ReplyMsg(mn); goto out; } error = open_libs(cc,SysBase); if(error == OK) { DECLARE_LOCALEBASE(cc); if(cc->cc_LocaleBase != NULL) cc->cc_Catalog = OpenCatalogA(NULL,"roadshow.catalog",NULL); result = cmd(cc); if(cc->cc_Catalog != NULL) CloseCatalog(cc->cc_Catalog); } else { pr->pr_Result2 = error; } close_libs(cc); out: return(result); } /****************************************************************************/ STATIC VOID close_libs(struct CommandContext * cc) { DECLARE_SYSBASE(cc); #if defined(__amigaos4__) { if(cc->cc_IDOS != NULL) DropInterface((struct Interface *)cc->cc_IDOS); if(cc->cc_ILocale != NULL) DropInterface((struct Interface *)cc->cc_ILocale); if(cc->cc_ISocket != NULL) DropInterface((struct Interface *)cc->cc_ISocket); } #endif /* __amigaos4__ */ if(cc->cc_SocketBase != NULL) CloseLibrary(cc->cc_SocketBase); if(cc->cc_LocaleBase != NULL) CloseLibrary(cc->cc_LocaleBase); if(cc->cc_DOSBase != NULL) CloseLibrary(cc->cc_DOSBase); } /****************************************************************************/ STATIC LONG open_libs(struct CommandContext * cc,struct Library *SysBase) { #if defined(__amigaos4__) struct ExecIFace * IExec = (struct ExecIFace *)((struct ExecBase *)SysBase)->MainInterface; #endif /* __amigaos4__ */ LONG error; cc->cc_SysBase = SysBase; #if defined(__amigaos4__) { cc->cc_IExec = IExec; } #endif /* __amigaos4__ */ cc->cc_DOSBase = OpenLibrary("dos.library",36); #if defined(__amigaos4__) { if(cc->cc_DOSBase != NULL) { cc->cc_IDOS = (struct DOSIFace *)GetInterface(cc->cc_DOSBase, "main", 1, 0); if(cc->cc_IDOS == NULL) { CloseLibrary(cc->cc_DOSBase); cc->cc_DOSBase = NULL; } } } #endif /* __amigaos4__ */ if(cc->cc_DOSBase == NULL) { error = ERROR_INVALID_RESIDENT_LIBRARY; goto out; } cc->cc_LocaleBase = OpenLibrary("locale.library",38); #if defined(__amigaos4__) { if(cc->cc_LocaleBase != NULL) { cc->cc_ILocale = (struct LocaleIFace *)GetInterface(cc->cc_LocaleBase, "main", 1, 0); if(cc->cc_ILocale == NULL) { CloseLibrary(cc->cc_LocaleBase); cc->cc_LocaleBase = NULL; } } } #endif /* __amigaos4__ */ /* The following may be necessary to flush out an inoperable bsdsocket.library which reached the end of the shutdown process. */ #if 1 { struct ExecBase * ex = (struct ExecBase *)SysBase; struct Library * lib; Forbid(); lib = (struct Library *)FindName(&ex->LibList,"bsdsocket.library"); if(lib != NULL) RemLibrary(lib); Permit(); } #endif cc->cc_SocketBase = OpenLibrary("bsdsocket.library",4); #if defined(__amigaos4__) { if(cc->cc_SocketBase != NULL) { cc->cc_ISocket = (struct SocketIFace *)GetInterface(cc->cc_SocketBase, "main", 1, 0); if(cc->cc_ISocket == NULL) { CloseLibrary(cc->cc_SocketBase); cc->cc_SocketBase = NULL; } } } #endif /* __amigaos4__ */ error = OK; out: return(error); } /****************************************************************************/ #define CATCOMP_ARRAY #define REMOVENETINTERFACE_CATALOG_STRINGS #include "roadshow.h" /****************************************************************************/ /****** ROADSHOW/REMOVENETINTERFACE ****************************************** * * NAME * RemoveNetInterface - Make the protocol stack forget about * a network interface * * FORMAT * RemoveNetInterface [QUIET] [FORCE] INTERFACE * * TEMPLATE * INTERFACE/K,QUIET/S,FORCE/S * * PATH * C:REMOVENETINTERFACE * * FUNCTION * REMOVENETINTERFACE attempts to shut down the specified network * interface, so that it may be added again with different parameters. * * OPTIONS * INTERFACE/K * The name of the interface to shut down. This must be the name * previously given to ADDNETINTERFACE. * * QUIET/S * This option causes the program not to emit any error messages * or progress reports. Also, if the program encounters an error * it will flag this as failure code 5 which can be looked at * using the "if warn" shell script command. If this option is * not in effect, failure codes will be more severe and all sorts * of progress information will be displayed. * * FORCE/S * REMOVENETINTERFACE tries not to shut down an interface which * may still be in use. You can override this with the FORCE * option which, however, carries the risk that not all the * resources associated with the network interface may be released * until you shut down the network with the NETSHUTDOWN command. * * EXAMPLES * Shut down the interface called "DSL", and run quietly. * * 1> RemoveNetInterface DSL QUIET * * SEE ALSO * AddNetInterface * NetShutdown * ****************************************************************************** */ STATIC LONG cmd(struct CommandContext * cc) { struct { KEY Interface; SWITCH Force; SWITCH Quiet; } args; STRPTR args_template = "INTERFACE/A," "FORCE/S," "QUIET/S" VERSTAG; DECLARE_DOSBASE(cc); DECLARE_SOCKETBASE(cc); LONG result = RETURN_FAIL; struct RDArgs * rda; BOOL quiet = FALSE; GetProgramName(cc->cc_ProgramName,sizeof(cc->cc_ProgramName)); memset(&args,0,sizeof(args)); rda = ReadArgs(args_template,(LONG *)&args,NULL); if(rda == NULL) { PrintFault(IoErr(),cc->cc_ProgramName); goto out; } quiet = (BOOL)(args.Quiet != 0); if(SocketBase == NULL) { if(NOT quiet) { Local_ErrorPrintf(cc,get_str(cc,MSG_REMOVENETINTERFACE_CANNOT_OPEN_BSDSOCKET_TXT), cc->cc_ProgramName); } goto out; } if(CANNOT RemoveInterface(args.Interface,args.Force)) { result = RETURN_ERROR; if(NOT quiet) { LONG error,code; /* Older bsdsocket.library versions do not support the RemoveInterface() functionality, which is why we will substitute the error code. */ error = Errno(); if(error == OK) error = EBUSY; code = error; if(Local_SocketBaseTags(cc, SBTM_GETREF(SBTC_ERRNOSTRPTR),&code, TAG_END) != 0) { code = (LONG)""; } Local_ErrorPrintf(cc,get_str(cc,MSG_REMOVENETINTERFACE_COULD_NOT_REMOVE_INTERFACE_TXT), cc->cc_ProgramName,args.Interface,error,code); } goto out; } if(NOT quiet) { Local_Printf(cc,get_str(cc,MSG_REMOVENETINTERFACE_INTERFACE_REMOVED_TXT), cc->cc_ProgramName,args.Interface); } result = RETURN_OK; out: if(quiet && result != RETURN_OK) result = RETURN_WARN; if(rda != NULL) FreeArgs(rda); return(result); } /****************************************************************************/ STATIC LONG VARARGS68K Local_Printf(struct CommandContext * cc,STRPTR format,...) { DECLARE_DOSBASE(cc); va_list args; LONG result; #if defined(__amigaos4__) { va_startlinear(args,format); result = VPrintf(format,va_getlinearva(args,APTR)); va_end(args); } #else { va_start(args,format); result = VPrintf(format,args); va_end(args); } #endif /* __amigaos4__ */ return(result); } /****************************************************************************/ STATIC LONG VARARGS68K Local_ErrorPrintf(struct CommandContext * cc,STRPTR format,...) { DECLARE_DOSBASE(cc); DECLARE_SYSBASE(cc); va_list args; LONG result; BPTR fh; #if defined(__amigaos4__) { fh = ErrorOutput(); } #else { struct Process * this_process = (struct Process *)FindTask(NULL); fh = this_process->pr_CES; } #endif /* __amigaos4__ */ if(fh == ZERO) fh = Output(); #if defined(__amigaos4__) { va_startlinear(args,format); result = VFPrintf(fh,format,va_getlinearva(args,APTR)); va_end(args); } #else { va_start(args,format); result = VFPrintf(fh,format,args); va_end(args); } #endif /* __amigaos4__ */ return(result); } /****************************************************************************/ /* This looks up a locale string ID in the builtin database; adapted from CygnusEd because I couldn't find my own implementation for this application... */ STATIC STRPTR get_builtin_str(LONG id) { LONG top,middle,bottom; STRPTR builtin_string; /* The search area is all those message between bottom and top, inclusive. */ bottom = 0; top = NUM_ENTRIES(CatCompArray) - 1; /* Binary search through the CatCompArray to find the requested string. Note that this assumes that the strings are sorted. Catcomp defaults to creating sorted arrays, but it does _not_ force it. If in the .cd file you specify out of order string numbers this routine will fail.*/ while(bottom != top) { middle = (bottom + top) / 2; if(CatCompArray[middle].cca_ID >= id) top = middle; else bottom = middle + 1; } /* The only time this error message should occur is if you've passed a garbage number OR if the CatCompArray is not sorted. */ if(CatCompArray[bottom].cca_ID == id) builtin_string = (STRPTR)CatCompArray[bottom].cca_Str; else builtin_string = ""; return(builtin_string); } STATIC STRPTR get_str(struct CommandContext * cc, LONG id) { STRPTR builtin_string; STRPTR result; builtin_string = get_builtin_str(id); if(cc->cc_Catalog != NULL) { DECLARE_LOCALEBASE(cc); result = (STRPTR)GetCatalogStr(cc->cc_Catalog,id,builtin_string); } else { result = builtin_string; } return(result); } /****************************************************************************/ STATIC LONG VARARGS68K Local_SocketBaseTags(struct CommandContext * cc,...) { DECLARE_SOCKETBASE(cc); va_list args; LONG result; #if defined(__amigaos4__) { va_startlinear(args,cc); result = SocketBaseTagList(va_getlinearva(args,struct TagItem *)); va_end(args); } #else { va_start(args,cc); result = SocketBaseTagList((struct TagItem *)args); va_end(args); } #endif /* __amigaos4__ */ return(result); }