Set permissions of created file
[oweals/busybox.git] / busybox.c
1 /* vi: set sw=4 ts=4: */
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include "busybox.h"
8
9 #define bb_need_full_version
10 #define BB_DECLARE_EXTERN
11 #include "messages.c"
12
13 #ifdef BB_LOCALE_SUPPORT
14 #include <locale.h>
15 #endif
16
17 int been_there_done_that = 0; /* Also used in applets.c */
18 const char *applet_name;
19
20 #ifdef BB_FEATURE_INSTALLER
21 /* 
22  * directory table
23  *              this should be consistent w/ the enum, busybox.h::Location,
24  *              or else...
25  */
26 static char* install_dir[] = {
27         "/",
28         "/bin",
29         "/sbin",
30         "/usr/bin",
31         "/usr/sbin",
32 };
33
34 /* abstract link() */
35 typedef int (*__link_f)(const char *, const char *);
36
37 /* 
38  * Where in the filesystem is this busybox?
39  * [return]
40  *              malloc'd string w/ full pathname of busybox's location
41  *              NULL on failure
42  */
43 static char *busybox_fullpath()
44 {
45         pid_t pid;
46         char path[256];
47         char proc[256];
48         int len;
49
50         pid = getpid();
51         sprintf(proc, "/proc/%d/exe", pid);
52         len = readlink(proc, path, 256);
53         if (len != -1) {
54                 path[len] = 0;
55         } else {
56                 perror_msg("%s", proc);
57                 return NULL;
58         }
59         return strdup(path);
60 }
61
62 /* create (sym)links for each applet */
63 static void install_links(const char *busybox, int use_symbolic_links)
64 {
65         __link_f Link = link;
66
67         char *fpc;
68         int i;
69         int rc;
70
71         if (use_symbolic_links) 
72                 Link = symlink;
73
74         for (i = 0; applets[i].name != NULL; i++) {
75                 fpc = concat_path_file(
76                         install_dir[applets[i].location], applets[i].name);
77                 rc = Link(busybox, fpc);
78                 if (rc!=0 && errno!=EEXIST) {
79                         perror_msg("%s", fpc);
80                 }
81                 free(fpc);
82         }
83 }
84
85 #endif /* BB_FEATURE_INSTALLER */
86
87 int main(int argc, char **argv)
88 {
89         const char *s;
90
91         for (s = applet_name = argv[0]; *s != '\0';) {
92                 if (*s++ == '/')
93                         applet_name = s;
94         }
95
96 #ifdef BB_SH
97         /* Add in a special case hack -- whenever **argv == '-'
98          * (i.e. '-su' or '-sh') always invoke the shell */
99         if (**argv == '-' && *(*argv+1)!= '-') {
100                 applet_name = "sh";
101         }
102 #endif
103
104 #ifdef BB_LOCALE_SUPPORT
105         if(getpid()!=1) /* Do not set locale for `init' */
106                 setlocale(LC_ALL, "");
107 #endif
108
109         run_applet_by_name(applet_name, argc, argv);
110         error_msg_and_die("applet not found");
111 }
112
113
114 int busybox_main(int argc, char **argv)
115 {
116         int col = 0, len, i;
117
118 #ifdef BB_FEATURE_INSTALLER     
119         /* 
120          * This style of argument parsing doesn't scale well 
121          * in the event that busybox starts wanting more --options.
122          * If someone has a cleaner approach, by all means implement it.
123          */
124         if (argc > 1 && (strcmp(argv[1], "--install") == 0)) {
125                 int use_symbolic_links = 0;
126                 int rc = 0;
127                 char *busybox;
128
129                 /* to use symlinks, or not to use symlinks... */
130                 if (argc > 2) {
131                         if ((strcmp(argv[2], "-s") == 0)) { 
132                                 use_symbolic_links = 1; 
133                         }
134                 }
135
136                 /* link */
137                 busybox = busybox_fullpath();
138                 if (busybox) {
139                         install_links(busybox, use_symbolic_links);
140                         free(busybox);
141                 } else {
142                         rc = 1;
143                 }
144                 return rc;
145         }
146 #endif /* BB_FEATURE_INSTALLER */
147
148         argc--;
149
150         /* If we've already been here once, exit now */
151         if (been_there_done_that == 1 || argc < 1) {
152                 const struct BB_applet *a = applets;
153
154                 fprintf(stderr, "%s\n\n"
155                                 "Usage: busybox [function] [arguments]...\n"
156                                 "   or: [function] [arguments]...\n\n"
157                                 "\tBusyBox is a multi-call binary that combines many common Unix\n"
158                                 "\tutilities into a single executable.  Most people will create a\n"
159                                 "\tlink to busybox for each function they wish to use, and BusyBox\n"
160                                 "\twill act like whatever it was invoked as.\n" 
161                                 "\nCurrently defined functions:\n", full_version);
162
163                 while (a->name != 0) {
164                         col +=
165                                 fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "),
166                                                 (a++)->name);
167                         if (col > 60 && a->name != 0) {
168                                 fprintf(stderr, ",\n");
169                                 col = 0;
170                         }
171                 }
172                 fprintf(stderr, "\n\n");
173                 exit(0);
174         }
175
176         /* Flag that we've been here already */
177         been_there_done_that = 1;
178         
179         /* Move the command line down a notch */
180         len = argv[argc] + strlen(argv[argc]) - argv[1];
181         memmove(argv[0], argv[1], len);
182         memset(argv[0] + len, 0, argv[1] - argv[0]);
183
184         /* Fix up the argv pointers */
185         len = argv[1] - argv[0];
186         memmove(argv, argv + 1, sizeof(char *) * (argc + 1));
187         for (i = 0; i < argc; i++)
188                 argv[i] -= len;
189
190         return (main(argc, argv));
191 }
192
193 /*
194 Local Variables:
195 c-file-style: "linux"
196 c-basic-offset: 4
197 tab-width: 4
198 End:
199 */