1 /* save (III) J. Gillogly 2 * save user core image for restarting 3 * usage: save(<command file (argv[0] from main)>,<output file>) 4 * bugs 5 * - impure code (i.e. changes in instructions) is not handled 6 * (but people that do that get what they deserve) 7 */ 8 9 static char sccsid[] = " save.c 4.1 82/05/11 "; 10 11 #include <a.out.h> 12 int filesize; /* accessible to caller */ 13 14 char *sbrk(); 15 16 save(cmdfile,outfile) /* save core image */ 17 char *cmdfile,*outfile; 18 { register char *c; 19 register int i,fd; 20 int fdaout; 21 struct exec header; 22 int counter; 23 char buff[512],pwbuf[120]; 24 fdaout=getcmd(cmdfile); /* open command wherever it is */ 25 if (fdaout<0) return(-1); /* can do nothing without text */ 26 if ((fd=open(outfile,0))>0) /* this restriction is so that */ 27 { printf("Can't use an existing file\n"); /* we don't try */ 28 close(fd); /* to write over the commnd file*/ 29 return(-1); 30 } 31 if ((fd=creat(outfile,0755))== -1) 32 { printf("Cannot create %s\n",outfile); 33 return(-1); 34 } 35 /* can get the text segment from the command that we were 36 * called with, and change all data from uninitialized to 37 * initialized. It will start at the top again, so the user 38 * is responsible for checking whether it was restarted 39 * could ignore sbrks and breaks for the first pass 40 */ 41 read(fdaout,&header,sizeof header);/* get the header */ 42 header.a_bss = 0; /* no data uninitialized */ 43 header.a_syms = 0; /* throw away symbol table */ 44 switch (header.a_magic) /* find data segment */ 45 { case 0407: /* non sharable code */ 46 c = (char *) header.a_text;/* data starts right after text */ 47 header.a_data=sbrk(0)-c; /* current size (incl allocs) */ 48 break; 49 case 0410: /* sharable code */ 50 c = (char *) 51 #ifdef pdp11 52 (header.a_text /* starts after text */ 53 & 0160000) /* on an 8K boundary */ 54 + 020000; /* i.e. the next one up */ 55 #endif 56 #ifdef vax 57 (header.a_text /* starts after text */ 58 & 037777776000) /* on an 1K boundary */ 59 + 02000; /* i.e. the next one up */ 60 #endif 61 #ifdef z8000 62 (header.a_text /* starts after text */ 63 & 0174000) /* on an 2K boundary */ 64 + 004000; /* i.e. the next one up */ 65 #endif 66 header.a_data=sbrk(0)-c; /* current size (incl allocs) */ 67 break; 68 case 0411: /* sharable with split i/d */ 69 c = 0; /* can't reach text */ 70 header.a_data=(int)sbrk(0);/* current size (incl allocs) */ 71 break; 72 case 0413: 73 c = (char *) header.a_text;/* starts after text */ 74 lseek(fdaout, 1024L, 0); /* skip unused part of 1st block*/ 75 } 76 if (header.a_data<0) /* data area very big */ 77 return(-1); /* fail for now */ 78 79 filesize=sizeof header+header.a_text+header.a_data; 80 write(fd,&header,sizeof header); /* make the new header */ 81 if (header.a_magic==0413) 82 lseek(fd, 1024L, 0); /* Start on 1K boundary */ 83 counter=header.a_text; /* size of text */ 84 while (counter>512) /* copy 512-byte blocks */ 85 { read(fdaout,buff,512); /* as long as possible */ 86 write(fd,buff,512); 87 counter -= 512; 88 } 89 read(fdaout,buff,counter); /* then pick up the rest */ 90 write(fd,buff,counter); 91 write(fd,c,header.a_data); /* write all data in 1 glob */ 92 close(fd); 93 } 94 95 #define NULL 0 96 97 char *execat(), *getenv(); 98 99 getcmd(command) /* get command name (wherever it is) like shell */ 100 char *command; 101 { 102 char *pathstr; 103 register char *cp; 104 char fname[128]; 105 int fd; 106 107 if ((pathstr = getenv("PATH")) == NULL) 108 pathstr = ":/bin:/usr/bin"; 109 cp = index(command, '/')? "": pathstr; 110 111 do { 112 cp = execat(cp, command, fname); 113 if ((fd=open(fname,0))>0) 114 return(fd); 115 } while (cp); 116 117 printf("Couldn't open %s\n",command); 118 return(-1); 119 } 120 121 static char * 122 execat(s1, s2, si) 123 register char *s1, *s2; 124 char *si; 125 { 126 register char *s; 127 128 s = si; 129 while (*s1 && *s1 != ':' && *s1 != '-') 130 *s++ = *s1++; 131 if (si != s) 132 *s++ = '/'; 133 while (*s2) 134 *s++ = *s2++; 135 *s = '\0'; 136 return(*s1? ++s1: 0); 137 } 138