/* Setup Instatllation Program * (C) Copyright 1987 by Microsoft * Written By Steven Zeck * * All the generic I/O functions are defined here. *************************************************************************/ #include "core.h" #include #include #include #include #include #include #define FAST //#define FAST _fastcall int FAST writeOutBuff(char c); int _cdecl _far _fmemcmp(const void far *, const void far *, int); int _cdecl _far _fmemcpy(const void far *, const void far *, int); long cbExpanded; FARB pInBuff, pInBuffEnd; FARB pOutBuff, pOutBuffEnd; int fhFrom, fhTo; char cPartFile; // file part of multi disk file /* loadFile - load a file into far memory * * Inputs * The global ST * Returns * ****************************************************************************/ loadFile (pST) ST *pST; { int fChange, cbRead; int fh; long cb; char buffT[TOKEN_MAX]; strcat (strcpy(buffT, pST->fileName), ".sus"); while ((fh = RpcOpen(buffT, O_RDONLY | O_BINARY)) == -1) { if (errno == ENOENT) if (fChange = changeDisk(buffT)) { if (fChange == DISKCHANGED && buffT[1] == ':') buffT[0] = pCopyDrive->v.pVal[0]; continue; } terminate("Can't open setup file: %s", buffT); } cb = RpcLseek(fh, 0L, 2); if (cb > 0xffff) terminate("Setup file over 64K\n"); RpcLseek(fh, 0L, 0); /* check to see if the script is compressed */ if ((cbRead = readFar(fh, pCopyBuff, COPYBUF_MAX)) > sizeof(FH) && _fmemcmp(((FH far *)pCopyBuff)->rgMagic, magicVal, cbMagic) == 0) { pInBuff = pCopyBuff + sizeof(FH); pInBuffEnd = pCopyBuff + cbRead; pOutBuff = pInBuffEnd; pOutBuffEnd = pCopyBuff2 + COPYBUF_MAX; pST->cbFile = cbExpanded = ((FH far *)pCopyBuff)->cb; pST->pBuff = pST->pBuffCur = fmemory(pST->cbFile); if (pST->cbFile > pOutBuffEnd - pOutBuff) terminate("Script file too big for compression\n"); unpack(); _fmemcpy(pST->pBuff, pInBuffEnd, pST->cbFile); } else { pST->cbFile = cb; pST->pBuff = pST->pBuffCur = fmemory((int) cb); _fmemcpy(pST->pBuff, pCopyBuff, cbRead); readFar(fh, pST->pBuff+cbRead, (int) cb-cbRead); } RpcClose(fh); } /* open an file for input * * Inputs * name of file * Returns * ****************************************************************************/ int pascal openFile(pName, mode) pSZ pName; int mode; { static pSZ lastName; if (pName) lastName = pName; else goto prompt; while ((fhFrom = RpcOpen(lastName, mode, S_IWRITE | S_IREAD )) == -1) { if (errno == ENOENT) prompt: if (changeDisk(lastName)) continue; terminate("Can't open file: %s", lastName); } return(fhFrom); } /* copyFile - a copy from one place to another * * Inputs * Source and desinstation files * ****************************************************************************/ copyFile(pFrom, pTo) pSZ pFrom; pSZ pTo; { UINT cbRead; FH far *pFH; fhTo = openFile(pTo, O_CREAT | O_TRUNC| O_WRONLY | O_BINARY); openFile(pFrom, O_RDONLY | O_BINARY); outStat("Copying file to %s", pTo); /* check to see if the files is compressed */ if ((cbRead = readFar(fhFrom, pCopyBuff, COPYBUF_MAX)) > sizeof(FH) && _fmemcmp(((FH far *)pCopyBuff)->rgMagic, magicVal, cbMagic) == 0) { pInBuff = pCopyBuff + sizeof(FH); pInBuffEnd = pCopyBuff + cbRead; pOutBuff = pCopyBuff2; pOutBuffEnd = pCopyBuff2 + COPYBUF_MAX; cbExpanded = ((FH far *)pCopyBuff)->cb; cPartFile = 1; unpack(); writeOutBuff(0); } else { do { writeFar(fhTo, pCopyBuff, cbRead); } while ((cbRead = readFar(fhFrom, pCopyBuff, COPYBUF_MAX))); } setCreateDate(fhFrom, fhTo); RpcClose(fhFrom); RpcClose(fhTo); } #define notEof() (cbOut < cbExpanded) #define readChar() (pInBuff < pInBuffEnd)? *pInBuff++: readInBuff() #define writeChar(c) if (pOutBuff < pOutBuffEnd) *pOutBuff++=c; else writeOutBuff(c); char FAST readInBuff(void) { int cbRead; Bool fNewOpen = FALSE; pInBuff = pCopyBuff; while (!(cbRead = readFar(fhFrom, pCopyBuff, COPYBUF_MAX))) { // change disks RpcClose(fhFrom); openFile(NIL, O_RDONLY | O_BINARY); fNewOpen++; } if (fNewOpen) { /* check for valide continued file */ if (memcmp(pInBuff, magicVal, cbMagic-1) != 0 || pInBuff[7] != ++cPartFile) terminate("Wrong part of multi disk file"); pInBuff += cbMagic; } pInBuffEnd = pCopyBuff + cbRead; return(*pInBuff++); } int FAST writeOutBuff(char c) { writeFar(fhTo, pCopyBuff2, pOutBuff - pCopyBuff2); pOutBuff = pCopyBuff2; *pOutBuff++ = c; } #define cbIndex 2 /* encode string into position and length */ #define cBufMax 4096 /* size of ring buffer */ #define cStrMax (16 + cbIndex) /* upper limit for match_length */ UCHAR ringBuf[cBufMax+cStrMax-1]; /* ring buffer of size cBufMax, with extra cStrMax-1 bytes to facilitate string comparison */ #ifdef cVERSION unpack(void) /* Just the reverse of Encode(). */ { int i, cb, oStart; register int iBufCur; unsigned char c; unsigned int flags; long cbOut; memset(ringBuf, ' ', cBufMax - cStrMax); iBufCur = cBufMax - cStrMax; flags = 0; cbOut = 0; while(notEof()) { c = readChar(); /* high order byte counts the # bits used in the low order byte */ if (((flags >>= 1) & 0x100) == 0) { flags = c | 0xff00; /* set bit mask describing the next 8 bytes */ c = readChar(); } if (flags & 1) { /* just store the literal character into the buffer */ writeChar(c); cbOut++; ringBuf[iBufCur++] = c; iBufCur &= cBufMax - 1; } else { /* extract the buffer offset and count to unpack */ cb = readChar(); oStart = (cb & 0xf0) << 4 | c; cb = (cb & 0x0f) + cbIndex; for (i = 0; i <= cb; i++) { c = ringBuf[(oStart + i) & (cBufMax - 1)]; writeChar(c); cbOut++; ringBuf[iBufCur++] = c; iBufCur &= cBufMax - 1; } } } } #endif /* getline - read another line into the global line buffer * * Inputs * current TS & buffers * Returns * ****************************************************************************/ Bool getline () { char far *pFrom; register UCHAR *pTo, c; UINT cbLeft; pTo = pLineCur = lineBuff; pFrom = pSTCur->pBuffCur; cbLeft = pSTCur->cbFile - (UINT) ((long) pFrom - (long) pSTCur->pBuff); if (!cbLeft) return(FALSE); while (cbLeft != 0) { c = *pFrom++; cbLeft--; if (! (c&0x80) && isLineEnd(c)) { if (cbLeft && isLineEnd(*pFrom)) { cbLeft--; pFrom++; } break; } *pTo++ = c; } *pTo = NIL; pSTCur->pBuffCur = pFrom; pSTCur->lineCur++; tokenPeek = NIL; return(TRUE); } /* centerOut/outStat/lineOut - output text to the screen * * Inputs * text to output * Returns * ****************************************************************************/ void pascal centerOut(atLine, pText) int atLine; pSZ pText; { int cb; cb = strlen(pText); textOut(atLine, (80 - cb) / 2, pText); } void outStat(format, a1, a2, a3, a4) /* output message at status line */ pSZ format; { char buffT[160]; sprintf(buffT, format, a1, a2, a3, a4); buffT[80] = NIL; textOut(cCrtLineMax, 1, buffT); fillCrt(cCrtLineMax, strlen(buffT)+1, cCrtLineMax, 81, defCrtAttr, ' '); } void pascal lineOut(pLine) /* plain message, but with scrolling */ pSZ pLine; { if (curCrtLine > cCrtLineMax-1) { /* need to scroll up */ curCrtLine = cCrtLineMax-1; scrollUp(); } textOut(curCrtLine++, 1, pLine); } /* getInput - get user input into a buffer * * Inputs * Line, column to get input * Symbol table to return value * Returns * ****************************************************************************/ void pascal getInput(row, column, pSY) int row; int column; SY *pSY; { char buffT[TOKEN_MAX]; int cb; pSZ pT; char aChar[2]; buffT[0] = NIL; aChar[1] = NIL; if (pSY->type == charSYT) { strcpy(buffT, pSY->v.pVal); free(pSY->v.pVal); } defCrtAttr--; textOut(row, column, buffT); cb = strlen(buffT); pT = buffT + cb; while((aChar[0] = RpcGetch()) != '\r') { if (aChar[0] == '\b') { if (cb) { cb--; pT--; textOut(row, column+cb, " "); moveTo(row, column+cb); } } else { textOut(row, column+cb, aChar); cb++; *pT++ = aChar[0]; } } *pT = NIL; pSY->type = charSYT; pSY->v.pVal = newStr(buffT); defCrtAttr++; } /* changeDisk - ask the user to change disks * * Inputs * What your were looking for * Returns * FALSE - If you should give up * TRUE - If you should try again * DISKCHAcBufMaxGED - If you should try again with a different disk drive * ****************************************************************************/ Bool pascal changeDisk(pcBufMaxame) pSZ pcBufMaxame; { char buffT[TOKEN_MAX], buffFile[80]; char lastVolId[20]; strcpy(lastVolId, volId); outStat("Insert disk `%s': \x11\xc4\xd9 to continue, Esc to change drive", pVolId->v.pVal); strcpy(buffT, pCopyDrive->v.pVal); if (RpcGetch() == 0x1b){ lineOut((char *) strcat( strcpy(buffFile, "Searching for file: "), pcBufMaxame) ); dispatcher("dialog simplePath,drive,\"Enter new source drive (and path): \""); } outStat(""); volIDFet(); if (RpcStrcmpi(buffT, pCopyDrive->v.pVal)) return (DISKCHANGED); if (RpcStrcmpi(lastVolId, volId)) return (TRUE); return(FALSE); } /* printf/sprintf - minie printf for use * * control string with only %s & %d * * Scaled down printf function that doesn't drag in the whole * ****************************************************************************/ int confd = 1; #define putc(c) *pOut++ = c; char outBuff[120]; char *pOut = outBuff; pSZ sprintf(pBuff, a, b) char *pBuff; { pOut = pBuff; format(a, &b); *pOut = NIL; return(pBuff); } printf(a, b) { pOut = outBuff; format(a, &b); write(1, outBuff, pOut - outBuff); } format(format, pParms) register char *format; register char *pParms; { while(*format){ switch(*format){ case '%': switch(*++format){ case 'd': { char T[10]; RpcItoa(*(int *)pParms, T, 10); puts(T); pParms += sizeof(int); break; } case 's': puts(*(char **)pParms); pParms += sizeof(char *); break; } break; case '\n': putc('\r'); default: putc(*format); } format++; } } puts(pString) register char *pString; { while(*pString){ if (*pString == '\n') putc('\r'); putc(*pString++); } }