/* * NewShellCX.c * * Commodity * * Author: Stefan Sticht * * Copyright: source is public domain, no copyright * * Version history: * * V1.01 initial release * V1.03 recompiled with main.c V1.02 * V1.04 completly rewritten; shared commodity code thrown away; smaller, uses less CPU time * V1.05 some really minor changes */ #define VERSION "V1.05" /******************************************************************** * interfacing * ********************************************************************/ /* * include files */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #define printf KPrintF #include #endif /* * prototypes */ long request(char *title, char *gadgets, char *text, ...); struct Library *myopenlibrary(char *name, unsigned long version); void processmessages(void); /* * global data defined in other moduls * * libraries opened by startup code; basepointers needed by function pragmas */ extern struct Library *DOSBase; extern struct Library *SysBase; /* * Disable SAS/C CTRL/C handling */ void chkabort(void) {} /******************************************************************** * global data * ********************************************************************/ /* * definition of all messages (multi language support not completed yet) */ #ifdef GERMAN #define RETRY_GADGETS "Wiederholen|Abbrechen" #define RESUME_GADGETS "Weiter" #define MSG_LIBRARY_OPENERR "Die %s (V%ld+) kann nicht geöffnet werden!" #define COM_NAME "NewShellCX" #define COM_DESCR "Öffnet eine neue Shell mit " #define TT_HOTKEY "TASTE" #define TT_COMMAND "KOMMANDO" #define NO "NEIN" #define YES "JA" #else #define RETRY_GADGETS "Retry|Cancel" #define RESUME_GADGETS "Resume" #define MSG_LIBRARY_OPENERR "%s (V%ld+) can't be opened!" #define COM_NAME "NewShellCX" #define COM_DESCR "Open new shell on " #define TT_HOTKEY "HOTKEY" #define TT_COMMAND "COMMAND" #define YES "YES" #define NO "NO" #endif #define COM_TITLE COM_NAME " " VERSION #define CX_PRIORITY "CX_PRIORITY" #define DEF_CX_PRIORITY 0 #define DEF_TT_HOTKEY "lcommand esc" #define DEF_TT_COMMAND "NewShell" /* * library base pointers */ struct Library *IntuitionBase; struct Library *CxBase; struct Library *IconBase; /* * message port */ struct MsgPort *cxport = NULL; /* * signal flag */ unsigned long cxsigflag = 0l; /* * programtitle and version for Version command */ char versionstring[] ="\0$VER: " COM_NAME " " VERSION; /* * helpstring */ #ifdef GERMAN char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) von Stefan Sticht\n"\ "Aufruf: " COM_NAME " [" CX_PRIORITY "=] [" TT_HOTKEY "=] ["\ TT_COMMAND "=]\n"; #else char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n" "Usage: " COM_NAME " [" CX_PRIORITY "=] [" TT_HOTKEY "=] ["\ TT_COMMAND "=]\n"; #endif /* * the tooltypearray */ char **tooltypes; /* * our broker */ CxObj *broker = NULL; /* * our commodity description */ char descr[CBD_DESCRLEN + 1] = COM_DESCR; /* * the command */ char *command; struct NewBroker newbroker = { NB_VERSION, /* BYTE nb_Version */ COM_NAME, /* BYTE *nb_Name */ COM_TITLE, /* BYTE *nb_Title */ descr, /* BYTE *nb_Descr */ NBU_NOTIFY | NBU_UNIQUE, /* SHORT nb_Unique */ 0, /* SHORT nb_Flags */ 0, /* BYTE nb_Pri */ NULL, /* struct MsgPort nb_Port */ 0 /* WORD nb_ReservedChannel */ }; #define NEWSHELL 1 /* * TagItem structure for System() */ #define P_SYS_Input 0 #define P_SYS_Output 1 struct TagItem systemtags[] = { SYS_Input, 0l, SYS_Output, 0l, SYS_Asynch, TRUE, SYS_UserShell, TRUE, TAG_DONE }; /******************************************************************** * functions * ********************************************************************/ /* * request(): a glue routine to EasyRequest as simple as printf plus * titlestring, gadgettexts * * Input: char *title: pointer to the title of the requester * char *gadgets: pointer to gadgettext * char *text: text displayed in requester * * Result: same as EasyrequestArgs() * * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!! */ long request(char *title, char *gadgets, char *text, ...) { /* * structure textreq only needed in this function, so hide it here * must be static, in order to be initialized only once */ static struct EasyStruct textreq = { sizeof (struct EasyStruct), /* ULONG es_StructSize */ 0l, /* ULONG es_Flags */ NULL, /* UBYTE *es_Title */ NULL, /* UBYTE *es_TextFormat */ NULL, /* UBYTE *es_GadgetFormat */ }; va_list ap; long rc; /* * get start of variable arguments */ va_start(ap, text); /* * update textreq */ textreq.es_Title = (UBYTE *)title; textreq.es_TextFormat = (UBYTE *)text; textreq.es_GadgetFormat = (UBYTE *)gadgets; /* * win may be NULL */ rc = EasyRequestArgs(NULL, &textreq, NULL, ap); va_end(ap); return(rc); } /* * myopenlibrary(): same as OpenLibrary(), but opens a retry-requester * if OpenLibrary() fails, to give the user a chance to * copy the library to libs: and retry * requires request(), see above */ struct Library *myopenlibrary(char *name, unsigned long version) { static char errortext[] = MSG_LIBRARY_OPENERR; struct Library *libptr; long ok = TRUE; do { if (!(libptr = OpenLibrary((UBYTE *)name, version))) { if (IntuitionBase) { ok = request(COM_NAME ":", RETRY_GADGETS, errortext, name, version); } else ok = FALSE; } } while (!libptr && ok); #ifdef DEBUG printf("myopenlibrary(%s, %ld) = 0x%lx\n", name, version, libptr); #endif return(libptr); } void main(int argc, char *argv[]) { CxObj *filter; char *hotkey; struct Message *msg; unsigned long len; if ((argc > 1) && (*argv[1] == '?')) { /* * display help string */ Write(Output(), helpstring, sizeof(helpstring) - 1l); return; } /* * open required libraries first */ if (IntuitionBase = myopenlibrary("intuition.library", 37l)) { if (CxBase = myopenlibrary("commodities.library", 37l)) { if (IconBase = myopenlibrary("icon.library", 37l)) { /* * create tooltypes array (requires icon.library open!!!) */ tooltypes = (char **)ArgArrayInit(argc, argv); /* * create our message port */ if (cxport = CreateMsgPort()) { cxsigflag = 1l << cxport->mp_SigBit; /* * set up some broker data */ newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY); newbroker.nb_Port = cxport; command = ArgString(tooltypes, TT_COMMAND, DEF_TT_COMMAND); if ((hotkey = ArgString(tooltypes, TT_HOTKEY, DEF_TT_HOTKEY)) && *hotkey && command && *command) { len = strlen(descr); strncpy(descr + len, hotkey, sizeof(descr) - len - 2l); if (broker = CxBroker(&newbroker, NULL)) { if (filter = HotKey(hotkey, cxport, NEWSHELL)) { AttachCxObj(broker, filter); if (!CxObjError(filter)) { /* * activate our commodity */ ActivateCxObj(broker, 1l); /* * now watch our numerous ports */ processmessages(); } /* if !CxObjError() */ } /* if centerfilter */ DeleteCxObjAll(broker); } /* if broker */ #ifdef DEBUG else printf("main(): CxBroker() failed!\n"); #endif } /* if hotkey */ /* * delete our message port after replying all pending messages */ while (msg = GetMsg(cxport)) ReplyMsg(msg); DeleteMsgPort(cxport); } /* if cxport */ #ifdef DEBUG else printf("main(): CraeteMsgPort() failed!\n"); #endif ArgArrayDone(); CloseLibrary(IconBase); } /* if IconBase */ CloseLibrary(CxBase); } /* if CxBase */ CloseLibrary(IntuitionBase); } /* if IntuitionBase */ } /* main() */ void processmessages(void) { BPTR fh; struct Message *msg; unsigned long msgid; unsigned long msgtype; unsigned long sigreceived; unsigned short quit = FALSE; while (!quit) { sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag); #ifdef DEBUG printf("processmessages(): signal received\n"); #endif if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE; if (sigreceived & cxsigflag) { while (msg = (struct Message *)GetMsg(cxport)) { msgid = CxMsgID((CxMsg *)msg); msgtype = CxMsgType((CxMsg *)msg); ReplyMsg(msg); switch (msgtype) { case CXM_IEVENT: switch (msgid) { case NEWSHELL: fh = Open("NIL:", MODE_NEWFILE); systemtags[P_SYS_Input].ti_Data = (ULONG)fh; fh = Open("NIL:", MODE_NEWFILE); systemtags[P_SYS_Output].ti_Data = (ULONG)fh; System(command, systemtags); break; } /* switch msgid */ break; case CXM_COMMAND: switch (msgid) { case CXCMD_UNIQUE: case CXCMD_KILL: quit = TRUE; break; case CXCMD_DISABLE: ActivateCxObj(broker, 0l); break; case CXCMD_ENABLE: ActivateCxObj(broker, 1l); break; } break; } /* switch msgtype */ } /* while CxMsg */ } /* if (sigreceived & cxsigflag) */ } /* while !quit */ ActivateCxObj(broker, 0l); }