int setfont_main(int argc UNUSED_PARAM, char **argv) { size_t len; struct psf_header *psfhdr; char *mapfilename; int fd; opt_complementary = "=1"; getopt32(argv, "m:", &mapfilename); argv += optind; // load font len = 32*1024; // can't be larger psfhdr = (struct psf_header *) xmalloc_open_zipped_read_close(*argv, &len); fd = get_console_fd_or_die(); do_load(fd, psfhdr, len); // load the screen map, if any if (option_mask32 & 1) { // -m void *map = xmalloc_open_zipped_read_close(mapfilename, &len); if (len == E_TABSZ || len == 2*E_TABSZ) { xioctl(fd, (len == 2*E_TABSZ) ? PIO_UNISCRNMAP : PIO_SCRNMAP, map); } } return EXIT_SUCCESS; }
static void modinfo(const char *path, const char *version, struct modinfo_env *env) { static const char *const shortcuts[] = { "filename", "description", "author", "license", "vermagic", "parm", }; size_t len; int j, length; char *ptr, *the_module; const char *field = env->field; int tags = env->tags; if (tags & 1) { /* filename */ display(path, shortcuts[0], 1 != tags); } len = MAXINT(ssize_t); the_module = xmalloc_open_zipped_read_close(path, &len); if (!the_module) { if (path[0] == '/') return; /* Newer depmod puts relative paths in modules.dep */ path = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path); the_module = xmalloc_open_zipped_read_close(path, &len); free((char*)path); if (!the_module) return; } if (field) tags |= OPT_F; for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) { const char *pattern = field; if ((1<<j) & OPT_TAGS) pattern = shortcuts[j]; if (!((1<<j) & tags)) continue; length = strlen(pattern); ptr = the_module; while (1) { ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module)); if (ptr == NULL) /* no occurance left, done */ break; if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') { ptr += length + 1; ptr += display(ptr, pattern, (1<<j) != tags); } ++ptr; } } free(the_module); }
int FAST_FUNC bb_init_module(const char *filename, const char *options) { size_t len; char *image; int rc; if (!options) options = ""; #if ENABLE_FEATURE_2_4_MODULES if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) return bb_init_module_24(filename, options); #endif /* Use the 2.6 way */ len = INT_MAX - 4095; rc = ENOENT; image = xmalloc_open_zipped_read_close(filename, &len); if (image) { rc = 0; if (init_module(image, len, options) != 0) rc = errno; free(image); } return rc; }
static void parse_module(module_info *info, const char *pathname) { char *module_image; char *ptr; size_t len; size_t pos; dbg1_error_msg("parse_module('%s')", pathname); /* Read (possibly compressed) module */ len = 64 * 1024 * 1024; /* 64 Mb at most */ module_image = xmalloc_open_zipped_read_close(pathname, &len); /* module_image == NULL is ok here, find_keyword handles it */ //TODO: optimize redundant module body reads /* "alias1 symbol:sym1 alias2 symbol:sym2" */ reset_stringbuf(); pos = 0; while (1) { ptr = find_keyword(module_image + pos, len - pos, "alias="); if (!ptr) { ptr = find_keyword(module_image + pos, len - pos, "__ksymtab_"); if (!ptr) break; /* DOCME: __ksymtab_gpl and __ksymtab_strings occur * in many modules. What do they mean? */ if (strcmp(ptr, "gpl") == 0 || strcmp(ptr, "strings") == 0) goto skip; dbg2_error_msg("alias:'symbol:%s'", ptr); append("symbol:"); } else { dbg2_error_msg("alias:'%s'", ptr); } append(ptr); appendc(' '); skip: pos = (ptr - module_image); } bksp(); /* remove last ' ' */ info->aliases = copy_stringbuf(); replace(info->aliases, '-', '_'); /* "dependency1 depandency2" */ reset_stringbuf(); ptr = find_keyword(module_image, len, "depends="); if (ptr && *ptr) { replace(ptr, ',', ' '); replace(ptr, '-', '_'); dbg2_error_msg("dep:'%s'", ptr); append(ptr); } info->deps = copy_stringbuf(); free(module_image); }
static int load_module(const char *fname, const char *options) { #if 1 int r; size_t len = MAXINT(ssize_t); char *module_image; dbg1_error_msg("load_module('%s','%s')", fname, options); module_image = xmalloc_open_zipped_read_close(fname, &len); r = (!module_image || init_module(module_image, len, options ? options : "") != 0); free(module_image); dbg1_error_msg("load_module:%d", r); return r; /* 0 = success */ #else /* For testing */ dbg1_error_msg("load_module('%s','%s')", fname, options); return 1; #endif }
/* Return: * 0 on success, * -errno on open/read error, * errno on init_module() error */ int FAST_FUNC bb_init_module(const char *filename, const char *options) { size_t image_size; char *image; int rc; bool mmaped; if (!options) options = ""; //TODO: audit bb_init_module_24 to match error code convention #if ENABLE_FEATURE_2_4_MODULES if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) return bb_init_module_24(filename, options); #endif image_size = INT_MAX - 4095; mmaped = 0; image = try_to_mmap_module(filename, &image_size); if (image) { mmaped = 1; } else { errno = ENOMEM; /* may be changed by e.g. open errors below */ image = xmalloc_open_zipped_read_close(filename, &image_size); if (!image) return -errno; } errno = 0; init_module(image, image_size, options); rc = errno; if (mmaped) munmap(image, image_size); else free(image); return rc; }
static void parse_module(module_info *info, const char *pathname) { char *module_image; char *ptr; size_t len; size_t pos; dbg1_error_msg("parse_module('%s')", pathname); /* Read (possibly compressed) module */ len = 64 * 1024 * 1024; /* 64 Mb at most */ module_image = xmalloc_open_zipped_read_close(pathname, &len); /* module_image == NULL is ok here, find_keyword handles it */ //TODO: optimize redundant module body reads /* "alias1 symbol:sym1 alias2 symbol:sym2" */ reset_stringbuf(); pos = 0; while (1) { unsigned start = stringbuf_idx; ptr = find_keyword(module_image + pos, len - pos, "alias="); if (!ptr) { ptr = find_keyword(module_image + pos, len - pos, "__ksymtab_"); if (!ptr) break; /* DOCME: __ksymtab_gpl and __ksymtab_strings occur * in many modules. What do they mean? */ if (strcmp(ptr, "gpl") == 0 || strcmp(ptr, "strings") == 0) goto skip; dbg2_error_msg("alias:'symbol:%s'", ptr); append("symbol:"); } else { dbg2_error_msg("alias:'%s'", ptr); } append(ptr); appendc(' '); /* * Don't add redundant aliases, such as: * libcrc32c.ko symbol:crc32c symbol:crc32c */ if (start) { /* "if we aren't the first alias" */ char *found, *last; stringbuf[stringbuf_idx] = '\0'; last = stringbuf + start; /* * String at last-1 is " symbol:crc32c " * (with both leading and trailing spaces). */ if (strncmp(stringbuf, last, stringbuf_idx - start) == 0) /* First alias matches us */ found = stringbuf; else /* Does any other alias match? */ found = strstr(stringbuf, last-1); if (found < last-1) { /* There is absolutely the same string before us */ dbg2_error_msg("redundant:'%s'", last); stringbuf_idx = start; goto skip; } } skip: pos = (ptr - module_image); } bksp(); /* remove last ' ' */ info->aliases = copy_stringbuf(); replace(info->aliases, '-', '_'); /* "dependency1 depandency2" */ reset_stringbuf(); ptr = find_keyword(module_image, len, "depends="); if (ptr && *ptr) { replace(ptr, ',', ' '); replace(ptr, '-', '_'); dbg2_error_msg("dep:'%s'", ptr); append(ptr); } info->deps = copy_stringbuf(); free(module_image); }
static int run_pipe(const char *pager, char *man_filename, int man, int level) { char *cmd; /* Prevent man page link loops */ if (level > 10) return 0; if (access(man_filename, R_OK) != 0) return 0; if (option_mask32 & OPT_w) { puts(man_filename); return 1; } if (man) { /* man page, not cat page */ /* Is this a link to another manpage? */ /* The link has the following on the first line: */ /* ".so another_man_page" */ struct stat sb; char *line; char *linkname, *p; /* On my system: * man1/genhostid.1.gz: 203 bytes - smallest real manpage * man2/path_resolution.2.gz: 114 bytes - largest link */ xstat(man_filename, &sb); if (sb.st_size > 300) /* err on the safe side */ goto ordinary_manpage; line = xmalloc_open_zipped_read_close(man_filename, NULL); if (!line || strncmp(line, ".so ", 4) != 0) { free(line); goto ordinary_manpage; } /* Example: man2/path_resolution.2.gz contains * ".so man7/path_resolution.7\n<junk>" */ *strchrnul(line, '\n') = '\0'; linkname = skip_whitespace(&line[4]); /* If link has no slashes, we just replace man page name. * If link has slashes (however many), we go back *once*. * ".so zzz/ggg/page.3" does NOT go back two levels. */ p = strrchr(man_filename, '/'); if (!p) goto ordinary_manpage; *p = '\0'; if (strchr(linkname, '/')) { p = strrchr(man_filename, '/'); if (!p) goto ordinary_manpage; *p = '\0'; } /* Links do not have .gz extensions, even if manpage * is compressed */ man_filename = xasprintf("%s/%s", man_filename, linkname); free(line); /* Note: we leak "new" man_filename string as well... */ if (show_manpage(pager, man_filename, man, level + 1)) return 1; /* else: show the link, it's better than nothing */ } ordinary_manpage: close(STDIN_FILENO); open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */ /* "2>&1" is added so that nroff errors are shown in pager too. * Otherwise it may show just empty screen */ cmd = xasprintf( /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */ man ? "gtbl | nroff -Tascii -mandoc 2>&1 | %s" : "%s", pager); system(cmd); free(cmd); return 1; }
int setfont_main(int argc UNUSED_PARAM, char **argv) { size_t len; unsigned opts; int fd; unsigned char *buffer; char *mapfilename; const char *tty_name = CURRENT_TTY; opt_complementary = "=1"; opts = getopt32(argv, "m:C:", &mapfilename, &tty_name); argv += optind; fd = xopen_nonblocking(tty_name); if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not "" if (*argv[0] != '/') { // goto default fonts location. don't die if doesn't exist chdir(CONFIG_DEFAULT_SETFONT_DIR "/consolefonts"); } } // load font len = 32*1024; // can't be larger buffer = xmalloc_open_zipped_read_close(*argv, &len); if (!buffer) bb_simple_perror_msg_and_die(*argv); do_load(fd, buffer, len); // load the screen map, if any if (opts & 1) { // -m unsigned mode = PIO_SCRNMAP; void *map; if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not "" if (mapfilename[0] != '/') { // goto default keymaps location chdir(CONFIG_DEFAULT_SETFONT_DIR "/consoletrans"); } } // fetch keymap map = xmalloc_open_zipped_read_close(mapfilename, &len); if (!map) bb_simple_perror_msg_and_die(mapfilename); // file size is 256 or 512 bytes? -> assume binary map if (len == E_TABSZ || len == 2*E_TABSZ) { if (len == 2*E_TABSZ) mode = PIO_UNISCRNMAP; } #if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP // assume textual Unicode console maps: // 0x00 U+0000 # NULL (NUL) // 0x01 U+0001 # START OF HEADING (SOH) // 0x02 U+0002 # START OF TEXT (STX) // 0x03 U+0003 # END OF TEXT (ETX) else { int i; char *token[2]; parser_t *parser; if (ENABLE_FEATURE_CLEAN_UP) free(map); map = xmalloc(E_TABSZ * sizeof(unsigned short)); #define unicodes ((unsigned short *)map) // fill vanilla map for (i = 0; i < E_TABSZ; i++) unicodes[i] = 0xf000 + i; parser = config_open(mapfilename); while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) { // parse code/value pair int a = ctoi(token[0]); int b = ctoi(token[1]); if (a < 0 || a >= E_TABSZ || b < 0 || b > 65535 ) { bb_error_msg_and_die("map format"); } // patch map unicodes[a] = b; // unicode character is met? if (b > 255) mode = PIO_UNISCRNMAP; } if (ENABLE_FEATURE_CLEAN_UP) config_close(parser); if (mode != PIO_UNISCRNMAP) { #define asciis ((unsigned char *)map) for (i = 0; i < E_TABSZ; i++) asciis[i] = unicodes[i]; #undef asciis } #undef unicodes } #endif // ENABLE_FEATURE_SETFONT_TEXTUAL_MAP // do set screen map xioctl(fd, mode, map); if (ENABLE_FEATURE_CLEAN_UP) free(map); } return EXIT_SUCCESS; }
static void modinfo(const char *path, const char *version, const struct modinfo_env *env) { static const char *const shortcuts[] = { "filename", "license", "author", "description", "version", "alias", "srcversion", "depends", "uts_release", "vermagic", "parm", "firmware", }; size_t len; int j; char *ptr, *fullpath, *the_module; const char *field = env->field; int tags = env->tags; if (tags & 1) { /* filename */ display(path, shortcuts[0], 1 != tags); } len = MAXINT(ssize_t); the_module = xmalloc_open_zipped_read_close(path, &len); if (!the_module) { if (path[0] == '/') return; /* Newer depmod puts relative paths in modules.dep */ fullpath = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path); the_module = xmalloc_open_zipped_read_close(fullpath, &len); #ifdef DONT_USE_UTS_REL_FOLDER if (!the_module) { free((char*)fullpath); fullpath = xasprintf("%s/%s", CONFIG_DEFAULT_MODULES_DIR, path); the_module = xmalloc_open_zipped_read_close(fullpath, &len); } #endif free((char*)fullpath); if (!the_module) { // outputs system error msg bb_perror_msg(""); return; } } if (field) tags |= OPT_F; for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) { const char *pattern; if (!((1<<j) & tags)) continue; pattern = field; if ((1<<j) & OPT_TAGS) pattern = shortcuts[j]; ptr = the_module; while (1) { char *after_pattern; ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module)); if (ptr == NULL) /* no occurance left, done */ break; after_pattern = is_prefixed_with(ptr, pattern); if (after_pattern && *after_pattern == '=') { /* field prefixes are 0x80 or 0x00 */ if ((ptr[-1] & 0x7F) == 0x00) { ptr = after_pattern + 1; display(ptr, pattern, (1<<j) != tags); ptr += strlen(ptr); } } ++ptr; } } free(the_module); }