/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available Software. */ /* \ 1011 / */ /* ------ */ /* */ /* (C) Copyright 1987-96, Bit Bucket Software Co. */ /* */ /* This module was written by Vince Perriello */ /* OS/2 code contributed by Bill Andrus */ /* DOS and OS/2 File I/O routines used by BinkleyTerm */ /* */ /* */ /* For complete details of the licensing restrictions, please refer */ /* to the License agreement, which is published in its entirety in */ /* the MAKEFILE and BT.C, and also contained in the file LICENSE.260. */ /* */ /* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */ /* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */ /* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */ /* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */ /* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */ /* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */ /* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */ /* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */ /* */ /* */ /* You can contact Bit Bucket Software Co. at any one of the following */ /* addresses: */ /* */ /* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */ /* P.O. Box 460398 AlterNet 7:42/1491 */ /* Aurora, CO 80046 BBS-Net 86:2030/1 */ /* Internet f491.n343.z1.fidonet.org */ /* */ /* Please feel free to contact us at any time to share your comments about */ /* our software and/or licensing policies. */ /* */ /*--------------------------------------------------------------------------*/ /* Include this file before any other includes or defines! */ #include "includes.h" #ifdef NEED_MKTEMP char * mktemp (char *template) { static char save[8] = "Z"; char *p; int i; p = save; if (*p == 'Z') sprintf (p, "%06d", TaskNumber); while (*p) { if (isdigit (*p)) { *p = 'a'; break; } if (*p++ < 'z') { break; } } if ((*p == '\0') || ((i = strlen (template)) < 6)) return (NULL); strcpy (&template[i - 6], save); return (template); } #endif #ifdef NEED_DOSREAD #ifdef _WIN32 int _dos_read (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read) { *bytes_read = read (fd, buf, nbytes); return (*bytes_read == nbytes) ? 0 : -1; } int _dos_write (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read) { *bytes_read = write (fd, buf, nbytes); return (*bytes_read == nbytes) ? 0 : -1; } #endif #ifdef DOS16 int _dos_read (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read) { union REGS regs; struct SREGS sregs; regs.h.ah = 0x3f; /* read file */ regs.x.bx = fd; regs.x.cx = nbytes; regs.x.dx = FP_OFF (buf); sregs.ds = FP_SEG (buf); *bytes_read = intdosx (®s, ®s, &sregs); return regs.x.cflag ? -1 : 0; } int _dos_write (int fd, void far * buf, unsigned nbytes, unsigned int *bytes_read) { union REGS regs; struct SREGS sregs; regs.h.ah = 0x40; /* write file */ regs.x.bx = fd; regs.x.cx = nbytes; regs.x.dx = FP_OFF (buf); sregs.ds = FP_SEG (buf); *bytes_read = intdosx (®s, ®s, &sregs); return regs.x.cflag ? -1 : 0; } #endif #endif /* For Borland C++ 2.0, change __TURBOC_OLD__ to __TURBOC__ */ #ifdef __TURBOC_OLD__ /* * utime function for Turbo / Borland C. * * We should make this more generic in case some other DOS * compiler comes up lacking, but for now the only one we * have that needs it happens to be Borland. * */ int cdecl utime (char *name, struct utimbuf *times) { int handle; struct date d; struct time t; struct ftime ft; unixtodos (times->modtime, &d, &t); ft.ft_tsec = t.ti_sec / 2; ft.ft_min = t.ti_min; ft.ft_hour = t.ti_hour; ft.ft_day = d.da_day; ft.ft_month = d.da_mon; ft.ft_year = d.da_year - 1980; if ((handle = open (name, O_RDONLY)) == -1) return -1; setftime (handle, &ft); close (handle); return 0; } #endif int dexists (char *filename) { struct stat stbuf; return (stat (filename, &stbuf) != -1) ? 1 : 0; } int got_error (char *string1, char *string2) { if (errno == 0x18) errno = 0; if (errno != 0) { status_line ("%s %d, %s %s %s", MSG_TXT (M_ERROR), errno, MSG_TXT (M_CANT), string1, string2); errno = 0; return (1); } return (0); } /* Z F R E E -- Return total number of free bytes on drive specified */ #ifdef DOS16 long zfree (char *drive) { union REGS r; unsigned char driveno; long stat; if (drive[0] != '\0' && drive[1] == ':') { driveno = (unsigned char) (islower (*drive) ? toupper (*drive) : *drive); driveno = (unsigned char) (driveno - 'A' + 1); } else driveno = 0; /* Default drive */ r.x.ax = 0x3600; /* get free space */ r.h.dl = driveno; /* on this drive */ (void) int86 (0x21, &r, &r);/* go do it */ if (r.x.ax == 0xffff) /* error return?? */ return (0); stat = (long) r.x.bx /* bx = clusters avail */ * (long) r.x.ax /* ax = sectors/clust */ * (long) r.x.cx; /* cx = bytes/sector */ return (stat); } #endif /* DOS16 */ #ifdef OS_2 long zfree (char *path) { int drive; FSALLOCATE dt; if (*path != '\0' && path[1] == ':') drive = tolower (*path) - 'a' + 1; else drive = 0; DosQFSInfo ((USHORT) drive, 1, (unsigned char far *) &dt, sizeof (FSALLOCATE)); return (dt.cSectorUnit * dt.cUnitAvail * dt.cbSector); } #endif #ifdef _WIN32 long zfree (char *drive) { unsigned driveno; struct _diskfree_t diskinfo; long stat; if (drive[0] != '\0' && drive[1] == ':') { driveno = (unsigned) (islower (*drive) ? toupper (*drive) : *drive); driveno = (unsigned) (driveno - 'A' + 1); } else driveno = 0; /* Default drive */ if (_getdiskfree (driveno, &diskinfo) != 0) return 0; stat = diskinfo.avail_clusters * diskinfo.sectors_per_cluster * diskinfo.bytes_per_sector; return (stat); } #endif /* _WIN32 */ static int share_flags[] = { #ifdef SH_COMPAT SH_COMPAT, #else 0, #endif SH_DENYNO, SH_DENYRD, SH_DENYRW, SH_DENYWR }; int share_open (char *filename, int oflag, int shflag) { #ifdef DOS16 if ((no_sharing == 0) && (_osmajor >= 3)) #else if (no_sharing == 0) #endif /* DOS16 */ return (sopen (filename, oflag, share_flags[shflag])); else return (open (filename, oflag)); } FILE * share_fopen (char *filename, char *mode, int shflag) { #ifdef MUST_FDOPEN int fd; int open_mode; char c, *p; int sflag = S_IREAD | S_IWRITE; FILE *stream; /* * Microsoft made this easy for us. They gave us a stream-open * function that supports file sharing. Borland was not so kind. * So -- what we do here is open the file using the only sharing * API they provide -- that gives us a file handle -- then we * use fdopen to get a file stream out of it. Sheesh! * * Of course, Microsoft 5.1 provides about the same level of * support as Borland -- almost. They explicitly warn you not * to do this neat thing I did for Borland. So I get no sharing * support for fopen() under 5.1. Double sheesh! */ if ((no_sharing == 0) && (_osmajor >= 3)) { /* Figure out the translation from fopen-mode to open-mode... */ p = mode; c = *p++; if (c == 'w') open_mode = O_CREAT | O_RDWR; else if (c == 'r') open_mode = O_RDONLY; else if (c == 'a') open_mode = O_CREAT | O_RDWR | O_APPEND; else return (FILE *) NULL; while (*p) { c = *p++; if (c == 't') open_mode = (open_mode & ~O_BINARY) | O_TEXT; if (c == 'b') open_mode = (open_mode & ~O_TEXT) | O_BINARY; if (c == '+') { if ((open_mode & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) { open_mode = (open_mode & ~O_RDONLY) | O_RDWR; } else if (!(open_mode & O_APPEND)) open_mode |= O_TRUNC; } } /* Open the file handle */ #ifdef SHARE_SOPEN fd = sopen (filename, open_mode, share_flags[shflag], sflag); #else fd = open (filename, open_mode | share_flags[shflag], sflag); #endif if (fd == -1) return (FILE *) NULL; /* Got the handle, make the stream */ if ((stream = fdopen (fd, mode)) == (FILE *) NULL) (void) close (fd); return (stream); } else #else #ifndef CANT_FSOPEN #ifdef DOS16 if ((no_sharing == 0) && (_osmajor >= 3)) #else if (no_sharing == 0) #endif /* DOS16 */ return (_fsopen (filename, mode, share_flags[shflag])); else #else happy_compiler = shflag; /* Makes the compiler happy */ #endif #endif return (fopen (filename, mode)); } #ifdef DOS16 int dfind (struct FILEINFO *dta, char *name, int times) { union REGS r; struct SREGS s; char far *dtaptr = (char *) dta; char far *nameptr = (char *) name; s.ds = FP_SEG (dtaptr); r.x.dx = FP_OFF (dtaptr); r.h.ah = 0x1a; (void) intdosx (&r, &r, &s); r.x.bx = 0; r.x.cx = (unsigned int) ~0x08; s.ds = FP_SEG (nameptr); r.x.dx = FP_OFF (nameptr); r.x.si = 0; r.x.di = 0; if (times == 0) { r.h.ah = 0x4e; (void) intdosx (&r, &r, &s); dta->nill = '\0'; /* If not found or a character device (e.g. "COM1") */ if ((r.x.cflag != 0) || ((dta->attr & 0x40) != 0)) { dta->name[0] = '\0'; return (1); } return (0); } else if (times == 1) { r.h.ah = 0x4f; (void) intdosx (&r, &r, &s); dta->nill = '\0'; /* If not found or a character device (e.g. "COM1") */ if ((r.x.cflag != 0) || ((dta->attr & 0x40) != 0)) { dta->name[0] = '\0'; return (1); } return (0); } else return (0); } #endif /* DOS16 */ #ifdef OS_2 #ifndef __32BIT__ static int dir_findfirst (char far *, int, struct FILEINFO *); static int dir_findnext (struct FILEINFO *); static int dir_findrelease (struct FILEINFO *); int dfind (struct FILEINFO *dta, char *name, int times) { if (times == 0) { return (dir_findfirst (name, 0x37, dta)); } else if (times == 1) { return (dir_findnext (dta)); } else return (dir_findrelease (dta)); } /*--------------------------------------------------------------------------*/ /* Static variable definitions */ /*--------------------------------------------------------------------------*/ struct FileTimeBuf { unsigned short c_date; /* date of file creation */ unsigned short c_time; /* time of file creation */ unsigned short a_date; /* date of last access */ unsigned short a_time; /* time of last access */ unsigned short w_date; /* date of last write */ unsigned short w_time; /* time of last write */ }; static struct FileTimeBuf TimeBuf; struct FileInfo { USHORT hDir; char rsvd[19]; char attrib; unsigned short wr_date; unsigned short wr_time; long size; char name[13]; char nill; }; struct FileFindBuf { unsigned short create_date; /* date of file creation */ unsigned short create_time; /* time of file creation */ unsigned short access_date; /* date of last access */ unsigned short access_time; /* time of last access */ unsigned short wr_date; /* date of last write */ unsigned short wr_time; /* time of last write */ unsigned long size; /* file size (end of data) */ unsigned long falloc_size; /* file allocated size */ unsigned short attrib; /* attributes of the file */ unsigned char string_len; /* returned length of ascii name str. */ /* length does not include null byte */ char name[255]; /* name string */ }; static struct FileFindBuf InfoBuf; /*--------------------------------------------------------------------------*/ /* Locally defined globals */ /*--------------------------------------------------------------------------*/ struct FileInfo *dtap; HDIR hDirA; USHORT cSearch; USHORT usAttrib; USHORT findrc; /*--------------------------------------------------------------------------*/ /* Local constants */ /*--------------------------------------------------------------------------*/ #define FILENAMELEN 13 static int dir_findfirst (char far * filename, int attribute, struct FILEINFO *dta) { cSearch = 1; dtap = (struct FileInfo *) dta; hDirA = dtap->hDir; usAttrib = (USHORT) attribute; if ((hDirA != 0xffff) && (hDirA != 0x0000)) (void) DosFindClose (hDirA); hDirA = 0xffff; findrc = DosFindFirst ((PSZ) filename ,&hDirA ,usAttrib ,(PFILEFINDBUF) & InfoBuf ,(USHORT)(sizeof (InfoBuf)) * cSearch ,&cSearch ,(ULONG) NULL); if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT))) { (void) DosFindClose (hDirA); dtap->hDir = 0xffff; errno = ENOENT; return (1); } else { dtap->wr_date = InfoBuf.wr_date; dtap->wr_time = InfoBuf.wr_time; dtap->attrib = (char) InfoBuf.attrib; dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1); strcpy (dtap->name, InfoBuf.name); (void) strupr (dtap->name); dtap->hDir = hDirA; errno = 0; return (0); } } static int dir_findnext (struct FILEINFO *dta) { cSearch = 1; dtap = (struct FileInfo *) dta; hDirA = dtap->hDir; findrc = DosFindNext (hDirA ,(PFILEFINDBUF) & InfoBuf ,(USHORT) (sizeof (InfoBuf)) * cSearch ,&cSearch); if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT))) { (void) DosFindClose (hDirA); dtap->hDir = 0xffff; errno = ENOENT; return (1); } else { dtap->wr_date = InfoBuf.wr_date; dtap->wr_time = InfoBuf.wr_time; dtap->attrib = (char) InfoBuf.attrib; dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1); strcpy (dtap->name, InfoBuf.name); (void) strupr (dtap->name); dtap->hDir = hDirA; errno = 0; return (0); } } static int dir_findrelease (struct FILEINFO *dta) { dtap = (struct FileInfo *) dta; hDirA = dtap->hDir; if (hDirA != 0xffff) { (void) DosFindClose (hDirA); dtap->hDir = 0xffff; errno = ENOENT; return (1); } else return (0); } void set_fileinfo (int fh, unsigned date, unsigned time) { if ((time / 2048) < (unsigned) (TIMEZONE / 3600L)) { TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date - 1; TimeBuf.c_time = time + ((unsigned) (86400 - ((unsigned) (TIMEZONE / 3600L) * 2048))); TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time; } else { TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date; TimeBuf.c_time = time - ((unsigned) (TIMEZONE / 3600L) * 2048); TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time; } (void) DosSetFileInfo ((HFILE) fh, (USHORT) 1, (PBYTE) & TimeBuf, (USHORT) 12); } #else /* ifndef __32BIT__ */ static int dir_findfirst (char far *, int, struct FILEINFO *); static int dir_findnext (struct FILEINFO *); static int dir_findrelease (struct FILEINFO *); int dfind (struct FILEINFO *dta, char *name, int times) { if (times == 0) { return (dir_findfirst (name, 0x37, dta)); } else if (times == 1) { return (dir_findnext (dta)); } else return (dir_findrelease (dta)); } /*--------------------------------------------------------------------------*/ /* Static variable definitions */ /*--------------------------------------------------------------------------*/ struct FileTimeBuf { unsigned short c_date; /* date of file creation */ unsigned short c_time; /* time of file creation */ unsigned short a_date; /* date of last access */ unsigned short a_time; /* time of last access */ unsigned short w_date; /* date of last write */ unsigned short w_time; /* time of last write */ }; static struct FileTimeBuf TimeBuf; struct FileInfo { unsigned short hDir; char rsvd[19]; char attrib; unsigned short wr_date; unsigned short wr_time; ULONG size; char name[13]; char nill; }; struct FileFindBuf { ULONG nDir; /* pointer to next structure */ unsigned short create_date; /* date of file creation */ unsigned short create_time; /* time of file creation */ unsigned short access_date; /* date of last access */ unsigned short access_time; /* time of last access */ unsigned short wr_date; /* date of last write */ unsigned short wr_time; /* time of last write */ ULONG size; /* file size (end of data) */ ULONG falloc_size; /* file allocated size */ ULONG attrib; /* attributes of the file */ UCHAR string_len; /* returned length of ascii name str. */ /* length does not include null byte */ char name[CCHMAXPATHCOMP]; /* name string */ }; static struct FileFindBuf InfoBuf; /*--------------------------------------------------------------------------*/ /* Locally defined globals */ /*--------------------------------------------------------------------------*/ struct FileInfo *dtap; HDIR hDirA; ULONG cSearch; ULONG usAttrib; ULONG infolevel; APIRET findrc; /*--------------------------------------------------------------------------*/ /* Local constants */ /*--------------------------------------------------------------------------*/ #define FILENAMELEN 13 static int dir_findfirst (char far * filename, int attribute, struct FILEINFO *dta) { cSearch = 1; dtap = (struct FileInfo *) dta; hDirA = dtap->hDir; usAttrib = (USHORT) attribute; infolevel = 1; if ((hDirA != 0xffff) && (hDirA != 0x0000) && (hDirA != 0xffffffff)) (void) DosFindClose (hDirA); hDirA = 0xffffffff; findrc = DosFindFirst ((PSZ) filename ,&hDirA ,usAttrib ,(PVOID) & InfoBuf ,(ULONG) (sizeof (InfoBuf) * cSearch) ,&cSearch ,infolevel); if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT))) { (void) DosFindClose (hDirA); dtap->hDir = 0xffff; errno = ENOENT; return (1); } else { dtap->wr_date = InfoBuf.wr_date; dtap->wr_time = InfoBuf.wr_time; dtap->attrib = (char) InfoBuf.attrib; dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1); strcpy (dtap->name, InfoBuf.name); (void) strupr (dtap->name); dtap->hDir = hDirA; errno = 0; return (0); } } static int dir_findnext (struct FILEINFO *dta) { cSearch = 1; dtap = (struct FileInfo *) dta; hDirA = dtap->hDir; findrc = DosFindNext (hDirA ,(PVOID) & InfoBuf ,(ULONG) (sizeof (InfoBuf) * cSearch) ,&cSearch); if ((cSearch != 1) || (findrc && (findrc != ERROR_EAS_DIDNT_FIT))) { (void) DosFindClose (hDirA); dtap->hDir = 0xffff; errno = ENOENT; return (1); } else { dtap->wr_date = InfoBuf.wr_date; dtap->wr_time = InfoBuf.wr_time; dtap->attrib = (char) InfoBuf.attrib; dtap->size = InfoBuf.size / ((_osmajor == 10) ? 2 : 1); strcpy (dtap->name, InfoBuf.name); (void) strupr (dtap->name); dtap->hDir = hDirA; errno = 0; return (0); } } static int dir_findrelease (struct FILEINFO *dta) { dtap = (struct FileInfo *) dta; hDirA = dtap->hDir; if ((hDirA != 0xffff) && (hDirA != 0xffffffff)) { (void) DosFindClose (hDirA); dtap->hDir = 0xffff; errno = ENOENT; return (1); } else return (0); } void set_fileinfo (int fh, unsigned date, unsigned time) { if ((time / 2048) < (unsigned) (TIMEZONE / 3600L)) { TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date - 1; TimeBuf.c_time = time + ((unsigned) (86400 - ((unsigned) (TIMEZONE / 3600L) * 2048))); TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time; } else { TimeBuf.a_date = TimeBuf.w_date = TimeBuf.c_date = date; TimeBuf.c_time = time - ((unsigned) (TIMEZONE / 3600L) * 2048); TimeBuf.a_time = TimeBuf.w_time = TimeBuf.c_time; } (void) DosSetFileInfo ((HFILE) fh, (USHORT) 1, (PBYTE) & TimeBuf, (USHORT) 12); } #endif /* ifndef __32BIT__ */ #endif /* ifdef OS_2 */ #ifdef _WIN32 static int dir_findfirst (char far *, struct FILEINFO *); static int dir_findnext (struct FILEINFO *); static int dir_findrelease (struct FILEINFO *); int dfind (struct FILEINFO *dta, char *name, int times) { if (times == 0) { return (dir_findfirst (name, dta)); } else if (times == 1) { return (dir_findnext (dta)); } else return (dir_findrelease (dta)); } /*--------------------------------------------------------------------------*/ /* Static variable definitions */ /*--------------------------------------------------------------------------*/ struct FileInfo { long hDir; int fActive; char rsvd[13]; char attrib; long time; long size; char name[13]; char nill; }; static struct _finddata_t InfoBuf; /*--------------------------------------------------------------------------*/ /* Local functions */ /*--------------------------------------------------------------------------*/ static void dir_move (struct FileInfo *dta); /*--------------------------------------------------------------------------*/ /* Local constants */ /*--------------------------------------------------------------------------*/ #define FILENAMELEN 13 static int dir_findfirst (char far * filename, struct FILEINFO *dta) { struct FileInfo *dtap = (struct FileInfo *) dta; long hDirA; if (dtap->fActive) { (void) dir_findrelease (dta); } hDirA = _findfirst (filename, &InfoBuf); if (hDirA == -1) { errno = ENOENT; return (1); } dir_move (dtap); dtap->hDir = hDirA; dtap->fActive = 1; return (0); } static int dir_findnext (struct FILEINFO *dta) { struct FileInfo *dtap = (struct FileInfo *) dta; long hDirA; int fResult; if (!dtap->fActive) return (1); hDirA = dtap->hDir; fResult = (_findnext (hDirA, &InfoBuf) != 0); if (fResult) { errno = ENOENT; (void) dir_findrelease (dta); return (1); } dir_move (dtap); return (0); } static void dir_move (struct FileInfo *dtap) { struct tm *ptm; long timelong; ptm = localtime (&InfoBuf.time_write); timelong = (long) (ptm->tm_sec / 2) + (long) ((ptm->tm_min) << 5) + (long) ((ptm->tm_hour) << 11) + (long) ((ptm->tm_mday) << 16) + (long) ((ptm->tm_mon + 1) << 21) + (long) ((ptm->tm_year - 80) << 25); dtap->time = timelong; dtap->size = InfoBuf.size; dtap->attrib = (char) InfoBuf.attrib; strncpy (dtap->name, InfoBuf.name, FILENAMELEN); (void) strupr (dtap->name); dtap->nill = 0; errno = 0; } static int dir_findrelease (struct FILEINFO *dta) { struct FileInfo *dtap = (struct FileInfo *) dta; long hDirA; if (!dtap->fActive) return (1); hDirA = dtap->hDir; (void) _findclose (hDirA); dtap->fActive = 0; return (0); } #endif /* ifdef _WIN32 */