/* * 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 POSIX-specific code. */ #include <assert.h> #include <libgen.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <types/common.h> #include <sys/wait.h> #include <unistd.h> #include <errno.h> #include "../mytypes.h" #include "os.h" /** Path to executable file via which we have been invoked. */ static char *ef_path; /* * The string functions are in fact standard C, but would not work under * HelenOS. * * XXX String functions used here only work with 8-bit text encoding. */ /** 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_len, b_len; char *str; a_len = strlen(a); b_len = strlen(b); str = malloc(a_len + b_len + 1); if (str == NULL) { printf("Memory allocation error.\n"); exit(1); } memcpy(str, a, a_len); memcpy(str + a_len, b, b_len); str[a_len + b_len] = '\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; assert(start + length <= strlen(str)); slice = malloc(length + 1); if (slice == NULL) { printf("Memory allocation error.\n"); exit(1); } strncpy(slice, str + start, length); slice[length] = '\0'; return slice; } /** Compare two strings. * * @param a First string * @param b Second string * @return Zero if equal, nonzero if not equal */ errno_t os_str_cmp(const char *a, const char *b) { return strcmp(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 strlen(str); } /** Duplicate string. * * @param str String * @return New string, duplicate of @a str. */ char *os_str_dup(const char *str) { return strdup(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 len; len = strlen(str); if (index < 0 || (size_t) index >= len) return EINVAL; *out_char = str[index]; return EOK; } /** Convert character to new string. * * @param chr Character * @return Newly allocated string. */ char *os_chr_to_astr(char32_t chr) { char *str; str = malloc(2); if (str == NULL) { printf("Memory allocation error.\n"); exit(1); } str[0] = (char) chr; str[1] = '\0'; return str; } #define OS_INPUT_BUFFER_SIZE 256 static char os_input_buffer[OS_INPUT_BUFFER_SIZE]; /** Display survival help message. */ void os_input_disp_help(void) { printf("Send ^C (SIGINT) 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) { printf("%s", prompt); if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL) os_input_buffer[0] = '\0'; if (ferror(stdin)) { *ptr = NULL; return EIO; } *ptr = strdup(os_input_buffer); 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[]) { pid_t pid; int status; pid = vfork(); if (pid == 0) { execvp(cmd[0], cmd); /* If we get here, exec failed. */ exit(1); } else if (pid == -1) { /* fork() failed */ return EBUSY; } if (waitpid(pid, &status, 0) == -1) { /* waitpid() failed */ printf("Error: Waitpid failed.\n"); exit(1); } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { printf("Error: Exec failed or child returned non-zero " "exit status.\n"); } 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_acat(dirname(ef_path), "/lib"); }