Annotation of GNUtools/emacs/src/unexshm.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.