home *** CD-ROM | disk | FTP | other *** search
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/param.h>
- #include <signal.h>
- #include "pmckpt.h"
- #undef main
-
- extern char *getenv();
- extern char *sbrk();
- extern ckpt_main();
- extern long tell();
- extern long lseek();
- extern int brk();
-
- #define NUMFDS NOFILE /* portable */
- #define NUMSIGS 32 /* XXX */
- #define SIGRET void
-
- /* XXX: t for text was an original misnomer. Should have been d for data. */
- /* XXX: Don't need the end of stack pointer. */
- /* XXX: Need BSD timer routines to signal through ckpt_point. */
-
- /* XXX: Must initialize all these variables. We assume that the loader */
- /* puts symbols in order, with initialized data before uninitialized data. */
-
- static int fd = -1; /* must be before sot */
- static long ckpt_diskbase = 1;
- static char *ckpt_stackbase = "";
- static char *ckpt_eotptr = ""; /* end of text pointer */
- static char *ckpt_sosptr = ""; /* start of stack pointer */
- static char *ckpt_eosptr = ""; /* end of stack pointer */
- static char *ckpt_origbrk = "";
- static char *ckpt_newbrk = "";
- char *ckpt_restore = (char *) 0;
- int ckpt_point = -1;
- static char ckpt_sot = 'x'; /* start of text */
- static char *ckpt_fn = "CHECKPOINT"; /* after sot: should be restored */
- static char *ckpt_fntemp = "CHECKPOINT.TEMP";
-
- static struct /* restored automatically with the rest of the data */
- {
- /* We should but don't make a lot of effort to restore uids. */
- /* It just wouldn't be portable between BSD and System V if we did. */
- int uid;
- long fpos[NUMFDS];
- SIGRET (*handler[NUMSIGS])();
- }
- ustate;
-
- static void get_ustate()
- {
- int i;
-
- ustate.uid = getuid();
- for (i = 0;i < NUMFDS;i++)
- ustate.fpos[i] = tell(i);
- for (i = 0;i < NUMSIGS;i++)
- {
- /* We assume that no signal arrives in this period. That's stupid. */
- ustate.handler[i] = signal(i,SIG_IGN);
- (void) signal(i,ustate.handler[i]);
- }
- }
-
- static void set_ustate()
- {
- int i;
-
- (void) setuid(ustate.uid); /*XXX*/
- for (i = 0;i < NUMFDS;i++)
- if (ustate.fpos[i] != -1)
- (void) lseek(i,ustate.fpos[i],L_SET); /* XXX: what if fails? */
- for (i = 0;i < NUMSIGS;i++)
- {
- /* XXX: race, race, glorious race */
- (void) signal(i,ustate.handler[i]);
- }
- }
-
- #define horribly 1
-
- static void die(e)
- int e;
- {
- exit(e); /*XXX*/
- }
-
- main(argc,argv,envp)
- int argc;
- char *argv[];
- char *envp[];
- {
- char ckpt_sos; /* start of stack */
-
- ckpt_point = 0;
- ckpt_origbrk = sbrk(0);
- ckpt_sosptr = &ckpt_sos;
- ckpt_set(&ckpt_eotptr);
- if (!strcmp(argv[0],"CHECKPOINT"))
- {
- if ((fd = open(argv[1],O_RDONLY)) == -1) die(horribly);
- argv += 2;
- if (read(fd,&ckpt_restore,sizeof(ckpt_restore)) == -1) die(horribly);
- if (read(fd,&ckpt_eosptr,sizeof(ckpt_eosptr)) == -1) die(horribly);
- if (read(fd,&ckpt_newbrk,sizeof(ckpt_newbrk)) == -1) die(horribly);
- ckpt_data_restore();
- ckpt_heap_restore();
- ckpt_stackbase = ckpt_sosptr;
- if (ckpt_sosptr - ckpt_eosptr > 0)
- ckpt_diskbase = lseek(fd,0L,L_XTND);
- else
- ckpt_diskbase = tell(fd);
- }
- return ckpt_main(argc,argv,envp);
- }
-
- void ckpt_data_restore()
- {
- /* read in information between &sot and eotptr */
- if (read(fd,&ckpt_sot,ckpt_eotptr - &ckpt_sot) == -1) die(horribly);
- }
-
- void ckpt_heap_restore()
- {
- (void) brk(ckpt_newbrk);
- if (read(fd,ckpt_origbrk,ckpt_newbrk - ckpt_origbrk) == -1) die(horribly);
- }
-
- void ckpt_increment(left,right)
- char *left;
- char *right;
- {
- if (right - left > 0)
- {
- if (lseek(fd,ckpt_diskbase + (left - ckpt_stackbase),L_SET) == -1)
- die(horribly);
- if (read(fd,left,right - left) == -1)
- die(horribly);
- }
- else
- {
- /* character at ckpt_stackbase - x is at ckpt_diskbase + x */
- if (lseek(fd,ckpt_diskbase - (ckpt_stackbase - right),L_SET) == -1)
- die(horribly);
- if (read(fd,right,left - right) == -1)
- die(horribly);
- }
- }
-
- void ckpt_stack_restore()
- {
- /* read in any final information between sosptr and ckpt_eosptr */
- (void) close(fd);
- set_ustate();
- return;
- }
-
- void ckpt_save(restore,eosptr)
- char *restore;
- char *eosptr;
- {
- get_ustate();
- if ((fd = open(ckpt_fntemp,O_RDWR | O_CREAT | O_TRUNC,0600)) == -1) return;
- if (write(fd,&restore,sizeof(restore)) == -1) return;
- if (write(fd,&eosptr,sizeof(eosptr)) == -1) return;
- ckpt_newbrk = sbrk(0);
- if (write(fd,&ckpt_newbrk,sizeof(ckpt_newbrk)) == -1) return;
- if (write(fd,&ckpt_sot,ckpt_eotptr - &ckpt_sot) == -1) return;
- if (write(fd,ckpt_origbrk,ckpt_newbrk - ckpt_origbrk) == -1) return;
- if (eosptr - ckpt_sosptr > 0)
- { if (write(fd,ckpt_sosptr,eosptr - ckpt_sosptr) == -1) return; }
- else
- { if (write(fd,eosptr,ckpt_sosptr - eosptr) == -1) return; }
- (void) close(fd);
- if (rename(ckpt_fntemp,ckpt_fn) == -1) return;
- }
-
- void ckpt_schedule()
- {
- ckpt_point = 1;
- }
-
- void ckpt_init()
- {
- if (getenv("CKPTFNTEMP"))
- ckpt_fntemp = getenv("CKPTFNTEMP");
- if (getenv("CKPTFN"))
- ckpt_fn = getenv("CKPTFN");
- }
-