summaryrefslogtreecommitdiff
path: root/dmake/msdos/dirlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'dmake/msdos/dirlib.c')
-rw-r--r--dmake/msdos/dirlib.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/dmake/msdos/dirlib.c b/dmake/msdos/dirlib.c
new file mode 100644
index 000000000000..eaef928772af
--- /dev/null
+++ b/dmake/msdos/dirlib.c
@@ -0,0 +1,285 @@
+/*
+ DIRLIB for MS-DOS
+ -----------------
+
+Enclosed is an implementation of the `dirlib' package for MS-DOS.
+The implementation is targeted for MS-C, although any reasonably
+competent C compiler should manage. The package consists of:
+
+ dir.h the header file
+ dir.c the functions
+ testdir.c a q&d test program
+
+The package tries to view directory naming in a Un*x light; in particular,
+directories such as '/.' and '/..' (as well as `.' and `..' if your
+current directory is root) are understood. Indefinite paths like
+`/../.././../..' will correctly refer to the root (of the particular disk).
+Names such as `a:////./../' are okay too.
+
+I've tried to be as sensible about DTA's as possible, since you never
+know who will be using one; they are set before use, and reset afterwards.
+
+There is some cruft in the package, namely the way `seekdir' and
+`telldir' are done. The code was derived from a little experimentation,
+and may not work after a certain point (although I believe the 2.x version
+to be solid). Caveat utilitor.
+
+Documentation for the package is available in the public domain; the
+package's functionality was derived from this documentation.
+
+Bug reports and comments are welcome. Enjoy!
+
+ - Matt
+
+-------
+UUCP: {ucbvax,ihnp4,randvax,trwrb!trwspp,ism780}!ucla-cs!matt
+ARPA: matt@LOCUS.UCLA.EDU
+Ph: (213) 825-2756
+
+--------
+Modified for use in dmake by Dennis Vadura. Mostly just clean up and an
+effort to make correctly typed objects are passed to functions in find.c.
+Also deleted all dos version 2.0 specific code. It is not required any
+more.
+*/
+
+/*
+ * revision history:
+ *
+ * VER MM/DD/YY COMMENTS
+ * ---- -------- --------
+ * 0.99 02/24/86 Beta release to INTERNET
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <dos.h>
+
+#include "dirent.h"
+
+extern int find_err;
+
+
+static char *
+getdcwd(drive)
+int drive;
+{
+ union REGS r;
+ struct SREGS s;
+ static char xcwd[64];
+ char far *cwd = xcwd;
+
+ r.h.ah = 0x47;
+ r.h.dl = drive;
+ r.x.si = FP_OFF(cwd);
+ s.ds = FP_SEG(cwd);
+ intdosx(&r, &r, &s);
+ find_err = r.x.ax;
+ if (r.x.cflag)
+ return (char *) 0;
+ return xcwd;
+}
+
+
+
+/*
+ * opendir
+ */
+
+#define SUFFIX "\\*.*"
+#define SLASH "\\"
+#define streq(a,b) (strcmp(a,b)==0)
+
+DIR *
+opendir(name)
+char *name;
+{
+ register DIR *nd;
+ char *cwd;
+ char drive[3];
+ int atroot = 0;
+ int rooted = 0;
+
+ /*
+ * hack off drive designator if present
+ */
+
+ if (name[1] == ':') {
+ cwd = getdcwd(toupper(name[0]) - 'A' + 1);
+ drive[0] = name[0]; drive[1] = ':'; drive[2] = '\0';
+ name += 2;
+ }
+ else {
+ cwd = getdcwd(0);
+ drive[0] = '\0';
+ }
+
+ /* is the name 'rooted'? */
+ if ((*name == '/') || (*name == '\\')) ++rooted;
+
+ /* see if we are at the root directory for this device */
+ if (!*cwd) ++atroot;
+
+ /*
+ * MSDOS '/' doesn't have a '.' or '..'
+ * also, double '/' sequences don't make sense.
+ * many ported programs expect them to work, so we fix it up...
+ */
+
+ /* chop off leading . and .. if at root */
+ if (atroot && (*name == '.')) {
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+
+ case '.':
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+ default:
+ --name;
+ --name;
+ }
+ break;
+
+ default:
+ --name;
+ }
+ }
+
+ /* chop off leading /'s, /.'s and /..'s to make naming sensible */
+ while (*name && ((*name == '/') || (*name == '\\'))) {
+ if (*++name == '.') {
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+
+ case '.':
+ switch (*++name) {
+ case '\0':
+ case '/':
+ case '\\':
+ break;
+
+ default:
+ --name;
+ --name;
+ }
+ break;
+
+ default:
+ --name;
+ }
+ }
+ }
+
+
+ /*
+ * name should now look like: path/path/path
+ * we must now construct name based on whether or not it
+ * was 'rooted' (started with a /)
+ */
+
+ if (rooted) cwd = "";
+
+ /* construct DIR */
+ if (!(nd = (DIR *)malloc(
+ sizeof(DIR)+strlen(drive)+strlen(cwd)+strlen(SLASH)+
+ strlen(name)+strlen(SUFFIX))))
+ return (DIR *) 0;
+
+ /* create long name */
+ strcpy(nd->dd_name, drive);
+ if (*cwd) {
+ strcat(nd->dd_name, SLASH);
+ strcat(nd->dd_name, cwd);
+ }
+ if (*name) {
+ strcat(nd->dd_name, SLASH);
+ strcat(nd->dd_name, name);
+ }
+ strcat(nd->dd_name, SUFFIX);
+
+ /* search */
+ if (!findfirst(&nd->dd_name[0], &nd->dd_dta)) {
+ free((char *)nd);
+ errno = ENOENT;
+ return (DIR *) 0;
+ }
+ nd->dd_stat = 0;
+ return nd;
+}
+
+
+struct dirent *
+readdir(dirp)
+DIR *dirp;
+{
+ static struct dirent dir;
+
+ if (dirp->dd_stat)
+ return (struct dirent *) 0;
+
+ /* format structure */
+ dir.d_ino = 0; /* not valid for DOS */
+ dir.d_reclen = 0;
+ strcpy(dir.d_name, dirp->dd_dta.name);
+ dir.d_namlen = strlen(dir.d_name);
+ strlwr(dir.d_name); /* DOSism */
+
+ /* read ahead */
+ if (findnext(&dirp->dd_dta) != NULL)
+ dirp->dd_stat = 0;
+ else
+ dirp->dd_stat = find_err;
+
+ return &dir;
+}
+
+
+void
+closedir(dirp)
+DIR *dirp;
+{
+ free((char *)dirp);
+}
+
+
+void
+seekdir(dirp, pos)
+DIR *dirp;
+long pos;
+{
+ /*
+ * check against DOS limits
+ */
+
+ if ((pos < 0) || (pos > 4095)) {
+ dirp->dd_stat = 1;
+ return;
+ }
+
+ *(short *)&dirp->dd_dta.fcb[13] = pos + 1;
+
+ /* read ahead */
+ if (findnext(&dirp->dd_dta))
+ dirp->dd_stat = 0;
+ else
+ dirp->dd_stat = find_err;
+}
+
+
+long
+telldir(dirp)
+DIR *dirp;
+{
+ return (long) (*(short *)&dirp->dd_dta.fcb[13] - 2);
+}