From fc3a696ca388856ea4afe1631024c53de72018ce Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Mon, 21 May 2007 03:46:06 +0000 Subject: [PATCH] Add share to the stable kernel too. git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1324 6ac86273-5f31-0410-b378-82cca8765d1b --- share/makefile | 33 +++ share/share.c | 761 ++++++++++++++++++++++++++++++++++++++++++++++++ share/share.hlp | 6 + 3 files changed, 800 insertions(+) create mode 100644 share/makefile create mode 100644 share/share.c create mode 100644 share/share.hlp diff --git a/share/makefile b/share/makefile new file mode 100644 index 0000000..f8dbbde --- /dev/null +++ b/share/makefile @@ -0,0 +1,33 @@ + +# nmake makefile +# share must be linked as COM file +# best is to use TC 2.01 which is freely available + +USETC2=1 +COM=1 + +!if $(USETC2) +TCC=d:\alt\tc201\tcc +TLINK=d:\alt\tc201\tlink +LIBS=d:\alt\tc201 +COPT=-c -mt -1 -Id:\alt\tc201 +LOPT=/m /s /c /t +!else +TCC=d:\alt\tc30\bin\tcc +TLINK=d:\alt\tc30\bin\tlink +LIBS=d:\alt\tc30\lib +!if $(COM) +COPT=-c -mt -1 -Id:\alt\tc30\Include +LOPT=-m -s -c -t +!else +COPT=-c -ms -1 -Id:\alt\tc30\Include +LOPT=-m -s -c +!endif +!endif + +SHARE.COM: SHARE.OBJ + $(TLINK) $(LOPT) $(LIBS)\c0t.obj share.obj,share.com,,$(LIBS)\cs.lib + +SHARE.OBJ: SHARE.C + $(TCC) $(COPT) share.c + diff --git a/share/share.c b/share/share.c new file mode 100644 index 0000000..46777d4 --- /dev/null +++ b/share/share.c @@ -0,0 +1,761 @@ +/* + FreeDOS SHARE + Copyright (c) 2000 Ronald B. Cemer under the GNU GPL + You know the drill. + If not, see www.gnu.org for details. Read it, learn it, BE IT. :-) +*/ + +/* #include */ /* (fprintf removed...) */ +/* #include */ /* Not used, using defines below... */ +#include /* write (what else?) */ +#include /* _psp, NULL, malloc, free, atol, atoi */ +#include /* MK_FP, FP_OFF, FP_SEG, int86, intdosx, */ + /* freemem, keep */ +#include /* strchr, strlen, memset */ + +#ifndef __TURBOC__ +#error "This software must be compiled with TurboC or TurboC++." +#endif + +/* Changed by Eric Auer 5/2004: Squeezing executable size a bit -> */ +/* Replaced fprint(stderr or stdout,...) by write(hand, buf, size) */ +/* Keeps stream stuff and printf stuff outside the file and TSR... */ + + /* ------------- DEFINES ------------- */ +#define MUX_INT_NO 0x2f +#define MULTIPLEX_ID 0x10 + +#define FILE_TABLE_MIN 128 +#define FILE_TABLE_MAX 62000U + +#define LOCK_TABLE_MIN 1 +#define LOCK_TABLE_MAX 3800 + + /* Valid values for openmode: */ +#define OPEN_READ_ONLY 0 +#define OPEN_WRITE_ONLY 1 +#define OPEN_READ_WRITE 2 + + /* Valid values for sharemode: */ +#define SHARE_COMPAT 0 +#define SHARE_DENY_ALL 1 +#define SHARE_DENY_WRITE 2 +#define SHARE_DENY_READ 3 +#define SHARE_DENY_NONE 4 + + /* ------------- TYPEDEFS ------------- */ + /* Register structure for an interrupt function. */ +typedef struct { + unsigned bp; + unsigned di; + unsigned si; + unsigned ds; + unsigned es; + unsigned dx; + unsigned cx; + unsigned bx; + unsigned ax; + unsigned ip; + unsigned cs; + unsigned flags; +} intregs_t; + + /* This table determines the action to take when attempting to open + a file. The first array index is the sharing mode of a previous + open on the same file. The second array index is the sharing mode + of the current open attempt on the same file. Action codes are + defined as follows: + 0 = open may proceed + 1 = open fails with error code 05h + 2 = open fails and an INT 24h is generated + 3 = open proceeds if the file is read-only; otherwise fails + with error code (used only in exception table below) + 4 = open proceeds if the file is read-only; otherwise fails + with INT 24H (used only in exception table below) + Exceptions to the rules are handled in the table + below, so this table only covers the general rules. + */ +static unsigned char open_actions[5][5] = { + { 0, 1, 1, 1, 1 }, + { 2, 1, 1, 1, 1 }, + { 2, 1, 1, 1, 1 }, + { 2, 1, 1, 1, 1 }, + { 2, 1, 1, 1, 0 }, +}; + +typedef struct { + unsigned char first_sharemode; + unsigned char first_openmode; + unsigned char current_sharemode; + unsigned char current_openmode; + unsigned char action; +} open_action_exception_t; + +static open_action_exception_t open_exceptions[] = { + { 0, 0, 2, 0, 3 }, + { 0, 0, 4, 0, 3 }, /* compatibility-read/deny none-read, MED 08/2004 */ + { 2, 0, 0, 0, 4 }, + { 2, 0, 2, 0, 0 }, + { 2, 0, 4, 0, 0 }, + { 3, 0, 2, 1, 0 }, + { 3, 0, 4, 1, 0 }, + { 3, 1, 4, 1, 0 }, + { 3, 2, 4, 1, 0 }, + { 4, 0, 0, 0, 4 }, + { 4, 0, 0, 1, 0 }, /* deny none-read/compatibility-write */ + { 4, 0, 0, 2, 0 }, /* deny none-read/compatibility-read+write */ + { 4, 0, 2, 0, 0 }, + { 4, 0, 2, 1, 0 }, + { 4, 0, 2, 2, 0 }, + { 4, 1, 3, 0, 0 }, + { 4, 1, 3, 1, 0 }, + { 4, 1, 3, 2, 0 }, +}; + + /* One of these exists for each instance of an open file. */ +typedef struct { + char filename[128]; /* fully-qualified filename; "\0" if unused */ + unsigned short psp; /* PSP of process which opened this file */ + unsigned char openmode; /* 0=read-only, 1=write-only, 2=read-write */ + unsigned char sharemode;/* SHARE_COMPAT, etc... */ + unsigned char first_openmode; /* openmode of first open */ + unsigned char first_sharemode; /* sharemode of first open */ +} file_t; + + /* One of these exists for each active lock region. */ +typedef struct { + unsigned char used; /* Non-zero if this entry is used. */ + unsigned long start; /* Beginning offset of locked region */ + unsigned long end; /* Ending offset of locked region */ + unsigned short fileno; /* file_table entry number */ + unsigned short psp; /* PSP of process which owns the lock */ +} lock_t; + + + /* ------------- GLOBALS ------------- */ +static char progname[9]; +static unsigned int file_table_size_bytes = 2048; +static unsigned int file_table_size = 0; /* # of file_t we can have */ +static file_t *file_table = NULL; +static unsigned int lock_table_size = 20; /* # of lock_t we can have */ +static lock_t *lock_table = NULL; + + + /* ------------- PROTOTYPES ------------- */ +/* PRINT added by Eric */ +#define ERR 2 /* handle of stderr */ +#define OUT 1 /* handle of stdout */ +static void PRINT(int handle, char * text); +static void PRINT(int handle, char * text) { + (void)write (handle, text, strlen(text)); + /* return value is -1 error or N bytes_written. Ignored. */ +}; + + + /* DOS calls this to see if it's okay to open the file. + Returns a file_table entry number to use (>= 0) if okay + to open. Otherwise returns < 0 and may generate a critical + error. If < 0 is returned, it is the negated error return + code, so DOS simply negates this value and returns it in + AX. */ +static int open_check + (char far *filename,/* far pointer to fully qualified filename */ + unsigned short psp,/* psp segment address of owner process */ + int openmode, /* 0=read-only, 1=write-only, 2=read-write */ + int sharemode); /* SHARE_COMPAT, etc... */ + + /* DOS calls this to record the fact that it has successfully + closed a file, or the fact that the open for this file failed. */ +static void close_file + (int fileno); /* file_table entry number */ + + /* DOS calls this to determine whether it can access (read or + write) a specific section of a file. We call it internally + from lock_unlock (only when locking) to see if any portion + of the requested region is already locked. If psp is zero, + then it matches any psp in the lock table. Otherwise, only + locks which DO NOT belong to psp will be considered. + Returns zero if okay to access or lock (no portion of the + region is already locked). Otherwise returns non-zero and + generates a critical error (if allowcriter is non-zero). + If non-zero is returned, it is the negated return value for + the DOS call. */ +static int access_check + (unsigned short psp,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to access */ + int allowcriter); /* allow a critical error to be generated */ + + /* DOS calls this to lock or unlock a specific section of a file. + Returns zero if successfully locked or unlocked. Otherwise + returns non-zero. + If the return value is non-zero, it is the negated error + return code for the DOS 0x5c call. */ +static int lock_unlock + (unsigned short psp,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to lock or unlock */ + int unlock); /* non-zero to unlock; zero to lock */ + + /* Multiplex interrupt handler */ + +static void interrupt far (*old_handler2f)() = NULL; + + + /* ------------- HOOK ------------- */ +static void interrupt far handler2f(intregs_t iregs) { + +#define chain_old_handler2f { \ + _BX = iregs.bx; /* Restore BX */ \ + _CX = iregs.ax; /* Save original AX contents into CX */ \ + iregs.ax = FP_SEG((void far *)old_handler2f); /* Set chain segment */ \ + iregs.bx = FP_OFF((void far *)old_handler2f); /* Set chain offset */ \ + _AX = _CX; /* Restore AX */ \ + __emit__(0x5D); /* POP BP */ \ + __emit__(0x5F); /* POP DI */ \ + __emit__(0x5E); /* POP SI */ \ + __emit__(0x1F); /* POP DS */ \ + __emit__(0x07); /* POP ES */ \ + __emit__(0x5A); /* POP DX */ \ + __emit__(0x59); /* POP CX */ \ + __emit__(0xCB); /* RETF */ \ +} /* This evil trick probably only works with Turbo C!?! */ + /* would have been better to link a NASM handler core: */ + /* nasm -fobj -o foo.obj foo.asm ... */ + + if (((iregs.ax >> 8) & 0xff) == MULTIPLEX_ID) { + if ((iregs.ax & 0xff) == 0) { + /* Installation check. Return 0xff in AL. */ + iregs.ax |= 0xff; + return; + } + /* These subfuctions are nonstandard, but are highly + unlikely to be used by another multiplex TSR, since + our multiplex Id (0x10) is basically reserved for + SHARE. So we should be able to get away with using + these for our own purposes. */ + /* open_check */ + if ((iregs.ax & 0xff) == 0xa0) { + iregs.ax = open_check + (MK_FP(iregs.ds, iregs.si), + iregs.bx, + iregs.cx, + iregs.dx); + return; + } + /* close_file */ + if ((iregs.ax & 0xff) == 0xa1) { + close_file(iregs.bx); + return; + } + /* access_check (0xa2) */ + /* access_check with critical error (0xa3) */ + if ((iregs.ax & 0xfe) == 0xa2) { + iregs.ax = access_check + (iregs.bx, + iregs.cx, +#if 0 + ( ((((unsigned long)iregs.si)<<16) & 0xffff0000L) | + (((unsigned long)iregs.di) & 0xffffL) ), + ( ((((unsigned long)iregs.es)<<16) & 0xffff0000L) | + (((unsigned long)iregs.dx) & 0xffffL) ), +#else + ( (((unsigned long)iregs.si)<<16) + iregs.di ), + ( (((unsigned long)iregs.es)<<16) + iregs.dx ), +#endif + (iregs.ax & 0x01)); + return; + } + /* lock_unlock lock (0xa4)*/ + /* lock_unlock unlock (0xa5) */ + if ((iregs.ax & 0xfe) == 0xa4) { + iregs.ax = lock_unlock + (iregs.bx, + iregs.cx, +#if 0 + ( ((((unsigned long)iregs.si)<<16) & 0xffff0000L) | + (((unsigned long)iregs.di) & 0xffffL) ), + ( ((((unsigned long)iregs.es)<<16) & 0xffff0000L) | + (((unsigned long)iregs.dx) & 0xffffL) ), +#else + ( (((unsigned long)iregs.si)<<16) | ((unsigned long)iregs.di) ), + ( (((unsigned long)iregs.es)<<16) | ((unsigned long)iregs.dx) ), +#endif + (iregs.ax & 0x01)); + return; + } + } + /* Chain to the next handler. */ + chain_old_handler2f; +} + +static void remove_all_locks(int fileno) { + int i; + lock_t *lptr; + + for (i = 0; i < lock_table_size; i++) { + lptr = &lock_table[i]; + if (lptr->fileno == fileno) lptr->used = 0; + } +} + +static void free_file_table_entry(int fileno) { + file_table[fileno].filename[0] = '\0'; +} + +/* DOS 7 does not have read-only restrictions, MED 08/2004 */ +/* +static int file_is_read_only(char far *filename) { + union REGS regs; + struct SREGS sregs; + + regs.x.ax = 0x4300; + sregs.ds = FP_SEG(filename); + regs.x.dx = FP_OFF(filename); + intdosx(®s, ®s, &sregs); + if (regs.x.cflag) return 0; + return ((regs.h.cl & 0x19) == 0x01); +} +*/ + +static int fnmatches(char far *fn1, char far *fn2) { + while (*fn1) { + if (*fn1 != *fn2) return 0; + fn1++; + fn2++; + } + return (*fn1 == *fn2); +} + +static int do_open_check + (int fileno) { /* file_table entry number */ + file_t *p, *fptr = &file_table[fileno]; + int i, j, action = 0, foundexc; + unsigned char current_sharemode = fptr->sharemode; + unsigned char current_openmode = fptr->openmode; + open_action_exception_t *excptr; + + fptr->first_sharemode = fptr->sharemode; + fptr->first_openmode = fptr->openmode; + for (i = 0; i < file_table_size; i++) { + if (i == fileno) continue; + p = &file_table[i]; + if (p->filename[0] == '\0') continue; + if (!fnmatches(p->filename, fptr->filename)) continue; + fptr->first_sharemode = p->first_sharemode; + fptr->first_openmode = p->first_openmode; + /* Look for exceptions to the general rules first. */ + foundexc = 0; + for (j = 0; + j < (sizeof(open_exceptions)/sizeof(open_action_exception_t)); + j++) { + excptr = &open_exceptions[j]; + if ( (excptr->first_sharemode == fptr->first_sharemode) + && (excptr->current_sharemode == current_sharemode) + && (excptr->first_openmode == fptr->first_openmode) + && (excptr->current_openmode == current_openmode) ) { + foundexc = 1; + action = excptr->action; + break; + } + } + /* If no exception to rules, use normal rules. */ + if (!foundexc) + action = open_actions[fptr->first_sharemode][current_sharemode]; + /* Fail appropriately based on action. */ + switch (action) { + +/* DOS 7 does not have read-only restrictions, fall through to proceed, MED 08/2004 */ + case 3: + case 4: + + case 0: /* proceed with open */ + break; +/* case 3: */ /* succeed if file read-only, else fail with error 05h */ +/* if (file_is_read_only(fptr->filename)) break; */ + case 1: /* fail with error code 05h */ + free_file_table_entry(fileno); + return -5; +/* case 4: */ /* succeed if file read-only, else fail with int 24h */ +/* if (file_is_read_only(fptr->filename)) break; */ + case 2: /* fail with int 24h */ + { + union REGS regs; + + regs.h.ah = 0x0e; /* disk I/O; fail allowed; data area */ + regs.h.al = 0; + regs.x.di = 0x0d; /* sharing violation */ + if ( (fptr->filename[0]!='\0') && (fptr->filename[1]==':') ) + regs.h.al = fptr->filename[0]-'A'; + free_file_table_entry(fileno); + int86(0x24, ®s, ®s); + } + return -0x20; /* sharing violation */ + } + break; + } + return fileno; +} + + /* DOS calls this to see if it's okay to open the file. + Returns a file_table entry number to use (>= 0) if okay + to open. Otherwise returns < 0 and may generate a critical + error. If < 0 is returned, it is the negated error return + code, so DOS simply negates this value and returns it in + AX. */ +static int open_check + (char far *filename,/* far pointer to fully qualified filename */ + unsigned short psp,/* psp segment address of owner process */ + int openmode, /* 0=read-only, 1=write-only, 2=read-write */ + int sharemode) { /* SHARE_COMPAT, etc... */ + + int i, fileno = -1; + file_t *fptr; + + /* Whack off unused bits in the share mode + in case we were careless elsewhere. */ + sharemode &= 0x07; + + /* Assume compatibility mode if invalid share mode. */ +/* ??? IS THIS CORRECT ??? */ + if ( (sharemode < SHARE_COMPAT) || (sharemode > SHARE_DENY_NONE) ) + sharemode = SHARE_COMPAT; + + /* Whack off unused bits in the open mode + in case we were careless elsewhere. */ + openmode &= 0x03; + + /* Assume read-only mode if invalid open mode. */ +/* ??? IS THIS CORRECT ??? */ + if ( (openmode < OPEN_READ_ONLY) || (openmode > OPEN_READ_WRITE) ) + openmode = OPEN_READ_ONLY; + + for (i = 0; i < file_table_size; i++) { + if (file_table[i].filename[0] == '\0') { + fileno = i; + break; + } + } + if (fileno == -1) return -1; + fptr = &file_table[fileno]; + + /* Copy the filename into ftpr->filename. */ + for (i = 0; i < sizeof(fptr->filename); i++) { + if ((fptr->filename[i] = filename[i]) == '\0') break; + } + fptr->psp = psp; + fptr->openmode = (unsigned char)openmode; + fptr->sharemode = (unsigned char)sharemode; + /* Do the sharing check and return fileno if + okay, or < 0 (and free the entry) if error. */ + return do_open_check(fileno); +} + + /* DOS calls this to record the fact that it has successfully + closed a file, or the fact that the open for this file failed. */ +static void close_file + (int fileno) { /* file_table entry number */ + + remove_all_locks(fileno); + free_file_table_entry(fileno); +} + + /* DOS calls this to determine whether it can access (read or + write) a specific section of a file. We call it internally + from lock_unlock (only when locking) to see if any portion + of the requested region is already locked. If psp is zero, + then it matches any psp in the lock table. Otherwise, only + locks which DO NOT belong to psp will be considered. + Returns zero if okay to access or lock (no portion of the + region is already locked). Otherwise returns non-zero and + generates a critical error (if allowcriter is non-zero). + If non-zero is returned, it is the negated return value for + the DOS call. */ +static int access_check + (unsigned short psp,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to access */ + int allowcriter) { /* allow a critical error to be generated */ + int i; + file_t *fptr = &file_table[fileno]; + char far *filename = fptr->filename; + lock_t *lptr; + unsigned long endofs = ofs + len; + + if (endofs < ofs) { + endofs = 0xffffffffL; + len = endofs-ofs; + } + + if (len < 1L) return 0; + + for (i = 0; i < lock_table_size; i++) { + lptr = &lock_table[i]; + if ( (lptr->used) + && ( (psp == 0) || (lptr->psp != psp) ) + && (fnmatches(filename, file_table[lptr->fileno].filename)) + && ( ( (ofs>=lptr->start) && (ofsend) ) + || ( (endofs>lptr->start) && (endofs<=lptr->end) ) ) ) { + if (allowcriter) { + union REGS regs; + + regs.h.ah = 0x0e; /* disk I/O; fail allowed; data area */ + regs.h.al = 0; + regs.x.di = 0x0e; /* lock violation */ + if ( (fptr->filename[0]!='\0') && (fptr->filename[1]==':') ) + regs.h.al = fptr->filename[0]-'A'; + free_file_table_entry(fileno); + int86(0x24, ®s, ®s); + } + return -0x21; /* lock violation */ + } + } + return 0; +} + + /* DOS calls this to lock or unlock a specific section of a file. + Returns zero if successfully locked or unlocked. Otherwise + returns non-zero. + If the return value is non-zero, it is the negated error + return code for the DOS 0x5c call. */ +static int lock_unlock + (unsigned short psp,/* psp segment address of owner process */ + int fileno, /* file_table entry number */ + unsigned long ofs, /* offset into file */ + unsigned long len, /* length (in bytes) of region to lock or unlock */ + int unlock) { /* non-zero to unlock; zero to lock */ + + int i; + lock_t *lptr; + unsigned long endofs = ofs + len; + + if (endofs < ofs) { + endofs = 0xffffffffL; + len = endofs-ofs; + } + + if (len < 1L) return 0; + + /* there was a error in the code below preventing any other + than the first locked region to be unlocked (japheth, 09/2005) */ + + if (unlock) { + for (i = 0; i < lock_table_size; i++) { + lptr = &lock_table[i]; + if ( (lptr->used) + && (lptr->psp == psp) + && (lptr->fileno == fileno) + && (lptr->start == ofs) + && (lptr->end == endofs) ) { + lptr->used = 0; + return 0; + } + } + /* Not already locked by us; can't unlock. */ + return -(0x21); /* lock violation */ + } else { + if (access_check(0, fileno, ofs, len, 0)) { + /* Already locked; can't lock. */ + return -(0x21); /* lock violation */ + } + for (i = 0; i < lock_table_size; i++) { + lptr = &lock_table[i]; + if (!lptr->used) { + lptr->used = 1; + lptr->start = ofs; + lptr->end = ofs+(unsigned long)len; + lptr->fileno = fileno; + lptr->psp = psp; + return 0; + } + } + return -(0x24); /* sharing buffer overflow */ + } +} + + /* ------------- INIT ------------- */ + /* Allocate tables and install hooks into the kernel. + If we run out of memory, return non-zero. */ +static int init(void) { + /* int i; */ + + file_table_size = file_table_size_bytes/sizeof(file_t); + if ((file_table=malloc(file_table_size_bytes)) == NULL) + return 1; + memset(file_table, 0, file_table_size_bytes); + if ((lock_table=malloc(lock_table_size*sizeof(lock_t))) == NULL) + return 1; + memset(lock_table, 0, lock_table_size*sizeof(lock_t)); + return 0; +} + +static void usage(void) { + PRINT(ERR, + "Installs file-sharing and locking " + "capabilities on your hard disk.\r\n\r\n"); + PRINT(ERR, progname); + PRINT(ERR, " [/F:space] [/L:locks]\r\n\r\n" + " /F:space Allocates file space (in bytes) " + "for file-sharing information.\r\n" + " /L:locks Sets the number of files that can " + "be locked at one time.\r\n"); +} + +static void bad_params(void) { + PRINT(ERR, progname); + PRINT(ERR, ": parameter out of range!\r\n"); +} + +static void out_of_memory(void) { + PRINT(ERR, progname); + PRINT(ERR,": out of memory!\r\n"); +} + + /* ------------- MAIN ------------- */ +int main(int argc, char **argv) { + unsigned short far *usfptr; + unsigned char far *uscptr; + unsigned short top_of_tsr; + int installed = 0; + int i; + + /* Extract program name from argv[0] into progname. */ + if (argv[0] != NULL) { + char *p = argv[0], *p2, c; + int i; + if ( (p[0] != '\0') && (p[1] == ':') ) + p += 2; + while ((p2 = strchr(p, '\\')) != NULL) + p = p2+1; + p2 = progname; + for (i = 0; i < 8; i++) { + c = p[i]; + if ( (c == '.') || (c == '\0') ) + break; + *(p2++) = c; + } + *p2 = '\0'; + } + + /* See if the TSR is already installed. */ + /* disable(); */ /* no multitasking, so don't worry */ + if (getvect(MUX_INT_NO) != NULL) { + union REGS regs; + /* enable(); */ + regs.h.ah = MULTIPLEX_ID; + regs.h.al = 0; + int86(MUX_INT_NO,®s,®s); + installed = ((regs.x.ax & 0xff) == 0xff); + + } /* else { enable(); } */ + + /* Process command line arguments. Bail if errors. */ + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + if (arg == NULL) continue; + if (arg[0] != '/') { + usage(); + return 3; + } + arg++; + switch(*arg) { + case '?': + usage(); + return 3; + case 'f': + case 'F': + arg++; + if (*arg != ':') { + usage(); + return 3; + } + arg++; + { + long temp = atol(arg); + if ( (temp < (long)FILE_TABLE_MIN) + || (temp > (long)FILE_TABLE_MAX) ) { + bad_params(); + return 3; + } + file_table_size_bytes = (unsigned int)temp; + } + break; + case 'l': + case 'L': + arg++; + if (*arg != ':') { + usage(); + return 3; + } + arg++; + lock_table_size = atoi(arg); + if ( (lock_table_size < LOCK_TABLE_MIN) + || (lock_table_size > LOCK_TABLE_MAX) ) { + bad_params(); + return 3; + } + break; + } + } + + /* Now try to install. */ + + if (installed) { + PRINT(ERR, progname); + PRINT(ERR, " is already installed!\r\n"); + return 1; + } + + if (init() != 0) { + out_of_memory(); + return 2; + } + + /* Allocate a single byte. This tells us the size of the TSR. + Free the byte when we know the address. */ + uscptr = (unsigned char far *)malloc(1); + if (uscptr == NULL) { + out_of_memory(); + return 2; + } + top_of_tsr = (FP_SEG(uscptr)+((FP_OFF(uscptr)+15) >> 4)) - _psp; + /* resident paras, counting from PSP:0 */ + free((void *)uscptr); + + + /* Hook the interrupt for the handler routine. */ + /* disable(); */ + old_handler2f = getvect(MUX_INT_NO); + setvect(MUX_INT_NO,handler2f); + /* enable(); */ + + /* Let them know we're installed. */ + PRINT(OUT, progname); + PRINT(OUT, " installed.\r\n"); + + /* Any access to environment variables must */ + /* be done prior to this point. Here we */ + /* free the environment table to prevent */ + /* wasting that memory. In fact, if the */ + /* TSR were removed from memory and we did */ + /* not do this, we would not be able to */ + /* recover this memory. */ + + usfptr = MK_FP(_psp, 0x2c); /* MK_FP is the counterpart */ + /* of FP_OFF and FP_SEG ... */ + freemem(*usfptr); /* deallocate MCB of ENV segment */ + +#if 0 + /* Free the remainder of memory for use by applications. */ + setblock(_psp,top_of_tsr); + /* resize self: already done by keep() */ +#endif + + /* Terminate and stay resident. */ + keep(0,top_of_tsr); /* size is set to top_of_tsr paragraphs */ + return 0; +} + diff --git a/share/share.hlp b/share/share.hlp new file mode 100644 index 0000000..dbb7a1e --- /dev/null +++ b/share/share.hlp @@ -0,0 +1,6 @@ +Installs file-sharing and locking capabilities on your hard disk. + +SHARE [/F:space] [/L:locks] + + /F:space Allocates file space (in bytes) for file-sharing information. + /L:locks Sets the number of files that can be locked at one time.