/* Also: The contents of both buffers is monitored in order to check if they got overflowed during the MUX call. If so, the executation is aborted. */ int runExtension(char ** const command , const char * const line , char ** const newargs) { int clen, llen, xlen, nlen; struct REGPACK r, r2; char *muxCmd, *muxArg, *muxBuf, *p; assert(command); assert(*command); assert(line); assert(newargs); if((clen = strlen(*command)) >= BUFFER_SIZE_MUX_AE || (llen = strlen(line)) >= BUFFER_SIZE_MUX_AE || llen + clen >= BUFFER_SIZE_MUX_AE) { error_long_mux_line(); return 0; } /* Duplicate & fill in the length bytes. */ /* Both buffers must be located in the same segment */ if((muxBuf = emalloc(2 * (BUFFER_SIZE_MUX_AE + 4))) == 0) return 0; /* fill everything with magic values */ memset(muxBuf, (char)BUFFER_SIZE_MUX_AE, 2 * (BUFFER_SIZE_MUX_AE + 4)); muxCmd = muxBuf + 2; muxArg = muxBuf + BUFFER_SIZE_MUX_AE + 4 + 2; memcpy(muxCmd, *command, clen); muxCmd[-1] = (char)clen; memcpy(muxArg, muxCmd, clen); memcpy(muxArg + clen, line, llen); muxArg[-1] = (char)(xlen = llen + clen); /* muxCmd[-2] = muxArg[-2] = (char)BUFFER_SIZE_MUX_AE; see above memset() */ assert(xlen <= 255); /* 4dos v4 compatible space padding */ memset(muxCmd + clen, ' ', BUFFER_SIZE_MUX_AE - clen); /* The command line is \xd terminated, for savety reasons an \0 is added too */ strcpy(muxArg + xlen, "\xd"); muxCmd[BUFFER_SIZE_MUX_AE] /* Make sure the buffers is terminated */ = muxArg[BUFFER_SIZE_MUX_AE] = '\0'; /* Both strings have been prepared now; the MUX call is going to happen */ r.r_ax = 0xae00; /* Installable Commands check for extension */ r.r_dx = 0xffff; /* Magic value */ r.r_cx = xlen | 0xff00; /* length of command line tail (4dos v4) */ r.r_ds = r.r_es = FP_SEG(muxBuf); r.r_bx = FP_OFF(muxArg); r.r_si = FP_OFF(muxCmd); r.r_di = 0; /* Magic value 4dos v4 */ memcpy(&r2, &r, sizeof(r2)); intr(0x2f, &r); if((byte)muxCmd[-2] != BUFFER_SIZE_MUX_AE #if BUFFER_SIZE_MUX_AE < 255 || (byte)muxCmd[-1] > BUFFER_SIZE_MUX_AE #endif || muxCmd[BUFFER_SIZE_MUX_AE] || (byte)muxArg[-2] != BUFFER_SIZE_MUX_AE #if BUFFER_SIZE_MUX_AE < 255 || (byte)muxArg[-1] > BUFFER_SIZE_MUX_AE #endif || muxArg[BUFFER_SIZE_MUX_AE]) { /* Yiek! That looks very much like an overflow!! */ dprintf( ("[Memory corrupted during Installable Commands handler]\n") ); longjmp(jmp_beginning, E_CorruptMemory); } switch(r.r_ax & 0xFF) { case 0x00: /* No appropriate extension found */ break; default: /* Invalid response */ dprintf( ("[Invalid response from Installable Commands handler: 0x%02x]\n", r.r_ax & 0xFF) ); break; case 0xFF: /* Is an extension -> execute the Installable Command */ r2.r_ax = 0xae01; r2.r_cx = clen; intr(0x2f, &r2); if((byte)muxCmd[-2] != BUFFER_SIZE_MUX_AE #if BUFFER_SIZE_MUX_AE < 255 || (byte)muxCmd[-1] > BUFFER_SIZE_MUX_AE #endif || muxCmd[BUFFER_SIZE_MUX_AE] || (byte)muxArg[-2] != BUFFER_SIZE_MUX_AE #if BUFFER_SIZE_MUX_AE < 255 || (byte)muxArg[-1] > BUFFER_SIZE_MUX_AE #endif || muxArg[BUFFER_SIZE_MUX_AE]) { /* Yiek! That looks very much like an overflow!! */ dprintf( ("[Memory corrupted during Installable Commands handler]\n") ); longjmp(jmp_beginning, E_CorruptMemory); } if(muxCmd[-1] == 0) { /* The command had been processed */ myfree(muxBuf); return 1; /* Stop interpreting the command */ } break; } /* Cleanup: Adjust buffers and check for overflow */ /* Check command and transform it back into C-style string */ p = muxCmd + (byte)muxCmd[-1]; while(--p >= muxCmd && isspace(*p)); *++p = 0; if(*muxCmd) { if((p = erealloc(*command, (nlen = p - muxCmd) + 1)) == 0) { myfree(muxBuf); return 0; } StrFUpr(muxCmd); /* make sure it's still uppercased */ memcpy(*command = p, muxCmd, nlen + 1); } else { chkPtr(*command); StrFree(*command); nlen = 0; } /* Check the command line and transform it into a C-style string */ /* Must terminate as line[BUFFER_SIZE] == 0 */ p = muxArg + (byte)muxArg[-1]; while(--p >= muxArg && *p == '\xd'); *++p = 0; if((p - muxArg) >= nlen && ((p - muxArg) - nlen != llen || strcmp(&muxArg[nlen], line) != 0)) { /* new arguments */ /* Should never trigger, because the buffer for the command has the same size as the buffer for the argument itself. Because of the spurious length bytes: &muxArg[nlen] - muxBuf > BUFFER_SIZE_MUX_AE and because: strlen(&muxArg[nlen]) <= BUFFER_SIZE_MUX_AE both memory areas cannot overlap. */ assert(&muxArg[nlen] - muxBuf > BUFFER_SIZE_MUX_AE); assert(strlen(&muxArg[nlen]) < BUFFER_SIZE_MUX_AE); strcpy(muxBuf, &muxArg[nlen]); *newargs = StrTrim(muxBuf); return 0; } myfree(muxBuf); return 0; /* Proceed command processing as usual */ }
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); }
char *aliasexpand(const char * const Xcmd) { char *cmd; /* work buffer */ char *cp, *name, *alias; unsigned ofs, *expanded, *he; int i, numExpanded, newlen, len; assert(Xcmd); if((cmd = estrdup(Xcmd)) == 0) return (char*)Xcmd; numExpanded = 0; expanded = 0; name = 0; redo: /* iteration to expand all aliases */ cp = ltrimcl(cmd); /* skip leading whitespaces */ /* Check if the user disabled alias expansion */ if(*cp == '*') { *cp = ' '; goto errRet; } myfree(name); /* Get the name of this command */ if((name = getCmdName(&(const char*)cp)) == 0 || is_pathdelim(*cp)) goto errRet; StrFUpr(name); /* all aliases are uppercased */ if((ofs = env_findVar(ctxtAlias, name)) == (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) ***********************/ alias = ctxtP(ctxtAlias, ofs + strlen(name) + 1); /* Check that the total command line won't overflow MAX_INT */ if((newlen = strlen(alias)) >= 0 && (len = strlen(cp)) >= 0 && ++len > 0 && newlen + len > 0) { int dst = cp - cmd; /* destination index within cmd[] */ if(newlen > dst) { /* need to increase the buffer */ char *p; if((p = realloc(cmd, newlen + len)) == 0) goto errRet1; cmd = p; } /* else ignore to shrink the buffer; it will be done automatically with the next ALIAS expansion or when this function returns */ assert(len); if(newlen != dst) /* need to move the command tail */ memmove(&cmd[newlen], &cmd[dst], len); /* prepend alias value to remaining command line */ memcpy(cmd, alias, newlen); goto redo; /* next expansion */ } errRet1: error_long_internal_line(); errRet: /* return to caller */ myfree(expanded); myfree(name); return StrTrim(cmd); }