home *** CD-ROM | disk | FTP | other *** search
- /* This file is SYSDJ.c
- ** contains :
- **
- ** - int21,ah=0xff djgpp syscall handler
- **
- ** Copyright (c) Rainer Schnitker 92 93
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <malloc.h>
- #include <fcntl.h>
- #include <direct.h>
- #include <io.h>
- #include <time.h>
- #include <ctype.h>
- #include <sys/timeb.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #include "DPMI.H"
- #include "PROCESS.H"
- #include "SIGNALS.H"
- #include "CDOSX32.H"
- #include "START32.H"
- #include "COPY32.H"
- #include "RSX.H"
- #include "DOSERRNO.H"
-
- #ifndef __TURBOC__
- #define MAXPATH _MAX_PATH
- #include <dos.h>
- static int stime(time_t *gmt_seconds)
- {
- struct tm *pTM;
- struct dostime_t dost;
-
- pTM = gmtime(gmt_seconds);
- dost.hour = (char) pTM->tm_hour;
- dost.minute = (char) pTM->tm_min;
- dost.second = (char) pTM->tm_sec;
- dost.hsecond = 0;
- _dos_settime(&dost);
- return 0;
- }
- int convert_open_attrib(int att)
- {
- int o_rdwr = (att & 0x0F) >> 1; /* bcc O_R/W flags */
- if (att & 0x800)
- o_rdwr &= O_APPEND;
- return (att & 0xFFF0) | o_rdwr;
- }
- #endif
-
- static int fscan_q(FILE *, char *);
- int unixlike_stat(char *, struct stat *);
-
-
- /*
- ** move stack,data,bss,heap
- ** |-CCCCC---------------------------------SSSS-DDDD-HHH-|
- ** 0 ^0x400000
- **
- ** to the end of text
- ** |-CCCCC-SSSS-DDDD-HHH-|
- */
-
- void compress_memory(void)
- {
- DWORD movedmem, newhandle, newaddress;
- DWORD r_esp = ESP & ~4095L;
-
- /* check djgpp segment, and stack */
- if (npz->data_start != 0x400000L || r_esp > npz->data_start)
- return;
-
- movedmem = npz->membytes - r_esp; /* memory to move */
- if (r_esp - npz->stack_down < movedmem) /* enough space? */
- return;
-
- cpy32_32(DS, r_esp, DS, npz->stack_down, movedmem);
-
- if (ResizeMem(npz->stack_down + movedmem, npz->memhandle, &newhandle,
- &newaddress)) {
- printf("error:resize memory block\n");
- return;
- }
- if (npz->memaddress != newaddress) {
- npz->memaddress = newaddress;
- SetBaseAddress(npz->code32sel, npz->memaddress);
- SetBaseAddress(npz->data32sel, npz->memaddress);
- SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
- }
- npz->p_flags |= PF_COMPRESS;
- }
-
- void uncompress_memory(void)
- {
- DWORD movedmem, newhandle, newaddress;
- DWORD r_esp = ESP & ~4095L;
-
- /* check djgpp segment, and stack */
- if (npz->data_start != 0x400000L || !(npz->p_flags & PF_COMPRESS))
- return;
-
- if (ResizeMem(npz->membytes, npz->memhandle, &newhandle, &newaddress)) {
- printf("Can't switch to parant process: ENOMEM\n");
- shut_down(1);
- }
- if (npz->memaddress != newaddress) {
- npz->memaddress = newaddress;
- SetBaseAddress(npz->code32sel, npz->memaddress);
- SetBaseAddress(npz->data32sel, npz->memaddress);
- SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
- }
- movedmem = npz->membytes - r_esp; /* memory to move */
- cpy32_32(DS, npz->stack_down, DS, r_esp, movedmem);
- npz->p_flags &= ~PF_COMPRESS;
- }
-
- void def_extention(char *dst, const char *ext)
- {
- int dot, sep;
-
- dot = 0; sep = 1;
- while (*dst != 0)
- switch (*dst++)
- {
- case '.':
- dot = 1;
- sep = 0;
- break;
- case ':':
- case '/':
- case '\\':
- dot = 0;
- sep = 1;
- break;
- default:
- sep = 0;
- break;
- }
- if (!dot && !sep)
- {
- *dst++ = '.';
- strcpy (dst, ext);
- }
- }
-
- char * search_path(char *file, char *path)
- {
- char *list, *end;
- int i;
-
- strcpy(path, file);
- if (access(path, 4) == 0)
- return path;
- list = getenv("PATH");
- if (list != NULL)
- for (;;) {
- while (*list == ' ' || *list == '\t')
- ++list;
- if (*list == 0)
- break;
- end = list;
- while (*end != 0 && *end != ';')
- ++end;
- i = end - list;
- while (i > 0 && (list[i - 1] == ' ' || list[i - 1] == '\t'))
- --i;
- if (i != 0) {
- memcpy(path, list, i);
- if (list[i - 1] != '/' && list[i - 1] != '\\' && list[i - 1] != ':')
- path[i++] = '\\';
- strcpy(path + i, file);
- if (access(path, 4) == 0)
- return path;
- }
- if (*end == 0)
- break;
- list = end + 1;
- }
- path[0] = 0;
- return (char *)0;
- }
-
- struct time32 {
- DWORD secs, usecs;
- };
-
- struct tz32 {
- DWORD offset, dst;
- };
-
- struct stat32 {
- short st_dev, st_ino, st_mode, st_nlink,
- st_uid, st_gid, st_rdev, st_align_for_DWORD;
- long st_size, st_atime, st_mtime, st_ctime, st_blksize;
- };
-
- int i_21_ff(void)
- {
- static int dev_count = 1;
- int r,i;
- DWORD p1 = EBX, p2 = ECX;
-
- switch (AX & 0xff) { /* al=? */
- case 1:
- strcpy32_16(DS, p1, iobuf); /* p1 -> iobuf */
- r = creat(iobuf, S_IREAD | S_IWRITE);
- break;
-
- case 2:
- strcpy32_16(DS, p1, iobuf); /* p1 -> iobuf */
- i = (int) (WORD) p2;
- #ifndef __TURBOC__
- i = convert_open_attrib(i);
- #endif
- r = open(iobuf, i, S_IREAD | S_IWRITE);
- break;
-
- case 3: /* fstat */
- {
- struct stat32 statbuf32;
- struct stat statbuf;
-
- memset(&statbuf, 0, sizeof(statbuf));
- if ((r = fstat((int) p1, &statbuf)) == -1)
- break;
- statbuf32.st_dev = dev_count++;
- statbuf32.st_ino = statbuf.st_ino;
- statbuf32.st_mode = statbuf.st_mode;
- statbuf32.st_nlink = statbuf.st_nlink;
- statbuf32.st_uid = statbuf.st_uid;
- statbuf32.st_gid = statbuf.st_gid;
- statbuf32.st_rdev = statbuf.st_rdev;
- statbuf32.st_size = statbuf.st_size;
- statbuf32.st_atime = statbuf.st_atime;
- statbuf32.st_mtime = statbuf.st_mtime;
- statbuf32.st_ctime = statbuf.st_ctime;
- statbuf32.st_blksize = 512;
- /* stat -> p2 */
- cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
- }
- break;
-
- case 4: /* get time & day */
- {
- struct time32 time32;
- struct tz32 tz32;
-
- if (p2) {
- tz32.offset = timezone;
- tz32.dst = (long) daylight;
- /* tz -> p2 */
- cpy16_32(DS, p2, &tz32, (DWORD) sizeof(tz32));
- }
- if (p1) {
- time32.secs = 0;
- time((time_t *) & (time32.secs));
- time32.usecs = 0;
- /* time -> p1 */
- cpy16_32(DS, p1, &time32, (DWORD) sizeof(time32));
- }
- r = 0;
- }
- break;
-
- case 5: /* set time & day */
- {
- struct time32 time32;
- struct tz32 tz32;
-
- if (p2) {
- /* p2 -> tz */
- cpy32_16(DS, p2, &tz32, (DWORD) sizeof(tz32));
- timezone = tz32.offset;
- daylight = (WORD) tz32.dst;
- }
- if (p1) {
- /* p1 -> time */
- cpy32_16(DS, p1, &time32, (DWORD) sizeof(time32));
- stime((time_t *) & (time32.secs));
- }
- r = 0;
- }
- break;
-
- case 6: /* stat */
- {
- struct stat32 statbuf32;
- struct stat statbuf;
- char fname[128];
-
- memset(&statbuf, 0, sizeof(statbuf));
- strcpy32_16(DS, p1, fname);
-
- r = unixlike_stat(fname, &statbuf);
-
- statbuf32.st_dev = dev_count++;
- statbuf32.st_ino = statbuf.st_ino;
- statbuf32.st_mode = statbuf.st_mode;
- statbuf32.st_nlink = statbuf.st_nlink;
- statbuf32.st_uid = statbuf.st_uid;
- statbuf32.st_gid = statbuf.st_gid;
- statbuf32.st_rdev = statbuf.st_rdev;
- statbuf32.st_size = statbuf.st_size;
- statbuf32.st_atime = statbuf.st_atime;
- statbuf32.st_mtime = statbuf.st_mtime;
- statbuf32.st_ctime = statbuf.st_ctime;
- statbuf32.st_blksize = 512;
- /* stat -> p2 */
- cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
- }
- break;
-
- case 7:
- {
- char *argmem;
- char **argp;
- char exe[260];
- int args;
-
- argmem = (char *) malloc(1000);
- argp = (char **) malloc(100);
- if (argmem == NULL || argp == NULL) {
- if (argmem != NULL)
- free(argmem);
- EAX = EMX_ENOMEM;
- return CARRY_ON;
- }
- strcpy32_16(DS, p1, argmem);
-
- /* make strings from cmdline ; build argv */
- argp[0] = argmem;
- args = 1;
- for (i = 0; *(argmem + i) != 0; i++)
- if (*(argmem + i) == ' ') {
- *(argmem + i) = 0;
- if (*(argmem + i + 1) == ' ')
- continue;
- if (*(argmem + i + 1) == 0)
- break;
- argp[args++] = (argmem + i + 1);
- }
- argp[args] = 0;
-
- /* check last argument, response file? */
- if (argp[args - 1][0] == '@') {
- FILE *f;
- char buf[80];
- char *s = &argmem[i + 2];
-
- args--;
- f = fopen(argp[args] + 1, "rt");
-
- while (fscan_q(f, buf) == 1) {
- if (!strcmp(buf, "\032"))
- continue;
- strcpy(s, buf);
- argp[args++] = s;
- s += strlen(buf) + 1;
- }
- fclose(f);
- argp[args] = 0;
- }
- if (access(argmem, 0))
- if (!search_path(argmem, exe)) {
- EAX = EMX_ENOENT;
- free(argmem);
- free(argp);
- return CARRY_ON;
- }
- else {
- argp[0] = exe;
- }
- /* resize memory to the real used page */
- if (npz->entry == 0x1020L)
- compress_memory();
-
- r = exec32(P_WAIT, argp[0], args, argp, org_envc, org_env);
-
- /* if error, try a real-mode prg */
- if (r == EMX_ENOEXEC) {
- r = realmode_prg(argmem, &(argp[0]), org_env);
- uncompress_memory(); /* we switch back to father process */
- }
- if (r) {
- errno = r;
- r = -1;
- }
- free(argmem);
- free(argp);
- }
- break;
-
- case 8:
- /* ioctl: get mode */
- tr.eax = 0x4400;
- tr.ebx = p1;
- realdos();
- i = (WORD) tr.edx;
- if (p2 & 0x8000) /* O_BINARY */
- i |= 0x20;
- else
- i &= ~0x20;
- /* ioctl: set mode */
- tr.eax = 0x4401;
- tr.ebx = p1;
- tr.edx = (DWORD) i;
- realdos();
- r = setmode((int) p1, (int) p2);
- break;
-
- case 9:
- strcpy32_16(DS, p1, iobuf); /* p1 -> iobuf */
- r = chmod(iobuf, (int) p2);
- break;
-
- default:
- r = -1;
- break;
- } /* switch */
-
- if (r == -1) {
- #ifdef __TURBOC__
- EAX = (DWORD) doserror_to_errno(_doserrno);
- #else
- EAX = errno;
- #endif
- return CARRY_ON;
- } else {
- EAX = (DWORD) r;
- return CARRY_OFF;
- }
- }
-
- static int fscan_q(FILE * f, char *buf)
- {
- char *ibuf = buf;
- int c, quote = -1, gotsome = 0, addquote = 0;
- while ((c = fgetc(f)) != EOF) {
- if (c == '\\') {
- char c2 = (char) fgetc(f);
- if (!strchr("\"'`\\ \t\n\r", c2))
- *buf++ = (char) c;
- *buf++ = c2;
- addquote = 0;
- } else if (c == quote) {
- quote = -1;
- if (c == '\'')
- addquote = 1;
- } else if (isspace(c) && (quote == -1)) {
- if (gotsome) {
- if (addquote)
- *buf++ = '\'';
- *buf = 0;
- return 1;
- }
- addquote = 0;
- } else {
- if ((quote == -1) && ((c == '"') || (c == '\''))) {
- quote = c;
- gotsome = 1;
- if ((c == '\'') && (buf == ibuf))
- *buf++ = (char) c;
- } else {
- *buf++ = (char) c;
- gotsome = 1;
- }
- addquote = 0;
- }
- }
- return 0;
- }
-
- /*
- * An improved version of stat(). This version ensures that "." and ".."
- * appear to exist in all directories, including Novell network drives, and
- * that the root directory also returns the correct result.
- *
- * This function replaces any \'s with /'s in the input string, it should
- * really take a copy of the string first, but this isn't necessary for go32
- * which uses a transfer buffer between the program and the DOS extender
- * anyway.
- *
- * Chris Boucher ccb@southampton.ac.uk
- */
-
-
- /*
- * I found the following function on SIMTEL20, it dates back to 1987 but
- * there's no mention of who the author was. I've modified/fixed it quite
- * a bit. It neatly avoids any problems with "." and ".." on Novell networks.
- */
- static int rootpath(const char *relpath, char *fullpath);
-
-
- int unixlike_stat(char *name, struct stat * buf)
- {
- static char path[2 * MAXPATH];
- char *s = name;
- int len;
-
- /* First off, try the standard stat(), if that works then all is well. */
- if (stat(name, buf) == 0) {
- return 0;
- }
- /* Swap all \'s for /'s. */
- while (*s) {
- if (*s == '\\')
- *s = '/';
- s++;
- }
-
- /* Convert path name into root based cannonical form. */
- if (rootpath(name, path) != 0) {
- return -1;
- }
- /* DOS doesn't stat "/" correctly, so fake it here. */
- if (strcmp(path + 1, ":/") == 0
- || strcmp(path + 1, ":") == 0) {
- buf->st_dev = 0;
- buf->st_ino = 0;
- buf->st_mode = S_IREAD | S_IWRITE | S_IFDIR;
- buf->st_uid = buf->st_gid = 0;
- buf->st_nlink = 1;
- buf->st_rdev = 0;
- buf->st_size = 0;
- buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
- return 0;
- }
- /* Now modify the string so that "dir/" works. */
- len = strlen(path);
- if (path[len - 1] == '/')
- path[len - 1] = '\0';
- return stat(path, buf);
- }
-
-
- /*
- * rootpath -- convert a pathname argument to root based cannonical form.
- *
- * rootpath determines the current directory, appends the path argument (which
- * may affect which disk the current directory is relative to), and qualifies
- * "." and ".." references. The result is a complete, simple, path name with
- * drive specifier.
- *
- * If the relative path the user specifies does not include a drive spec., the
- * default drive will be used as the base. (The default drive will never be
- * changed.)
- *
- * entry: relpath -- pointer to the pathname to be expanded
- * fullpath -- must point to a working buffer, see warning
- * exit: fullpath -- the full path which results
- * return: -1 if an error occurs, 0 otherwise
- *
- * warning: fullpath must point to a working buffer large enough to hold the
- * longest possible relative path argument plus the longest possible
- * current directory path.
- */
- static int rootpath(const char *relpath, char *fullpath)
- {
- register char *lead, *follow, *s;
- char tempchar;
- int drivenum;
-
- /* Extract drive spec. */
- if ((*relpath != '\0') && (relpath[1] == ':')) {
- drivenum = toupper(*relpath) - 'A';
- relpath += 2;
- } else {
- drivenum = _getdrive();
- }
-
- /* Fill in the drive path. */
- strcpy(fullpath, " :/");
- fullpath[0] = (char) (drivenum + 'A');
-
- #ifdef __TURBOC__
- /* Get cwd for drive - also checks that drive exists. */
- if (getcurdir(drivenum + 1, fullpath + 3) == -1) {
- return -1; /* No such drive - give up. */
- }
- #else
- if (!_getdcwd(drivenum +1 , fullpath + 3, _MAX_PATH))
- return -1;
- #endif
-
- /* Swap all \'s for /'s. */
- s = fullpath;
- while (*s) {
- if (*s == '\\')
- *s = '/';
- s++;
- }
-
- /* Append relpath to fullpath/base. */
- if (*relpath == '/') { /* relpath starts at base... */
- strcpy(fullpath + 2, relpath); /* ...so ignore cwd. */
- } else { /* relpath is relative to cwd. */
- if (*relpath != '\0') {
- if (strlen(fullpath) > 3) {
- strcat(fullpath, "/"); /* Add a '/' to end of cwd. */
- }
- strcat(fullpath, relpath); /* Add relpath to end of cwd. */
- }
- }
-
- /* Convert path to cannonical form. */
- lead = fullpath;
- while (*lead != '\0') {
- /* Mark next path segment. */
- follow = lead;
- lead = (char *) strchr(follow + 1, '/');
- if (lead == 0) {
- lead = fullpath + strlen(fullpath);
- }
- tempchar = *lead;
- *lead = '\0';
-
- /* "." segment? */
- if (strcmp(follow + 1, ".") == 0) {
- *lead = tempchar;
- strcpy(follow, lead); /* Remove "." segment. */
- lead = follow;
- }
- /* ".." segment? */
- else if (strcmp(follow + 1, "..") == 0) {
- *lead = tempchar;
- do {
- if (--follow < fullpath) {
- follow = fullpath + 2;
- break;
- }
- } while (*follow != '/');
- strcpy(follow, lead); /* Remove ".." segment. */
- lead = follow;
- }
- /* Normal segment. */
- else {
- *lead = tempchar;
- }
- }
-
- if (strlen(fullpath) == 2) {/* 'D:' or some such. */
- strcat(fullpath, "/");
- }
- /* All done. */
- return 0;
- }
-