home *** CD-ROM | disk | FTP | other *** search
- /*
- File : DEMO24.C
- Author : Grant Echols
- Purpose : To demonstrate the possible use of a critical error
- handler to re-establish a connection to a server with
- or without user intervention.
- Return Values : 0 = Aborted operation.
- 1 = Normal Termination.
- 2 = Unable to re-establish connection.
- 3 = NetWare shell was not loaded.
- */
-
- #include <stdio.h>
- #include <dos.h>
- #include <conio.h>
- #include <time.h>
- #include <dir.h>
-
- #define EXIT_NORM 1
- #define EXIT_NO_CONNECT 2
- #define EXIT_NO_SHELL 3
-
- int CheckForNetwork ();
- int EstablishConnection ();
- int FirstNetworkDisk ();
- void DoDirectory (int);
- int MyInt24Handler (int, int, int, int);
-
- int main ()
- {
- /* Install our own critical error handler. */
- harderr (MyInt24Handler);
-
- /* first, check to see if we have a current connection */
- if (!CheckForNetwork ())
- EstablishConnection ();
-
- /* Ok, we have a connection. Now lets get started. */
- /* Here we just do something representing a network task. */
- /* In this case it attempts to do a directory of the first */
- /* network drive, pausing between each directory entry to */
- /* allow time to unplug the cable. */
- DoDirectory (FirstNetworkDisk ());
-
- /* ok, we are exiting with normal exit code */
- /* no need to restore the previous critical error handler, since */
- /* DOS will do it for us when we terminate. */
- exit (EXIT_NORM);
- }
-
- int CheckForNetwork ()
- /* returns 0 if no valid file server name is found.
- else returns 1.
- */
- {
- union REGS regs;
- struct SREGS sregs;
- int count;
- char far *fsNamePtr;
-
- /* first, see if the NetWare shell is loaded */
- regs.h.ah = 0xDC; /* Get Connection Number */
- regs.x.cx = 0; /* the NetWare shell will return non-zero here */
- intdos (®s, ®s);
- if (!regs.x.cx)
- {
- printf ("\nError - NetWare shell not loaded.");
- printf ("\nThis program depends on the NetWare DOS shell");
- printf (" to be loaded first.%c", 7);
- printf ("\nLoad the NetWare shell and then re-run this program.");
- exit (EXIT_NO_SHELL); /* the shell is not loaded */
- /* this program cannot continue */
- }
-
- /* get a pointer to the File Server Name Table */
- regs.x.ax = 0xEF04; /* Get File Server Name table */
- intdosx (®s, ®s, &sregs);
-
- /* point our temporary pointer to the table */
- fsNamePtr = MK_FP (sregs.es, regs.x.si);
- for (count = 0; count < 8; count++)
- {
- if (fsNamePtr[0] != 0)
- return (1); /* found a valid file server */
- fsNamePtr += 48; /* point to the next table entry */
- }
- return (0); /* no valid file server found */
- }
-
- int EstablishConnection ()
- /* returns to caller if able to establish a connection.
- else exits with errorlevel = 2.
- attempts to establish an initial connection to any file server
- using the DOS function parse file name, with an invalid
- drive as the path and file name.
- */
- {
- char string [4];
- struct fcb tFCB;
-
- sprintf (string, "%c:", 'A' + (FirstNetworkDisk () - 1));
- if (!parsfnm (string, &tFCB, 0))
- {
- printf ("\nUnable to re-establish a connection to a server at this time.%c", 7);
- exit (EXIT_NO_CONNECT);
- }
- }
-
- int FirstNetworkDisk ()
- /* returns the number of the first network disk (ie. A = 1, etc.)
- */
- {
- union REGS regs;
-
- regs.h.ah = 0xDB; /* Get Number Of Local Drives */
- intdos (®s, ®s);
- return (regs.h.al + 1);
- }
-
- void DoDirectory (int disk)
- /* returns nothing.
- displays all directory entries on the specified disk.
- */
- {
- struct ffblk fBlock;
- char fname[] = {" :*.*"};
- int ccode,
- attrib = FA_DIREC; /* label, directories and files */
-
- fname [0] = disk + 'A' - 1;
- printf ("\nDirectory of drive %c:", fname[0]);
- printf ("\nName Type");
- ccode = findfirst (fname, &fBlock, attrib);
- while (!ccode)
- {
- printf ("\n%-12s %s", fBlock.ff_name, (fBlock.ff_attrib & FA_DIREC) ?
- "<DIR>" : "<FILE>");
-
- /* slow down a bit so the cable can be pulled */
- delay (100);
-
- /* now find the next directory entry */
- ccode = findnext (&fBlock);
- }
- printf ("\nNo more files\n");
- }
-
- /********************** Critical Error Data and Handler *****************/
-
- char *errStrList[] = { "Write protecte viloation",
- "Unknown unit",
- "Drive not ready",
- "Unknown command",
- "Data error (CRC)",
- "Bad request structure length",
- "Seek error",
- "Unknown media type",
- "Sector not found",
- "Printer out of paper",
- "Write fault",
- "Read fault",
- "General failure"},
- abortMess[] = {"\n\rAbort "},
- retryMess[] = {", Retry "},
- ignoreMess[] = {", Ignore "};
-
- #define ABORT 2
- #define RETRY 1
- #define IGNORE 0
-
- /************************** MyInt24Handler function *********************/
-
- int MyInt24Handler (int errval, int ax, int bp, int si)
- /* returns 0 if ignore, 1 if retry, 2 if abort.
- prompts user for input, if no input, then selects abort.
- */
- {
- char string[80];
- time_t start, now;
- double delay = 30.0;
- int key;
-
- /* first, display that we had a Critical Error */
- sprintf (string, "\n\rCritical error - %s", errStrList[errval]);
- BIOSPrintString (string);
-
- /* now see if this is a Disk error or not */
- if (ax & 0x8000)
- /* Bit 7 was set, so its a non-disk error */
- /* print out the device name that BP:SI is pointing at */
- sprintf (string, "\n\rDevice = %.8Fs", MK_FP (bp, si+10));
- else
- sprintf (string, "\n\rDisk error on drive %c:", 'A' + (ax & 0x00FF));
-
- /* now display whatever error it was */
- BIOSPrintString (string);
-
- /* now display the Abort option which is allways allowed */
- BIOSPrintString (abortMess);
-
- /* print the Retry option if it is allowed */
- if (ax & 0x1000)
- BIOSPrintString (retryMess);
-
- /* print the Ignore option if it is allowed */
- if (ax & 0x2000)
- BIOSPrintString (ignoreMess);
-
- BIOSPrintString (" : ");
- time (&start);
-
- /* start a loop which waits for a specified time for a key */
- WaitForKey:
- key = 0;
- while (!KeyHit(&key) && (difftime (time(&now), start) < delay));
-
- /* either a key was hit or the time elapsed, determine which */
- if (key)
- {
- /* a key was hit so get the key and process it */
- key = toupper (key);
- switch (key)
- {
- case 'A': /* Abort selected */
- BIOSPrintString ("Abort\n\r");
- return (ABORT);
- case 'R': /* Retry selected */
- BIOSPrintString ("Retry\n\r");
- return (RETRY);
- case 'I': /* Ignore selected */
- BIOSPrintString ("Ignore\n\r");
- return (IGNORE);
- default: /* invalid response, ring the bell */
- putch (7);
- goto WaitForKey;
- }
- }
-
- /* the time out occured without a key being hit so return Abort */
- BIOSPrintString ("Automatic Abort\n\r");
- return (ABORT);
- }
-
- BIOSPrintString (char *str)
- /* returns nothing.
- prints out a NULL terminated string in TTY fashion on the current
- video page using the BIOS video interrupt.
- */
- {
- union REGS regs;
- char *strPtr;
-
- /* first, get the current video state, page, etc. */
- regs.h.ah = 0xF; /* Get Current Video State */
- int86 (0x10, ®s, ®s);
- /* now regs.h.bh = active display page */
-
- /* set up the registers that won't be changing */
- regs.h.bl = 0x7; /* Normal, white on black attribute */
- regs.h.ah = 0xE; /* BIOS Video TTY Character Output */
- strPtr = str;
-
- /* now print out the string through BIOS video */
- while (*strPtr)
- {
- regs.h.al = *strPtr++;
- int86 (0x10, ®s, ®s);
- }
- }
-
- KeyHit (int *key)
- /* returns 0 if no key.
- non-zero if a key is pressed, and key is set the the value.
- */
- {
- union REGS regs;
-
- regs.h.ah = 1; /* Read Keyboard Status */
- int86 (0x16, ®s, ®s); /* Keyboard BIOS interrupt */
-
- /* check to see if the zero flag is set */
- if (!(regs.x.flags & (1 << 6)))
- {
- /* it wasn't set so there was a key */
- *key = regs.x.ax;
- return (1);
- }
- else
- {
- *key = 0;
- return (0);
- }
- }