/****************************************************************/ /* */ /* newstuff.c */ /* DOS-C */ /* */ /* Copyright (c) 1996 */ /* Svante Frey */ /* All Rights Reserved */ /* */ /* This file is part of DOS-C. */ /* */ /* DOS-C is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version */ /* 2, or (at your option) any later version. */ /* */ /* DOS-C is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ /* the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public */ /* License along with DOS-C; see the file COPYING. If not, */ /* write to the Free Software Foundation, 675 Mass Ave, */ /* Cambridge, MA 02139, USA. */ /****************************************************************/ #ifdef VERSION_STRINGS static BYTE *mainRcsId = "$Id$"; #endif /* * $Log$ * Revision 1.8 2000/08/06 05:50:17 jimtabor * Add new files and update cvs with patches and changes * * Revision 1.7 2000/06/21 18:16:46 jimtabor * Add UMB code, patch, and code fixes * * Revision 1.6 2000/06/01 06:37:38 jimtabor * Read History for Changes * * Revision 1.5 2000/05/26 19:25:19 jimtabor * Read History file for Change info * * Revision 1.4 2000/05/25 20:56:21 jimtabor * Fixed project history * * Revision 1.3 2000/05/17 19:15:12 jimtabor * Cleanup, add and fix source. * * Revision 1.2 2000/05/08 04:30:00 jimtabor * Update CVS to 2020 * * Revision 1.1.1.1 2000/05/06 19:34:53 jhall1 * The FreeDOS Kernel. A DOS kernel that aims to be 100% compatible with * MS-DOS. Distributed under the GNU GPL. * * Revision 1.8 2000/04/02 06:11:35 jtabor * Fix ChgDir Code * * Revision 1.7 2000/04/02 05:30:48 jtabor * Fix ChgDir Code * * Revision 1.6 2000/03/31 05:40:09 jtabor * Added Eric W. Biederman Patches * * Revision 1.5 2000/03/09 06:07:11 kernel * 2017f updates by James Tabor * * Revision 1.4 1999/08/25 03:18:09 jprice * ror4 patches to allow TC 2.01 compile. * * Revision 1.3 1999/04/11 04:33:39 jprice * ror4 patches * * Revision 1.2 1999/04/04 18:51:43 jprice * no message * * Revision 1.1.1.1 1999/03/29 15:41:22 jprice * New version without IPL.SYS * * Revision 1.4 1999/02/08 05:55:57 jprice * Added Pat's 1937 kernel patches * * Revision 1.3 1999/02/01 01:48:41 jprice * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) * * Revision 1.2 1999/01/22 04:13:26 jprice * Formating * * Revision 1.1.1.1 1999/01/20 05:51:01 jprice * Imported sources * * * Rev 1.4 06 Dec 1998 8:49:02 patv * Bug fixes. * * Rev 1.3 04 Jan 1998 23:15:22 patv * Changed Log for strip utility * * Rev 1.2 04 Jan 1998 17:26:14 patv * Corrected subdirectory bug * * Rev 1.1 22 Jan 1997 13:21:22 patv * pre-0.92 Svante Frey bug fixes. */ #include "portab.h" #include "globals.h" #include "proto.h" int SetJFTSize(UWORD nHandles) { UWORD block, maxBlock; psp FAR *ppsp = MK_FP(cu_psp, 0); UBYTE FAR *newtab; COUNT i; if (nHandles <= ppsp->ps_maxfiles) { ppsp->ps_maxfiles = nHandles; return SUCCESS; } if ((DosMemAlloc((nHandles + 0xf) >> 4, mem_access_mode, &block, &maxBlock)) < 0) return DE_NOMEM; ++block; newtab = MK_FP(block, 0); for (i = 0; i < ppsp->ps_maxfiles; i++) newtab[i] = ppsp->ps_filetab[i]; for (; i < nHandles; i++) newtab[i] = 0xff; ppsp->ps_maxfiles = nHandles; ppsp->ps_filetab = newtab; return SUCCESS; } int DosMkTmp(BYTE FAR * pathname, UWORD attr) { /* create filename from current date and time */ static const char tokens[] = "0123456789ABCDEF"; char FAR *ptmp = pathname; BYTE wd, month, day; BYTE h, m, s, hund; WORD sh; WORD year; int rc; while (*ptmp) ptmp++; if (ptmp == pathname || (ptmp[-1] != '\\' && ptmp[-1] != '/')) *ptmp++ = '\\'; DosGetDate(&wd, &month, &day, (COUNT FAR *) & year); DosGetTime(&h, &m, &s, &hund); sh = s * 100 + hund; ptmp[0] = tokens[year & 0xf]; ptmp[1] = tokens[month]; ptmp[2] = tokens[day & 0xf]; ptmp[3] = tokens[h & 0xf]; ptmp[4] = tokens[m & 0xf]; ptmp[5] = tokens[(sh >> 8) & 0xf]; ptmp[6] = tokens[(sh >> 4) & 0xf]; ptmp[7] = tokens[sh & 0xf]; ptmp[8] = '.'; ptmp[9] = 'A'; ptmp[10] = 'A'; ptmp[11] = 'A'; ptmp[12] = 0; while ((rc = DosOpen(pathname, 0)) >= 0) { DosClose(rc); if (++ptmp[11] > 'Z') { if (++ptmp[10] > 'Z') { if (++ptmp[9] > 'Z') return DE_TOOMANY; ptmp[10] = 'A'; } ptmp[11] = 'A'; } } if (rc == DE_FILENOTFND) { rc = DosCreat(pathname, attr); } return rc; } COUNT get_verify_drive(char FAR *src) { COUNT drive; /* First, adjust the source pointer */ src = adjust_far(src); /* Do we have a drive? */ if (src[1] == ':') { drive = (src[0] | 0x20) - 'a'; } else drive = default_drive; if ((drive < 0) || (drive > lastdrive)) { drive = DE_INVLDDRV; } return drive; } /* * Added support for external and internal calls. * Clean buffer before use. Make the true path and expand file names. * Example: *.* -> ????????.??? as in the currect way. * MSD returns \\D.\A.\????????.??? with SHSUCDX. So, this code is not * compatible MSD Func 60h. */ COUNT truename(char FAR * src, char FAR * dest, COUNT t) { static char buf[128] = "A:\\\0\0\0\0\0\0\0\0\0"; /* /// Changed to FNAME_SIZE from 8 for cleanliness. - Ron Cemer */ static char Name[FNAME_SIZE]; char *bufp = buf + 3; COUNT i, n, rootEndPos = 2; /* renamed x to rootEndPos - Ron Cemer */ struct cds FAR *cdsp; struct dhdr FAR *dhp; BYTE FAR *froot; WORD d; dest[0] = '\0'; /* First, adjust the source pointer */ src = adjust_far(src); /* Do we have a drive? */ if (src[1] == ':') { buf[0] = (src[0] | 0x20) + 'A' - 'a'; if (buf[0] > lastdrive + 'A') return DE_PATHNOTFND; src += 2; } else buf[0] = default_drive + 'A'; /* /// Added to adjust for filenames which begin with ".\" The problem was manifesting itself in the inability to run an program whose filename (without the extension) was longer than six characters and the PATH variable contained ".", unless you explicitly specified the full path to the executable file. Jun 11, 2000 - rbc */ /* /// Changed to "while" from "if". - Ron Cemer */ while ( (src[0] == '.') && (src[1] == '\\') ) src += 2; i = buf[0] - 'A'; /* Code repoff from dosfns.c MSD returns X:/CON for truename con. Not X:\CON */ /* check for a device */ froot = get_root(src); for (d = 0; d < FNAME_SIZE; d++) { if (*froot != '\0' && *froot != '.') Name[d] = *froot++; else break; } for (; d < FNAME_SIZE; d++) Name[d] = ' '; /* /// Bugfix: NUL.LST is the same as NUL. This is true for all devices. On a device name, the extension is irrelevant as long as the name matches. - Ron Cemer */ #if (0) /* if we have an extension, can't be a device */ if (*froot != '.') { #endif for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) { if (fnmatch((BYTE FAR *) &Name, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) { buf[2] ='/'; /* /// Bug: should be only copying up to first space. - Ron Cemer for (d = 0; d < FNAME_SIZE || Name[d] == ' '; d++) */ for (d = 0; ( (d < FNAME_SIZE) && (Name[d] != ' ') ); d++) *bufp++ = Name[d]; /* /// DOS will return C:/NUL.LST if you pass NUL.LST in. DOS will also return C:/NUL.??? if you pass NUL.* in. Code added here to support this. - Ron Cemer */ while ( (*froot != '.') && (*froot != '\0') ) froot++; if (*froot) froot++; if (*froot) { *bufp++ = '.'; for (i = 0; i < FEXT_SIZE; i++) { if ( (*froot == '\0') || (*froot == '.') ) break; if (*froot == '*') { for (; i < FEXT_SIZE; i++) *bufp++ = '?'; break; } *bufp++ = *froot++; } } /* /// End of code additions. - Ron Cemer */ goto exit_tn; } } #if (0) } #endif cdsp = &CDSp->cds_table[i]; current_ldt = cdsp; /* Always give the redirector a chance to rewrite the filename */ fsncopy((BYTE FAR *) src, bufp -1, sizeof(buf) - (bufp - buf)); if ((QRemote_Fn(buf, dest) == SUCCESS) && (dest[0] != '\0')) { return SUCCESS; } else { bufp[-1] = '\\'; } if (t == FALSE) { fsncopy((BYTE FAR *) & cdsp->cdsCurrentPath[0], (BYTE FAR *) & buf[0], cdsp->cdsJoinOffset); bufp = buf + cdsp->cdsJoinOffset; rootEndPos = cdsp->cdsJoinOffset; /* renamed x to rootEndPos - Ron Cemer */ *bufp++ = '\\'; } if (*src != '\\' && *src != '/') /* append current dir */ { DosGetCuDir(i+1, bufp); if (*bufp) { while (*bufp) bufp++; *bufp++ = '\\'; } } else src++; move_name: /* /// The block inside the "#if (0) ... #endif" is seriously broken. New code added below to replace it. This eliminates many serious bugs, specifically with FreeCOM where truename is required to work according to the DOS specification in order for the COPY and other file-related commands to work properly. This should be a major improvement to all apps which use truename. - Ron Cemer */ #if (0) /* * The code here is brain dead. It works long as the calling * function are operating with in normal parms. * jt */ n = 9; /* convert all forward slashes to backslashes, and uppercase all characters */ while (*src) { char c; c = *src++; if(!n) return DE_PATHNOTFND; /* do this for now */ n--; switch (c) { case '*': if (*src == '.') { while (n--) *bufp++ = '?'; break; } else { if (src[-2] == '.') { while (n--) *bufp++ = '?'; break; } else { while (n--) *bufp++ = '?'; break; } } case '/': /* convert to backslash */ case '\\': if (bufp[-1] != '\\'){ *bufp++ = '\\'; n = 9; } break; /* look for '.' and '..' dir entries */ case '.': if (bufp[-1] == '\\') { if (*src == '.' && (src[1] == '/' || src[1] == '\\' || !src[1])) { /* '..' dir entry: rewind bufp to last backslash */ for (bufp -= 2; *bufp != '\\'; bufp--) { if (bufp < buf + rootEndPos) /* '..' illegal in root dir */ return DE_PATHNOTFND; } src++; if (bufp[-1] == ':') bufp++; } else if (*src == '/' || *src == '\\' || *src == 0) break; /* --bufp;*/ else return DE_PATHNOTFND; } else if ( *src == '/' || *src == '\\' || *src == 0) { break; } else { n = 4; *bufp++ = c; } break; default: *bufp++ = c; break; } } /* remove trailing backslashes */ while (bufp[-1] == '\\') --bufp; #endif /* /// Beginning of new code. - Ron Cemer */ bufp--; { char c, *bufend = buf+(sizeof(buf)-1); int gotAnyWildcards = 0; int seglen, copylen, state; while ( (*src) && (bufp < bufend) ) { /* Skip duplicated slashes. */ while ( (*src == '/') || (*src == '\\') ) src++; if (!(*src)) break; /* Find the end of this segment in the source string. */ for (seglen = 0; ; seglen++) { c = src[seglen]; if ( (c == '\0') || (c == '/') || (c == '\\') ) break; } if (seglen > 0) { /* Ignore all ".\" or "\." path segments. */ if ( (seglen != 1) || (*src != '.') ) { /* Apply ".." to the path by removing last path segment from buf. */ if ( (seglen==2) && (src[0] == '.') && (src[1] == '.') ) { if (bufp > (buf+rootEndPos)) { bufp--; while ( (bufp > (buf+rootEndPos)) && (*bufp != '/') && (*bufp != '\\') ) bufp--; } } else { /* New segment. If any wildcards in previous segment(s), this is an invalid path. */ if (gotAnyWildcards) return DE_PATHNOTFND; /* Append current path segment to result. */ *(bufp++) = '\\'; if (bufp >= bufend) break; copylen = state = 0; for (i=0; ( (i < seglen) && (bufp < bufend) ); i++) { c = src[i]; gotAnyWildcards |= ( (c == '?') || (c == '*') ); switch (state) { case 0: /* Copying filename (excl. extension) */ if (c == '*') { while (copylen < FNAME_SIZE) { *(bufp++) = '?'; if (bufp >= bufend) break; copylen++; } copylen = 0; state = 1; /* Go wait for dot */ break; } if (c == '.') { *(bufp++) = '.'; copylen = 0; state = 2; /* Copy extension next */ break; } *(bufp++) = c; copylen++; if (copylen >= FNAME_SIZE) { copylen = 0; state = 1; /* Go wait for dot */ break; } break; case 1: /* Looking for dot so we can copy exten */ if (src[i] == '.') { *(bufp++) = '.'; state = 2; } break; case 2: /* Copying extension */ if (c == '*') { while (copylen < FEXT_SIZE) { *(bufp++) = '?'; if (bufp >= bufend) break; copylen++; } i = seglen; /* Done with segment */ break; } if (c == '.') { i = seglen; /* Done with segment */ break; } *(bufp++) = c; copylen++; if (copylen >= FEXT_SIZE) { i = seglen; /* Done with segment */ break; } break; } } } } } /* if (seglen > 0) */ src += seglen; if (*src) src++; } /* while ( (*src) && (bufp < bufend) ) */ } /* /// End of new code. - Ron Cemer */ if (bufp == buf + 2) ++bufp; exit_tn: *bufp++ = 0; /* finally, uppercase everything */ DosUpString(buf); /* copy to user's buffer */ fbcopy(buf, dest, bufp - buf); return SUCCESS; }