|
|
1.1 root 1: /* Attempted unexec for AIX.
2: Copyright (c) 1990 Free Software Foundation, Inc.
3:
4: This file is not used because it occasionally fails to work. This
5: happens because the bss address when Emacs is run is not always the
6: same. If it happens to be different from what it was
7: when Emacs was dumped, the dumped data won't work.
8: No one has been able to prevent the address from varying.
9:
10: This file is part of GNU Emacs.
11:
12: GNU Emacs is free software; you can redistribute it and/or modify
13: it under the terms of the GNU General Public License as published by
14: the Free Software Foundation; either version 1, or (at your option)
15: any later version.
16:
17: GNU Emacs is distributed in the hope that it will be useful,
18: but WITHOUT ANY WARRANTY; without even the implied warranty of
19: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20: GNU General Public License for more details.
21:
22: You should have received a copy of the GNU General Public License
23: along with GNU Emacs; see the file COPYING. If not, write to
24: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25:
26: /* This is based on a public domain program written by IBM. */
27:
28: /*************** SYSTEM DEFINES *********************************/
29:
30: #include "config.h"
31: #include "paths.h"
32: #include <sys/types.h>
33: #include <sys/file.h>
34: #include <fcntl.h>
35: #include <sys/mode.h>
36: #include <sys/ipc.h>
37: #include <sys/shm.h>
38: #include <malloc.h>
39: #include <stdio.h> /* MWW */
40: #include "lisp.h"
41:
42: /*************** LOCAL DEFINES **********************************/
43:
44: struct data_header /* saved data header */
45: {
46: char *start; /* dump _data addr */
47: char *end; /* dump _end addr */
48: char *sbrk1; /* dump original sbrk addr */
49: char *sbrk2; /* dump final sbrk addr */
50: int puresize; /* size of pure data dumped */
51: };
52:
53: #define EMACSSHMKEY "EMACSSHMKEY"
54: #define EMACS_DATA_FILE "EMACS-DATA"
55: #define NEW_SHMGET_FLAGS (IPC_CREAT | S_IWUSR | S_IRUSR \
56: | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH)
57: #define OLD_SHMAT_FLAGS SHM_RDONLY
58: #define OLD_SHMGET_FLAGS (S_IRUSR | S_IRGRP | S_IROTH)
59: #define OLD_OPEN_FLAGS O_RDONLY
60: #define NEW_OPEN_FLAGS (O_RDWR | O_CREAT | O_TRUNC)
61:
62: /*************** EXTERNAL / GLOBAL DATA AREA ********************/
63:
64: extern char _data; /* start of data addr */
65: extern char _end; /* end of all data + 1 addr */
66: static char *original_sbrk; /* sbrk when dump first run */
67:
68: void
69: map_in_data (use_dumped_data)
70: int use_dumped_data;
71: {
72: int bufsize; /* malloc buffer size */
73: struct data_header dh; /* saved data header */
74: int fd; /* saved data file descriptor */
75: char *finaladdr; /* last addr in bucket */
76: char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string */
77: int length; /* dumped data lengths */
78: char *newaddr; /* new malloc buffer addr */
79: int numblks; /* number of remaining mallocs */
80: int shmid; /* shared memory id */
81: key_t shmkey; /* shared memory key */
82: /* Note that using malloc here may not be safe. */
83: char name[sizeof (PATH_EXEC) + sizeof (EMACS_DATA_FILE) + 2];
84:
85: /* Consume remaining malloc space without increasing */
86: /* the end of data space */
87: original_sbrk = sbrk (0);
88: for (bufsize = 16; bufsize < getpagesize (); bufsize *= 2)
89: {
90: while ((newaddr = (char *)malloc (bufsize - 8)) < original_sbrk)
91: ;
92: for (numblks = (getpagesize () / bufsize) - 1; numblks > 0; numblks--)
93: malloc (bufsize - 8);
94: finaladdr = sbrk (0);
95: }
96: original_sbrk = sbrk (0);
97:
98: /* Determine ipc key from environment or default */
99: if (ipckey && *ipckey)
100: shmkey = atoi (ipckey);
101: else
102: shmkey = SHMKEY;
103:
104: /* If we don't want the dumped data, get an unshared segment. */
105: if (!use_dumped_data)
106: {
107: shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
108: if (shmid == -1
109: || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
110: {
111: fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
112: exit (1);
113: }
114: return;
115: }
116:
117: /* Compute the file name with the dumped data. */
118: strcpy (name, PATH_EXEC);
119: strcat (name, "/");
120: strcat (name, EMACS_DATA_FILE);
121:
122: /* Open the file and make sure the addresses have not changed. */
123: fd = open (name, OLD_OPEN_FLAGS, 0);
124: if (fd < 0)
125: {
126: fprintf (stderr, "emacs: failure opening `%s'\n", name);
127: exit (1);
128: }
129: if (read (fd, (char *)&dh, sizeof (dh)) != sizeof (dh)
130: || dh.start != &_data
131: || dh.end != &_end
132: || dh.sbrk1 != original_sbrk
133: || dh.puresize != PURESIZE)
134: {
135: fprintf (stderr, "emacs: header mismatch in `%s'\n", name);
136: exit (1);
137: }
138:
139: /* Load in the unshared contents. */
140: if (!(length = dh.end - dh.start)
141: || read (fd, (char *)&_data, length) != length
142: || !(length = dh.sbrk2 - dh.sbrk1)
143: || brk (dh.sbrk2) == -1
144: || read (fd, dh.sbrk1, length) != length)
145: {
146: fprintf (stderr, "emacs: failure loading unshared data.\n");
147: exit (1);
148: }
149:
150: /* Attach to "pure data" shared memory segment */
151: if ((shmid = shmget (shmkey, 0, 0)) == -1
152: || (newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS)) == -1)
153: {
154: /* We were unable to open an existing segment. Make a new one. */
155: struct shmid_ds buf;
156:
157: /* First get rid of the one we tried to get. */
158: shmdt ((char *)PURE_SEG_BITS);
159: shmctl (shmid, IPC_RMID, 0);
160:
161: /* If we could not write the data file,
162: don't make a shared segment that we could write.
163: Make an unshared segment instead. */
164: if (access (name, W_OK) != 0)
165: {
166: shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
167: if (shmid == -1
168: || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
169: {
170: fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
171: exit (1);
172: }
173:
174: /* Load the proper data into it. */
175: if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
176: {
177: fprintf (stderr, "emacs: failure loading shared memory data.\n");
178: shmdt ((char *)PURE_SEG_BITS);
179: shmctl (shmid, IPC_RMID, 0);
180: exit (1);
181: }
182:
183: close (fd);
184: return;
185: }
186:
187: /* Allocate the new shared segment and arrange to write it. */
188: if ((shmid = shmget (shmkey, PURESIZE, NEW_SHMGET_FLAGS)) == -1
189: || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
190: {
191: fprintf (stderr, "emacs: failure obtaining new shared memory segment.\n");
192: shmdt ((char *)PURE_SEG_BITS);
193: shmctl (shmid, IPC_RMID, 0);
194: exit (1);
195: }
196:
197: /* Load the proper data into it. */
198: if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
199: {
200: fprintf (stderr, "emacs: failure loading shared memory data.\n");
201: shmdt ((char *)PURE_SEG_BITS);
202: shmctl (shmid, IPC_RMID, 0);
203: exit (1);
204: }
205:
206: /* Detach from the segment and bring it back readonly. */
207: shmdt ((char *)PURE_SEG_BITS);
208:
209: shmctl (shmid, IPC_STAT, &buf);
210: buf.shm_perm.mode = OLD_SHMGET_FLAGS;
211: shmctl (shmid, IPC_SET, &buf);
212:
213: newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS);
214: if (newaddr == -1)
215: {
216: fprintf (stderr, "emacs: failure reattaching shared memory segment.\n");
217: shmctl (shmid, IPC_RMID, 0);
218: exit (1);
219: }
220: }
221:
222: close (fd);
223: }
224:
225: /* Dump the appropriate parts of memory into a file named NEW
226: from which the shared segment can be initialized. */
227:
228: void
229: map_out_data (new)
230: char *new;
231: {
232: struct data_header dh; /* saved data header */
233: int fd; /* saved data file descriptor */
234: int length; /* dumped data length; */
235: int shmid;
236: key_t shmkey; /* shared memory key */
237: char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string */
238:
239: /* Determine ipc key from environment or default */
240: if (ipckey && *ipckey)
241: shmkey = atoi (ipckey);
242: else
243: shmkey = SHMKEY;
244:
245: /* Create "saved data" file header */
246: dh.start = &_data;
247: dh.end = &_end;
248: dh.sbrk1 = original_sbrk;
249: dh.sbrk2 = sbrk (0);
250: dh.puresize = PURESIZE;
251:
252: /* Create new "saved data" dump file */
253: unlink (new);
254: fd = open (new, NEW_OPEN_FLAGS, 0666);
255: if (fd < 0)
256: report_file_error ("Opening dump file", Fcons (build_string (new), Qnil));
257:
258: /* Delete obsolete shared segment. */
259: shmid = shmget (shmkey, 0, 0);
260: if (shmid != -1)
261: {
262: if (shmctl (shmid, IPC_RMID, 0) == 0)
263: fprintf (stderr, "Destroying existing shared segment\n");
264: }
265:
266:
267: /* Write saved header and data */
268: length = sizeof (dh);
269: if (write (fd, (char *)&dh, length) != length)
270: report_file_error ("Writing dump file header",
271: Fcons (build_string (new), Qnil));
272: length = dh.end - dh.start;
273: if (write (fd, dh.start, length) != length)
274: report_file_error ("Writing low core in dump file",
275: Fcons (build_string (new), Qnil));
276: length = dh.sbrk2 - dh.sbrk1;
277: if (write (fd, dh.sbrk1, length) != length)
278: report_file_error ("Writing heap in dump file",
279: Fcons (build_string (new), Qnil));
280: length = PURESIZE;
281: if (write (fd, PURE_SEG_BITS, length) != length)
282: report_file_error ("Writing pure data in dump file",
283: Fcons (build_string (new), Qnil));
284: close (fd);
285: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.