This is dguxsave.c in view mode; [Download] [Up]
/* (C) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved. */ #include "include.h" struct nsection { unsigned int logical_start; unsigned int logical_length; unsigned int file_start; unsigned int file_length; unsigned int file_reloc; unsigned int file_reloc_length; unsigned int attributes; }; struct prformat { unsigned short magic_number; /* magic */ unsigned short format_rev_number; /* format rev. number */ unsigned short num_non_exec_sect; /* # of non-exec. sects */ unsigned short num_exec_sect; /* # of executable sects */ struct nsection syshead; /* system header */ struct nsection symbolt; /* symbol table */ struct nsection ds; /* */ struct nsection dl; /* */ struct nsection lt; /* */ struct nsection exec[2]; /* two executable sections */ }; struct system_header { unsigned int start_pc; unsigned int stacks; unsigned int unlabeled; unsigned int time_stamp; unsigned int user_rev_number; unsigned short flags; unsigned short ntasks; unsigned short nchannels; }; struct stack_register { unsigned int fp; unsigned int sp; unsigned int sl; unsigned int sb; }; #define NUM_ENVIRON 6 /* saved_init copies arg and environment variables from top of data segment to stack area and shrink the memory. When execed by system, arg and environment variables are as follows; break value --> | | +--------------------+ | environ array ptr |--------+ +--------------------+ | | argument array ptr |----+ | +--------------------+ | | AC2 ----------> | argument count | | | +--------------------+ | | | | | | +============> | environment | | | ! | | | | ! +--------------------+ | | ! | | | | ! +====> | arguments | | | ! ! | | | | ! ! +--------------------+ | | +====== ! ===== | environment array |<-- | --+ ! +--------------------+ | +====== | argument array |<---+ +--------------------+ | | */ void saved_init() { char *break_value; char *new_break_value; char *sbrk(); char *old_start; /* old data area start byte address */ char *new_start; /* new data area start byte address */ int size; /* data size */ int *sp; /* wide stack pointer */ int i; int argc; char **argv; char **envp; break_value = sbrk(0); argc = *((unsigned int *)break_value - 3); /* arg count */ argv = (char **)(*((unsigned int *)break_value - 2)); /* arg array ptr */ envp = (char **)(*((unsigned int *)break_value - 1)); /* env array ptr */ /* old_start will be new break value after initialization. */ new_break_value = old_start = (char *)&argv[0]; /* calc total space required. size is byte size and is multiple of 4 becase both break_value and argv[0] are double word boundary. */ size = break_value - old_start; /* allocate space from stack. */ sp = getsp(); /* current stack pointer */ setsp(sp + size / 4); /* extent stack */ new_start = (char *)(sp + 1); blockmove(new_start, old_start, size); /* set up new argv and new envp */ argv = ((unsigned int)argv - (old_start - new_start) / 2); envp = ((unsigned int)envp - (old_start - new_start) / 2); for (i = 0; i < argc; i++) argv[i] -= (old_start - new_start); for (i = 0; i < NUM_ENVIRON; i++) envp[i] -= (old_start - new_start); new_break_value = (((unsigned int)new_break_value + PAGESIZE -1 ) / PAGESIZE) * PAGESIZE; brk(new_break_value); /* shrink memory */ main(argc, argv, envp); /* call main routine */ exit(0); } filecpy(to, from, n) FILE *to, *from; int n; { char buffer[BUFSIZ]; for (;;) if (n > BUFSIZ) { fread(buffer, BUFSIZ, 1, from); fwrite(buffer, BUFSIZ, 1, to); n -= BUFSIZ; } else if (n > 0) { fread(buffer, n, 1, from); fwrite(buffer, n, 1, to); break; } else break; } memory_save(original_file, save_file) char *original_file, *save_file; { int s, n; char *data_start; int data_size; int orig_e0_start, orig_e0_len, orig_e1_start, orig_e1_len; char *p, *sbrk(); void SVINIT(); /* special initializer */ FILE *in, *out; struct prformat head; struct system_header system; struct stack_register sregs; char buffer0[BUFSIZ], buffer1[BUFSIZ]; char buffer[BUFSIZ]; out = fopen(save_file, "w+"); if (out == NULL) FEerror("Can't open output file.", 0); setbuf(out, buffer0); in = fopen(original_file, "r"); if (in == NULL) FEerror("Can't open original KCl.", 0); setbuf(in, buffer1); /* First, we must build file header. File header is built by modifying the origial program's file header. */ fread((char *)&head, sizeof(struct prformat), 1, in); orig_e0_start = head.exec[0].file_start; orig_e0_len = head.exec[0].file_length; orig_e1_start = head.exec[1].file_start; orig_e1_len = head.exec[1].file_length; data_size = sbrk(0) - (char *)034000000000; head.exec[1].file_start = (orig_e0_start + data_size + 02000) & ~01777; s = head.exec[1].file_start - orig_e1_start; head.symbolt.file_start += s; head.ds.file_start += s; head.dl.file_start += s; head.lt.file_start += s; head.exec[0].logical_length += (s / 2); head.exec[0].file_length = data_size; fwrite((char *)&head, sizeof(struct prformat), 1, out); /* header */ /* Start_pc should be changed to special initializer for a saved program. */ fread((char *)&system, sizeof(system), 1, in); system.start_pc = &SVINIT; system.stacks = *(unsigned int *)016000000024 - *(unsigned int *)016000000026; fwrite((char *)&system, sizeof(system), 1, out); /* gap */ filecpy(out, in, orig_e0_start - sizeof(struct prformat) - sizeof(struct system_header)); /* data segment */ for (p = (char *)034000000000, n = data_size; ;p += BUFSIZ, n -= BUFSIZ) if (n > BUFSIZ) fwrite(p, BUFSIZ, 1, out); else if (n > 0) { fwrite(p, n, 1, out); break; } else break; /* gap */ zero(buffer, BUFSIZ); fwrite(buffer, head.exec[1].file_start - (head.exec[0].file_start + data_size), 1, out); /* text segment */ fseek(in, orig_e1_start, 0); filecpy(out, in, head.exec[1].file_length); /* others */ filecpy(out, in, head.symbolt.file_length); filecpy(out, in, head.ds.file_length); filecpy(out, in, head.dl.file_length); filecpy(out, in, head.lt.file_length); fclose(out); fclose(in); chmod(save_file, 0777); /* change file mode */ } Lsave() { char filename[256]; check_arg(1); check_type_or_pathname_string_symbol_stream(&vs_base[0]); coerce_to_filename(vs_base[0], filename); memory_save(kcl_self, filename); exit(0); } init_dguxsave() { make_function("SAVE", Lsave); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.