int main(int argc, char *argv[]) { void *lowest_segments[2] = { NULL, NULL }; Elf32_Ehdr hdr; Elf32_Phdr *phdr; FILE *fi; maps_range maps[16]; int map_cnt; int i, ret, envc, sfp; long *stack_frame; struct stat st; char buf[64]; long lret; if (argc < 2) { fprintf(stderr, "usage: %s <program> [args]\n", argv[0]); return 1; } g_argv = argv; lret = g_personality(-1); if (g_syscall_error(lret) != -1) { lret |= 0x0240000; // ADDR_COMPAT_LAYOUT | ADDR_NO_RANDOMIZE g_personality(lret); } fi = fopen("/proc/self/maps", "r"); CHECK_NE(fi, NULL, "fopen maps"); for (i = 0; i < ARRAY_SIZE(maps); i++) { ret = fscanf(fi, "%lx-%lx %*s %*s %*s %*s %*s\n", &maps[i].start, &maps[i].end); if (ret <= 0) break; CHECK_EQ(ret, 2, "maps parse error"); } fclose(fi); map_cnt = i; CHECK_NE(map_cnt, 0, "no maps"); CHECK_NE(map_cnt, ARRAY_SIZE(maps), "too many maps"); fi = fopen(argv[1], "rb"); if (fi == NULL) FAIL_PERROR("fopen"); if (fread(&hdr, 1, sizeof(hdr), fi) != sizeof(hdr)) FAIL_PERROR("too small or"); if (memcmp(hdr.e_ident, ELFMAG "\x01\x01", SELFMAG + 2) != 0) { fprintf(stderr, "not 32bit LE ELF?\n"); return 1; } HDR_CHECK_EQ(e_type, ET_EXEC, "not executable"); HDR_CHECK_EQ(e_machine, EM_ARM, "not ARM"); HDR_CHECK_EQ(e_phentsize, sizeof(Elf32_Phdr), "bad PH entry size"); HDR_CHECK_NE(e_phnum, 0, "no PH entries"); phdr = malloc(hdr.e_phnum * hdr.e_phentsize); CHECK_NE(phdr, NULL, "OOM"); if (fread(phdr, hdr.e_phentsize, hdr.e_phnum, fi) != hdr.e_phnum) FAIL_PERROR("too small or"); for (i = 0; i < hdr.e_phnum; i++) { Elf32_Addr end_addr = phdr[i].p_vaddr + phdr[i].p_memsz; Elf32_Addr align; void *ptr, *map_ptr; if (phdr[i].p_type == PT_NOTE) continue; if (phdr[i].p_type != PT_LOAD) { fprintf(stderr, "skipping section %d\n", phdr[i].p_type); continue; } ret = is_range_used(maps, map_cnt, phdr[i].p_vaddr, end_addr); if (ret) { fprintf(stderr, "segment %d (%08x-%08x) hits %08lx-%08lx in maps\n", i, phdr[i].p_vaddr, end_addr, maps[ret - 1].start, maps[ret - 1].end); return 1; } log("load %d %08x-%08x from %08x\n", phdr[i].p_type, phdr[i].p_vaddr, end_addr, phdr[i].p_offset); align = phdr[i].p_vaddr & 0xfff; map_ptr = (void *)(phdr[i].p_vaddr - align); ptr = mmap(map_ptr, phdr[i].p_memsz + align, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (ptr == MAP_FAILED || ptr != map_ptr) FAIL_PERROR("mmap"); if (phdr[i].p_filesz > 0) { if (fseek(fi, phdr[i].p_offset, SEEK_SET) != 0) FAIL_PERROR("fseek"); if (fread((char *)ptr + align, 1, phdr[i].p_filesz, fi) != phdr[i].p_filesz) FAIL_PERROR("too small or"); if (phdr[i].p_flags & PF_X) do_patches((char *)ptr + align, phdr[i].p_filesz); } if (lowest_segments[0] == NULL || map_ptr < lowest_segments[0]) lowest_segments[0] = map_ptr; } // build self bin path snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fileno(fi)); if (lstat(buf, &st) != 0) FAIL_PERROR("lstat bin_path"); bin_path = malloc(st.st_size + 1); CHECK_NE(bin_path, NULL, "bin_path"); ret = readlink(buf, bin_path, st.st_size); if (ret < 0) FAIL_PERROR("readlink"); bin_path[ret] = 0; fclose(fi); emu_init(lowest_segments, 0); // generate stack frame: argc, argv[], NULL, env[], NULL for (envc = 0; environ[envc] != NULL; envc++) ; stack_frame = calloc(argc + envc + 3, sizeof(stack_frame[0])); if (stack_frame == NULL) { fprintf(stderr, "stack_frame OOM\n"); return 1; } // update the environment setenv("_", bin_path, 1); sfp = 0; stack_frame[sfp++] = argc - 1; for (i = 1; i < argc; i++) stack_frame[sfp++] = (long)argv[i]; stack_frame[sfp++] = 0; for (i = 0; i < envc; i++) stack_frame[sfp++] = (long)environ[i]; stack_frame[sfp++] = 0; log("entering %08x, %d stack entries\n", hdr.e_entry, sfp); do_entry(hdr.e_entry, stack_frame, sfp, NULL); fprintf(stderr, "do_entry failed!\n"); return 1; }
int main(int argc, char **argv) { struct conf_entry *p, *q, *x, *y; struct pidinfo *pidlist, *pl; int status, listlen; char **av; parse_args(argc, argv); argc -= optind; argv += optind; if (needroot && getuid() && geteuid()) errx(1, "You must be root."); p = parse_file(&listlen); if (argc > 0) { /* Only rotate specified files. */ x = y = NULL; listlen = 0; for (av = argv; *av; av++) { for (q = p; q; q = q->next) if (strcmp(*av, q->log) == 0) { if (x == NULL) x = y = q; else { y->next = q; y = q; } listlen++; break; } if (q == NULL) warnx("%s: %s not found", conf, *av); } if (x == NULL) errx(1, "%s: no specified log files", conf); y->next = NULL; p = x; } pidlist = (struct pidinfo *)calloc(listlen + 1, sizeof(struct pidinfo)); if (pidlist == NULL) err(1, "calloc"); signal(SIGCHLD, child_killer); /* Step 1, rotate all log files */ for (q = p; q; q = q->next) do_entry(q); /* Step 2, make a list of unique pid files */ for (q = p, pl = pidlist; q; ) { if (q->flags & CE_ROTATED) { struct pidinfo *pltmp; for (pltmp = pidlist; pltmp < pl; pltmp++) { if ((q->pidfile && pltmp->file && strcmp(pltmp->file, q->pidfile) == 0 && pltmp->signal == q->signal) || (q->runcmd && pltmp->file && strcmp(q->runcmd, pltmp->file) == 0)) break; } if (pltmp == pl) { /* unique entry */ if (q->runcmd) { pl->file = q->runcmd; pl->signal = -1; } else { pl->file = q->pidfile; pl->signal = q->signal; } pl++; } } q = q->next; } /* Step 3, send a signal or run a command */ for (pl--; pl >= pidlist; pl--) { if (pl->file != NULL) { if (pl->signal == -1) run_command(pl->file); else send_signal(pl->file, pl->signal); } } if (!noaction) sleep(5); /* Step 4, compress the log.0 file if configured to do so and free */ while (p) { if ((p->flags & CE_COMPACT) && (p->flags & CE_ROTATED) && p->numlogs > 0) compress_log(p); q = p; p = p->next; free(q); } /* Wait for children to finish, then exit */ while (waitpid(-1, &status, 0) != -1) ; exit(0); }
void compile() { char line[1024]; int token_type; USE_ITEM *ptr; int old_use_count; token_type = get_token(); if (token_type != NAMES) err_abort("File does not start with terminal names in column one"); while (token_type != EOF) token_type = do_entry(NULL); DEBUG0(2, "Starting handling of forward USE's\n"); for (part2=0; part2<2; part2++) { old_use_count = -1; DEBUG(2, "\n\nPART %d\n\n", part2); while (use_list.head != NULL && old_use_count != use_count) { old_use_count = use_count; for (ptr = use_list.tail; ptr != NULL; ptr = ptr->bptr) { fseek(stdin, ptr->offset, 0); reset_input(); if ((token_type = get_token()) != NAMES) syserr_abort("Token after a seek not NAMES"); (void) do_entry(ptr); if (complete) dequeue(ptr); } for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { fseek(stdin, ptr->offset, 0); reset_input(); if ((token_type = get_token()) != NAMES) syserr_abort("Token after a seek not NAMES"); (void) do_entry(ptr); if (complete) dequeue(ptr); } DEBUG0(2, "Finished a pass through enqueued forward USE's\n"); } } if (use_list.head != NULL) { fprintf(stderr, "\nError in following up use-links. Either there is\n"); fprintf(stderr, "a loop in the links or they reference non-existant\n"); fprintf(stderr, "terminals. The following is a list of the entries\n"); fprintf(stderr, "involved:\n\n"); for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { fseek(stdin, ptr->offset, 0); fgets(line, 1024, stdin); fprintf(stderr, "%s", line); } exit(1); } }