char *skipfnam(const char * const fnam) { const char *p; assert(fnam); p = fnam - 1; while(is_fnchar(*++p)); return (char*)p; }
int is_fnstr(const char * const s) { const char *p; assert(s); for(p = s; *p; ++p) if(!is_fnchar(*p)) return 0; return 1; }
void aliasexpand(char * const cmd, const int maxlen) { char *hbuf; /* work buffer */ char *cp, *p; unsigned ofs, *expanded, *he; int i, numExpanded; assert(cmd); assert(strlen(cmd) < maxlen); if((hbuf = malloc(maxlen)) == 0) { error_out_of_memory(); return; } numExpanded = 0; expanded = 0; redo: /* iteration to expand all aliases */ cp = ltrimcl(cmd); /* skip leading whitespaces */ /* Check if the user disabled alias expansion */ if(*cp == '*') { memmove(cmd, cp + 1, strlen(cp)); goto errRet; } /* Get the name of this command */ for(p = hbuf; is_fnchar(*cp) || *cp == '.';) *p++ = *cp++; if(p == hbuf || is_pathdelim(*cp) || is_quote(*cp)) /* no name || part of path -> no alias */ goto errRet; *p = 0; StrFUpr(hbuf); /* all aliases are uppercased */ if((ofs = env_findVar(ctxtAlias, hbuf)) == (unsigned)-1) /* not found -> no alias */ goto errRet; /* Prevent recursion by recording the offset of the found variable */ for(i = 0; i < numExpanded; ++i) if(expanded[i] == ofs) /* already used -> ignore */ goto errRet; if((he = realloc(expanded, ++numExpanded)) == 0) { error_out_of_memory(); goto errRet; } expanded = he; expanded[numExpanded - 1] = ofs; /************ Expand the command line "cp" with the alias at MK_FP(ctxtAlias, ofs) ***********************/ ofs += strlen(hbuf) + 1; /* advance to value */ if(_fstrlen(MK_FP(ctxtAlias, ofs)) < maxlen - strlen(cp)) { /* prepend alias value to remaining command line */ _fstrcpy(TO_FP(hbuf), MK_FP(ctxtAlias, ofs)); strcat(hbuf, cp); assert(strlen(hbuf) < maxlen); strcpy(cmd, hbuf); goto redo; /* next expansion */ } error_command_too_long(); errRet: /* return to caller */ free(expanded); free(hbuf); }
static void docommand(char *line) { /* * look through the internal commands and determine whether or not this * command is one of them. If it is, call the command. If not, call * execute to run it as an external program. * * line - the command line of the program to run */ char *cp; char *rest; /* pointer to the rest of the command line */ struct CMD *cmdptr = 0; #ifdef FEATURE_INSTALLABLE_COMMANDS /* Duplicate the command line into such buffer in order to allow Installable Commands to alter the command line. *line cannot be modified as pipes would be destroyed. */ /* Place both buffers immediately following each other in order to make sure the contents of args can be appended to com without any buffer overflow checks. *2 -> one buffer for com and one for args +2 -> max length byte of com + cur length of com +3 -> max length byte of args + cur length of args + additional '\0' */ char *buf = malloc(2+2*BUFFER_SIZE_MUX_AE+2+1); #define args (buf + 2) #define ARGS_BUFFER_SIZE (2 + BUFFER_SIZE_MUX_AE + 3) #define com (buf + ARGS_BUFFER_SIZE) #define BUFFER_SIZE BUFFER_SIZE_MUX_AE #else char *com = malloc(MAX_INTERNAL_COMMAND_SIZE); #define args line #define buf com #define BUFFER_SIZE MAX_INTERNAL_COMMAND_SIZE #endif assert(line); if(!buf) { error_out_of_memory(); return; } /* delete leading spaces, but keep trailing whitespaces */ line = ltrimcl(line); #ifdef FEATURE_INSTALLABLE_COMMANDS #if BUFFER_SIZE < MAX_INTERNAL_COMMAND_SIZE if(strlen(line) > BUFFER_SIZE) { error_line_too_long(); goto errRet; } #endif strcpy(args, line); #endif if (*(rest = args)) /* Anything to do ? */ { cp = com; /* Copy over 1st word as upper case */ /* Internal commands are constructed out of non-delimiter characters; ? had been parsed already */ while(*rest && is_fnchar(*rest) && !strchr(QUOTE_STR, *rest)) *cp++ = toupper(*rest++); if(*rest && strchr(QUOTE_STR, *rest)) /* If the first word is quoted, it is no internal command */ cp = com; /* invalidate it */ *cp = '\0'; /* Terminate first word */ if(*com) { #ifdef FEATURE_INSTALLABLE_COMMANDS int tryMUXAE; for(tryMUXAE = MUX_AE_MAX_REPEAT_CALL; tryMUXAE > 0; --tryMUXAE) { /* Check for installed COMMAND extension */ switch(runExtension(com, args)) { case 1: /* OK, done */ goto errRet; case 0: /* no extension */ tryMUXAE = 0; } /* reset the argument pointer */ rest = &args[(unsigned char)com[-1]]; dprintf( ("[Command on return of Installable Commands check: >%s]\n", com) ); #ifndef NDEBUG dprintf( ("[Command line: >") ); for(cp = args; cp < rest; ++cp) dprintf( ("%c", *cp) ); dprintf( ("|%s]\n", rest) ); #endif /* !defined(NDEBUG) */ #endif /* Scan internal command table */ for (cmdptr = internalCommands ; cmdptr->name && strcmp(com, cmdptr->name) != 0 ; cmdptr++); if(cmdptr && cmdptr->name) { /* internal command found */ #ifdef FEATURE_INSTALLABLE_COMMANDS cp = realloc(buf, ARGS_BUFFER_SIZE); #ifndef NDEBUG if(cp != buf) { dprintf( ("[INTERNAL error: realloc() returned wrong result]") ); buf = cp; } #endif #else free(buf); buf = 0; /* no further useage of this buffer */ #endif switch(cmdptr->flags & (CMD_SPECIAL_ALL | CMD_SPECIAL_DIR)) { case CMD_SPECIAL_ALL: /* pass everything into command */ break; case CMD_SPECIAL_DIR: /* pass '\\' & '.' too */ if(*rest == '\\' || *rest == '.' || *rest == ':') break; default: /* pass '/', ignore ',', ';' & '=' */ if(!*rest || *rest == '/') break; if(isargdelim(*rest)) { rest = ltrimcl(rest); break; } /* else syntax error */ error_syntax(0); goto errRet; } currCmdHelpScreen = cmdptr->help_id; /* JPP this will print help for any command */ if(memcmp(ltrimcl(rest), "/?", 2) == 0) { displayString(currCmdHelpScreen); } else { dprintf(("CMD '%s' : '%s'\n", cmdptr->name, rest)); cmdptr->func(rest); } goto errRet; } #ifdef FEATURE_INSTALLABLE_COMMANDS } #endif } free(buf); buf = 0; /* no longer used */ /* no internal command --> spawn an external one */ cp = unquote(line, rest = skip_word(line)); if(!cp) { error_out_of_memory(); goto errRet; } execute(cp, rest); free(cp); } #undef com #undef args #undef BUFFER_SIZE #undef ARGS_BUFFER_SIZE errRet: free(buf); }
static void docommand(char *line) { /* * look through the internal commands and determine whether or not this * command is one of them. If it is, call the command. If not, call * execute to run it as an external program. * * line - the command line of the program to run */ #ifdef FEATURE_INSTALLABLE_COMMANDS /* Duplicate the command line into such buffer in order to allow Installable Commands to alter the command line. *line cannot be modified as pipes would be destroyed. */ /* Place both buffers immediately following each other in order to make sure the contents of args can be appended to com without any buffer overflow checks. *2 -> one buffer for com and one for args +2 -> max length byte of com + cur length of com +3 -> max length byte of args + cur length of args + additional '\0' */ char buf[2+2*BUFFER_SIZE_MUX_AE+2+1]; #define com (buf + 2) #define args (buf + 2 + BUFFER_SIZE_MUX_AE + 2) #define BUFFER_SIZE BUFFER_SIZE_MUX_AE #else char com[MAX_INTERNAL_COMMAND_SIZE]; #define BUFFER_SIZE MAX_INTERNAL_COMMAND_SIZE #endif char *cp; char *rest; /* pointer to the rest of the command line */ struct CMD *cmdptr; assert(line); /* delete leading spaces, but keep trailing whitespaces */ line = ltrimcl(line); #ifdef FEATURE_INSTALLABLE_COMMANDS #if BUFFER_SIZE < MAX_INTERNAL_COMMAND_SIZE if(strlen(line) > BUFFER_SIZE) { error_line_too_long(); return; } #endif line = strcpy(args, line); #endif if (*(rest = line)) /* Anything to do ? */ { cp = com; /* Copy over 1st word as lower case */ /* Internal commands are constructed out of non-delimiter characters; ? had been parsed already */ while(*rest && is_fnchar(*rest) && !strchr(QUOTE_STR, *rest)) *cp++ = toupper(*rest++); if(*rest && strchr(QUOTE_STR, *rest)) /* If the first word is quoted, it is no internal command */ cp = com; /* invalidate it */ *cp = '\0'; /* Terminate first word */ if(*com) { #ifdef FEATURE_INSTALLABLE_COMMANDS /* Check for installed COMMAND extension */ if(runExtension(com, args)) return; /* OK, executed! */ dprintf( ("[Command on return of Installable Commands check: >%s<]\n", com) ); #endif /* Scan internal command table */ for (cmdptr = internalCommands ; cmdptr->name && strcmp(com, cmdptr->name) != 0 ; cmdptr++); } if(*com && cmdptr->name) { /* internal command found */ switch(cmdptr->flags & (CMD_SPECIAL_ALL | CMD_SPECIAL_DIR)) { case CMD_SPECIAL_ALL: /* pass everything into command */ break; case CMD_SPECIAL_DIR: /* pass '\\' & '.' too */ if(*rest == '\\' || *rest == '.' || *rest == ':') break; default: /* pass '/', ignore ',', ';' & '=' */ if(!*rest || *rest == '/') break; if(isargdelim(*rest)) { rest = ltrimcl(rest); break; } /* else syntax error */ error_syntax(0); return; } /* JPP this will print help for any command */ if (strstr(rest, "/?")) { displayString(cmdptr->help_id); } else { dprintf(("CMD '%s' : '%s'\n", com, rest)); cmdptr->func(rest); } } else { #ifdef FEATURE_INSTALLABLE_COMMANDS if(*com) { /* external command */ /* Installable Commands are allowed to change both: "com" and "args". Therefore, we may need to reconstruct the external command line */ /* Because com and *rest are located within the very same buffer and rest is definitely terminated with '\0', the followinf memmove() operation is fully robust against buffer overflows */ memmove(com + strlen(com), rest, strlen(rest) + 1); /* Unsave, but probably more efficient operation: strcat(com, rest); -- 2000/12/10 ska*/ line = com; } #endif /* no internal command --> spawn an external one */ cp = unquote(line, rest = skip_word(line)); if(!cp) { error_out_of_memory(); return; } execute(cp, ltrimsp(rest)); free(cp); } } #undef line #undef com #undef args #undef BUFFER_SIZE }