setfont: new applet by Vladimir
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 17 Aug 2008 14:12:26 +0000 (14:12 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 17 Aug 2008 14:12:26 +0000 (14:12 -0000)
console-tools/Config.in
console-tools/Kbuild
console-tools/loadfont.c
include/applets.h
include/usage.h

index 4b7f02d2571102f1d14cf254de676db9615518eb..efba9cd0971f7ef5ecadee70261db266f4f697da 100644 (file)
@@ -95,6 +95,12 @@ config FEATURE_SETCONSOLE_LONG_OPTIONS
        help
          Support long options for the setconsole applet.
 
+config SETFONT
+       bool "setfont"
+       default n
+       help
+         Allows to load console screen map. Useful for i18n.
+
 config SETKEYCODES
        bool "setkeycodes"
        default n
index cf3825ec6236fe84ac57a0a6fb7ac2026596cde9..0a182500e44d6c97b46ef3a717b46501efd05de9 100644 (file)
@@ -16,5 +16,6 @@ lib-$(CONFIG_LOADKMAP)                += loadkmap.o
 lib-$(CONFIG_OPENVT)           += openvt.o
 lib-$(CONFIG_RESET)            += reset.o
 lib-$(CONFIG_RESIZE)           += resize.o
+lib-$(CONFIG_SETFONT)          += loadfont.o
 lib-$(CONFIG_SETKEYCODES)      += setkeycodes.o
 lib-$(CONFIG_SETLOGCONS)       += setlogcons.o
index 567aa38aeb94453009d90d4596eae5ee6852f060..78700706f3bca337139307c06e51e49d6eee5a11 100644 (file)
@@ -26,7 +26,7 @@ struct psf_header {
        unsigned char charsize;         /* Character size */
 };
 
-#define PSF_MAGIC_OK(x)        ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2)
+#define PSF_MAGIC_OK(x)        ((x)->magic1 == PSF_MAGIC1 && (x)->magic2 == PSF_MAGIC2)
 
 static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
 {
@@ -37,7 +37,6 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
                bb_error_msg_and_die("bad character size %d", unit);
 
        buf = xzalloc(16 * 1024);
-       /*memset(buf, 0, 16 * 1024);*/
        for (i = 0; i < fontsize; i++)
                memcpy(buf + (32 * i), inbuf + (unit * i), unit);
 
@@ -58,8 +57,7 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
        free(buf);
 }
 
-static void
-do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
+static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
 {
        struct unimapinit advice;
        struct unimapdesc ud;
@@ -68,7 +66,7 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
        int glyph;
        uint16_t unicode;
 
-       maxct = tailsz;                         /* more than enough */
+       maxct = tailsz; /* more than enough */
        up = xmalloc(maxct * sizeof(struct unipair));
 
        for (glyph = 0; glyph < fontsize; glyph++) {
@@ -96,86 +94,104 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
        xioctl(fd, PIO_UNIMAP, &ud);
 }
 
-static void loadnewfont(int fd)
+static void do_load(int fd, struct psf_header *psfhdr, size_t len)
 {
-       enum { INBUF_SIZE = 32*1024 + 1 };
-
        int unit;
-       unsigned inputlth, offset;
-       /* Was on stack, but 32k is a bit too much: */
-       unsigned char *inbuf = xmalloc(INBUF_SIZE);
-
-       /*
-        * We used to look at the length of the input file
-        * with stat(); now that we accept compressed files,
-        * just read the entire file.
-        */
-       inputlth = full_read(STDIN_FILENO, inbuf, INBUF_SIZE);
-       if (inputlth < 0)
-               bb_perror_msg_and_die("error reading input font");
-       if (inputlth >= INBUF_SIZE)
-               bb_error_msg_and_die("font too large");
+       int fontsize;
+       int hastable;
+       unsigned head0, head = head;
 
        /* test for psf first */
-       {
-               struct psf_header psfhdr;
-               int fontsize;
-               int hastable;
-               unsigned head0, head;
-
-               if (inputlth < sizeof(struct psf_header))
-                       goto no_psf;
-
-               psfhdr = *(struct psf_header *) &inbuf[0];
-
-               if (!PSF_MAGIC_OK(psfhdr))
-                       goto no_psf;
-
-               if (psfhdr.mode > PSF_MAXMODE)
+       if (len >= sizeof(struct psf_header) && PSF_MAGIC_OK(psfhdr)) {
+               if (psfhdr->mode > PSF_MAXMODE)
                        bb_error_msg_and_die("unsupported psf file mode");
-               fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
+               fontsize = ((psfhdr->mode & PSF_MODE512) ? 512 : 256);
 #if !defined(PIO_FONTX) || defined(__sparc__)
                if (fontsize != 256)
                        bb_error_msg_and_die("only fontsize 256 supported");
 #endif
-               hastable = (psfhdr.mode & PSF_MODEHASTAB);
-               unit = psfhdr.charsize;
+               hastable = (psfhdr->mode & PSF_MODEHASTAB);
+               unit = psfhdr->charsize;
                head0 = sizeof(struct psf_header);
 
                head = head0 + fontsize * unit;
-               if (head > inputlth || (!hastable && head != inputlth))
+               if (head > len || (!hastable && head != len))
                        bb_error_msg_and_die("input file: bad length");
-               do_loadfont(fd, inbuf + head0, unit, fontsize);
-               if (hastable)
-                       do_loadtable(fd, inbuf + head, inputlth - head, fontsize);
-               return;
-       }
-
- no_psf:
-       /* file with three code pages? */
-       if (inputlth == 9780) {
-               offset = 40;
-               unit = 16;
        } else {
-               /* bare font */
-               if (inputlth & 0377)
-                       bb_error_msg_and_die("bad input file size");
-               offset = 0;
-               unit = inputlth / 256;
+               /* file with three code pages? */
+               if (len == 9780) {
+                       head0 = 40;
+                       unit = 16;
+               } else {
+                       /* bare font */
+                       if (len & 0377)
+                               bb_error_msg_and_die("input file: bad length");
+                       head0 = 0;
+                       unit = len / 256;
+               }
+               fontsize = 256;
+               hastable = 0;
        }
-       do_loadfont(fd, inbuf + offset, unit, 256);
+
+       do_loadfont(fd, (unsigned char *)psfhdr + head0, unit, fontsize);
+       if (hastable)
+               do_loadtable(fd, (unsigned char *)psfhdr + head, len - head, fontsize);
 }
 
+#if ENABLE_LOADFONT
 int loadfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int loadfont_main(int argc, char **argv UNUSED_PARAM)
+int loadfont_main(int argc UNUSED_PARAM, char **argv)
 {
+       size_t len;
+       struct psf_header *psfhdr;
+
+       // no arguments allowed!
+       opt_complementary = "=0";
+       getopt32(argv, "");
+
+       /*
+        * We used to look at the length of the input file
+        * with stat(); now that we accept compressed files,
+        * just read the entire file.
+        */
+       len = 32*1024; // can't be larger
+       psfhdr = (struct psf_header *) xmalloc_read(STDIN_FILENO, &len);
+       // xmalloc_open_zipped_read_close(filename, &len);
+       if (!psfhdr)
+               bb_perror_msg_and_die("error reading input font");
+       do_load(get_console_fd_or_die(), psfhdr, len);
+
+       return EXIT_SUCCESS;
+}
+#endif
+
+#if ENABLE_SETFONT
+int setfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int setfont_main(int argc UNUSED_PARAM, char **argv)
+{
+       size_t len;
+       struct psf_header *psfhdr;
+       char *mapfilename;
        int fd;
 
-       if (argc != 1)
-               bb_show_usage();
+       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();
-       loadnewfont(fd);
+       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;
 }
+#endif
index 5dd485ab4df034b94afc2f3187c1bb5c3883b32e..ee96357192a324dd3569be127aa3a382bc0b5bd4 100644 (file)
@@ -220,7 +220,7 @@ USE_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_NEVER, linux6
 USE_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_NEVER, linuxrc))
 USE_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN, _BB_SUID_NEVER, ln))
 USE_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
-USE_LOADFONT(APPLET(loadfont, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_ALWAYS))
@@ -319,6 +319,7 @@ USE_SETARCH(APPLET(setarch, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_SETCONSOLE(APPLET(setconsole, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_SETENFORCE(APPLET(setenforce, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_SETFILES(APPLET(setfiles, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_SETFONT(APPLET(setfont, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_SETKEYCODES(APPLET(setkeycodes, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_SETLOGCONS(APPLET(setlogcons, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_SETSEBOOL(APPLET(setsebool, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
index e242990887e0ea4a6072ee8f16311c6b4dae639a..feeaadd52a0abc902194ab744aa0a64bb56b0c03 100644 (file)
      "\n       -vv     Show changes in file labels, if type, role, or user are changing" \
      "\n       -W      Display warnings about entries that had no matching files" \
 
+#define setfont_trivial_usage \
+       "[-m mapfile] font"
+#define setfont_full_usage "\n\n" \
+       "Load a console font\n" \
+     "\nOptions:" \
+     "\n       -m mapfile      Load console screen map from mapfile"
+#define setfont_example_usage \
+       "$ setfont -m koi8-r /etc/i18n/fontname\n"
+
 #define setkeycodes_trivial_usage \
        "SCANCODE KEYCODE..."
 #define setkeycodes_full_usage "\n\n" \