/* CLI shell program 11/85 REJ */ /* This program has been put into the public domain by Lunge Software. Feel free to modify this, but please do not remove the credits. If you have any suggestions for improvement, please either send me mail. Written By: Randell E Jesup Lunge Software 2340 15th St Troy, NY 12180 To use this program, create a 'command file' named 'commands' in the sys: directory. This file should consist of lines with the following format: nnnnnn yyyy;zzzzz;xxxxx;... 'nnnnnn' is a string that you type from the cli (like 'ls'). 'yyyy',etc, are the commands to be executed when the program sees 'nnnnnn'. Multiple commands are seperated by ';'. Example: ls list dl delete cp copy dlram cd ram:;delete #?;cd df0: Whatever you typed after the command will concatenated to the end of the final command. You may also type multiple commands directly from the keyboard (i.e. 'list x;type y'.) There is one other thing cpp does. If you give it a line in the command file like this: prd type %1 to %2; delete %1 it will replace %n with the nth argument you entered from the keyboard. All arguments after the highest used by %n will be appended to the end of the last command line. example: 'prd test prt:' -> 'type test to prt:; delete test' I have a number of plans for enhancements to this, so get word to me soon with any ideas you might have. This code may not be the prettiest, but it works. A problem in 1.0 caused me to have to simulate the 'cd' command. As soon as I get 1.1, I will update this (if it was fixed.) There are certain things that don't work exactly as they do under cli (yet). Ctrl-C won't be passed through, and if you use 'xxx ?' it won't work, and any program that wants input from the current window won't work. To solve this, redirect input to '*' or a 'con' window. Good luck, and have fun! */ #include "stdio.h" #include "libraries/dos.h" extern char *strrchr(),*stpblk(),*strchr(); char curr_dir[100]; char tmpbuf[256]; int old_lock,new_lock; struct CMD { struct CMD *Next_CMD; char *string; char *replace; } *CMD_List[16], *End[16], temp; char buff[256]; char buff2[256]; FILE *cf; int input_file,output_file; extern char *malloc(); long * alloc(lth) register unsigned lth; { register char *ptr; if(!(ptr = malloc(lth))) { printf("Not enough memory for getting %d bytes", lth); exit(20); } return((long *) ptr); } /* * This is a pain! I have to handle cd as a special case! */ void exec_cmd(p) char *p; { char *q; if ((*p == 'c') && (*(p+1) == 'd') && ((*(p+2) == ' ') || (*(p+2) == '\0'))) { q = p + 1; while (*++q == ' ') ; /* skip blanks */ if (*q == '\0') { printf(curr_dir); printf("\n"); } else { while (*q == '/') { register char *t; q++; t = strrchr(curr_dir,'/'); if (t == NULL) { t = strchr(curr_dir,':'); if (t++ == NULL) { printf("Bad Dir Name!"); break; } } *t = '\0'; } if ((*q != ' ') && (*q != '\0')) { if (strchr(q,':') != NULL) if (*q == ':') { *(strchr(curr_dir,':')) = '\0'; strcat(curr_dir,q); } else strcpy(curr_dir,q); else { if (curr_dir[strlen(curr_dir)-1] != ':') strcat(curr_dir,"/"); strcat(curr_dir,q); } } new_lock = Lock(curr_dir,SHARED_LOCK); if (new_lock != NULL) { old_lock = CurrentDir(new_lock); UnLock(old_lock); } else printf("Directory %s does not exist\n",q); } } else Execute(p,0,output_file); } void command_loop() /* command arrays are initialized */ /* now loop, replacing commands, until "stop" is seen */ { /* current dir is set to df0:, as there is no way to find * out what the current dir is. * If you pass a 'cd xxx' command to dos, it'll execute it, * but neither the program's or the cli's dir will be * changed. This means it must be simulated. Also, if you * type this from dos: * 'cd devs:', 'cd :', 'cd', it will say you are in the * 'devs:' directory, but in reality you are in df0: * (assuming the disk is in df0:). This works correctly * here. */ strcpy(curr_dir,"df0:"); new_lock = Lock(curr_dir,SHARED_LOCK); old_lock = CurrentDir(new_lock); UnLock(old_lock); for(;;) { int total; struct CMD *ptr; int i; register char *p,*q,*s,*t; printf("cpp> "); total = 0; fgets(tmpbuf,256,stdin); /* get an input line */ s = p = tmpbuf; while ((*p != '\n') && (*p != '\0')) p++; *p = '\0'; /* strip newline */ if (tmpbuf[0] == '\0') continue; if (!strcmp(tmpbuf,"stop")) break; while (*s != NULL) { q = strchr(s,';'); /* break multiple input cmds */ if (q == NULL) /* copy 1 at a time into buff */ { strcpy(buff,s); *s = NULL; } else { t = buff; while (s < q) *t++ = *s++; /* copy first command into buff */ s++; *t = '\0'; } sscanf(buff,"%s",temp.string); for (i=0;istring,temp.string)) { char *u; struct { char *x;} args[10]; int n; int m = -1; /* got a match for replace */ strcpy(buff2,ptr->replace); u = buff2; /* break out args, then replace '%n's */ break_buff(&buff[strlen(ptr->string)],args); while ((u = strchr(u,'%')) != NULL) { n = *(u+1) - '0' - 1; insstr(u,args[n].x,args[n+1].x); if (n > m) m = n; } strcat(buff2," "); strcat(buff2,args[m+1].x); break; } ptr = ptr->Next_CMD; } /* now, execute the command */ if (ptr == NULL) /* was replacement done ? */ p = buff; else p = buff2; /* printf("total cmd: %s\n",p); */ for (;p != NULL;) { q = strchr(p,';'); /* each command may expand */ if (q != NULL) /* to multiple commands */ *q++ = '\0'; /* printf("cmd: %s\n",p); */ exec_cmd(p); p = q; } } } } main(argc, argv) int argc; char *argv[]; { char *FileName; char NullFile[30]; register int i; NullFile[0] = '\0'; temp.Next_CMD = NULL; for (i=0;i<16;i++) { CMD_List[i] = NULL; End[i] = NULL; } if (argc < 2) FileName = "sys:commands\0"; else { argv++; if ((*argv)[0] == '?') { printf("command_file/K: "); FileName = NullFile; scanf("%s",FileName); } else FileName = argv[0]; } printf("Filename: "); printf(FileName); printf("\n"); cf = fopen(FileName,"r"); if (cf == NULL) { printf("Command file not found!\n"); return(10); } /* * right now, abbreviations can be no more than 30 chars */ temp.string = (char *) alloc(31); temp.replace = (char *) alloc(226); while (fgets(buff,255,cf) != NULL) { register int total = 0; register char *p = buff; register char *s = temp.replace; while ((*p != '\n') && (*p != '\0')) p++; *p = '\0'; /* drop newline char */ sscanf(buff,"%s",temp.string); p = &buff[strlen(temp.string)+2]; while (*p == ' ') /* drop leading spaces */ p++; strcpy(s,p); /* copy p to s */ for (i=0;iNext_CMD = (struct CMD *) alloc(sizeof(struct CMD)); End[total] = End[total]->Next_CMD; *End[total] = temp; } End[total]->string = (char *) alloc(strlen(temp.string)); strcpy(End[total]->string,temp.string); End[total]->replace = (char *) alloc(strlen(temp.replace)); strcpy(End[total]->replace,temp.replace); } /* get input and output files */ input_file = Input(); output_file = Output(); printf("Command Pre-Processor v1.00\n"); printf(" courtesy Lunge Software Development\n"); buff[0] = '\0'; buff2[0] = '\0'; command_loop(); printf("Command Pre-Processing terminated\n"); } break_buff(src,args) /* parse arguments */ char *src; struct { char *x;} args[]; { int i = 0; src = stpblk(src); /* skip leading blanks */ args[0].x = src; while (*src != '\0') /* delims = \0 and space */ { if (*src == ' ') { args[++i].x = ++src; src = stpblk(src); } else ++src; } for (i++;i<10;i++) /* all others are null */ args[i].x = src; /* for (i=0;i<10;i++) printf("arg[%d] = %s\n",i,args[i].x); */ } insstr(dest,src,end) /* * insert a string at a given position. string starts at * src and goes to end-1 */ char *dest,*src,*end; { char tmp[256]; strcpy(tmp,&dest[2]); /* printf("start=%d, end=%d, remainder=%s, replace=%s\n", src,end,tmp,src); */ while (src != end) *dest++ = *src++; strcpy(dest,tmp); } /* There are various debugs commented out in the code. If you wish to understand how this works in more detail, put them back in. Look for an Amiga version of Hack (similar to Rogue) in several months and an optimizing version of Forth, both from Lunge Software. (And maybe a few other goodies as well!) Good luck to all of you out there. */ /* ------------- eof -------------- */