Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!sri-unix!ctnews!pyramid!amdahl!ames!ptsfa!hoptoad!pozar From: pozar@hoptoad.uucp (Tim Pozar) Newsgroups: comp.sys.ibm.pc Subject: Finding the address of functions in MSC, and the ^C interupt Message-ID: <2042@hoptoad.uucp> Date: Fri, 24-Apr-87 22:58:10 EDT Article-I.D.: hoptoad.2042 Posted: Fri Apr 24 22:58:10 1987 Date-Received: Sun, 26-Apr-87 20:17:46 EDT Reply-To: pozar@hoptoad.UUCP (Tim Pozar) Organization: Syncstream (San Francisco) Lines: 210 I was wondering how one finds the address of a function and would apply it to setting a vector interupt with it. This is the code that I came up with. It compiles with one error (see below). If anyone has any insite on how this could be better done, I would like to hear it. Tim Pozar --- /* * CTLC.C * * A control-break or ^C handler demo. * * This programme will push the "DOS CONTROL-C Exit Address" vector * and set it to the "bye()" function. bye() should pop the old * address and then executes the users code. The old vector should * be restored if the programme ends through the remaped vector or before * a standard exit(). bye() should also come before the retrival of the * function's address with the way MSC is set up. * * This is a way to make graceful exits from complex programmes that * may have several files open or be communication programmes that need * to handle the comm paths a paticular way to exit properly. (Well, *I* * thought it was an interesting hack in "C" !) * * CTLC will count 20 seconds and exit, or if the user types a ^C or * a CONTROL-BREAK the programme will exit with our routine. If a char * is typed before the ^C is entered, the programme will exit normally * because the keyboard buffer is not polled. To correct this, keep * checking on the kbhit() function supplied with MSC 4.0 and call on * the console input, or keep watching the int 9 (KB_INT) for a keyboard * hit while you're in your routine. * * I would guess you could make this function return back into the * programme by having it call a assembly function that would pop an * appropiate number off the stack and then execute an "iret". (messy) * * BUGS: * Because we don't disable the interupts, if an interupt occurs while * the programme is in the middle of stuffing the new or old address, your * up the creek. * Also do not change the vector to the BIOS ^C vector (1Ah). It seems * that DOS has a go at the keyboard break first and so it exits leaving * the modified vector unrestored. * * This source is complier dependent. It was written for the Microsoft * C Compiler 4.0. And it goes without saying, it is VERY DOS dependent. * * At this point there is a complie waring at "funcp = bye;" in the * main function. But everything works perfectly. Has anyone any ideas * on how to make this compile cleanly? * * Tim Pozar -- 24.April.1987 * pozar@hoptoad.UUCP or Tim Pozar at Fido 125/406 * KLOK-FM * 77 Maiden Lane * San Francisco CA 94108 * (415) 788-2022 * * Copyright 1987 Timothy M. Pozar -- All rights reserved. * */ #include #include #define CNTLBK 0x23 #define SET_VECTOR 0x25 #define GET_TIME 0x2c #define GET_VECTOR 0x35 typedef struct timetype { unsigned hour; unsigned minute; unsigned sec; unsigned hsec; } TIME, *TIME_PTR; unsigned int pvoff; unsigned int pvseg; /* * bye() * * If a keyboard break occurs, this routine is executed. * This routine needs to be stuck into the vector table and taken out * properly when the programme exits. * */ bye() { set_int(CNTLBK,pvseg,pvoff); /* reset old vector */ /* * Put code here. */ printf("Restoreing old keyboard vector and exiting. \n"); exit(0); } main() { char far *funcp; unsigned int off; unsigned int seg; funcp = bye; off = FP_OFF(funcp); seg = FP_SEG(funcp); set_int(CNTLBK,seg,off); printf("bye() is located at %04X:%04X.\n",seg,off); printf("The breakint was located at %04X:%04X.\n",pvseg,pvoff); sleep(20); printf("No keyboard break. Exiting normally.\n"); bye(); } /* * set_int(n,segm,offs) * * Set the interupt speced with the segment and offset passed to it, * and push its old address vector. * */ set_int(n,segm,offs) int n; /* interupt number */ unsigned int segm, offs; /* segment and offset to point to */ { union REGS inregs; union REGS outregs; struct SREGS segregs; inregs.h.ah = GET_VECTOR; /* get orginal vector */ inregs.h.al = n; intdosx(&inregs, &outregs, &segregs); pvoff = outregs.x.bx; /* push it old vector offset */ pvseg = segregs.es; /* and segment */ inregs.h.ah = SET_VECTOR; /* set new vector */ inregs.h.al = n; inregs.x.dx = offs; segregs.ds = segm; intdosx(&inregs, &outregs, &segregs); return(0); } /* * * get_time(n) * TIME_PTR n; * * Fills timetype structure n with current time. This function could * be replace by calles to time() and then gmtime() to get a structor, * but since were fooling with vectors anyway... * */ get_time(n) TIME_PTR n; { union REGS inregs; union REGS outregs; inregs.h.ah = GET_TIME; intdos(&inregs, &outregs); n->hour = outregs.h.ch; n->minute = outregs.h.cl; n->sec = outregs.h.dh; n->hsec = outregs.h.dl; return(0); } sleep(x) int x; { int i; unsigned s; TIME n; /* current time record */ i = 0; get_time(&n); s = n.sec; while (i < x){ printf("secs = %d \r",i); /* for debug only */ while (s == n.sec) /* while Mickey's hand hasn't moved... */ get_time(&n); s = n.sec; /* if Mickey's hand moved... */ ++i; /* increment the counter */ } } -- Tim Pozar UUCP pozar@hoptoad.UUCP Fido 125/406 USNail KLOK-FM 77 Maiden Lane San Francisco CA 94108