Added more syscalls
[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(argv[0][0] == '/')
51                         fn = argv[0];
52                 else
53                 {
54                         buf = (char*)malloc(sizeof(char)*(strlen(argv[0])+strlen(path)+2));
55                         while(fn == NULL)
56                         {
57                                 const char* end = strchr(path,':');
58                                 int len = end ? end-path : strlen(path);
59                                 memcpy(buf,path,len);
60                                 if(len && buf[len-1] != '/')
61                                         buf[len++] = '/';
62                                 strcpy(buf+len,argv[0]);
63
64                                 if(access(buf,X_OK) == 0)
65                                         fn = buf;
66                                 if(end == NULL)
67                                         break;
68                                 path = end+1;
69                         }
70
71                         if(fn == NULL)
72                         {
73                                 printf("%s: not found\n",argv[0]);
74                                 exit(1);
75                         }
76                 }
77
78                 execve(fn,argv,envp);
79                 free(buf);
80                 perror("execvp");
81                 exit(1);
82         }
83         else if(ret > 0)
84         {
85                 int status;
86                 if(wait(&status))
87                         perror("wait");
88                 else
89                         debug_in_out("%s returned %d\n",argv[0],status);
90         }
91         else
92                 perror("fork");
93
94         free(p0);
95         return 0;
96 }
97
98 extern char * readline(const char *prompt);
99
100 #define MALLOC_SIZE     1048576
101 #define READ_SIZE       1024
102
103 int run_binary_filename(const char* cmdline, size_t colors)
104 {
105         int ret = 0;
106
107         const char* cmdptr = cmdline;
108         char argv_buf[PROCINFO_MAX_ARGV_SIZE] = {0};
109         intreg_t* argv = (intreg_t*)argv_buf;
110         argv[0] = 0;
111         int argc;
112         for(argc = 0; ; argc++)
113         {
114                 while(*cmdptr == ' ')
115                         cmdptr++;
116                 if(*cmdptr == 0)
117                         break;
118
119                 char* p = strchr(cmdptr,' ');
120                 int len = p == NULL ? 1+strlen(cmdptr) : 1+p-cmdptr;
121
122                 argv[argc+1] = argv[argc]+len;
123
124                 if(p == NULL)
125                 {
126                         argc++;
127                         break;
128                 }
129
130                 cmdptr = p;
131         }
132         for(int i = 0; i < argc; i++)
133         {
134                 intreg_t offset = argv[i];
135                 argv[i] += (argc+1)*sizeof(char*);
136                 memcpy(argv_buf+argv[i],cmdline+offset,argv[i+1]-offset-1);
137                 argv_buf[argv[i]+argv[i+1]-offset-1] = 0;
138         }
139         argv[argc] = 0;
140
141         char* filename = argv_buf+argv[0];
142         int fd = open(filename, O_RDONLY, 0);
143         if(fd < 0)
144         {
145                 printf("open failed\n");
146                 ret = -1;
147                 goto open_error;
148         }
149         
150         int total_bytes_read = 0;
151         int bytes_read = 0;
152         int bufsz = 0;
153         void* binary_buf = NULL;
154         
155         while(1) {
156                 if(total_bytes_read+READ_SIZE > bufsz)
157                 {
158                         void* temp_buf = realloc(binary_buf,bufsz+MALLOC_SIZE);
159                         if(temp_buf == NULL)
160                         {
161                                 printf("realloc failed\n");
162                                 ret = -1;
163                                 goto realloc_error;
164                         }
165
166                         binary_buf = temp_buf;
167                         bufsz += MALLOC_SIZE;
168                 }
169
170                 bytes_read = read(fd, binary_buf+total_bytes_read, READ_SIZE);
171                 total_bytes_read += bytes_read;
172                 if(bytes_read < 0)
173                 {
174                         printf("read error\n");
175                         ret = -1;
176                         goto read_error;
177                 }
178                 if(bytes_read == 0) break;
179         }
180         //printf("Loading Binary: %s, ROMSIZE: %d\n",filename,total_bytes_read);
181         ret = sys_run_binary(binary_buf, total_bytes_read, argv_buf, colors);
182         if(ret < 0)
183                 fprintf(stderr, "Error: Unable to run remote binary\n");
184         else
185                 syscall(SYS_yield,0,0,0,0,0);
186
187 read_error:
188 realloc_error:
189         free(binary_buf);
190         close(fd);
191 open_error:
192         return ret;
193 }
194
195 void run_binary(size_t colors)
196 {
197         char* readline_result = readline("\nEnter name of binary to execute: ");
198         if (readline_result == NULL) {
199                 printf("Error reading from console.\n");
200                 return;
201         }
202         run_binary_filename(readline_result, colors);
203 }
204