xref: /original-bsd/games/adventure/save.c (revision 7a4e9f34)
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