|
|
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.