source: MondoRescue/branches/3.3/mindi-busybox/applets/applet_tables.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
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 cmp_name(const void *a, const void *b)
45{
46 const struct bb_applet *aa = a;
47 const struct bb_applet *bb = b;
48 return strcmp(aa->name, bb->name);
49}
50
51static int str_isalnum_(const char *s)
52{
53 while (*s) {
54 if (!isalnum(*s) && *s != '_')
55 return 0;
56 s++;
57 }
58 return 1;
59}
60
61int main(int argc, char **argv)
62{
63 int i, j;
64
65 // In find_applet_by_name(), before linear search, narrow it down
66 // by looking at N "equidistant" names. With ~350 applets:
67 // KNOWN_APPNAME_OFFSETS cycles
68 // 0 9057
69 // 2 4604 + ~100 bytes of code
70 // 4 2407 + 4 bytes
71 // 8 1342 + 8 bytes
72 // 16 908 + 16 bytes
73 // 32 884 + 32 bytes
74 // With 8, int16_t applet_nameofs[] table has 7 elements.
75 int KNOWN_APPNAME_OFFSETS = 8;
76 // With 128 applets we do two linear searches, with 1..7 strcmp's in the first one
77 // and 1..16 strcmp's in the second. With 256 apps, second search does 1..32 strcmp's.
78 if (NUM_APPLETS < 128)
79 KNOWN_APPNAME_OFFSETS = 4;
80 if (NUM_APPLETS < 32)
81 KNOWN_APPNAME_OFFSETS = 0;
82
83 qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name);
84
85 if (!argv[1])
86 return 1;
87 i = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0666);
88 if (i < 0)
89 return 1;
90 dup2(i, 1);
91
92 /* Keep in sync with include/busybox.h! */
93
94 printf("/* This is a generated file, don't edit */\n\n");
95
96 printf("#define NUM_APPLETS %u\n", NUM_APPLETS);
97 if (NUM_APPLETS == 1) {
98 printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name);
99 printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].main);
100 }
101
102 printf("#define KNOWN_APPNAME_OFFSETS %u\n\n", KNOWN_APPNAME_OFFSETS);
103 if (KNOWN_APPNAME_OFFSETS > 0) {
104 int ofs, offset[KNOWN_APPNAME_OFFSETS], index[KNOWN_APPNAME_OFFSETS];
105 for (i = 0; i < KNOWN_APPNAME_OFFSETS; i++)
106 index[i] = i * NUM_APPLETS / KNOWN_APPNAME_OFFSETS;
107 ofs = 0;
108 for (i = 0; i < NUM_APPLETS; i++) {
109 for (j = 0; j < KNOWN_APPNAME_OFFSETS; j++)
110 if (i == index[j])
111 offset[j] = ofs;
112 ofs += strlen(applets[i].name) + 1;
113 }
114 /* If the list of names is too long refuse to proceed */
115 if (ofs > 0xffff)
116 return 1;
117 printf("const uint16_t applet_nameofs[] ALIGN2 = {\n");
118 for (i = 1; i < KNOWN_APPNAME_OFFSETS; i++)
119 printf("%d,\n", offset[i]);
120 printf("};\n\n");
121 }
122
123 //printf("#ifndef SKIP_definitions\n");
124 printf("const char applet_names[] ALIGN1 = \"\"\n");
125 for (i = 0; i < NUM_APPLETS; i++) {
126 printf("\"%s\" \"\\0\"\n", applets[i].name);
127// if (MAX_APPLET_NAME_LEN < strlen(applets[i].name))
128// MAX_APPLET_NAME_LEN = strlen(applets[i].name);
129 }
130 printf(";\n\n");
131
132 for (i = 0; i < NUM_APPLETS; i++) {
133 if (str_isalnum_(applets[i].name))
134 printf("#define APPLET_NO_%s %d\n", applets[i].name, i);
135 }
136 printf("\n");
137
138 printf("#ifndef SKIP_applet_main\n");
139 printf("int (*const applet_main[])(int argc, char **argv) = {\n");
140 for (i = 0; i < NUM_APPLETS; i++) {
141 printf("%s_main,\n", applets[i].main);
142 }
143 printf("};\n");
144 printf("#endif\n\n");
145
146#if ENABLE_FEATURE_PREFER_APPLETS
147 printf("const uint8_t applet_flags[] ALIGN1 = {\n");
148 i = 0;
149 while (i < NUM_APPLETS) {
150 int v = applets[i].nofork + (applets[i].noexec << 1);
151 if (++i < NUM_APPLETS)
152 v |= (applets[i].nofork + (applets[i].noexec << 1)) << 2;
153 if (++i < NUM_APPLETS)
154 v |= (applets[i].nofork + (applets[i].noexec << 1)) << 4;
155 if (++i < NUM_APPLETS)
156 v |= (applets[i].nofork + (applets[i].noexec << 1)) << 6;
157 printf("0x%02x,\n", v);
158 i++;
159 }
160 printf("};\n\n");
161#endif
162
163#if ENABLE_FEATURE_SUID
164 printf("const uint8_t applet_suid[] ALIGN1 = {\n");
165 i = 0;
166 while (i < NUM_APPLETS) {
167 int v = applets[i].need_suid; /* 2 bits */
168 if (++i < NUM_APPLETS)
169 v |= applets[i].need_suid << 2;
170 if (++i < NUM_APPLETS)
171 v |= applets[i].need_suid << 4;
172 if (++i < NUM_APPLETS)
173 v |= applets[i].need_suid << 6;
174 printf("0x%02x,\n", v);
175 i++;
176 }
177 printf("};\n\n");
178#endif
179
180#if ENABLE_FEATURE_INSTALLER
181 printf("const uint8_t applet_install_loc[] ALIGN1 = {\n");
182 i = 0;
183 while (i < NUM_APPLETS) {
184 int v = applets[i].install_loc; /* 3 bits */
185 if (++i < NUM_APPLETS)
186 v |= applets[i].install_loc << 4; /* 3 bits */
187 printf("0x%02x,\n", v);
188 i++;
189 }
190 printf("};\n");
191#endif
192 //printf("#endif /* SKIP_definitions */\n");
193// printf("\n");
194// printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
195
196 if (argv[2]) {
197 char line_old[80];
198 char line_new[80];
199 FILE *fp;
200
201 line_old[0] = 0;
202 fp = fopen(argv[2], "r");
203 if (fp) {
204 fgets(line_old, sizeof(line_old), fp);
205 fclose(fp);
206 }
207 sprintf(line_new, "#define NUM_APPLETS %u\n", NUM_APPLETS);
208 if (strcmp(line_old, line_new) != 0) {
209 fp = fopen(argv[2], "w");
210 if (!fp)
211 return 1;
212 fputs(line_new, fp);
213 }
214 }
215
216 return 0;
217}
Note: See TracBrowser for help on using the repository browser.