bruceb@amiga.UUCP (Bruce Barrett) (05/13/86)
/* Ever wonder if the system you're running on has enough system resources for you to do what you would like too (or need to) do? Ever want to use the same CLI or workbench diskette to boot a 256k, 512k, and 8.5 meg system, and take advantage of the extra memory if it's available? Well your prayers have just been answered. Introducing "enough" (a CLI execute file command). Enough will test to see if you have enough RAM memory, disk (DF0:, DF1:, ...) memory or if a file, directory or device exists. Any combination of tests may be done at once. For example, if you need c:copy, c:assign, and 200k of RAM in order to copy your C: directory to RAM disk you can test for this in your startup-sequence execute file as follows: failat 10 {optional} ENOUGH MEM 200k EXISTS c:copy EXISTS c:assign if NOT warn copy c: ram: assign c: ram: endif echo "ready." The advantage of using: enough exists foo:bar if NOT warn : over: if exists foo:bar : is that enough prevents the "Please insert volume foo in any drive" requester. So your batch file can check for the existence of a volume without "help" from the user. For example you can say: enough exists MY-C-VOL: if NOT warn cd My-C-Vol: endif Anyway, I hope this gives you some ideas for a few creative execute files. If you add additional keywords please send your code to me and I will coordinate updates. Thank you. The source code that follows compiles under Lattice V3.03 without warnings or errors. Bruce Barrett Commodore-Amiga Software QA. */ /* enough.c */ /* */ /* Run from a CLI execute file. If the resources you are */ /* checking for exist enough returns a return code of zero */ /* (0), if not it returns a warning value of five (5). */ /* Enough can be used to check for available memory and/or */ /* disk space, along with the existence of files. */ /* */ /* Syntax: */ /* enough [{MEM|FAST|CHIP} nnn[K]] [EXISTS file] */ /* [DISK drv: fff[K]] */ /* */ /* Typical usage (in startup script): */ /* failat 10 */ /* enough MEM 880k */ /* if NOT warn */ /* copy df0: ram: all */ /* assign c: ram:c */ /* assign .... */ /* endif */ /* */ /* Logic: * 1. verify CLI parameters, as they are used. * 2. For memory (MEM, FAST and CHIP) checks use Avail() to * see if there is enough memory. * 3. For disk (DISK) checks use Info() * 4. For existence testing (EXISTS) disable requesters and * use Lock(). * 5. If any of them fail return 5. * 6. If there is a syntax error in the command line return 20. * * Notes and cautions: * 1. the do_<function>() functions should be stand-alone. * freeing any resources they might allocate. * 2. the do_<function>() functions should increment the * cur_argc pointer past their keyword and any parameters * they use. This is a global. * 3. MAX_KEYWD_LEN is the length of the longest keyword, or more * * New featues that might be added: * 1. enough<cr> currently does nothing, could add a check for * this case and return DIE_BADARGS. * 2. Be nice to add something that would test for enough room * on a disk for a given file (enough FILESPACE foo bar:) */ #include "exec/types.h" #include "exec/memory.h" #include "libraries/dos.h" #include "libraries/dosextens.h" /* #include "stdio.h" #include "clib/macros.h" */ /* ------------ Constant Definitions ------------ */ /* version release and date information */ #define VERNO 1 #define RELNO 0 #define DATE "13-May-86" #define AUTHOR Bruce A. Barrett #define PUBLIC_DOMAIN TRUE /* reason for terminating through cleanup() */ #define DIE_OK 0 #define DIE_MEM 1 #define DIE_NOOUTPUT 2 #define DIE_BADARGS 3 #define DIE_S_DIR 4 #define DIE_D_DIR 5 #define DIE_S_FILE 6 #define DIE_D_FILE 7 #define DIE_FIBOVERFLOW 8 #define DIE_FIBUNDERFLOW 9 #define DIE_CTRL_C 10 #define DIE_NOT_ENOUGH 11 #define MAX_KEYWD_LEN 12 /* For debugging, as required */ #define FIX FALSE #if FIX #define ROUTINE(foo) kprintf(foo) /* debug */ #else #define ROUTINE(foo) /* don't */ #endif /* ------------ Global Variables ------------ */ int f_lock; struct FileInfoBlock *file_info_block; int cur_argc; int gl_argc; main(argc, argv) int argc; char *argv[]; { /* ------------ Local Variables ------------ */ char key_wd[MAX_KEYWD_LEN]; int ret_val; /* */ /* M A I N L O G I C */ /* */ /* setup */ ROUTINE("main\n"); /* kprintf("\n---------------------------------\n"); kprintf("%s: Version %ld.%ld, %s\n", argv[0], VERNO, RELNO, DATE); */ gl_argc = argc; ret_val = DIE_OK; cur_argc = 1; while ( (cur_argc < argc) && (ret_val == DIE_OK)) { testbreak(); uc_copy(key_wd, argv[cur_argc]); if (0 == strcmp(&key_wd[0],"MEM")) ret_val = do_mem(argv); else if (0 == strcmp(&key_wd[0],"CHIP")) ret_val = do_chip(argv); else if (0 == strcmp(&key_wd[0],"FAST")) ret_val = do_fast(argv); else if (0 == strcmp(&key_wd[0],"DISK")) ret_val = do_disk(argv); else if (0 == strcmp(&key_wd[0],"EXISTS")) ret_val = do_exists(argv); else {ret_val = DIE_BADARGS; printf("%s: Version %ld.%ld, %s\n", argv[0], VERNO, RELNO, DATE); } } cleanup(argv, ret_val); } /* ------------ suppress_IO_err() ------------ */ /* Prevent AmigaDOS from putting up a "Please insert */ /* volume..." requester. */ APTR suppress_IO_err() { struct Process *my_proc, *FindTask(); APTR old_window; ROUTINE("suppress_IO_err\n"); my_proc = FindTask(""); old_window = my_proc->pr_WindowPtr; my_proc->pr_WindowPtr = (APTR) -1; return(old_window); } /* ------------ allow_IO_err() ------------ */ /* Allow AmigaDOS to put up a "Please insert volume..." */ /* requester. */ void allow_IO_err(old_wind) APTR old_wind; { struct Process *my_proc; ROUTINE("allow_IO_err\n"); my_proc = FindTask(""); my_proc->pr_WindowPtr = old_wind; } /* ---------- do_mem_type() ------------------------------ */ /* Given a memory type, see if there is enough available */ do_mem_type(argv, type) char *argv[]; int type; { int avail; /* memory available of this type */ int need; /* memory of this type needed */ ROUTINE("do_mem_type\n"); if (cur_argc >= gl_argc) return(DIE_BADARGS); avail = AvailMem(type); sscanf(argv[cur_argc], "%d", &need); cur_argc++; if (need == 0) return(DIE_BADARGS); if ((need*1024) <= avail) return(DIE_OK); else return(DIE_NOT_ENOUGH); } /* ---------- do_mem() ------------------------------ */ do_mem(argv) char *argv[]; { ROUTINE("do_mem\n"); cur_argc++; return(do_mem_type(argv, MEMF_LARGEST)); } /* ---------- do_chip() ------------------------------ */ do_chip(argv) char *argv[]; { ROUTINE("do_chip\n"); cur_argc++; return(do_mem_type(argv, MEMF_CHIP|MEMF_LARGEST)); } /* ---------- do_fast() ------------------------------ */ do_fast(argv) char *argv[]; { ROUTINE("do_fast\n"); cur_argc++; return(do_mem_type(argv, MEMF_FAST|MEMF_LARGEST)); } /* ---------- do_disk() ------------------------------ */ /* Format is: ENOUGH DISK disk_name: fff[k] */ do_disk(argv) char *argv[]; { /* do_disk */ int need; int ret_val; LONG my_lock; LONG free; BOOL result; APTR old_ptr; struct InfoData *info_data; ROUTINE("do_disk\n"); info_data = 0; /* remove a Lattice warning */ cur_argc++; /* Skip "DISK" keyword */ ret_val = DIE_NOT_ENOUGH; /* -- test for enough arguments on the command line -- */ if ((cur_argc+1) >= gl_argc) return(DIE_BADARGS); /* -- test for the existence of the drive/volume -- */ old_ptr = (APTR) suppress_IO_err(); /* defeat "insert vol" requester */ my_lock = Lock(argv[cur_argc], MODE_OLDFILE); allow_IO_err(old_ptr); /* re-enable requesters. */ cur_argc++; if (my_lock == 0) return(ret_val); /* -- get info about the drive -- */ info_data = (struct InfoData *) AllocMem(sizeof(*info_data), 0); if (info_data == 0) { UnLock(my_lock); return(ret_val); } result = Info(my_lock, info_data); if (!result) { UnLock(my_lock); FreeMem(info_data, sizeof(*info_data)); return(ret_val); } /* -- get the amount of disk space needed -- */ sscanf(argv[cur_argc], "%d", &need); cur_argc++; if (need == 0) { UnLock(my_lock); FreeMem(info_data, sizeof(*info_data)); return(DIE_BADARGS); } free = (info_data->id_NumBlocks - info_data->id_NumBlocksUsed) * info_data->id_BytesPerBlock; UnLock(my_lock); FreeMem(info_data, sizeof(*info_data)); if (free > (need*1024) ) ret_val = DIE_OK; return(ret_val); } /* ---------- do_exists() ------------------------------ */ do_exists(argv) char *argv[]; { LONG my_lock; APTR old_ptr; ROUTINE("do_exists\n"); cur_argc++; old_ptr = (APTR) suppress_IO_err(); /* defeat "insert vol" requester */ if (cur_argc >= gl_argc) return(DIE_BADARGS); my_lock = Lock(argv[cur_argc], MODE_OLDFILE); allow_IO_err(old_ptr); cur_argc++; if (my_lock == 0) return(DIE_NOT_ENOUGH); UnLock(my_lock); return(DIE_OK); } /* ==================================================== */ /* ================== Subroutines ===================== */ /* enough.h /* ==================================================== */ /* ---------- uc_copy() ------------------------------ */ /* Copy characters from one string to another, making */ /* it upper case at it goes. */ uc_copy(to, from) char *to; char *from; { ROUTINE("uc_copy\n"); while (*to++ = toupper(*from++)) ; } /* ---------- testbreak() ------------------------------ */ /* tests for a ^C (CTRL-C), calls cleanup() if found, */ /* otherwise returns. */ testbreak(argv) char *argv[]; { LONG newsigs; LONG oldsigs; ROUTINE("testbreak\n"); newsigs = 0; oldsigs = SetSignal(newsigs, SIGBREAKF_CTRL_C); if (oldsigs & (SIGBREAKF_CTRL_C) ) { cleanup(argv, DIE_CTRL_C); } /* end of if */ } /* end of testbreak() */ /* ------------ cleanup(argv, cause) ------------ */ cleanup(argv, cause) int cause; char *argv[]; { ROUTINE("cleanup\n"); /* kprintf ("cleanup # %ld, IoErr() = %ld\n", cause, IoErr()); */ switch (cause) { case DIE_OK: case DIE_MEM: case DIE_NOOUTPUT: case DIE_S_DIR: case DIE_D_DIR: case DIE_S_FILE: case DIE_D_FILE: case DIE_FIBOVERFLOW: case DIE_FIBUNDERFLOW: case DIE_NOT_ENOUGH: break; case DIE_BADARGS: printf("%s: Error -- Bad command line arguments.\n", argv[0]); /* enough */ /* */ printf("%s: Syntax is %s [{MEM|FAST|CHIP} nnn[K]] [EXISTS file]\n", argv[0], argv[0]); printf(" [DISK drv: fff[K]]\n"); printf("nnn is the number of K in RAM required, fff is the\n"); printf("number of K on the disk \"drv:\" required, file is a\n"); printf("path name you want to check for the existence of.\n"); break; case DIE_CTRL_C: printf("%s: *Break* Stopped by user.\n", argv[0]); break; } ROUTINE("exit\n"); if (cause == DIE_OK) exit(0); else if (cause == DIE_BADARGS) exit(20); /* syntax error!! */ else exit(5); }