[dd74e612] | 1 | /* |
---|
| 2 | * |
---|
| 3 | * Instantatiate a new terminal shell. |
---|
| 4 | * |
---|
[aed742c] | 5 | * Author: |
---|
[dd74e612] | 6 | * |
---|
[aed742c] | 7 | * WORK: fernando.ruiz@ctv.es |
---|
[dd74e612] | 8 | * HOME: correo@fernando-ruiz.com |
---|
| 9 | * |
---|
[4e5299f] | 10 | * The license and distribution terms for this file may be |
---|
| 11 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 12 | * http://www.rtems.org/license/LICENSE. |
---|
[dd74e612] | 13 | */ |
---|
[814d9588] | 14 | |
---|
[b2712e3] | 15 | #ifdef HAVE_CONFIG_H |
---|
| 16 | #include "config.h" |
---|
| 17 | #endif |
---|
[dd74e612] | 18 | |
---|
| 19 | #include <stdio.h> |
---|
[84206479] | 20 | #include <time.h> |
---|
[dd74e612] | 21 | |
---|
| 22 | #include <rtems.h> |
---|
| 23 | #include <rtems/error.h> |
---|
| 24 | #include <rtems/libio.h> |
---|
[aed742c] | 25 | #include <rtems/libio_.h> |
---|
| 26 | #include <rtems/system.h> |
---|
[b2712e3] | 27 | #include <rtems/shell.h> |
---|
[4e5299f] | 28 | #include <rtems/shellconfig.h> |
---|
[06f8e558] | 29 | #include <rtems/console.h> |
---|
[4e5299f] | 30 | #include "internal.h" |
---|
[dd74e612] | 31 | |
---|
| 32 | #include <termios.h> |
---|
| 33 | #include <string.h> |
---|
| 34 | #include <stdlib.h> |
---|
| 35 | #include <ctype.h> |
---|
[70d689a] | 36 | #include <sys/stat.h> |
---|
[dd74e612] | 37 | #include <unistd.h> |
---|
| 38 | #include <errno.h> |
---|
[b2712e3] | 39 | #include <pwd.h> |
---|
[6cd4a5c] | 40 | #include <pthread.h> |
---|
| 41 | #include <assert.h> |
---|
[dd74e612] | 42 | |
---|
[5f0ab5cf] | 43 | const rtems_shell_env_t rtems_global_shell_env = { |
---|
[06f8e558] | 44 | .magic = rtems_build_name('S', 'E', 'N', 'V'), |
---|
| 45 | .devname = CONSOLE_DEVICE_NAME, |
---|
| 46 | .taskname = "SHGL", |
---|
| 47 | .exit_shell = false, |
---|
| 48 | .forever = true, |
---|
| 49 | .errorlevel = -1, |
---|
| 50 | .echo = false, |
---|
| 51 | .cwd = "/", |
---|
| 52 | .input = NULL, |
---|
| 53 | .output = NULL, |
---|
| 54 | .output_append = false, |
---|
| 55 | .wake_on_end = RTEMS_ID_NONE, |
---|
[8a775c27] | 56 | .login_check = NULL |
---|
[06f8e558] | 57 | }; |
---|
| 58 | |
---|
[373ccbb9] | 59 | static pthread_once_t rtems_shell_once = PTHREAD_ONCE_INIT; |
---|
| 60 | |
---|
[6cd4a5c] | 61 | static pthread_key_t rtems_shell_current_env_key; |
---|
[4e5299f] | 62 | |
---|
| 63 | /* |
---|
[814d9588] | 64 | * Initialize the shell user/process environment information |
---|
[4e5299f] | 65 | */ |
---|
[94547d1] | 66 | static rtems_shell_env_t *rtems_shell_init_env( |
---|
[13c37ad] | 67 | rtems_shell_env_t *shell_env_p |
---|
[4e5299f] | 68 | ) |
---|
| 69 | { |
---|
[13c37ad] | 70 | rtems_shell_env_t *shell_env; |
---|
| 71 | |
---|
| 72 | shell_env = malloc(sizeof(rtems_shell_env_t)); |
---|
| 73 | if ( !shell_env ) |
---|
| 74 | return NULL; |
---|
| 75 | if ( !shell_env_p ) { |
---|
[1ff9922] | 76 | *shell_env = rtems_global_shell_env; |
---|
[13c37ad] | 77 | } else { |
---|
| 78 | *shell_env = *shell_env_p; |
---|
[4e5299f] | 79 | } |
---|
[13c37ad] | 80 | shell_env->taskname = NULL; |
---|
[4e5299f] | 81 | |
---|
[814d9588] | 82 | return shell_env; |
---|
[dd74e612] | 83 | } |
---|
[4e5299f] | 84 | |
---|
[798ff5a] | 85 | /* |
---|
| 86 | * Completely free a shell_env_t and all associated memory |
---|
| 87 | */ |
---|
[94547d1] | 88 | static void rtems_shell_env_free( |
---|
[798ff5a] | 89 | void *ptr |
---|
| 90 | ) |
---|
| 91 | { |
---|
| 92 | rtems_shell_env_t *shell_env; |
---|
| 93 | shell_env = (rtems_shell_env_t *) ptr; |
---|
| 94 | |
---|
| 95 | if ( !ptr ) |
---|
| 96 | return; |
---|
| 97 | |
---|
| 98 | if ( shell_env->input ) |
---|
| 99 | free((void *)shell_env->input); |
---|
| 100 | if ( shell_env->output ) |
---|
| 101 | free((void *)shell_env->output); |
---|
| 102 | free( ptr ); |
---|
| 103 | } |
---|
| 104 | |
---|
[373ccbb9] | 105 | static void rtems_shell_create_file(const char *name, const char *content) |
---|
[6cd4a5c] | 106 | { |
---|
[373ccbb9] | 107 | FILE *fp = fopen(name, "wx"); |
---|
| 108 | |
---|
| 109 | if (fp != NULL) { |
---|
| 110 | fputs(content, fp); |
---|
| 111 | fclose(fp); |
---|
| 112 | } |
---|
| 113 | } |
---|
| 114 | |
---|
[7840b66] | 115 | static void rtems_shell_init_commands(void) |
---|
| 116 | { |
---|
| 117 | rtems_shell_cmd_t * const *c; |
---|
| 118 | rtems_shell_alias_t * const *a; |
---|
| 119 | |
---|
| 120 | for ( c = rtems_shell_Initial_commands ; *c ; c++ ) { |
---|
| 121 | rtems_shell_add_cmd_struct( *c ); |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | for ( a = rtems_shell_Initial_aliases ; *a ; a++ ) { |
---|
| 125 | rtems_shell_alias_cmd( (*a)->name, (*a)->alias ); |
---|
| 126 | } |
---|
| 127 | } |
---|
| 128 | |
---|
[373ccbb9] | 129 | static void rtems_shell_init_once(void) |
---|
| 130 | { |
---|
| 131 | struct passwd pwd; |
---|
| 132 | struct passwd *pwd_res; |
---|
| 133 | |
---|
| 134 | pthread_key_create(&rtems_shell_current_env_key, rtems_shell_env_free); |
---|
| 135 | |
---|
| 136 | /* dummy call to init /etc dir */ |
---|
| 137 | getpwuid_r(0, &pwd, NULL, 0, &pwd_res); |
---|
| 138 | |
---|
| 139 | rtems_shell_create_file("etc/issue", |
---|
| 140 | "\n" |
---|
| 141 | "Welcome to @V\\n" |
---|
| 142 | "Login into @S\\n"); |
---|
| 143 | |
---|
| 144 | rtems_shell_create_file("/etc/issue.net", |
---|
| 145 | "\n" |
---|
| 146 | "Welcome to %v\n" |
---|
| 147 | "running on %m\n"); |
---|
[7840b66] | 148 | |
---|
| 149 | rtems_shell_init_commands(); |
---|
[89fd08e] | 150 | rtems_shell_register_monitor_commands(); |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | void rtems_shell_init_environment(void) |
---|
| 154 | { |
---|
| 155 | assert(pthread_once(&rtems_shell_once, rtems_shell_init_once) == 0); |
---|
[6cd4a5c] | 156 | } |
---|
| 157 | |
---|
| 158 | /* |
---|
| 159 | * Return the current shell environment |
---|
| 160 | */ |
---|
| 161 | rtems_shell_env_t *rtems_shell_get_current_env(void) |
---|
| 162 | { |
---|
[bb58190] | 163 | return (rtems_shell_env_t *) pthread_getspecific(rtems_shell_current_env_key); |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | /* |
---|
| 167 | * Duplication the current shell environment and if none is set |
---|
| 168 | * clear it. |
---|
| 169 | */ |
---|
| 170 | void rtems_shell_dup_current_env(rtems_shell_env_t *copy) |
---|
| 171 | { |
---|
| 172 | rtems_shell_env_t *env = rtems_shell_get_current_env(); |
---|
| 173 | if (env) { |
---|
| 174 | *copy = *env; |
---|
| 175 | } |
---|
| 176 | else { |
---|
| 177 | memset(copy, 0, sizeof(rtems_shell_env_t)); |
---|
| 178 | copy->magic = rtems_build_name('S', 'E', 'N', 'V'); |
---|
| 179 | copy->devname = CONSOLE_DEVICE_NAME; |
---|
| 180 | copy->taskname = "RTSH"; |
---|
| 181 | } |
---|
[6cd4a5c] | 182 | } |
---|
| 183 | |
---|
[814d9588] | 184 | /* |
---|
| 185 | * Get a line of user input with modest features |
---|
| 186 | */ |
---|
[94547d1] | 187 | static int rtems_shell_line_editor( |
---|
[ea90df23] | 188 | char *cmds[], |
---|
| 189 | int count, |
---|
| 190 | int size, |
---|
| 191 | const char *prompt, |
---|
| 192 | FILE *in, |
---|
| 193 | FILE *out |
---|
| 194 | ) |
---|
| 195 | { |
---|
| 196 | unsigned int extended_key; |
---|
[7c4cdeb9] | 197 | int c; |
---|
[ea90df23] | 198 | int col; |
---|
| 199 | int last_col; |
---|
| 200 | int output; |
---|
| 201 | char line[size]; |
---|
| 202 | char new_line[size]; |
---|
| 203 | int up; |
---|
| 204 | int cmd = -1; |
---|
| 205 | int inserting = 1; |
---|
[8a775c27] | 206 | |
---|
[ea90df23] | 207 | output = (out && isatty(fileno(in))); |
---|
| 208 | |
---|
| 209 | col = last_col = 0; |
---|
[8a775c27] | 210 | |
---|
[ea90df23] | 211 | tcdrain(fileno(in)); |
---|
| 212 | if (out) |
---|
| 213 | tcdrain(fileno(out)); |
---|
| 214 | |
---|
| 215 | if (output && prompt) |
---|
| 216 | fprintf(out, "\r%s", prompt); |
---|
[8a775c27] | 217 | |
---|
[ea90df23] | 218 | line[0] = 0; |
---|
| 219 | new_line[0] = 0; |
---|
[8a775c27] | 220 | |
---|
[ea90df23] | 221 | for (;;) { |
---|
[8a775c27] | 222 | |
---|
[ea90df23] | 223 | if (output) |
---|
| 224 | fflush(out); |
---|
| 225 | |
---|
| 226 | extended_key = rtems_shell_getchar(in); |
---|
| 227 | |
---|
| 228 | if (extended_key == EOF) |
---|
| 229 | return -2; |
---|
[8a775c27] | 230 | |
---|
[ea90df23] | 231 | c = extended_key & RTEMS_SHELL_KEYS_NORMAL_MASK; |
---|
[8a775c27] | 232 | |
---|
[ea90df23] | 233 | /* |
---|
| 234 | * Make the extended_key usable as a boolean. |
---|
| 235 | */ |
---|
| 236 | extended_key &= ~RTEMS_SHELL_KEYS_NORMAL_MASK; |
---|
[8a775c27] | 237 | |
---|
[ea90df23] | 238 | up = 0; |
---|
[8a775c27] | 239 | |
---|
[ea90df23] | 240 | if (extended_key) |
---|
| 241 | { |
---|
| 242 | switch (c) |
---|
| 243 | { |
---|
| 244 | case RTEMS_SHELL_KEYS_END: |
---|
| 245 | if (output) |
---|
[8bca4fc] | 246 | fprintf(out, "%s", line + col); |
---|
[ea90df23] | 247 | col = (int) strlen (line); |
---|
| 248 | break; |
---|
| 249 | |
---|
| 250 | case RTEMS_SHELL_KEYS_HOME: |
---|
| 251 | if (output) { |
---|
| 252 | if (prompt) |
---|
| 253 | fprintf(out,"\r%s", prompt); |
---|
| 254 | } |
---|
| 255 | col = 0; |
---|
| 256 | break; |
---|
| 257 | |
---|
| 258 | case RTEMS_SHELL_KEYS_LARROW: |
---|
[22e98377] | 259 | c = 2; |
---|
| 260 | extended_key = 0; |
---|
[ea90df23] | 261 | break; |
---|
| 262 | |
---|
[22e98377] | 263 | case RTEMS_SHELL_KEYS_RARROW: |
---|
| 264 | c = 6; |
---|
| 265 | extended_key = 0; |
---|
| 266 | break; |
---|
[ea90df23] | 267 | |
---|
| 268 | case RTEMS_SHELL_KEYS_UARROW: |
---|
[22e98377] | 269 | c = 16; |
---|
| 270 | extended_key = 0; |
---|
| 271 | break; |
---|
[ea90df23] | 272 | |
---|
| 273 | case RTEMS_SHELL_KEYS_DARROW: |
---|
[22e98377] | 274 | c = 14; |
---|
| 275 | extended_key = 0; |
---|
| 276 | break; |
---|
[ea90df23] | 277 | |
---|
| 278 | case RTEMS_SHELL_KEYS_DEL: |
---|
| 279 | if (line[col] != '\0') |
---|
| 280 | { |
---|
| 281 | int end; |
---|
| 282 | int bs; |
---|
| 283 | strcpy (&line[col], &line[col + 1]); |
---|
| 284 | if (output) { |
---|
| 285 | fprintf(out,"\r%s%s ", prompt, line); |
---|
| 286 | end = (int) strlen (line); |
---|
| 287 | for (bs = 0; bs < ((end - col) + 1); bs++) |
---|
| 288 | fputc('\b', out); |
---|
| 289 | } |
---|
| 290 | } |
---|
| 291 | break; |
---|
| 292 | |
---|
| 293 | case RTEMS_SHELL_KEYS_INS: |
---|
| 294 | inserting = inserting ? 0 : 1; |
---|
| 295 | break; |
---|
| 296 | } |
---|
| 297 | } |
---|
[22e98377] | 298 | if (!extended_key) |
---|
[ea90df23] | 299 | { |
---|
| 300 | switch (c) |
---|
| 301 | { |
---|
[22e98377] | 302 | case 1: /*Control-a*/ |
---|
[ea90df23] | 303 | if (output) { |
---|
| 304 | if (prompt) |
---|
| 305 | fprintf(out,"\r%s", prompt); |
---|
| 306 | } |
---|
| 307 | col = 0; |
---|
| 308 | break; |
---|
[8a775c27] | 309 | |
---|
[22e98377] | 310 | case 2: /* Control-B */ |
---|
| 311 | if (col > 0) |
---|
| 312 | { |
---|
| 313 | col--; |
---|
| 314 | if (output) |
---|
| 315 | fputc('\b', out); |
---|
| 316 | } |
---|
| 317 | break; |
---|
| 318 | |
---|
| 319 | case 4: /* Control-D */ |
---|
| 320 | if (strlen(line)) { |
---|
| 321 | if (col < strlen(line)) { |
---|
| 322 | strcpy (line + col, line + col + 1); |
---|
| 323 | if (output) { |
---|
| 324 | int bs; |
---|
| 325 | fprintf(out,"%s \b", line + col); |
---|
| 326 | for (bs = 0; bs < ((int) strlen (line) - col); bs++) |
---|
| 327 | fputc('\b', out); |
---|
| 328 | } |
---|
| 329 | } |
---|
| 330 | break; |
---|
| 331 | } |
---|
| 332 | /* Fall through */ |
---|
| 333 | |
---|
| 334 | case EOF: |
---|
| 335 | if (output) |
---|
| 336 | fputc('\n', out); |
---|
| 337 | return -2; |
---|
| 338 | |
---|
| 339 | case 5: /*Control-e*/ |
---|
[ea90df23] | 340 | if (output) |
---|
[8bca4fc] | 341 | fprintf(out, "%s", line + col); |
---|
[ea90df23] | 342 | col = (int) strlen (line); |
---|
| 343 | break; |
---|
| 344 | |
---|
[22e98377] | 345 | case 6: /* Control-F */ |
---|
| 346 | if ((col < size) && (line[col] != '\0')) { |
---|
| 347 | if (output) |
---|
| 348 | fputc(line[col], out); |
---|
| 349 | col++; |
---|
| 350 | } |
---|
| 351 | break; |
---|
| 352 | |
---|
| 353 | case 7: /* Control-G */ |
---|
| 354 | if (output) { |
---|
[06ac8b71] | 355 | /* |
---|
| 356 | * The (int) cast is needed because the width specifier (%*) |
---|
| 357 | * must be an int, but strlen() returns a size_t. Without |
---|
| 358 | * the case, the result is a printf() format warning. |
---|
| 359 | */ |
---|
| 360 | fprintf(out,"\r%s%*c", prompt, (int) strlen (line), ' '); |
---|
[22e98377] | 361 | fprintf(out,"\r%s\x7", prompt); |
---|
| 362 | } |
---|
| 363 | memset (line, '\0', strlen(line)); |
---|
| 364 | col = 0; |
---|
| 365 | break; |
---|
| 366 | |
---|
| 367 | case 11: /*Control-k*/ |
---|
[ea90df23] | 368 | if (line[col]) { |
---|
| 369 | if (output) { |
---|
| 370 | int end = strlen(line); |
---|
| 371 | int bs; |
---|
| 372 | fprintf(out,"%*c", end - col, ' '); |
---|
| 373 | for (bs = 0; bs < (end - col); bs++) |
---|
| 374 | fputc('\b', out); |
---|
| 375 | } |
---|
| 376 | line[col] = '\0'; |
---|
| 377 | } |
---|
| 378 | break; |
---|
[8a775c27] | 379 | |
---|
[ea90df23] | 380 | case '\f': |
---|
| 381 | if (output) { |
---|
| 382 | int end; |
---|
| 383 | int bs; |
---|
| 384 | fputc('\f',out); |
---|
| 385 | fprintf(out,"\r%s%s", prompt, line); |
---|
| 386 | end = (int) strlen (line); |
---|
| 387 | for (bs = 0; bs < (end - col); bs++) |
---|
| 388 | fputc('\b', out); |
---|
| 389 | } |
---|
| 390 | break; |
---|
| 391 | |
---|
| 392 | case '\b': |
---|
| 393 | case '\x7f': |
---|
| 394 | if (col > 0) |
---|
| 395 | { |
---|
| 396 | int bs; |
---|
| 397 | col--; |
---|
| 398 | strcpy (line + col, line + col + 1); |
---|
| 399 | if (output) { |
---|
| 400 | fprintf(out,"\b%s \b", line + col); |
---|
| 401 | for (bs = 0; bs < ((int) strlen (line) - col); bs++) |
---|
| 402 | fputc('\b', out); |
---|
| 403 | } |
---|
| 404 | } |
---|
| 405 | break; |
---|
| 406 | |
---|
| 407 | case '\n': |
---|
| 408 | case '\r': |
---|
| 409 | { |
---|
| 410 | /* |
---|
| 411 | * Process the command. |
---|
| 412 | */ |
---|
| 413 | if (output) |
---|
| 414 | fprintf(out,"\n"); |
---|
[8a775c27] | 415 | |
---|
[ea90df23] | 416 | /* |
---|
| 417 | * Only process the command if we have a command and it is not |
---|
| 418 | * repeated in the history. |
---|
| 419 | */ |
---|
| 420 | if (strlen(line) == 0) { |
---|
| 421 | cmd = -1; |
---|
| 422 | } else { |
---|
| 423 | if ((cmd < 0) || (strcmp(line, cmds[cmd]) != 0)) { |
---|
| 424 | if (count > 1) |
---|
| 425 | memmove(cmds[1], cmds[0], (count - 1) * size); |
---|
| 426 | memmove (cmds[0], line, size); |
---|
| 427 | cmd = 0; |
---|
[22e98377] | 428 | } else { |
---|
| 429 | if ((cmd > 1) && (strcmp(line, cmds[cmd]) == 0)) { |
---|
| 430 | memmove(cmds[1], cmds[0], cmd * size); |
---|
| 431 | memmove (cmds[0], line, size); |
---|
| 432 | cmd = 0; |
---|
| 433 | } |
---|
[ea90df23] | 434 | } |
---|
| 435 | } |
---|
| 436 | } |
---|
| 437 | return cmd; |
---|
| 438 | |
---|
[22e98377] | 439 | case 16: /* Control-P */ |
---|
| 440 | if ((cmd >= (count - 1)) || (strlen(cmds[cmd + 1]) == 0)) { |
---|
| 441 | if (output) |
---|
| 442 | fputc('\x7', out); |
---|
| 443 | break; |
---|
| 444 | } |
---|
| 445 | |
---|
| 446 | up = 1; |
---|
| 447 | /* drop through */ |
---|
| 448 | |
---|
| 449 | case 14: /* Control-N */ |
---|
| 450 | { |
---|
| 451 | int last_cmd = cmd; |
---|
| 452 | int clen = strlen (line); |
---|
| 453 | |
---|
| 454 | if (prompt) |
---|
| 455 | clen += strlen(prompt); |
---|
| 456 | |
---|
| 457 | if (up) { |
---|
| 458 | cmd++; |
---|
| 459 | } else { |
---|
| 460 | if (cmd < 0) { |
---|
| 461 | if (output) |
---|
| 462 | fprintf(out, "\x7"); |
---|
| 463 | break; |
---|
| 464 | } |
---|
| 465 | else |
---|
| 466 | cmd--; |
---|
| 467 | } |
---|
| 468 | |
---|
| 469 | if ((last_cmd < 0) || (strcmp(cmds[last_cmd], line) != 0)) |
---|
| 470 | memcpy (new_line, line, size); |
---|
| 471 | |
---|
| 472 | if (cmd < 0) |
---|
| 473 | memcpy (line, new_line, size); |
---|
| 474 | else |
---|
| 475 | memcpy (line, cmds[cmd], size); |
---|
| 476 | |
---|
| 477 | col = strlen (line); |
---|
| 478 | |
---|
| 479 | if (output) { |
---|
| 480 | fprintf(out,"\r%s%*c", prompt, clen, ' '); |
---|
| 481 | fprintf(out,"\r%s%s", prompt, line); |
---|
| 482 | } |
---|
| 483 | } |
---|
| 484 | break; |
---|
| 485 | |
---|
| 486 | case 20: /* Control-T */ |
---|
| 487 | if (col > 0) |
---|
| 488 | { |
---|
| 489 | char tmp; |
---|
| 490 | if (col == strlen(line)) { |
---|
| 491 | col--; |
---|
| 492 | if (output) |
---|
| 493 | fprintf(out,"\b"); |
---|
| 494 | } |
---|
| 495 | tmp = line[col]; |
---|
| 496 | line[col] = line[col - 1]; |
---|
| 497 | line[col - 1] = tmp; |
---|
| 498 | if (output) |
---|
| 499 | fprintf(out,"\b%c%c", line[col - 1], line[col]); |
---|
| 500 | col++; |
---|
| 501 | } else { |
---|
| 502 | if (output) |
---|
| 503 | fputc('\x7', out); |
---|
| 504 | } |
---|
| 505 | break; |
---|
| 506 | |
---|
| 507 | case 21: /* Control-U */ |
---|
| 508 | if (col > 0) |
---|
| 509 | { |
---|
| 510 | int clen = strlen (line); |
---|
| 511 | |
---|
| 512 | strcpy (line, line + col); |
---|
| 513 | if (output) { |
---|
| 514 | fprintf(out,"\r%s%*c", prompt, clen, ' '); |
---|
| 515 | fprintf(out,"\r%s%s", prompt, line); |
---|
| 516 | } |
---|
| 517 | col = 0; |
---|
| 518 | } |
---|
| 519 | break; |
---|
| 520 | |
---|
[ea90df23] | 521 | default: |
---|
[7311863] | 522 | if ((col < (size - 1)) && (c >= ' ') && (c <= '~')) { |
---|
[ea90df23] | 523 | int end = strlen (line); |
---|
| 524 | if (inserting && (col < end) && (end < size)) { |
---|
| 525 | int ch, bs; |
---|
| 526 | for (ch = end + 1; ch > col; ch--) |
---|
| 527 | line[ch] = line[ch - 1]; |
---|
| 528 | if (output) { |
---|
[8bca4fc] | 529 | fprintf(out, "%s", line + col); |
---|
[ea90df23] | 530 | for (bs = 0; bs < (end - col + 1); bs++) |
---|
| 531 | fputc('\b', out); |
---|
| 532 | } |
---|
| 533 | } |
---|
| 534 | line[col++] = c; |
---|
| 535 | if (col > end) |
---|
| 536 | line[col] = '\0'; |
---|
| 537 | if (output) |
---|
| 538 | fputc(c, out); |
---|
| 539 | } |
---|
| 540 | break; |
---|
| 541 | } |
---|
| 542 | } |
---|
| 543 | } |
---|
| 544 | return -2; |
---|
| 545 | } |
---|
| 546 | |
---|
[fa028bb] | 547 | static bool rtems_shell_login(rtems_shell_env_t *env, FILE * in,FILE * out) |
---|
| 548 | { |
---|
[bb58190] | 549 | FILE *fd; |
---|
| 550 | int c; |
---|
| 551 | time_t t; |
---|
| 552 | |
---|
[6dd411aa] | 553 | if (out) { |
---|
[bb58190] | 554 | if ((env->devname[5]!='p')|| |
---|
| 555 | (env->devname[6]!='t')|| |
---|
| 556 | (env->devname[7]!='y')) { |
---|
[6dd411aa] | 557 | fd = fopen("/etc/issue","r"); |
---|
| 558 | if (fd) { |
---|
| 559 | while ((c=fgetc(fd))!=EOF) { |
---|
| 560 | if (c=='@') { |
---|
| 561 | switch(c=fgetc(fd)) { |
---|
| 562 | case 'L': |
---|
[bb58190] | 563 | fprintf(out,"%s", env->devname); |
---|
[6dd411aa] | 564 | break; |
---|
| 565 | case 'B': |
---|
| 566 | fprintf(out,"0"); |
---|
| 567 | break; |
---|
[70d689a] | 568 | case 'T': |
---|
[6dd411aa] | 569 | case 'D': |
---|
| 570 | time(&t); |
---|
| 571 | fprintf(out,"%s",ctime(&t)); |
---|
| 572 | break; |
---|
| 573 | case 'S': |
---|
| 574 | fprintf(out,"RTEMS"); |
---|
| 575 | break; |
---|
| 576 | case 'V': |
---|
[a3ddb08b] | 577 | fprintf(out,"%s\n%s",_RTEMS_version, _Copyright_Notice); |
---|
[6dd411aa] | 578 | break; |
---|
| 579 | case '@': |
---|
| 580 | fprintf(out,"@"); |
---|
| 581 | break; |
---|
| 582 | default : |
---|
| 583 | fprintf(out,"@%c",c); |
---|
| 584 | break; |
---|
| 585 | } |
---|
| 586 | } else if (c=='\\') { |
---|
| 587 | switch(c=fgetc(fd)) { |
---|
| 588 | case '\\': fprintf(out,"\\"); break; |
---|
| 589 | case 'b': fprintf(out,"\b"); break; |
---|
| 590 | case 'f': fprintf(out,"\f"); break; |
---|
| 591 | case 'n': fprintf(out,"\n"); break; |
---|
| 592 | case 'r': fprintf(out,"\r"); break; |
---|
| 593 | case 's': fprintf(out," "); break; |
---|
| 594 | case 't': fprintf(out,"\t"); break; |
---|
| 595 | case '@': fprintf(out,"@"); break; |
---|
| 596 | } |
---|
| 597 | } else { |
---|
| 598 | fputc(c,out); |
---|
| 599 | } |
---|
| 600 | } |
---|
| 601 | fclose(fd); |
---|
| 602 | } |
---|
| 603 | } else { |
---|
| 604 | fd = fopen("/etc/issue.net","r"); |
---|
| 605 | if (fd) { |
---|
| 606 | while ((c=fgetc(fd))!=EOF) { |
---|
| 607 | if (c=='%') { |
---|
| 608 | switch(c=fgetc(fd)) { |
---|
| 609 | case 't': |
---|
[bb58190] | 610 | fprintf(out,"%s", env->devname); |
---|
[6dd411aa] | 611 | break; |
---|
| 612 | case 'h': |
---|
| 613 | fprintf(out,"0"); |
---|
| 614 | break; |
---|
| 615 | case 'D': |
---|
| 616 | fprintf(out," "); |
---|
| 617 | break; |
---|
| 618 | case 'd': |
---|
| 619 | time(&t); |
---|
| 620 | fprintf(out,"%s",ctime(&t)); |
---|
| 621 | break; |
---|
| 622 | case 's': |
---|
| 623 | fprintf(out,"RTEMS"); |
---|
| 624 | break; |
---|
| 625 | case 'm': |
---|
| 626 | fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")"); |
---|
| 627 | break; |
---|
| 628 | case 'r': |
---|
| 629 | fprintf(out,_RTEMS_version); |
---|
| 630 | break; |
---|
| 631 | case 'v': |
---|
| 632 | fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice); |
---|
| 633 | break; |
---|
| 634 | case '%':fprintf(out,"%%"); |
---|
| 635 | break; |
---|
| 636 | default: |
---|
| 637 | fprintf(out,"%%%c",c); |
---|
| 638 | break; |
---|
| 639 | } |
---|
| 640 | } else { |
---|
| 641 | fputc(c,out); |
---|
| 642 | } |
---|
| 643 | } |
---|
| 644 | fclose(fd); |
---|
| 645 | } |
---|
| 646 | } |
---|
| 647 | } |
---|
| 648 | |
---|
[bb58190] | 649 | return rtems_shell_login_prompt(in, out, env->devname, env->login_check); |
---|
[b2712e3] | 650 | } |
---|
| 651 | |
---|
[814d9588] | 652 | #if defined(SHELL_DEBUG) |
---|
[2eeb648c] | 653 | void rtems_shell_print_env( |
---|
| 654 | rtems_shell_env_t * shell_env |
---|
[6dd411aa] | 655 | ) |
---|
| 656 | { |
---|
| 657 | if ( !shell_env ) { |
---|
| 658 | printk( "shell_env is NULL\n" ); |
---|
| 659 | return; |
---|
| 660 | } |
---|
| 661 | printk( "shell_env=%p\n" |
---|
| 662 | "shell_env->magic=0x%08x\t" |
---|
| 663 | "shell_env->devname=%s\n" |
---|
| 664 | "shell_env->taskname=%s\t" |
---|
| 665 | "shell_env->exit_shell=%d\t" |
---|
| 666 | "shell_env->forever=%d\n", |
---|
| 667 | shell_env->magic, |
---|
| 668 | shell_env->devname, |
---|
| 669 | ((shell_env->taskname) ? shell_env->taskname : "NOT SET"), |
---|
| 670 | shell_env->exit_shell, |
---|
| 671 | shell_env->forever |
---|
| 672 | ); |
---|
| 673 | } |
---|
| 674 | #endif |
---|
[dd74e612] | 675 | |
---|
[94547d1] | 676 | static rtems_task rtems_shell_task(rtems_task_argument task_argument) |
---|
[6dd411aa] | 677 | { |
---|
[1ff9922] | 678 | rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument; |
---|
| 679 | rtems_id wake_on_end = shell_env->wake_on_end; |
---|
| 680 | rtems_shell_main_loop( shell_env ); |
---|
| 681 | if (wake_on_end != RTEMS_INVALID_ID) |
---|
| 682 | rtems_event_send (wake_on_end, RTEMS_EVENT_1); |
---|
| 683 | rtems_task_delete( RTEMS_SELF ); |
---|
[6dd411aa] | 684 | } |
---|
[dd74e612] | 685 | |
---|
[fa028bb] | 686 | static bool rtems_shell_init_user_env(void) |
---|
| 687 | { |
---|
| 688 | rtems_status_code sc; |
---|
| 689 | |
---|
| 690 | /* Make sure we have a private user environment */ |
---|
| 691 | sc = rtems_libio_set_private_env(); |
---|
| 692 | if (sc != RTEMS_SUCCESSFUL) { |
---|
| 693 | rtems_error(sc, "rtems_libio_set_private_env():"); |
---|
| 694 | return false; |
---|
| 695 | } |
---|
| 696 | |
---|
| 697 | /* Make an effective root user */ |
---|
| 698 | seteuid(0); |
---|
| 699 | setegid(0); |
---|
| 700 | |
---|
| 701 | return chroot("/") == 0; |
---|
| 702 | } |
---|
| 703 | |
---|
[ea90df23] | 704 | #define RTEMS_SHELL_MAXIMUM_ARGUMENTS (128) |
---|
| 705 | #define RTEMS_SHELL_CMD_SIZE (128) |
---|
| 706 | #define RTEMS_SHELL_CMD_COUNT (32) |
---|
| 707 | #define RTEMS_SHELL_PROMPT_SIZE (128) |
---|
[aed742c] | 708 | |
---|
[1167235] | 709 | bool rtems_shell_main_loop( |
---|
[2eeb648c] | 710 | rtems_shell_env_t *shell_env_arg |
---|
[798ff5a] | 711 | ) |
---|
[6dd411aa] | 712 | { |
---|
[2eeb648c] | 713 | rtems_shell_env_t *shell_env; |
---|
[6cd4a5c] | 714 | int eno; |
---|
[6dd411aa] | 715 | struct termios term; |
---|
[8084ce80] | 716 | struct termios previous_term; |
---|
[ea90df23] | 717 | char *prompt = NULL; |
---|
| 718 | int cmd; |
---|
| 719 | int cmd_count = 1; /* assume a script and so only 1 command line */ |
---|
| 720 | char *cmds[RTEMS_SHELL_CMD_COUNT]; |
---|
[8c422e2] | 721 | char *cmd_argv; |
---|
[6dd411aa] | 722 | int argc; |
---|
[2eeb648c] | 723 | char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS]; |
---|
[1167235] | 724 | bool result = true; |
---|
[ff90595] | 725 | bool input_file = false; |
---|
[1ff9922] | 726 | int line = 0; |
---|
[a3ddb08b] | 727 | FILE *stdinToClose = NULL; |
---|
| 728 | FILE *stdoutToClose = NULL; |
---|
[2eeb648c] | 729 | |
---|
[89fd08e] | 730 | rtems_shell_init_environment(); |
---|
[7840b66] | 731 | |
---|
[6cd4a5c] | 732 | shell_env = rtems_shell_init_env(shell_env_arg); |
---|
| 733 | if (shell_env == NULL) { |
---|
| 734 | rtems_error(0, "rtems_shell_init_env"); |
---|
| 735 | return false; |
---|
| 736 | } |
---|
| 737 | |
---|
| 738 | eno = pthread_setspecific(rtems_shell_current_env_key, shell_env); |
---|
| 739 | if (eno != 0) { |
---|
| 740 | rtems_error(0, "pthread_setspecific(shell_current_env_key)"); |
---|
[1167235] | 741 | return false; |
---|
[814d9588] | 742 | } |
---|
[dd74e612] | 743 | |
---|
[fa028bb] | 744 | if (!rtems_shell_init_user_env()) { |
---|
| 745 | rtems_error(0, "rtems_shell_init_user_env"); |
---|
| 746 | return false; |
---|
| 747 | } |
---|
[6dd411aa] | 748 | |
---|
[1ff9922] | 749 | fileno(stdout); |
---|
| 750 | |
---|
[8a775c27] | 751 | /* fprintf( stderr, |
---|
[a3ddb08b] | 752 | "-%s-%s-\n", shell_env->input, shell_env->output ); |
---|
[ea90df23] | 753 | */ |
---|
[be8ab6a] | 754 | |
---|
| 755 | if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) { |
---|
[1ff9922] | 756 | if (strcmp(shell_env->output, "stderr") == 0) { |
---|
| 757 | stdout = stderr; |
---|
| 758 | } else if (strcmp(shell_env->output, "/dev/null") == 0) { |
---|
| 759 | fclose (stdout); |
---|
| 760 | } else { |
---|
| 761 | FILE *output = fopen(shell_env_arg->output, |
---|
| 762 | shell_env_arg->output_append ? "a" : "w"); |
---|
| 763 | if (!output) { |
---|
| 764 | fprintf(stderr, "shell: open output %s failed: %s\n", |
---|
| 765 | shell_env_arg->output, strerror(errno)); |
---|
[1167235] | 766 | return false; |
---|
[1ff9922] | 767 | } |
---|
| 768 | stdout = output; |
---|
[a3ddb08b] | 769 | stdoutToClose = output; |
---|
[1ff9922] | 770 | } |
---|
| 771 | } |
---|
[8a775c27] | 772 | |
---|
[be8ab6a] | 773 | if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) { |
---|
[1ff9922] | 774 | FILE *input = fopen(shell_env_arg->input, "r"); |
---|
| 775 | if (!input) { |
---|
| 776 | fprintf(stderr, "shell: open input %s failed: %s\n", |
---|
| 777 | shell_env_arg->input, strerror(errno)); |
---|
[1167235] | 778 | return false; |
---|
[1ff9922] | 779 | } |
---|
| 780 | stdin = input; |
---|
[a3ddb08b] | 781 | stdinToClose = input; |
---|
[1167235] | 782 | shell_env->forever = false; |
---|
| 783 | input_file =true; |
---|
[1ff9922] | 784 | } |
---|
| 785 | else { |
---|
| 786 | /* make a raw terminal,Linux Manuals */ |
---|
[8084ce80] | 787 | if (tcgetattr(fileno(stdin), &previous_term) >= 0) { |
---|
| 788 | term = previous_term; |
---|
[1ff9922] | 789 | term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); |
---|
| 790 | term.c_oflag &= ~OPOST; |
---|
| 791 | term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */ |
---|
| 792 | term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); |
---|
| 793 | term.c_cflag |= CLOCAL | CREAD; |
---|
| 794 | term.c_cc[VMIN] = 1; |
---|
| 795 | term.c_cc[VTIME] = 0; |
---|
| 796 | if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) { |
---|
| 797 | fprintf(stderr, |
---|
| 798 | "shell:cannot set terminal attributes(%s)\n",shell_env->devname); |
---|
| 799 | } |
---|
[814d9588] | 800 | } |
---|
[ea90df23] | 801 | cmd_count = RTEMS_SHELL_CMD_COUNT; |
---|
| 802 | prompt = malloc(RTEMS_SHELL_PROMPT_SIZE); |
---|
| 803 | if (!prompt) |
---|
| 804 | fprintf(stderr, |
---|
| 805 | "shell:cannot allocate prompt memory\n"); |
---|
[6dd411aa] | 806 | } |
---|
| 807 | |
---|
[1ff9922] | 808 | setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/ |
---|
| 809 | setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/ |
---|
| 810 | |
---|
[ea90df23] | 811 | /* |
---|
| 812 | * Allocate the command line buffers. |
---|
| 813 | */ |
---|
[8c422e2] | 814 | cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE); |
---|
| 815 | if (!cmd_argv) { |
---|
| 816 | fprintf(stderr, "no memory for command line buffers\n" ); |
---|
| 817 | } |
---|
[8a775c27] | 818 | |
---|
[ea90df23] | 819 | cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE); |
---|
| 820 | if (!cmds[0]) { |
---|
| 821 | fprintf(stderr, "no memory for command line buffers\n" ); |
---|
| 822 | } |
---|
[8c422e2] | 823 | |
---|
| 824 | if (cmd_argv && cmds[0]) { |
---|
[ea90df23] | 825 | |
---|
| 826 | memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); |
---|
| 827 | |
---|
| 828 | for (cmd = 1; cmd < cmd_count; cmd++) { |
---|
| 829 | cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE; |
---|
[6dd411aa] | 830 | } |
---|
[8a775c27] | 831 | |
---|
[ea90df23] | 832 | do { |
---|
[fa028bb] | 833 | result = rtems_shell_init_user_env(); |
---|
| 834 | |
---|
| 835 | if (result) { |
---|
| 836 | /* |
---|
| 837 | * By using result here, we can fall to the bottom of the |
---|
| 838 | * loop when the connection is dropped during login and |
---|
| 839 | * keep on trucking. |
---|
| 840 | */ |
---|
| 841 | if (shell_env->login_check != NULL) { |
---|
| 842 | result = rtems_shell_login(shell_env, stdin,stdout); |
---|
| 843 | } else { |
---|
[ffd5285] | 844 | setuid(shell_env->uid); |
---|
| 845 | setgid(shell_env->gid); |
---|
| 846 | seteuid(shell_env->uid); |
---|
| 847 | setegid(shell_env->gid); |
---|
| 848 | rtems_current_user_env_getgroups(); |
---|
| 849 | |
---|
[fa028bb] | 850 | result = true; |
---|
| 851 | } |
---|
[7c4cdeb9] | 852 | } |
---|
| 853 | |
---|
| 854 | if (result) { |
---|
[ea90df23] | 855 | const char *c; |
---|
| 856 | memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); |
---|
[1ff9922] | 857 | if (!input_file) { |
---|
[ea90df23] | 858 | rtems_shell_cat_file(stdout,"/etc/motd"); |
---|
| 859 | fprintf(stdout, "\n" |
---|
[a2097c5] | 860 | "RTEMS Shell on %s. Use 'help' to list commands.\n", |
---|
[ea90df23] | 861 | shell_env->devname); |
---|
[1ff9922] | 862 | } |
---|
[55c64fc9] | 863 | |
---|
| 864 | if (input_file) |
---|
| 865 | chdir(shell_env->cwd); |
---|
| 866 | else |
---|
| 867 | chdir("/"); /* XXX: chdir to getpwent homedir */ |
---|
[8a775c27] | 868 | |
---|
[1167235] | 869 | shell_env->exit_shell = false; |
---|
[ea90df23] | 870 | |
---|
| 871 | for (;;) { |
---|
| 872 | int cmd; |
---|
[8a775c27] | 873 | |
---|
[ea90df23] | 874 | /* Prompt section */ |
---|
| 875 | if (prompt) { |
---|
| 876 | rtems_shell_get_prompt(shell_env, prompt, |
---|
| 877 | RTEMS_SHELL_PROMPT_SIZE); |
---|
| 878 | } |
---|
[8a775c27] | 879 | |
---|
[ea90df23] | 880 | /* getcmd section */ |
---|
| 881 | cmd = rtems_shell_line_editor(cmds, cmd_count, |
---|
| 882 | RTEMS_SHELL_CMD_SIZE, prompt, |
---|
| 883 | stdin, stdout); |
---|
| 884 | |
---|
| 885 | if (cmd == -1) |
---|
| 886 | continue; /* empty line */ |
---|
[8a775c27] | 887 | |
---|
[ea90df23] | 888 | if (cmd == -2) |
---|
| 889 | break; /*EOF*/ |
---|
| 890 | |
---|
| 891 | line++; |
---|
| 892 | |
---|
[55c64fc9] | 893 | if (shell_env->echo) |
---|
| 894 | fprintf(stdout, "%d: %s\n", line, cmds[cmd]); |
---|
[8a775c27] | 895 | |
---|
[ea90df23] | 896 | /* evaluate cmd section */ |
---|
| 897 | c = cmds[cmd]; |
---|
| 898 | while (*c) { |
---|
[bab5c5fa] | 899 | if (!isblank((unsigned char)*c)) |
---|
[ea90df23] | 900 | break; |
---|
| 901 | c++; |
---|
| 902 | } |
---|
[1ff9922] | 903 | |
---|
[ea90df23] | 904 | if (*c == '\0') /* empty line */ |
---|
| 905 | continue; |
---|
[a5de1ef] | 906 | |
---|
[ea90df23] | 907 | if (*c == '#') { /* comment character */ |
---|
| 908 | cmds[cmd][0] = 0; |
---|
| 909 | continue; |
---|
| 910 | } |
---|
[1ff9922] | 911 | |
---|
[ea90df23] | 912 | if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) { |
---|
| 913 | fprintf(stdout, "Shell exiting\n" ); |
---|
| 914 | break; |
---|
| 915 | } |
---|
[6dd411aa] | 916 | |
---|
[ea90df23] | 917 | /* exec cmd section */ |
---|
| 918 | /* TODO: |
---|
| 919 | * To avoid user crash catch the signals. |
---|
| 920 | * Open a new stdio files with posibility of redirection * |
---|
| 921 | * Run in a new shell task background. (unix &) |
---|
| 922 | * Resuming. A little bash. |
---|
| 923 | */ |
---|
[8c422e2] | 924 | memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE); |
---|
| 925 | if (!rtems_shell_make_args(cmd_argv, &argc, argv, |
---|
[ea90df23] | 926 | RTEMS_SHELL_MAXIMUM_ARGUMENTS)) { |
---|
[5c141d6a] | 927 | shell_env->errorlevel = rtems_shell_execute_cmd(argv[0], argc, argv); |
---|
[6dd411aa] | 928 | } |
---|
[ea90df23] | 929 | |
---|
| 930 | /* end exec cmd section */ |
---|
| 931 | if (shell_env->exit_shell) |
---|
| 932 | break; |
---|
[6dd411aa] | 933 | } |
---|
| 934 | |
---|
[ea90df23] | 935 | fflush( stdout ); |
---|
| 936 | fflush( stderr ); |
---|
[6dd411aa] | 937 | } |
---|
[ea90df23] | 938 | } while (result && shell_env->forever); |
---|
| 939 | |
---|
| 940 | } |
---|
| 941 | |
---|
[8c422e2] | 942 | if (cmds[0]) |
---|
| 943 | free (cmds[0]); |
---|
| 944 | if (cmd_argv) |
---|
| 945 | free (cmd_argv); |
---|
[798ff5a] | 946 | if (prompt) |
---|
| 947 | free (prompt); |
---|
| 948 | |
---|
[8084ce80] | 949 | if (stdinToClose) { |
---|
[a3ddb08b] | 950 | fclose( stdinToClose ); |
---|
[8084ce80] | 951 | } else { |
---|
[798ff5a] | 952 | if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) { |
---|
[8084ce80] | 953 | fprintf( |
---|
| 954 | stderr, |
---|
| 955 | "shell: cannot reset terminal attributes (%s)\n", |
---|
| 956 | shell_env->devname |
---|
| 957 | ); |
---|
| 958 | } |
---|
| 959 | } |
---|
[a3ddb08b] | 960 | if ( stdoutToClose ) |
---|
| 961 | fclose( stdoutToClose ); |
---|
[1ff9922] | 962 | return result; |
---|
[dd74e612] | 963 | } |
---|
[6dd411aa] | 964 | |
---|
[dd74e612] | 965 | /* ----------------------------------------------- */ |
---|
[cbd1e87] | 966 | static rtems_status_code rtems_shell_run ( |
---|
| 967 | const char *task_name, |
---|
| 968 | size_t task_stacksize, |
---|
| 969 | rtems_task_priority task_priority, |
---|
| 970 | const char *devname, |
---|
| 971 | bool forever, |
---|
| 972 | bool wait, |
---|
| 973 | const char *input, |
---|
| 974 | const char *output, |
---|
| 975 | bool output_append, |
---|
| 976 | rtems_id wake_on_end, |
---|
| 977 | bool echo, |
---|
| 978 | rtems_shell_login_check_t login_check |
---|
[6dd411aa] | 979 | ) |
---|
| 980 | { |
---|
| 981 | rtems_id task_id; |
---|
| 982 | rtems_status_code sc; |
---|
[2eeb648c] | 983 | rtems_shell_env_t *shell_env; |
---|
[4e5299f] | 984 | rtems_name name; |
---|
| 985 | |
---|
[e41eaa88] | 986 | if ( task_name && strlen(task_name) >= 4) |
---|
[814d9588] | 987 | name = rtems_build_name( |
---|
| 988 | task_name[0], task_name[1], task_name[2], task_name[3]); |
---|
[4e5299f] | 989 | else |
---|
| 990 | name = rtems_build_name( 'S', 'E', 'N', 'V' ); |
---|
[6dd411aa] | 991 | |
---|
| 992 | sc = rtems_task_create( |
---|
[4e5299f] | 993 | name, |
---|
[6dd411aa] | 994 | task_priority, |
---|
[4e5299f] | 995 | task_stacksize, |
---|
[3899a537] | 996 | RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR, |
---|
[6dd411aa] | 997 | RTEMS_LOCAL | RTEMS_FLOATING_POINT, |
---|
| 998 | &task_id |
---|
| 999 | ); |
---|
| 1000 | if (sc != RTEMS_SUCCESSFUL) { |
---|
| 1001 | rtems_error(sc,"creating task %s in shell_init()",task_name); |
---|
| 1002 | return sc; |
---|
| 1003 | } |
---|
| 1004 | |
---|
[2eeb648c] | 1005 | shell_env = rtems_shell_init_env( NULL ); |
---|
[6dd411aa] | 1006 | if ( !shell_env ) { |
---|
[1ff9922] | 1007 | rtems_error(RTEMS_NO_MEMORY, |
---|
| 1008 | "allocating shell_env %s in shell_init()",task_name); |
---|
[6dd411aa] | 1009 | return RTEMS_NO_MEMORY; |
---|
| 1010 | } |
---|
[1ff9922] | 1011 | shell_env->devname = devname; |
---|
| 1012 | shell_env->taskname = task_name; |
---|
[1167235] | 1013 | shell_env->exit_shell = false; |
---|
[1ff9922] | 1014 | shell_env->forever = forever; |
---|
[55c64fc9] | 1015 | shell_env->echo = echo; |
---|
[1ff9922] | 1016 | shell_env->input = strdup (input); |
---|
| 1017 | shell_env->output = strdup (output); |
---|
| 1018 | shell_env->output_append = output_append; |
---|
| 1019 | shell_env->wake_on_end = wake_on_end; |
---|
[8a775c27] | 1020 | shell_env->login_check = login_check; |
---|
[ffd5285] | 1021 | shell_env->uid = getuid(); |
---|
| 1022 | shell_env->gid = getgid(); |
---|
[6dd411aa] | 1023 | |
---|
[55c64fc9] | 1024 | getcwd(shell_env->cwd, sizeof(shell_env->cwd)); |
---|
| 1025 | |
---|
[798ff5a] | 1026 | sc = rtems_task_start(task_id, rtems_shell_task, |
---|
[2eeb648c] | 1027 | (rtems_task_argument) shell_env); |
---|
[798ff5a] | 1028 | if (sc != RTEMS_SUCCESSFUL) { |
---|
| 1029 | rtems_error(sc,"starting task %s in shell_init()",task_name); |
---|
| 1030 | return sc; |
---|
| 1031 | } |
---|
| 1032 | |
---|
| 1033 | if (wait) { |
---|
| 1034 | rtems_event_set out; |
---|
| 1035 | sc = rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT, 0, &out); |
---|
| 1036 | } |
---|
| 1037 | |
---|
| 1038 | return 0; |
---|
[6dd411aa] | 1039 | } |
---|
[1ff9922] | 1040 | |
---|
[798ff5a] | 1041 | rtems_status_code rtems_shell_init( |
---|
[cbd1e87] | 1042 | const char *task_name, |
---|
| 1043 | size_t task_stacksize, |
---|
| 1044 | rtems_task_priority task_priority, |
---|
| 1045 | const char *devname, |
---|
| 1046 | bool forever, |
---|
| 1047 | bool wait, |
---|
| 1048 | rtems_shell_login_check_t login_check |
---|
[1ff9922] | 1049 | ) |
---|
| 1050 | { |
---|
[06f8e558] | 1051 | rtems_id to_wake = RTEMS_ID_NONE; |
---|
[798ff5a] | 1052 | |
---|
| 1053 | if ( wait ) |
---|
| 1054 | to_wake = rtems_task_self(); |
---|
| 1055 | |
---|
| 1056 | return rtems_shell_run( |
---|
| 1057 | task_name, /* task_name */ |
---|
| 1058 | task_stacksize, /* task_stacksize */ |
---|
| 1059 | task_priority, /* task_priority */ |
---|
| 1060 | devname, /* devname */ |
---|
| 1061 | forever, /* forever */ |
---|
| 1062 | wait, /* wait */ |
---|
| 1063 | "stdin", /* input */ |
---|
| 1064 | "stdout", /* output */ |
---|
[06f8e558] | 1065 | false, /* output_append */ |
---|
[798ff5a] | 1066 | to_wake, /* wake_on_end */ |
---|
[06f8e558] | 1067 | false, /* echo */ |
---|
[8a775c27] | 1068 | login_check /* login check */ |
---|
[798ff5a] | 1069 | ); |
---|
[1ff9922] | 1070 | } |
---|
| 1071 | |
---|
| 1072 | rtems_status_code rtems_shell_script ( |
---|
[e41eaa88] | 1073 | const char *task_name, |
---|
[06f8e558] | 1074 | size_t task_stacksize, |
---|
[1ff9922] | 1075 | rtems_task_priority task_priority, |
---|
| 1076 | const char* input, |
---|
| 1077 | const char* output, |
---|
[06f8e558] | 1078 | bool output_append, |
---|
| 1079 | bool wait, |
---|
| 1080 | bool echo |
---|
[1ff9922] | 1081 | ) |
---|
| 1082 | { |
---|
| 1083 | rtems_id current_task = RTEMS_INVALID_ID; |
---|
| 1084 | rtems_status_code sc; |
---|
| 1085 | |
---|
| 1086 | if (wait) { |
---|
| 1087 | sc = rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, ¤t_task); |
---|
| 1088 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 1089 | return sc; |
---|
| 1090 | } |
---|
[8a775c27] | 1091 | |
---|
[798ff5a] | 1092 | sc = rtems_shell_run( |
---|
| 1093 | task_name, /* task_name */ |
---|
| 1094 | task_stacksize, /* task_stacksize */ |
---|
| 1095 | task_priority, /* task_priority */ |
---|
| 1096 | NULL, /* devname */ |
---|
| 1097 | 0, /* forever */ |
---|
| 1098 | wait, /* wait */ |
---|
| 1099 | input, /* input */ |
---|
| 1100 | output, /* output */ |
---|
| 1101 | output_append, /* output_append */ |
---|
| 1102 | current_task, /* wake_on_end */ |
---|
[06f8e558] | 1103 | echo, /* echo */ |
---|
[8a775c27] | 1104 | NULL /* login check */ |
---|
[798ff5a] | 1105 | ); |
---|
[1ff9922] | 1106 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 1107 | return sc; |
---|
| 1108 | |
---|
| 1109 | return sc; |
---|
| 1110 | } |
---|