busybox/applets/applet_tables.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Applet table generator.
   4 * Runs on host and produces include/applet_tables.h
   5 *
   6 * Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
   7 *
   8 * Licensed under GPLv2, see file LICENSE in this source tree.
   9 */
  10#include <sys/types.h>
  11#include <sys/stat.h>
  12#include <fcntl.h>
  13#include <stdlib.h>
  14#include <string.h>
  15#include <stdio.h>
  16#include <unistd.h>
  17#include <ctype.h>
  18
  19#undef ARRAY_SIZE
  20#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
  21
  22#include "../include/autoconf.h"
  23#include "../include/applet_metadata.h"
  24
  25struct bb_applet {
  26        const char *name;
  27        const char *main;
  28        enum bb_install_loc_t install_loc;
  29        enum bb_suid_t need_suid;
  30        /* true if instead of fork(); exec("applet"); waitpid();
  31         * one can do fork(); exit(applet_main(argc,argv)); waitpid(); */
  32        unsigned char noexec;
  33        /* Even nicer */
  34        /* true if instead of fork(); exec("applet"); waitpid();
  35         * one can simply call applet_main(argc,argv); */
  36        unsigned char nofork;
  37};
  38
  39/* Define struct bb_applet applets[] */
  40#include "../include/applets.h"
  41
  42enum { NUM_APPLETS = ARRAY_SIZE(applets) };
  43
  44static int offset[NUM_APPLETS];
  45
  46static int cmp_name(const void *a, const void *b)
  47{
  48        const struct bb_applet *aa = a;
  49        const struct bb_applet *bb = b;
  50        return strcmp(aa->name, bb->name);
  51}
  52
  53static int str_isalnum_(const char *s)
  54{
  55        while (*s) {
  56                if (!isalnum(*s) && *s != '_')
  57                        return 0;
  58                s++;
  59        }
  60        return 1;
  61}
  62
  63int main(int argc, char **argv)
  64{
  65        int i;
  66        int ofs;
  67//      unsigned MAX_APPLET_NAME_LEN = 1;
  68
  69        qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name);
  70
  71        ofs = 0;
  72        for (i = 0; i < NUM_APPLETS; i++) {
  73                offset[i] = ofs;
  74                ofs += strlen(applets[i].name) + 1;
  75        }
  76        /* We reuse 4 high-order bits of offset array for other purposes,
  77         * so if they are indeed needed, refuse to proceed */
  78        if (ofs > 0xfff)
  79                return 1;
  80        if (!argv[1])
  81                return 1;
  82
  83        i = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0666);
  84        if (i < 0)
  85                return 1;
  86        dup2(i, 1);
  87
  88        /* Keep in sync with include/busybox.h! */
  89
  90        printf("/* This is a generated file, don't edit */\n\n");
  91
  92        printf("#define NUM_APPLETS %u\n", NUM_APPLETS);
  93        if (NUM_APPLETS == 1) {
  94                printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name);
  95                printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].main);
  96        }
  97        printf("\n");
  98
  99        //printf("#ifndef SKIP_definitions\n");
 100        printf("const char applet_names[] ALIGN1 = \"\"\n");
 101        for (i = 0; i < NUM_APPLETS; i++) {
 102                printf("\"%s\" \"\\0\"\n", applets[i].name);
 103//              if (MAX_APPLET_NAME_LEN < strlen(applets[i].name))
 104//                      MAX_APPLET_NAME_LEN = strlen(applets[i].name);
 105        }
 106        printf(";\n\n");
 107
 108        for (i = 0; i < NUM_APPLETS; i++) {
 109                if (str_isalnum_(applets[i].name))
 110                        printf("#define APPLET_NO_%s %d\n", applets[i].name, i);
 111        }
 112        printf("\n");
 113
 114        printf("#ifndef SKIP_applet_main\n");
 115        printf("int (*const applet_main[])(int argc, char **argv) = {\n");
 116        for (i = 0; i < NUM_APPLETS; i++) {
 117                printf("%s_main,\n", applets[i].main);
 118        }
 119        printf("};\n");
 120        printf("#endif\n\n");
 121
 122        printf("const uint16_t applet_nameofs[] ALIGN2 = {\n");
 123        for (i = 0; i < NUM_APPLETS; i++) {
 124                printf("0x%04x,\n",
 125                        offset[i]
 126#if ENABLE_FEATURE_PREFER_APPLETS
 127                        + (applets[i].nofork << 12)
 128                        + (applets[i].noexec << 13)
 129#endif
 130#if ENABLE_FEATURE_SUID
 131                        + (applets[i].need_suid << 14) /* 2 bits */
 132#endif
 133                );
 134        }
 135        printf("};\n\n");
 136
 137#if ENABLE_FEATURE_INSTALLER
 138        printf("const uint8_t applet_install_loc[] ALIGN1 = {\n");
 139        i = 0;
 140        while (i < NUM_APPLETS) {
 141                int v = applets[i].install_loc; /* 3 bits */
 142                if (++i < NUM_APPLETS)
 143                        v |= applets[i].install_loc << 4; /* 3 bits */
 144                printf("0x%02x,\n", v);
 145                i++;
 146        }
 147        printf("};\n");
 148#endif
 149        //printf("#endif /* SKIP_definitions */\n");
 150//      printf("\n");
 151//      printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
 152
 153        if (argv[2]) {
 154                char line_old[80];
 155                char line_new[80];
 156                FILE *fp;
 157
 158                line_old[0] = 0;
 159                fp = fopen(argv[2], "r");
 160                if (fp) {
 161                        fgets(line_old, sizeof(line_old), fp);
 162                        fclose(fp);
 163                }
 164                sprintf(line_new, "#define NUM_APPLETS %u\n", NUM_APPLETS);
 165                if (strcmp(line_old, line_new) != 0) {
 166                        fp = fopen(argv[2], "w");
 167                        if (!fp)
 168                                return 1;
 169                        fputs(line_new, fp);
 170                }
 171        }
 172
 173        return 0;
 174}
 175