/* * Copyright (c) 2010 Jiri Svoboda * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file HelenOS-specific code. */ #include <assert.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <str.h> #include <task.h> #include <tinput.h> #include <str_error.h> #include "os.h" /** Path to executable file via which we have been invoked. */ static char *ef_path; /* * Using HelenOS-specific string API. */ static tinput_t *tinput = NULL; /** Concatenate two strings. * * @param a First string * @param b Second string * @return New string, concatenation of @a a and @a b. */ char *os_str_acat(const char *a, const char *b) { int a_size, b_size; char *str; a_size = str_size(a); b_size = str_size(b); str = malloc(a_size + b_size + 1); if (str == NULL) { printf("Memory allocation error.\n"); exit(1); } memcpy(str, a, a_size); memcpy(str + a_size, b, b_size); str[a_size + b_size] = '\0'; return str; } /** Return slice (substring) of a string. * * Copies the specified range of characters from @a str and returns it * as a newly allocated string. @a start + @a length must be less than * or equal to the length of @a str. * * @param str String * @param start Index of first character (starting from zero). * @param length Number of characters to copy. * * @return Newly allocated string holding the slice. */ char *os_str_aslice(const char *str, size_t start, size_t length) { char *slice; size_t offset; size_t i; size_t size; char32_t c; assert(start + length <= str_length(str)); offset = 0; for (i = 0; i < start; ++i) { c = str_decode(str, &offset, STR_NO_LIMIT); assert(c != '\0'); assert(c != U_SPECIAL); (void) c; } size = str_lsize(str, length); slice = str_ndup(str + offset, size); return slice; } /** Compare two strings. * * @param a First string * @param b Second string * @return Zero if equal, nonzero if not equal */ int os_str_cmp(const char *a, const char *b) { return str_cmp(a, b); } /** Return number of characters in string. * * @param str String * @return Number of characters in @a str. */ size_t os_str_length(const char *str) { return str_length(str); } /** Duplicate string. * * @param str String * @return New string, duplicate of @a str. */ char *os_str_dup(const char *str) { return str_dup(str); } /** Get character from string at the given index. * * @param str String * @param index Character index (starting from zero). * @param out_char Place to store character. * @return EOK on success, EINVAL if index is out of bounds, * EIO on decoding error. */ errno_t os_str_get_char(const char *str, int index, int *out_char) { size_t offset; int i; char32_t c = 0; if (index < 0) return EINVAL; offset = 0; for (i = 0; i <= index; ++i) { c = str_decode(str, &offset, STR_NO_LIMIT); if (c == '\0') return EINVAL; if (c == U_SPECIAL) return EIO; } *out_char = (int) c; return EOK; } /** Convert character to new string. * * @param chr Character * @return Newly allocated string. */ char *os_chr_to_astr(char32_t chr) { char *str; size_t offset; str = malloc(STR_BOUNDS(1) + 1); if (str == NULL) { printf("Memory allocation error.\n"); exit(1); } offset = 0; if (chr_encode(chr, str, &offset, STR_BOUNDS(1)) != EOK) { /* XXX Should handle gracefully */ printf("String conversion error.\n"); exit(1); } str[offset] = '\0'; return str; } /** Display survival help message. */ void os_input_disp_help(void) { printf("Press Ctrl-Q to quit.\n"); } /** Read one line of input from the user. * * @param ptr Place to store pointer to new string. */ errno_t os_input_line(const char *prompt, char **ptr) { char *line; errno_t rc; if (tinput == NULL) { tinput = tinput_new(); if (tinput == NULL) return EIO; tinput_set_prompt(tinput, prompt); } rc = tinput_read(tinput, &line); if (rc == ENOENT) { /* User-requested abort */ *ptr = os_str_dup(""); return EOK; } if (rc != EOK) { /* Error in communication with console */ return EIO; } /* XXX Input module needs trailing newline to keep going. */ *ptr = os_str_acat(line, "\n"); free(line); return EOK; } /** Simple command execution. * * @param cmd Command and arguments (NULL-terminated list of strings.) * Command is present just one, not duplicated. */ errno_t os_exec(char *const cmd[]) { task_id_t tid; task_wait_t twait; task_exit_t texit; errno_t rc; int retval; rc = task_spawnv(&tid, &twait, cmd[0], (char const *const *) cmd); if (rc != EOK) { printf("Error: Failed spawning '%s' (%s).\n", cmd[0], str_error(rc)); exit(1); } /* XXX Handle exit status and return value. */ rc = task_wait(&twait, &texit, &retval); (void) rc; return EOK; } /** Store the executable file path via which we were executed. * * @param path Executable path via which we were executed. */ void os_store_ef_path(char *path) { ef_path = path; } /** Return path to the Sysel library * * @return New string. Caller should deallocate it using @c free(). */ char *os_get_lib_path(void) { return os_str_dup("/src/sysel/lib"); }