home *** CD-ROM | disk | FTP | other *** search
- /* NOS porting kit for UNIX with LWP
- * 900410
- *
- * Files are: bsdunix.c, asy.h, bsd_io.c, bsd_nit.c, bsd_tun.c, kernel.c,
- * proc.h, global.h, Makefile
- *
- * This runs on a Sun-4, Sun-3, and Sun386i with the LWP library.
- * The NIT and TUN drivers are activated by defining PACKET in config.h but
- * you need to run NOS as root to use them. TUN is the more efficient, so
- * I recommend its usage over NIT.
- *
- * You need release 900312 or later of KA9Q NOS to use these files.
- *
- * You will probably have to increase the definition of MSPTICK in
- * timer.h. Try setting it to 100 (100 milliseconds/tick).
- * Delete any lines that cause troubles in hardware.h.
- * (The definition of "setbit", "clrbit", and "Intstk" are usually
- * the only problems)
- *
- * You need to add the following line to the assignment of Daemons[]
- * in the file config.c:
- * "interval timer", 1024, ctick,
- *
- * There will be other compiler errors too, since NOS was written for
- * Turbo-C. But you are expected to fix those yourself.
- *
- *
- * Written by Anders Klemets, SM0RGV, klemets@sics.se
- * (a few functions at the end were written by Mikel Matthews, N9DVG
- * Jere Sandidge, K4FUM, and some others.)
- * I would appreciate to see any improvements you make.
- *
- */
-
- /*
- * Overhaul by KA9WSB, November, 1991 for later versions of NOS.
- * See the "README" file for more details! KA9WSB
- */
-
- /* KA9WSB
- * Seems that the original stuff used unbuffered output... Seems a
- * shame to make the system hang up waiting to send some characters
- * to a display. By inserting a line like:
- * #define BUFFERED_OUTPUT
- * we will turn on buffered output. The side effect is that
- * we have to call fflush every few clock ticks... You can do
- * #define TICKS_PER_FLUSH 10
- * to call fflush once every 10 ticks (default is once every 5 ticks).
- * Shoot for between a quarter and a half of a second...
- * Note that this makes debugging a bit more difficult, as the progam
- * may crash without printing the final bit of output...
- */
- /* KA9WSB
- * Seems that LWP crashes if you use buffered output... Don't know
- * why, but until we find and fix it, best not use it.
- */
- #undef BUFFERED_OUTPUT
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <lwp/lwp.h>
- #include <lwp/lwperror.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <sys/stat.h>
- #include <sys/param.h>
- #include <dirent.h>
- #include <ctype.h>
-
- /* KA9WSB
- * free handling...
- * This is grungy 'cause free() in most unix machines pukes if handed
- * a null pointer. So we have to check. The "easy" way is to define
- * a variable named "xxfree" which is an indirect pointer to the real
- * system free(). Then, in "global.h", we define free to be a macro:
- * ((char *)p != NULLCHAR ? (*xxfree)(p) : 0)
- * Neat huh??
- * Only one problem -- code like this:
- * free(*argv++);
- * fails! Why? Well, it translates to:
- * ((char *)*argv++ != NULLCHAR ? (*xxfree)(*argv++) : 0)
- * which increments argv twice; the first time by one byte,
- * the second time by whatever argv is declared to be! (this
- * little gem was gleaned from kernel.c; it ended up incrementing
- * argv by 5 bytes instead of 4) To solve this problem, you are
- * offered two choices: search for all every occurence of "free"
- * in all the c sources (grep works nicely), and verify that none
- * will break if expanded into the above macro. Or, add the
- * following flag to the CCFLAGS line in the makefile:
- * -DBULLET_PROOF_FREE
- *
- */
- int free(); /* This must be before we include global.h */
- #ifndef BULLET_PROOF_FREE
- int (*xxfree)() = free; /* if we are not using alloc.c */
- #else
- int xyfree(q) char *q;{if(q)return free(q);else return 0;}
- #endif
-
- #include "global.h"
- #include "config.h"
- #include "iface.h"
- #include "proc.h"
- #include "timer.h"
- #include "session.h"
- #include "asy.h"
- #include "hardware.h"
-
- void inpint(),iostop();
- int32 Clock, StartSec, StartUsec;
- int Tick, console;
- FILE *Rawterm = stdout;
- struct sgttyb mysavetty, savecon;
- int console_saved = 0;
- int Intstk[1024]; /* The signal stack */
- struct proc *ctickp = NULLPROC;
- static struct proc *inpintp = NULLPROC;
- static mon_t mid;
-
- /* Interface list header */
- struct iface *Ifaces;
-
- /* Keyboard input buffer */
- struct fifo Keyboard;
-
- extern struct proc *Display;
-
- int shell=0,intoff=0;
-
- /* KA9WSB
- * define MALLOCDEBUG in the makefile to use the malloc debugging stuff.
- * Note that if you do this, you will have to load /usr/lib/debug/malloc.o
- * before libc in the makefile...
- */
- #ifdef MALLOCDEBUG
- int malloc_debug(); /* in the /usr/lib/debug/malloc.o library */
- int malloc_verify(); /* in the /usr/lib/debug/malloc.o library */
- #endif
-
- /* KA9WSB
- * Debugging trick... #define QUERY_INPUT and NOS will check the NOS_TTY
- * environment variable for the device to use for input... thus making
- * it possible to debug NOS under dbxtool. Fire up another shelltool,
- * use the tty command to find out the tty name (something like
- * /dev/ttyp2), and then type "sleep 30000" to make the shell in that
- * window go away. Now in another shelltool type "setenv NOS_TTY
- * /dev/ttyp2", fire up dbxtool with nos in it, type "ignore IO"
- * (so dbxtool will let nos handle the SIGIO envents, and type "run".
- * NOS will now be happily taking input from the sleeping window.
- */
- #define QUERY_INPUT
-
- /* Called at startup time to set up console I/O, memory heap */
- void
- ioinit()
- {
- struct sgttyb ttybuf;
- struct sigstack ss;
- struct sigvec sv;
- struct timeval tp;
- char *ttydev;
-
- #ifdef MALLOCDEBUG
- #ifndef MALLOCDEBUG_LEVEL
- #define MALLOCDEBUG_LEVEL 1
- #endif
- (void)malloc_debug(MALLOCDEBUG_LEVEL);
- #endif
-
- /* begin by recording the start time as NOW */
- gettimeofday(&tp,NULL);
- StartSec = tp.tv_sec;
- StartUsec = tp.tv_usec;
- Clock = 0;
-
- /* We want unbuffered output */
- if(isatty(1)) {
- #ifndef BUFFERED_OUTPUT
- freopen(ttyname(1),"w",stdout);
- setbuf(stdout,NULLCHAR);
- #endif
-
- #ifdef QUERY_INPUT
- ttydev = getenv("NOS_TTY");
- if(ttydev==NULL) ttydev = "/dev/tty";
- #else
- ttydev = "/dev/tty";
- #endif
- if ((console = open(ttydev,O_RDONLY|O_NDELAY)) < 0) {
- perror(ttydev);
- exit(1);
- }
- ioctl(console,TIOCGETP,&ttybuf);
- savecon = ttybuf;
- ttybuf.sg_flags &= ~ECHO;
- ttybuf.sg_flags |= CBREAK;
- ioctl(console,TIOCSETP,&ttybuf);
- console_saved = 1;
- }
- else console = 0;
-
- (void) signal(SIGHUP, iostop);
- (void) signal(SIGINT, iostop);
- (void) signal(SIGQUIT, iostop);
- (void) signal(SIGTERM, iostop);
-
- /* Initialize keyboard queue */
- Keyboard.bufsize = 256;
- Keyboard.buf = malloc (256);
- Keyboard.rp = Keyboard.wp = Keyboard.buf;
-
- mon_create(&mid);
- }
-
- void
- ctick(p, v1, v2)
- int p;
- void *v1, *v2;
- {
- char i_state;
- struct timeval timout;
- newproc("interrupt handler",1024,inpint,0,NULL,NULL);
-
- /* We will awaken the timer process at every MSPTICK milliseconds.
- You may try to tweak its definition in timer.h */
-
- ctickp = Curproc;
-
- #undef LWP_USE_PRIO /* Doesn't work yet KA9WSB */
- #ifdef LWP_USE_PRIO
- if(lwp_setpri(SELF, MINPRIO+2) < 0){
- lwp_perror("ctick: lwp_setpri");
- abort();
- }
- #endif
-
- while(1) {
- timout.tv_sec = 0;
- timout.tv_usec = MSPTICK * 1000;
- if(lwp_sleep(&timout) < 0){
- lwp_perror("ctick: lwp_sleep");
- abort();
- }
- Curproc = ctickp;
- i_state = dirps();
- ++Tick;
- psignal(&Tick,1);
- restore(i_state);
- }
- }
-
- /* Called just before exiting to restore console state */
- void
- iostop()
- {
- struct iface *ifp, *ifptmp;
- void (**fp)();
-
- for(ifp = Ifaces; ifp != NULLIF; ifp = ifptmp){
- ifptmp = ifp->next;
- if_detach(ifp);
- }
-
- for(fp = Shutdown; *fp != NULLVFP; fp++){
- (**fp)();
- }
-
- if(console_saved)
- ioctl(console,TIOCSETP,&savecon);
-
- pod_exit(0);
- }
-
-
- /* Disable all "interrupts", don't mask any signals however */
- int dirps()
- {
- if (intoff)
- return 0;
- mon_enter(mid);
- intoff = 1;
- return 1;
- }
-
- /* Restore the "interrupts" */
- void restore (mask)
- char mask;
- {
- if (mask) {
- intoff = 0;
- mon_exit(mid);
- }
- }
-
- /* Return the interrupt state */
- int istate()
- {
- return !intoff;
- }
-
- /* Input interrupt handler.
- This function is called whenever there is input from stdin, the
- asynchronus interfaces or the NIT driver. But unfortunately only if their
- respective input queues were empty.
- Speeding up this function would probably enhance the general performance
- of the program.
- */
- void
- inpint(p, v1, v2)
- int p;
- void *v1, *v2;
- {
- int i,ok,r,cnt;
- struct timeval timeout;
- fd_set readfds;
- thread_t agt;
- eventinfo_t argbuf;
- char evbuf[100], *dummy, i_state;
-
- inpintp = Curproc;
-
- #ifdef LWP_USE_PRIO
- if(lwp_setpri(SELF, MINPRIO+1) < 0){
- lwp_perror("inpintp: lwp_setpri");
- abort();
- }
- #endif
-
- /* Create an agent for the SIGIO signal */
- agt_create(&agt, SIGIO, evbuf);
-
- /* This will send a SIGIO signal whenever a key is pressed and
- the stdin queue is empty. It would be better if the signal would
- always be sent, regardless of the status of the queue. */
- if(isatty(console)) {
- fcntl(console,F_SETFL, fcntl(console,F_GETFL,0) | FASYNC);
- fcntl(console,F_SETOWN,getpid());
- }
-
- /* This loop should never exit... it should be running as the
- "interrupt handler"... */
-
- while (1) {
- i = 0;
- r = 0;
- dummy = NULL;
- msg_recv(&agt,(caddr_t)&argbuf,&i,(caddr_t)&dummy,&r,INFINITY);
- Curproc = inpintp;
- FD_ZERO (&readfds);
- for (i=0; i<Nasy; ++i)
- FD_SET(Asy[i].IORser,&readfds);
- #ifdef PACKET
- /* This is only for the NIT and Tun drivers */
- for (i=0; i<Nnit; ++i)
- FD_SET(Nitdrvr[i].IOser,&readfds);
- for (i=0; i<Ntun; ++i)
- FD_SET(Tundrvr[i].IOser,&readfds);
- #endif
- if(isatty(console))
- FD_SET(console,&readfds);
- msg_reply(agt); /* Reply before we read anything */
- timeout.tv_sec = 0;
- timeout.tv_usec = 35;
- ok = select(NOFILE,&readfds,(fd_set *)0,(fd_set *)0,&timeout);
- i_state = dirps();
- cnt = 0;
- if (ok > 0) {
- #ifdef PACKET
- for (i=0; i<Nnit; ++i)
- if (FD_ISSET(Nitdrvr[i].IOser,&readfds))
- psignal(&Nitdrvr[i],1);
- for (i=0; i<Ntun; ++i)
- if (FD_ISSET(Tundrvr[i].IOser,&readfds))
- psignal(&Tundrvr[i],1);
- #endif
- /* Now scan the asynchronus interfaces. Remember, this is
- supposed to be efficient. */
- for (i=0; i<Nasy; ++i)
- if (FD_ISSET(Asy[i].IORser,&readfds)) {
- if (Asy[i].fifo.cnt == Asy[i].fifo.bufsize)
- continue; /* No room */
- /* Try to read as much as we are allowed to */
- r = read(Asy[i].IORser, Asy[i].fifo.wp,
- Asy[i].fifo.rp > Asy[i].fifo.wp ?
- Asy[i].fifo.rp - Asy[i].fifo.wp :
- &Asy[i].fifo.buf[Asy[i].fifo.bufsize] - Asy[i].fifo.wp);
- if (r <= 0)
- continue;
- cnt += r;
- Asy[i].rxchar += r;
- Asy[i].fifo.wp += r;
- Asy[i].fifo.cnt += r;
- if(Asy[i].fifo.wp >= &Asy[i].fifo.buf[Asy[i].fifo.bufsize])
- /* Wrap around */
- Asy[i].fifo.wp = Asy[i].fifo.buf;
- /* Signal "asy_rx" that we have got new data. */
- psignal(&Asy[i].fifo,1);
- }
- }
- /* This function would be a monster if I didn't split it up
- into a special part for keyboard input. */
- if (ok > 0 && FD_ISSET(console,&readfds))
- kbraw();
- /* Now do it all over again since we might have received more input */
- restore(i_state);
- }
- }
-
- /* Read characters from stdin. Called from the generic interrupt handler. */
- int
- kbraw()
- {
- int cnt;
-
- if (shell)
- /* We are executing a shell right now */
- return 0;
-
- if (Keyboard.cnt == Keyboard.bufsize)
- return 0;
- /* Try to read as much as we are allowed to */
- cnt = read(console, Keyboard.wp,
- Keyboard.rp > Keyboard.wp ? Keyboard.rp - Keyboard.wp :
- Keyboard.buf + Keyboard.bufsize - Keyboard.wp);
- if (cnt <= 0)
- return 0;
- Keyboard.cnt += cnt;
- Keyboard.wp += cnt;
- if(Keyboard.wp >= Keyboard.buf + Keyboard.bufsize)
- Keyboard.wp = Keyboard.buf;
- psignal(&Keyboard,1);
- return cnt;
- }
- /* Blocking read from the keyboard */
- int
- kbread()
- {
- int i_state;
- char c;
-
- i_state = dirps();
- while(Keyboard.cnt == 0)
- pwait (&Keyboard);
- c = *Keyboard.rp++;
- if(Keyboard.rp == &Keyboard.buf[Keyboard.bufsize])
- Keyboard.rp = Keyboard.buf;
- Keyboard.cnt--;
- restore(i_state);
-
- if (c == 0x7f) /* DEL key */
- c = '\b';
- if (c == '\n') /* Emulate MS/DOS. SysV would reset the ICRNL flag */
- c = '\r';
- return c;
- }
- void
- systick()
- {
- }
-
- void
- sysreset()
- {
- }
-
- /* This function is only needed if you DO use alloc.c */
- unsigned long coreleft()
- {
- struct rlimit rlp;
- extern end;
- getrlimit(RLIMIT_CORE,&rlp);
- return ((unsigned long) (rlp.rlim_cur - end));
- }
- /* Sleep gracefully until the next interrupt. */
- void
- giveup()
- {
- restore(1); /* Interrupts must be enabled */
- sigpause(0);
- dirps();
- }
- /* To be removed if alloc.c is to be used */
- memstat()
- {
- return 0;
- }
-
- /* Note: make sure that there is no previous definition of tolower() */
- char tolower (c)
- char c;
- {
- return ((c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c);
- }
-
- FILE *
- tmpfile()
- {
- FILE *tmp;
- char *mktemp();
- char *ptr = "SMTPXXXXXX";
- char *name;
- name = mktemp(ptr);
- if ( ( tmp = fopen(name, "w+") ) == NULL)
- {
- tprintf("tmpfile: counld not create temp file.\n");
- return(NULL);
- }
- (void) unlink(name);
- return ( tmp );
- }
-
- /* wildcard filename lookup */
- filedir(name, times, ret_str)
- char *name;
- int times;
- char *ret_str;
- {
- static char dname[128], fname[128];
- static DIR *dirp = NULL;
- struct dirent *dp;
- struct stat sbuf;
- char *cp, temp[128];
-
- /*
- * Make sure that the NULL is there in case we don't find anything
- */
- ret_str[0] = '\0';
-
- if (times == 0) {
- /* default a null name to *.* */
- if (name == NULL || *name == '\0')
- name = "*.*";
- /* split path into directory and filename */
- if ((cp = strrchr(name, '/')) == NULL) {
- strcpy(dname, ".");
- strcpy(fname, name);
- } else {
- strcpy(dname, name);
- dname[cp - name] = '\0';
- strcpy(fname, cp + 1);
- /* root directory */
- if (dname[0] == '\0')
- strcpy(dname, "/");
- /* trailing '/' */
- if (fname[0] == '\0')
- strcpy(fname, "*.*");
- }
- /* close directory left over from another call */
- if (dirp != NULL)
- closedir(dirp);
- /* open directory */
- if ((dirp = opendir(dname)) == NULL) {
- tprintf("Could not open DIR (%s)\n", dname);
- return;
- }
- } else {
- /* for people who don't check return values */
- if (dirp == NULL)
- return;
- }
-
- /* scan directory */
- while ((dp = readdir(dirp)) != NULL) {
- /* test for name match */
- /* if (wildmat(dp->d_name, fname)) {*/
- if (!strcmp(dp->d_name, fname) || (fname[0] == '*' &&
- !strcmp(&dp->d_name[strlen(dp->d_name) - strlen(fname)+1],
- &fname[1]))) { /* ...when we do not use wildmat */
- /* test for regular file */
- sprintf(temp, "%s/%s", dname, dp->d_name);
- if (stat(temp, &sbuf) < 0)
- continue;
- if ((sbuf.st_mode & S_IFREG) == 0)
- continue;
- strcpy(ret_str, dp->d_name);
- break;
- }
- }
-
- /* close directory if we hit the end */
- if (dp == NULL) {
- closedir(dirp);
- dirp = NULL;
- }
- }
- doshell(argc, argv)
- char **argv;
- {
- register int pid, pid1, i;
- void (*savi)();
- int rc;
- char str[256], *cp;
- struct sgttyb ttybuf;
- extern struct sgttyb savecon;
- shell = 1;
-
- ioctl(console, TIOCGETP, &ttybuf);
- ioctl(console, TIOCSETP, &savecon);
-
- str[0] = '\0';
- for (i = 1; i < argc; i++) {
- strcat(str, argv[i]);
- strcat(str, " ");
- }
- if ((cp = getenv("SHELL")) == NULLCHAR)
- cp = "/bin/sh";
- if ((pid = fork()) == 0) {
- seteuid(getuid()); /* Restore original user ID */
- if (argc > 1)
- (void)execl(cp, cp, "-c", str, 0);
- else
- (void)execl(cp, cp, (char *)0,(char *)0,0);
- tprintf("Can't execl() (%d)\n", errno);
- exit(1);
- } else if (pid == -1) {
- tprintf("Can't fork() (%d)\n", errno);
- rc = -1;
- } else {
- savi = signal(SIGINT, SIG_IGN);
- while ((pid1 = wait(&rc)) != pid && pid1 != -1)
- ;
- signal(SIGINT, savi);
- }
- ioctl(console, TIOCSETP, &ttybuf);
- shell = 0;
- return (rc);
- }
-
- dodir(argc, argv)
- char **argv;
- {
- register int i;
- char str[256];
-
- strcpy(str, "ls -lL ");
- for (i = 1; i < argc; i++) {
- strcat(str, argv[i]);
- strcat(str, " ");
- }
-
- return system(str);
- }
-
- /* Terminal printf that counts newlines. At end of the page,
- * prints "--More--" and waits for a keystroke before continuing.
- */
- void
- display(i,v1,v2)
- int i;
- void *v1;
- void *v2;
- {
- int c;
- struct session *sp;
-
- /* This is very tricky code. Because the value of "Current" can
- * change any time we do a pwait, we have to be careful to detect
- * any change and go back and start again.
- */
- for(;;){
- sp = Current;
-
- if(sp->morewait){
- pwait(&sp->row);
- if(sp != Current || sp->row <= 0){
- /* Current changed value, or the user
- * hasn't really hit a key
- */
- continue;
- }
- /* Erase the prompt */
- printf("\r \r");
- }
- sp->morewait = 0;
- if((c = recvchar(sp->output)) == -1){
- /* the alert() in swapscreen will cause this to
- * return -1 when current changes
- */
- pwait(NULL); /* Prevent a nasty loop */
- continue;
- }
- putchar(c);
- if(sp->record != NULLFILE)
- fputc(c,sp->record);
- if(sp->flowmode && c == '\n' && --sp->row <= 0){
- printf("--More--");
- sp->morewait = 1;
- }
- }
- }
- void swapscreen(old, new)
- struct session *old;
- struct session *new;
- {
- if(old == new)
- return; /* Nothing to do */
-
- fflush(stdout);
- if(old != NULLSESSION){
- /* Save old screen */
- }
- if(new != NULLSESSION){
- /* Load new screen */
- }
- alert(Display,1); /* Wake him up */
- }
- void
- newscreen(sp)
- struct session *sp;
- {
- if(sp != NULLSESSION)
- sp->screen = (struct screen *)callocw(1,sizeof(struct screen));
- }
- void
- freescreen(sp)
- struct session *sp;
- {
- if(sp == NULLSESSION || sp->screen == NULLSCREEN)
- return;
- if(sp->screen->save != NULLCHAR)
- free(sp->screen->save);
- free((char *)sp->screen);
- }
-
- /* Case-insensitive string comparison (Needed on some machines) */
- int
- stricmp(a,b)
- register char *a,*b;
- {
- char a1,b1;
-
- while((a1 = *a++) != '\0' && (b1 = *b++) != '\0'){
- if(a1 == b1)
- continue; /* No need to convert */
- if(isupper(a1))
- a1 = tolower(a1);
- if(isupper(b1))
- b1 = tolower(b1);
- if(a1 == b1)
- continue; /* NOW they match! */
- if(a1 > b1)
- return 1;
- if(a1 < b1)
- return -1;
- }
- return 0;
- }
-
- /* Create directory */
- int
- domkd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(mkdir(argv[1]) == -1)
- tprintf("Can't make %s: %s\n",argv[1],sys_errlist[errno]);
- return 0;
- }
- /* Remove directory */
- int
- dormd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(rmdir(argv[1]) == -1)
- tprintf("Can't remove %s: %s\n",argv[1],sys_errlist[errno]);
- return 0;
- }
-
- /* Routines we don't do... but don't want to constantly hack config.c */
- int
- dofkey(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- tprintf("This command is not supported under UNIX yet...\n");
- return 0;
- }
-
- int
- dobmail(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- tprintf("This command is not supported under UNIX yet...\n");
- return 0;
- }
-
- void rflush()
- {
- fflush(Rawterm);
- }
-
- char Hashtab[256];
-
- int16
- hash_ip(ipaddr)
- int32 ipaddr;
- {
- return 0; /* A nicer technique later on :-) KA9WSB */
- }
-
- void
- kbint()
- {
- }
-
- void
- uchtimer()
- {
- }
-
- int32
- secclock()
- {
- struct timeval tp;
- int32 t, u;
-
- gettimeofday(&tp,NULL);
- t = tp.tv_sec - StartSec;
- u = tp.tv_usec - StartUsec;
- if(u>499999)t++;
- return t;
- }
-
- int32
- msclock()
- {
- struct timeval tp;
- int32 t, u;
-
-
- gettimeofday(&tp,NULL);
- t = tp.tv_sec - StartSec;
- u = tp.tv_usec - StartUsec;
- return ((t * 1000) + (u / 1000));
- }
-
- #ifdef BUFFERED_OUTPUT
- int FlushTock = 0;
- #ifndef TICKS_PER_FLUSH
- #define TICKS_PER_FLUSH 5
- #endif
- #endif
-
- #ifdef MALLOCDEBUG
- int MallocTock = 0;
- #endif
-
- void
- pctick()
- {
- Clock++;
-
- #ifdef BUFFERED_OUTPUT
- FlushTock++;
- if(FlushTock>=TICKS_PER_FLUSH){
- fflush(stdout);
- FlushTock = 0;
- }
- #endif
-
- #ifdef MALLOCDEBUG
- MallocTock++;
- if(MallocTock>=10){
- if( malloc_verify() == 0 )
- printf("Warning: malloc_verify: Corrupted heap!\n");
- MallocTock = 0;
- }
- #endif
- }
-