1/** 2 * \file 3 * \brief SKB library functions 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <stddef.h> 17#include <string.h> 18#include <stdarg.h> 19 20#include <barrelfish/barrelfish.h> 21#include <skb/skb.h> 22#include <if/skb_defs.h> 23#include <barrelfish/core_state_arch.h> 24#include "skb_internal.h" 25 26#define BUFFER_SIZE skb__run_call_input_MAX_ARGUMENT_SIZE 27#define OUTPUT_SIZE skb__run_response_output_MAX_ARGUMENT_SIZE 28 29/* XXX: The following static chars make the skb connection not thread 30 safe and we probably don't want to put them in the per dispatcher 31 corestate as they are so big. */ 32static char buffer[skb__run_call_input_MAX_ARGUMENT_SIZE + 1]; 33static char output[skb__run_response_output_MAX_ARGUMENT_SIZE + 1]; 34static char error_output[skb__run_response_str_error_MAX_ARGUMENT_SIZE + 1]; 35static char *last_goal; 36static int error_code; 37 38int skb_read_error_code(void) 39{ 40 return error_code; 41} 42 43char *skb_get_output(void) 44{ 45 return (output); 46} 47 48char *skb_get_error_output(void) 49{ 50 return (error_output); 51} 52 53char *skb_get_last_goal(void) 54{ 55 return last_goal; 56} 57 58errval_t skb_execute(char *goal) 59{ 60 errval_t err; 61 struct skb_state *skb_state = get_skb_state(); 62 63 last_goal = goal; 64 err = skb_state->skb->rpc_tx_vtbl.run(skb_state->skb, goal, output, 65 error_output, &error_code); 66 if (err_is_fail(err)) { 67 return err_push(err, SKB_ERR_RUN); 68 } 69 70 if (error_code != 0) { 71 return err_push(err, SKB_ERR_EXECUTION); 72 } 73 74 return err; 75} 76 77errval_t skb_add_fact(char *fmt, ...) 78{ 79 errval_t err; 80 va_list va_l; 81 va_start(va_l, fmt); 82 int len = skb_vsnprintf(buffer, BUFFER_SIZE, fmt, va_l); 83 va_end(va_l); 84 85 if (len >= BUFFER_SIZE) { 86 err = SKB_ERR_OVERFLOW; 87 goto out; 88 } 89 90 if (len > 0 && buffer[len - 1] == '.') { 91 len--; 92 } 93 94 SKB_DEBUG("skb_add_fact(): %s\n", buffer); 95 int assert_len = snprintf(buffer + len, BUFFER_SIZE - len, 96 "assert(%.*s).", len, buffer); 97 if (assert_len >= BUFFER_SIZE - len) { 98 err = SKB_ERR_OVERFLOW; 99 goto out; 100 } 101 102 err = skb_execute(buffer + len); 103 104out: 105 return err; 106} 107 108errval_t skb_execute_query(char *fmt, ...) 109{ 110 va_list va_l; 111 va_start(va_l, fmt); 112 int len = skb_vsnprintf(buffer, BUFFER_SIZE, fmt, va_l); 113 va_end(va_l); 114 115#if 0 116 va_start(va_l, fmt); 117 char* buffer2 = malloc(BUFFER_SIZE+1); 118 len = vsnprintf(buffer2, BUFFER_SIZE, fmt, va_l); 119 va_end(va_l); 120 if (strcmp(buffer, buffer2) != 0) { 121 printf("%s:%s:%d: fmt = %s\n", __FILE__, __FUNCTION__, __LINE__, fmt); 122 printf("%s:%s:%d: skb_vsnprintf: %s\n", __FILE__, __FUNCTION__, __LINE__, buffer); 123 printf("%s:%s:%d: vsnprintf: %s\n", __FILE__, __FUNCTION__, __LINE__, buffer2); 124 USER_PANIC("skb_vsnprintf doesn't quite work!"); 125 } 126 free(buffer2); 127#endif 128 129 if (len >= BUFFER_SIZE) { 130 return SKB_ERR_OVERFLOW; 131 } 132 133 if (len > 0 && buffer[len - 1] == '.') { 134 buffer[len - 1] = '\0'; 135 } 136 137 return skb_execute(buffer); 138} 139 140static inline int count_expected_conversions(char *s, int len) 141{ 142 int expected_conversions = 0; 143 //count the number of single occurences of '%' to calculate the expected 144 //number of conversions made by sscanf 145 //if % is followed by % -> escapes % and hence not a conversion 146 //if % is followed by * -> ignore output hence not a conversion 147 for (int i = 0; i < len; i++) { 148 if ((s[i] == '%') && 149 ( 150 ((i + 1 < len) && (s[i + 1] != '%') && (s[i + 1] != '*')) || 151 (i + 1 >= len)) 152 ) { 153 expected_conversions++; 154 } 155 } 156 return (expected_conversions); 157} 158 159errval_t skb_vread_output_at(char *out, char *fmt, va_list va_l) 160{ 161 int expected_conversions = 0; 162 int nr_conversions; 163 int fmtlen = strlen(fmt); 164 expected_conversions = count_expected_conversions(fmt, fmtlen); 165 nr_conversions = skb_vsscanf(out, fmt, va_l); 166 if (nr_conversions != expected_conversions) { 167 printf("skb_vread_output_at(): Could not convert the SKB's result (expected conversions=%d, got instead=%d)\n", 168 expected_conversions, nr_conversions); 169 printf("SKB returned: %s\nSKB error: %s\n", skb_get_output(), skb_get_error_output()); 170 printf("%s:%s:%d: fmt = %s out = %s\n", __FILE__, __FUNCTION__, __LINE__, fmt, out); 171 return SKB_ERR_CONVERSION_ERROR; 172 } 173 return SYS_ERR_OK; 174} 175 176errval_t skb_read_output_at(char *out, char *fmt, ...) 177{ 178 errval_t r; 179 va_list va_l; 180 181 va_start(va_l, fmt); 182 r = skb_vread_output_at(out, fmt, va_l); 183 va_end(va_l); 184 185 return(r); 186} 187 188errval_t skb_read_output(char *fmt, ...) 189{ 190 errval_t r; 191 va_list va_l; 192 va_start(va_l, fmt); 193 r = skb_vread_output_at(skb_get_output(), fmt, va_l); 194 va_end(va_l); 195 return r; 196} 197 198 199void skb_read_list_init_offset(struct list_parser_status *status, char *s, 200 int offset) 201{ 202 status->s = s + offset; 203 status->conv_ptr = s; 204 status->len = strlen(s); 205 status->element_name[0] = 0; 206 status->expected_conversions = -1; 207} 208 209void skb_read_list_init(struct list_parser_status *status) 210{ 211 skb_read_list_init_offset(status, skb_get_output(), 0); 212} 213 214bool skb_read_list(struct list_parser_status *status, char *fmt, ...) 215{ 216 va_list va_l; 217 va_start(va_l, fmt); 218 219 int nr_conversions; 220 int lpar = 0; 221 int fmtlen = strlen(fmt); 222 if (status->element_name[0] == 0) { 223 for (lpar = 0; lpar < fmtlen; lpar++) { 224 if (fmt[lpar] == '(') { 225 break; 226 } 227 } 228 strncpy(status->element_name, fmt, 229 (lpar < ELEMENT_NAME_BUF_SIZE) ? lpar : ELEMENT_NAME_BUF_SIZE); 230 status->element_name[ 231 (lpar < ELEMENT_NAME_BUF_SIZE) ? lpar : ELEMENT_NAME_BUF_SIZE 232 ] = 0; 233 status->element_len = lpar; 234 } 235 if (status->expected_conversions == -1) { 236 status->expected_conversions = 237 count_expected_conversions(fmt, fmtlen); 238 } 239 240 //iterate over all buselements 241 while (status->conv_ptr < status->s + status->len) { 242 // search the beginning of the next buselement 243 while ((status->conv_ptr < status->s + status->len) && 244 (strncmp(status->conv_ptr, status->element_name, 245 status->element_len)) != 0) { 246 status->conv_ptr++; 247 } 248 //convert the string to single elements and numbers 249 nr_conversions = skb_vsscanf(status->conv_ptr, fmt, va_l); 250 va_end(va_l); 251 status->conv_ptr++; 252 if (nr_conversions != status->expected_conversions) { 253 return false; 254 } 255 return true; 256 } 257 return false; 258} 259