8d4c6d7c0e751e7e1d5232ec7b0dcd87ec383ef9
[akaros.git] / user / apps / parlib / run_binary.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/wait.h>
6 #include <fcntl.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <parlib.h>
11 #include <newlib_backend.h>
12
13 int shell_exec(const char* cmdline)
14 {
15         #define MY_MAX_ARGV 16
16         char* argv[MY_MAX_ARGV+1] = {0};
17         char* p0 = strdup(cmdline);
18         char* p = p0;
19         for(int i = 0; i < MY_MAX_ARGV; i++)
20         {
21                 argv[i] = p;
22                 p = strchr(p,' ');
23                 if(p)
24                         *p++ = 0;
25                 else
26                         break;
27         }
28
29         int ret = fork();
30         if(ret == 0)
31         {
32                 char** envp = environ;
33                 const char* path = NULL;
34                 int nenv;
35                 for(nenv = 0; environ[nenv]; nenv++)
36                         if(strncmp(environ[nenv],"PATH=",5) == 0)
37                                 path = environ[nenv]+5;
38
39                 if(path == NULL)
40                 {
41                         envp = (char**)malloc(sizeof(char**)*(nenv+2));
42                         for(int i = 0; i < nenv; i++)
43                                 envp[i] = environ[i];
44                         envp[nenv] = "PATH=:/bin:/usr/bin";
45                         path = envp[nenv]+5;
46                         envp[nenv+1] = 0;
47                 }
48
49                 char* fn = NULL, *buf = NULL;
50                 if(strchr(argv[0],'/'))
51                 {
52                         if(access(argv[0],X_OK) == 0)
53                                 fn = argv[0];
54                 }
55                 else
56                 {
57                         buf = (char*)malloc(sizeof(char)*(strlen(argv[0])+strlen(path)+2));
58                         while(fn == NULL)
59                         {
60                                 const char* end = strchr(path,':');
61                                 int len = end ? end-path : strlen(path);
62                                 memcpy(buf,path,len);
63                                 if(len && buf[len-1] != '/')
64                                         buf[len++] = '/';
65                                 strcpy(buf+len,argv[0]);
66
67                                 if(access(buf,X_OK) == 0)
68                                         fn = buf;
69                                 if(end == NULL)
70                                         break;
71                                 path = end+1;
72                         }
73                 }
74
75                 if(fn == NULL)
76                 {
77                         printf("%s: not found\n",argv[0]);
78                         exit(1);
79                 }
80
81                 execve(fn,argv,envp);
82                 free(buf);
83                 perror("execvp");
84                 exit(1);
85         }
86         else if(ret > 0)
87         {
88                 int status;
89                 if(wait(&status))
90                         perror("wait");
91                 else
92                         debug_in_out("%s returned %d\n",argv[0],status);
93         }
94         else
95                 perror("fork");
96
97         free(p0);
98         return 0;
99 }
100
101 extern char * readline(const char *prompt);
102
103 #define MALLOC_SIZE     1048576
104 #define READ_SIZE       1024
105
106 int run_binary_filename(const char* cmdline, size_t colors)
107 {
108         int ret = 0;
109
110         const char* cmdptr = cmdline;
111         char argv_buf[PROCINFO_MAX_ARGV_SIZE] = {0};
112         intreg_t* argv = (intreg_t*)argv_buf;
113         argv[0] = 0;
114         int argc;
115         for(argc = 0; ; argc++)
116         {
117                 while(*cmdptr == ' ')
118                         cmdptr++;
119                 if(*cmdptr == 0)
120                         break;
121
122                 char* p = strchr(cmdptr,' ');
123                 int len = p == NULL ? 1+strlen(cmdptr) : 1+p-cmdptr;
124
125                 argv[argc+1] = argv[argc]+len;
126
127                 if(p == NULL)
128                 {
129                         argc++;
130                         break;
131                 }
132
133                 cmdptr = p;
134         }
135         for(int i = 0; i < argc; i++)
136         {
137                 intreg_t offset = argv[i];
138                 argv[i] += (argc+1)*sizeof(char*);
139                 memcpy(argv_buf+argv[i],cmdline+offset,argv[i+1]-offset-1);
140                 argv_buf[argv[i]+argv[i+1]-offset-1] = 0;
141         }
142         argv[argc] = 0;
143
144         char* filename = argv_buf+argv[0];
145         int fd = open(filename, O_RDONLY, 0);
146         if(fd < 0)
147         {
148                 printf("open failed\n");
149                 ret = -1;
150                 goto open_error;
151         }
152         
153         int total_bytes_read = 0;
154         int bytes_read = 0;
155         int bufsz = 0;
156         void* binary_buf = NULL;
157         
158         while(1) {
159                 if(total_bytes_read+READ_SIZE > bufsz)
160                 {
161                         void* temp_buf = realloc(binary_buf,bufsz+MALLOC_SIZE);
162                         if(temp_buf == NULL)
163                         {
164                                 printf("realloc failed\n");
165                                 ret = -1;
166                                 goto realloc_error;
167                         }
168
169                         binary_buf = temp_buf;
170                         bufsz += MALLOC_SIZE;
171                 }
172
173                 bytes_read = read(fd, binary_buf+total_bytes_read, READ_SIZE);
174                 total_bytes_read += bytes_read;
175                 if(bytes_read < 0)
176                 {
177                         printf("read error\n");
178                         ret = -1;
179                         goto read_error;
180                 }
181                 if(bytes_read == 0) break;
182         }
183         //printf("Loading Binary: %s, ROMSIZE: %d\n",filename,total_bytes_read);
184         ret = sys_run_binary(binary_buf, total_bytes_read, argv_buf, colors);
185         if(ret < 0)
186                 fprintf(stderr, "Error: Unable to run remote binary\n");
187         else
188                 syscall(SYS_yield,0,0,0,0,0);
189
190 read_error:
191 realloc_error:
192         free(binary_buf);
193         close(fd);
194 open_error:
195         return ret;
196 }
197
198 void run_binary(size_t colors)
199 {
200         char* readline_result = readline("\nEnter name of binary to execute: ");
201         if (readline_result == NULL) {
202                 printf("Error reading from console.\n");
203                 return;
204         }
205         run_binary_filename(readline_result, colors);
206 }
207