/branches/dd/uspace/lib/libc/generic/time.c |
---|
47,6 → 47,8 |
#include <as.h> |
#include <ddi.h> |
#include <time.h> |
/* Pointers to public variables with time */ |
struct { |
volatile sysarg_t seconds1; |
/branches/dd/uspace/lib/libc/generic/ddi.c |
---|
33,8 → 33,12 |
*/ |
#include <ddi.h> |
#include <libarch/ddi.h> |
#include <libc.h> |
#include <task.h> |
#include <as.h> |
#include <align.h> |
#include <libarch/config.h> |
#include <kernel/ddi/ddi_arg.h> |
/** Map piece of physical memory to task. |
41,18 → 45,20 |
* |
* Caller of this function must have the CAP_MEM_MANAGER capability. |
* |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the sterting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* @param pf Physical address of the starting frame. |
* @param vp Virtual address of the starting page. |
* @param pages Number of pages to map. |
* @param flags Flags for the new address space area. |
* |
* @return 0 on success, EPERM if the caller lacks the CAP_MEM_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in creating address space area. |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_MEM_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in creating address space area. |
*/ |
int physmem_map(void *pf, void *vp, unsigned long pages, int flags) |
{ |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, flags); |
return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, |
flags); |
} |
/** Enable I/O space range to task. |
59,13 → 65,14 |
* |
* Caller of this function must have the IO_MEM_MANAGER capability. |
* |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* @param id Task ID. |
* @param ioaddr Starting address of the I/O range. |
* @param size Size of the range. |
* |
* @return 0 on success, EPERM if the caller lacks the CAP_IO_MANAGER capability, |
* ENOENT if there is no task with specified ID and ENOMEM if there |
* was some problem in allocating memory. |
* @return 0 on success, EPERM if the caller lacks the |
* CAP_IO_MANAGER capability, ENOENT if there is no task |
* with specified ID and ENOMEM if there was some problem |
* in allocating memory. |
*/ |
int iospace_enable(task_id_t id, void *ioaddr, unsigned long size) |
{ |
80,7 → 87,7 |
/** Interrupt control |
* |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
* @param enable 1 - enable interrupts, 0 - disable interrupts |
*/ |
int preemption_control(int enable) |
{ |
87,5 → 94,36 |
return __SYSCALL1(SYS_PREEMPT_CONTROL, (sysarg_t) enable); |
} |
/** Enable PIO for specified I/O range. |
* |
* @param pio_addr I/O start address. |
* @param size Size of the I/O region. |
* @param use_addr Address where the final address for application's PIO |
* will be stored. |
* |
* @return Zero on success or negative error code. |
*/ |
int pio_enable(void *pio_addr, size_t size, void **use_addr) |
{ |
void *phys; |
void *virt; |
size_t offset; |
unsigned int pages; |
#ifdef IO_SPACE_BOUNDARY |
if (pio_addr < IO_SPACE_BOUNDARY) { |
*use_addr = pio_addr; |
return iospace_enable(task_get_id(), pio_addr, size); |
} |
#endif |
phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); |
offset = pio_addr - phys; |
pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH; |
virt = as_get_mappable_page(pages); |
*use_addr = virt + offset; |
return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/kbd.c |
---|
0,0 → 1,61 |
/* |
* Copyright (c) 2009 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <stdio.h> |
#include <io/stream.h> |
#include <kbd/kbd.h> |
#include <ipc/ipc.h> |
#include <ipc/console.h> |
#include <async.h> |
int kbd_get_event(kbd_event_t *ev) |
{ |
int console_phone = get_console_phone(); |
ipcarg_t r0, r1, r2, r3; |
int rc; |
rc = async_req_0_4(console_phone, CONSOLE_GETKEY, &r0, &r1, &r2, &r3); |
if (rc < 0) |
return -1; |
ev->type = r0; |
ev->key = r1; |
ev->mods = r2; |
ev->c = r3; |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/task.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
34,6 → 35,10 |
#include <task.h> |
#include <libc.h> |
#include <stdlib.h> |
#include <errno.h> |
#include <loader/loader.h> |
#include <string.h> |
task_id_t task_get_id(void) |
{ |
44,5 → 49,74 |
return task_id; |
} |
/** Set the task name. |
* |
* @param name The new name, typically the command used to execute the |
* program. |
* @return Zero on success or negative error code. |
*/ |
int task_set_name(const char *name) |
{ |
return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, strlen(name)); |
} |
/** Create a new task by running an executable from the filesystem. |
* |
* This is really just a convenience wrapper over the more complicated |
* loader API. |
* |
* @param path pathname of the binary to execute |
* @param argv command-line arguments |
* @return ID of the newly created task or zero on error. |
*/ |
task_id_t task_spawn(const char *path, char *const argv[]) |
{ |
loader_t *ldr; |
task_id_t task_id; |
int rc; |
/* Connect to a program loader. */ |
ldr = loader_connect(); |
if (ldr == NULL) |
return 0; |
/* Get task ID. */ |
rc = loader_get_task_id(ldr, &task_id); |
if (rc != EOK) |
goto error; |
/* Send program pathname. */ |
rc = loader_set_pathname(ldr, path); |
if (rc != EOK) |
goto error; |
/* Send arguments. */ |
rc = loader_set_args(ldr, argv); |
if (rc != EOK) |
goto error; |
/* Load the program. */ |
rc = loader_load_program(ldr); |
if (rc != EOK) |
goto error; |
/* Run it. */ |
rc = loader_run(ldr); |
if (rc != EOK) |
goto error; |
/* Success */ |
free(ldr); |
return task_id; |
/* Error exit */ |
error: |
loader_abort(ldr); |
free(ldr); |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/tls.c |
---|
116,7 → 116,7 |
tcb_t *tcb; |
size = ALIGN_UP(size, &_tls_alignment); |
*data = memalign(&_tls_alignment, sizeof(tcb_t) + size); |
*data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size); |
tcb = (tcb_t *) (*data + size); |
tcb->self = tcb; |
/branches/dd/uspace/lib/libc/generic/console.c |
---|
0,0 → 1,97 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <async.h> |
#include <io/stream.h> |
#include <ipc/console.h> |
#include <console.h> |
void console_clear(void) |
{ |
int cons_phone = get_console_phone(); |
async_msg_0(cons_phone, CONSOLE_CLEAR); |
} |
void console_goto(int row, int col) |
{ |
int cons_phone = get_console_phone(); |
async_msg_2(cons_phone, CONSOLE_GOTO, row, col); |
} |
void console_flush(void) |
{ |
int cons_phone = get_console_phone(); |
async_msg_0(cons_phone, CONSOLE_FLUSH); |
} |
int console_get_size(int *rows, int *cols) |
{ |
int cons_phone = get_console_phone(); |
ipcarg_t r, c; |
int rc; |
rc = async_req_0_2(cons_phone, CONSOLE_GETSIZE, &r, &c); |
*rows = (int) r; |
*cols = (int) c; |
return rc; |
} |
void console_set_style(int style) |
{ |
int cons_phone = get_console_phone(); |
async_msg_1(cons_phone, CONSOLE_SET_STYLE, style); |
} |
void console_set_color(int fg_color, int bg_color, int flags) |
{ |
int cons_phone = get_console_phone(); |
async_msg_3(cons_phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); |
} |
void console_set_rgb_color(int fg_color, int bg_color) |
{ |
int cons_phone = get_console_phone(); |
async_msg_2(cons_phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); |
} |
void console_cursor_visibility(int show) |
{ |
int cons_phone = get_console_phone(); |
async_msg_1(cons_phone, CONSOLE_CURSOR_VISIBILITY, show != 0); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/getopt.c |
---|
0,0 → 1,478 |
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */ |
/*- |
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
* All rights reserved. |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* by Dieter Baron and Thomas Klausner. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. 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. |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``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 FOUNDATION OR CONTRIBUTORS |
* 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. |
*/ |
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */ |
#include <assert.h> |
#include <stdarg.h> |
#include <err.h> |
#include <errno.h> |
#include <getopt.h> |
#include <stdlib.h> |
#include <string.h> |
/* HelenOS Port : We're incorporating only the modern getopt_long with wrappers |
* to keep legacy getopt() usage from breaking. All references to REPLACE_GETOPT |
* are dropped, we just include the code */ |
int opterr = 1; /* if error message should be printed */ |
int optind = 1; /* index into parent argv vector */ |
int optopt = '?'; /* character checked for validity */ |
int optreset; /* reset getopt */ |
char *optarg; /* argument associated with option */ |
#define IGNORE_FIRST (*options == '-' || *options == '+') |
#define PRINT_ERROR ((opterr) && ((*options != ':') \ |
|| (IGNORE_FIRST && options[1] != ':'))) |
/*HelenOS Port - POSIXLY_CORRECT is always false */ |
#define IS_POSIXLY_CORRECT 0 |
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) |
/* XXX: GNU ignores PC if *options == '-' */ |
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') |
/* return values */ |
#define BADCH (int)'?' |
#define BADARG ((IGNORE_FIRST && options[1] == ':') \ |
|| (*options == ':') ? (int)':' : (int)'?') |
#define INORDER (int)1 |
#define EMSG "" |
static int getopt_internal(int, char **, const char *); |
static int gcd(int, int); |
static void permute_args(int, int, int, char **); |
static const char *place = EMSG; /* option letter processing */ |
/* XXX: set optreset to 1 rather than these two */ |
static int nonopt_start = -1; /* first non option argument (for permute) */ |
static int nonopt_end = -1; /* first option after non options (for permute) */ |
/* Error messages */ |
/* HelenOS Port: Calls to warnx() were eliminated (as we have no stderr that |
* may be redirected) and replaced with printf. As such, error messages now |
* end in a newline */ |
static const char recargchar[] = "option requires an argument -- %c\n"; |
static const char recargstring[] = "option requires an argument -- %s\n"; |
static const char ambig[] = "ambiguous option -- %.*s\n"; |
static const char noarg[] = "option doesn't take an argument -- %.*s\n"; |
static const char illoptchar[] = "unknown option -- %c\n"; |
static const char illoptstring[] = "unknown option -- %s\n"; |
/* |
* Compute the greatest common divisor of a and b. |
*/ |
static int |
gcd(a, b) |
int a; |
int b; |
{ |
int c; |
c = a % b; |
while (c != 0) { |
a = b; |
b = c; |
c = a % b; |
} |
return b; |
} |
/* |
* Exchange the block from nonopt_start to nonopt_end with the block |
* from nonopt_end to opt_end (keeping the same order of arguments |
* in each block). |
*/ |
static void |
permute_args(panonopt_start, panonopt_end, opt_end, nargv) |
int panonopt_start; |
int panonopt_end; |
int opt_end; |
char **nargv; |
{ |
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
char *swap; |
assert(nargv != NULL); |
/* |
* compute lengths of blocks and number and size of cycles |
*/ |
nnonopts = panonopt_end - panonopt_start; |
nopts = opt_end - panonopt_end; |
ncycle = gcd(nnonopts, nopts); |
cyclelen = (opt_end - panonopt_start) / ncycle; |
for (i = 0; i < ncycle; i++) { |
cstart = panonopt_end+i; |
pos = cstart; |
for (j = 0; j < cyclelen; j++) { |
if (pos >= panonopt_end) |
pos -= nnonopts; |
else |
pos += nopts; |
swap = nargv[pos]; |
nargv[pos] = nargv[cstart]; |
nargv[cstart] = swap; |
} |
} |
} |
/* |
* getopt_internal -- |
* Parse argc/argv argument vector. Called by user level routines. |
* Returns -2 if -- is found (can be long option or end of options marker). |
*/ |
static int |
getopt_internal(nargc, nargv, options) |
int nargc; |
char **nargv; |
const char *options; |
{ |
char *oli; /* option letter list index */ |
int optchar; |
assert(nargv != NULL); |
assert(options != NULL); |
optarg = NULL; |
/* |
* XXX Some programs (like rsyncd) expect to be able to |
* XXX re-initialize optind to 0 and have getopt_long(3) |
* XXX properly function again. Work around this braindamage. |
*/ |
if (optind == 0) |
optind = 1; |
if (optreset) |
nonopt_start = nonopt_end = -1; |
start: |
if (optreset || !*place) { /* update scanning pointer */ |
optreset = 0; |
if (optind >= nargc) { /* end of argument vector */ |
place = EMSG; |
if (nonopt_end != -1) { |
/* do permutation, if we have to */ |
permute_args(nonopt_start, nonopt_end, |
optind, nargv); |
optind -= nonopt_end - nonopt_start; |
} |
else if (nonopt_start != -1) { |
/* |
* If we skipped non-options, set optind |
* to the first of them. |
*/ |
optind = nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((*(place = nargv[optind]) != '-') |
|| (place[1] == '\0')) { /* found non-option */ |
place = EMSG; |
if (IN_ORDER) { |
/* |
* GNU extension: |
* return non-option as argument to option 1 |
*/ |
optarg = nargv[optind++]; |
return INORDER; |
} |
if (!PERMUTE) { |
/* |
* if no permutation wanted, stop parsing |
* at first non-option |
*/ |
return -1; |
} |
/* do permutation */ |
if (nonopt_start == -1) |
nonopt_start = optind; |
else if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, |
optind, nargv); |
nonopt_start = optind - |
(nonopt_end - nonopt_start); |
nonopt_end = -1; |
} |
optind++; |
/* process next argument */ |
goto start; |
} |
if (nonopt_start != -1 && nonopt_end == -1) |
nonopt_end = optind; |
if (place[1] && *++place == '-') { /* found "--" */ |
place++; |
return -2; |
} |
} |
if ((optchar = (int)*place++) == (int)':' || |
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { |
/* option letter unknown or ':' */ |
if (!*place) |
++optind; |
if (PRINT_ERROR) |
printf(illoptchar, optchar); |
optopt = optchar; |
return BADCH; |
} |
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ |
/* XXX: what if no long options provided (called by getopt)? */ |
if (*place) |
return -2; |
if (++optind >= nargc) { /* no arg */ |
place = EMSG; |
if (PRINT_ERROR) |
printf(recargchar, optchar); |
optopt = optchar; |
return BADARG; |
} else /* white space */ |
place = nargv[optind]; |
/* |
* Handle -W arg the same as --arg (which causes getopt to |
* stop parsing). |
*/ |
return -2; |
} |
if (*++oli != ':') { /* doesn't take argument */ |
if (!*place) |
++optind; |
} else { /* takes (optional) argument */ |
optarg = NULL; |
if (*place) /* no white space */ |
optarg = *place; |
/* XXX: disable test for :: if PC? (GNU doesn't) */ |
else if (oli[1] != ':') { /* arg not optional */ |
if (++optind >= nargc) { /* no arg */ |
place = EMSG; |
if (PRINT_ERROR) |
printf(recargchar, optchar); |
optopt = optchar; |
return BADARG; |
} else |
optarg = nargv[optind]; |
} |
place = EMSG; |
++optind; |
} |
/* dump back option letter */ |
return optchar; |
} |
/* |
* getopt -- |
* Parse argc/argv argument vector. |
*/ |
int |
getopt(nargc, nargv, options) |
int nargc; |
char * const *nargv; |
const char *options; |
{ |
int retval; |
assert(nargv != NULL); |
assert(options != NULL); |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
++optind; |
/* |
* We found an option (--), so if we skipped non-options, |
* we have to permute. |
*/ |
if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, optind, |
(char **)nargv); |
optind -= nonopt_end - nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
retval = -1; |
} |
return retval; |
} |
/* |
* getopt_long -- |
* Parse argc/argv argument vector. |
*/ |
int |
getopt_long(nargc, nargv, options, long_options, idx) |
int nargc; |
char * const *nargv; |
const char *options; |
const struct option *long_options; |
int *idx; |
{ |
int retval; |
#define IDENTICAL_INTERPRETATION(_x, _y) \ |
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ |
long_options[(_x)].flag == long_options[(_y)].flag && \ |
long_options[(_x)].val == long_options[(_y)].val) |
assert(nargv != NULL); |
assert(options != NULL); |
assert(long_options != NULL); |
/* idx may be NULL */ |
retval = getopt_internal(nargc, (char **)nargv, options); |
if (retval == -2) { |
char *current_argv, *has_equal; |
size_t current_argv_len; |
int i, ambiguous, match; |
current_argv = (char *)place; |
match = -1; |
ambiguous = 0; |
optind++; |
place = EMSG; |
if (*current_argv == '\0') { /* found "--" */ |
/* |
* We found an option (--), so if we skipped |
* non-options, we have to permute. |
*/ |
if (nonopt_end != -1) { |
permute_args(nonopt_start, nonopt_end, |
optind, (char **)nargv); |
optind -= nonopt_end - nonopt_start; |
} |
nonopt_start = nonopt_end = -1; |
return -1; |
} |
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
/* argument found (--option=arg) */ |
current_argv_len = has_equal - current_argv; |
has_equal++; |
} else |
current_argv_len = strlen(current_argv); |
for (i = 0; long_options[i].name; i++) { |
/* find matching long option */ |
if (strncmp(current_argv, long_options[i].name, |
current_argv_len)) |
continue; |
if (strlen(long_options[i].name) == |
(unsigned)current_argv_len) { |
/* exact match */ |
match = i; |
ambiguous = 0; |
break; |
} |
if (match == -1) /* partial match */ |
match = i; |
else if (!IDENTICAL_INTERPRETATION(i, match)) |
ambiguous = 1; |
} |
if (ambiguous) { |
/* ambiguous abbreviation */ |
if (PRINT_ERROR) |
printf(ambig, (int)current_argv_len, |
current_argv); |
optopt = 0; |
return BADCH; |
} |
if (match != -1) { /* option found */ |
if (long_options[match].has_arg == no_argument |
&& has_equal) { |
if (PRINT_ERROR) |
printf(noarg, (int)current_argv_len, |
current_argv); |
/* |
* XXX: GNU sets optopt to val regardless of |
* flag |
*/ |
if (long_options[match].flag == NULL) |
optopt = long_options[match].val; |
else |
optopt = 0; |
return BADARG; |
} |
if (long_options[match].has_arg == required_argument || |
long_options[match].has_arg == optional_argument) { |
if (has_equal) |
optarg = has_equal; |
else if (long_options[match].has_arg == |
required_argument) { |
/* |
* optional argument doesn't use |
* next nargv |
*/ |
optarg = nargv[optind++]; |
} |
} |
if ((long_options[match].has_arg == required_argument) |
&& (optarg == NULL)) { |
/* |
* Missing argument; leading ':' |
* indicates no error should be generated |
*/ |
if (PRINT_ERROR) |
printf(recargstring, current_argv); |
/* |
* XXX: GNU sets optopt to val regardless |
* of flag |
*/ |
if (long_options[match].flag == NULL) |
optopt = long_options[match].val; |
else |
optopt = 0; |
--optind; |
return BADARG; |
} |
} else { /* unknown option */ |
if (PRINT_ERROR) |
printf(illoptstring, current_argv); |
optopt = 0; |
return BADCH; |
} |
if (long_options[match].flag) { |
*long_options[match].flag = long_options[match].val; |
retval = 0; |
} else |
retval = long_options[match].val; |
if (idx) |
*idx = match; |
} |
return retval; |
#undef IDENTICAL_INTERPRETATION |
} |
/branches/dd/uspace/lib/libc/generic/as.c |
---|
85,6 → 85,20 |
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address); |
} |
/** Change address-space area flags. |
* |
* @param address Virtual address pointing into the address space area being |
* modified. |
* @param flags New flags describing type of the area. |
* |
* @return Zero on success or a code from @ref errno.h on failure. |
*/ |
int as_area_change_flags(void *address, int flags) |
{ |
return __SYSCALL2(SYS_AS_AREA_CHANGE_FLAGS, (sysarg_t) address, |
(sysarg_t) flags); |
} |
static size_t heapsize = 0; |
static size_t maxheapsize = (size_t) (-1); |
/branches/dd/uspace/lib/libc/generic/pcb.c |
---|
0,0 → 1,40 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <loader/pcb.h> |
pcb_t *__pcb; |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/string.c |
---|
1,5 → 1,6 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
33,96 → 34,16 |
*/ |
#include <string.h> |
#include <unistd.h> |
#include <stdlib.h> |
#include <limits.h> |
#include <ctype.h> |
#include <limits.h> |
#include <align.h> |
#include <sys/types.h> |
#include <malloc.h> |
/* Dummy implementation of mem/ functions */ |
void *memset(void *s, int c, size_t n) |
{ |
char *os = s; |
while (n--) |
*(os++) = c; |
return s; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) src; |
} |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1))) |
return unaligned_memcpy(dst, src, n); |
for (i = 0; i < n / sizeof(unsigned long); i++) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) src; |
} |
void *memmove(void *dst, const void *src, size_t n) |
{ |
int i, j; |
if (src > dst) |
return memcpy(dst, src, n); |
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--) |
((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j]; |
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--) |
((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; |
return (char *) src; |
} |
/** Compare two memory areas. |
/** Count the number of characters in the string, not including terminating 0. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have the same |
* length. |
* @return If len is 0, return zero. If the areas match, return zero. |
* Otherwise return non-zero. |
* @param str String. |
* @return Number of characters in string. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** Count the number of characters in the string, not including terminating 0. |
* @param str string |
* @return number of characters in string. |
*/ |
size_t strlen(const char *str) |
{ |
size_t counter = 0; |
141,7 → 62,6 |
c++; |
return (a[c] - b[c]); |
} |
int strncmp(const char *a, const char *b, size_t n) |
155,10 → 75,22 |
} |
/** Return pointer to the first occurence of character c in string |
* @param str scanned string |
* @param c searched character (taken as one byte) |
* @return pointer to the matched character or NULL if it is not found in given string. |
int stricmp(const char *a, const char *b) |
{ |
int c = 0; |
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c])))) |
c++; |
return (tolower(a[c]) - tolower(b[c])); |
} |
/** Return pointer to the first occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strchr(const char *str, int c) |
{ |
171,10 → 103,12 |
return NULL; |
} |
/** Return pointer to the last occurence of character c in string |
* @param str scanned string |
* @param c searched character (taken as one byte) |
* @return pointer to the matched character or NULL if it is not found in given string. |
/** Return pointer to the last occurence of character c in string. |
* |
* @param str Scanned string. |
* @param c Searched character (taken as one byte). |
* @return Pointer to the matched character or NULL if it is not |
* found in given string. |
*/ |
char *strrchr(const char *str, int c) |
{ |
191,13 → 125,16 |
/** Convert string to a number. |
* Core of strtol and strtoul functions. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @param sgn its set to 1 if minus found |
* @return result of conversion. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character. |
* @param base Zero or number between 2 and 36 inclusive. |
* @param sgn It's set to 1 if minus found. |
* @return Result of conversion. |
*/ |
static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn) |
static unsigned long |
_strtoul(const char *nptr, char **endptr, int base, char *sgn) |
{ |
unsigned char c; |
unsigned long result = 0; |
219,7 → 156,8 |
/* FIXME: set errno to EINVAL */ |
return 0; |
} |
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) { |
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || |
(str[1] == 'X'))) { |
str += 2; |
} |
} else { |
238,7 → 176,8 |
while (*str) { |
c = *str; |
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff))); |
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : |
(c <= '9' ? c - '0' : 0xff))); |
if (c > base) { |
break; |
} |
257,7 → 196,10 |
} |
if (str == tmpptr) { |
/* no number was found => first invalid character is the first character of the string */ |
/* |
* No number was found => first invalid character is the first |
* character of the string. |
*/ |
/* FIXME: set errno to EINVAL */ |
str = nptr; |
result = 0; |
275,14 → 217,17 |
} |
/** Convert initial part of string to long int according to given base. |
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-'). |
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one. |
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8). |
* Otherwise the base 0 is taken as decimal. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @return result of conversion. |
* The number may begin with an arbitrary number of whitespaces followed by |
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be |
* inserted and the number will be taken as hexadecimal one. If the base is 0 |
* and the number begin with a zero, number will be taken as octal one (as with |
* base 8). Otherwise the base 0 is taken as decimal. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character. |
* @param base Zero or number between 2 and 36 inclusive. |
* @return Result of conversion. |
*/ |
long int strtol(const char *nptr, char **endptr, int base) |
{ |
305,14 → 250,17 |
/** Convert initial part of string to unsigned long according to given base. |
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-'). |
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one. |
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8). |
* Otherwise the base 0 is taken as decimal. |
* @param nptr pointer to string |
* @param endptr if not NULL, function stores here pointer to the first invalid character |
* @param base zero or number between 2 and 36 inclusive |
* @return result of conversion. |
* The number may begin with an arbitrary number of whitespaces followed by |
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be |
* inserted and the number will be taken as hexadecimal one. If the base is 0 |
* and the number begin with a zero, number will be taken as octal one (as with |
* base 8). Otherwise the base 0 is taken as decimal. |
* |
* @param nptr Pointer to string. |
* @param endptr If not NULL, function stores here pointer to the first |
* invalid character |
* @param base Zero or number between 2 and 36 inclusive. |
* @return Result of conversion. |
*/ |
unsigned long strtoul(const char *nptr, char **endptr, int base) |
{ |
353,5 → 301,48 |
return orig; |
} |
char * strdup(const char *s1) |
{ |
size_t len = strlen(s1) + 1; |
void *ret = malloc(len); |
if (ret == NULL) |
return (char *) NULL; |
return (char *) memcpy(ret, s1, len); |
} |
char *strtok(char *s, const char *delim) |
{ |
static char *next; |
return strtok_r(s, delim, &next); |
} |
char *strtok_r(char *s, const char *delim, char **next) |
{ |
char *start, *end; |
if (s == NULL) |
s = *next; |
/* Skip over leading delimiters. */ |
while (*s && (strchr(delim, *s) != NULL)) ++s; |
start = s; |
/* Skip over token characters. */ |
while (*s && (strchr(delim, *s) == NULL)) ++s; |
end = s; |
*next = (*s ? s + 1 : s); |
if (start == end) { |
return NULL; /* No more tokens. */ |
} |
/* Overwrite delimiter with NULL terminator. */ |
*end = '\0'; |
return start; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/loader.c |
---|
0,0 → 1,264 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <ipc/ipc.h> |
#include <ipc/loader.h> |
#include <ipc/services.h> |
#include <libc.h> |
#include <task.h> |
#include <string.h> |
#include <stdlib.h> |
#include <async.h> |
#include <errno.h> |
#include <vfs/vfs.h> |
#include <loader/loader.h> |
/** Connect to a new program loader. |
* |
* Spawns a new program loader task and returns the connection structure. |
* @param name Symbolic name to set on the newly created task. |
* @return Pointer to the loader connection structure (should be |
* de-allocated using free() after use). |
*/ |
int loader_spawn(const char *name) |
{ |
return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER, |
(sysarg_t) name, strlen(name)); |
} |
loader_t *loader_connect(void) |
{ |
loader_t *ldr; |
int phone_id; |
phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0); |
if (phone_id < 0) |
return NULL; |
ldr = malloc(sizeof(loader_t)); |
if (ldr == NULL) |
return NULL; |
ldr->phone_id = phone_id; |
return ldr; |
} |
/** Get ID of the new task. |
* |
* Retrieves the ID of the new task from the loader. |
* |
* @param ldr Loader connection structure. |
* @param task_id Points to a variable where the ID should be stored. |
* @return Zero on success or negative error code. |
*/ |
int loader_get_task_id(loader_t *ldr, task_id_t *task_id) |
{ |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
/* Get task ID. */ |
req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer); |
rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &retval); |
return (int)retval; |
} |
/** Set pathname of the program to load. |
* |
* Sets the name of the program file to load. The name can be relative |
* to the current working directory (it will be absolutized before |
* sending to the loader). |
* |
* @param ldr Loader connection structure. |
* @param path Pathname of the program file. |
* @return Zero on success or negative error code. |
*/ |
int loader_set_pathname(loader_t *ldr, const char *path) |
{ |
ipc_call_t answer; |
aid_t req; |
int rc; |
ipcarg_t retval; |
char *pa; |
size_t pa_len; |
pa = absolutize(path, &pa_len); |
if (!pa) |
return 0; |
/* Send program pathname */ |
req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer); |
rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
free(pa); |
async_wait_for(req, &retval); |
return (int)retval; |
} |
/** Set command-line arguments for the program. |
* |
* Sets the vector of command-line arguments to be passed to the loaded |
* program. By convention, the very first argument is typically the same as |
* the command used to execute the program. |
* |
* @param ldr Loader connection structure. |
* @param argv NULL-terminated array of pointers to arguments. |
* @return Zero on success or negative error code. |
*/ |
int loader_set_args(loader_t *ldr, char *const argv[]) |
{ |
aid_t req; |
ipc_call_t answer; |
ipcarg_t rc; |
char *const *ap; |
char *dp; |
char *arg_buf; |
size_t buffer_size; |
/* |
* Serialize the arguments into a single array. First |
* compute size of the buffer needed. |
*/ |
ap = argv; |
buffer_size = 0; |
while (*ap != NULL) { |
buffer_size += strlen(*ap) + 1; |
++ap; |
} |
arg_buf = malloc(buffer_size); |
if (arg_buf == NULL) return ENOMEM; |
/* Now fill the buffer with null-terminated argument strings */ |
ap = argv; |
dp = arg_buf; |
while (*ap != NULL) { |
strcpy(dp, *ap); |
dp += strlen(*ap) + 1; |
++ap; |
} |
/* Send serialized arguments to the loader */ |
req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer); |
rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
return rc; |
} |
async_wait_for(req, &rc); |
if (rc != EOK) return rc; |
/* Free temporary buffer */ |
free(arg_buf); |
return EOK; |
} |
/** Instruct loader to load the program. |
* |
* If this function succeeds, the program has been successfully loaded |
* and is ready to be executed. |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
*/ |
int loader_load_program(loader_t *ldr) |
{ |
int rc; |
rc = async_req_0_0(ldr->phone_id, LOADER_LOAD); |
if (rc != EOK) |
return rc; |
return EOK; |
} |
/** Instruct loader to execute the program. |
* |
* Note that this function blocks until the loader actually replies |
* so you cannot expect this function to return if you are debugging |
* the task and its thread is stopped. |
* |
* After using this function, no further operations must be performed |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
*/ |
int loader_run(loader_t *ldr) |
{ |
int rc; |
rc = async_req_0_0(ldr->phone_id, LOADER_RUN); |
if (rc != EOK) |
return rc; |
return EOK; |
} |
/** Cancel the loader session. |
* |
* Tells the loader not to load any program and terminate. |
* After using this function, no further operations must be performed |
* on the loader structure. It should be de-allocated using free(). |
* |
* @param ldr Loader connection structure. |
* @return Zero on success or negative error code. |
*/ |
void loader_abort(loader_t *ldr) |
{ |
ipc_hangup(ldr->phone_id); |
ldr->phone_id = 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/fibril.c |
---|
342,4 → 342,3 |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/thread.c |
---|
108,8 → 108,8 |
uarg->uspace_thread_arg = arg; |
uarg->uspace_uarg = uarg; |
rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) tid); |
rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, |
(sysarg_t) strlen(name), (sysarg_t) tid); |
if (rc) { |
/* |
/branches/dd/uspace/lib/libc/generic/libc.c |
---|
48,28 → 48,41 |
#include <ipc/ipc.h> |
#include <async.h> |
#include <as.h> |
#include <loader/pcb.h> |
extern char _heap; |
extern int main(int argc, char *argv[]); |
int _errno; |
void _exit(int status) |
{ |
thread_exit(status); |
} |
void __main(void) |
void __main(void *pcb_ptr) |
{ |
fibril_t *f; |
int argc; |
char **argv; |
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ); |
_async_init(); |
f = fibril_setup(); |
__tcb_set(f->tcb); |
} |
/* Save the PCB pointer */ |
__pcb = (pcb_t *)pcb_ptr; |
void __io_init(void) |
{ |
open_stdin(); |
open_stdout(); |
if (__pcb == NULL) { |
argc = 0; |
argv = NULL; |
} else { |
argc = __pcb->argc; |
argv = __pcb->argv; |
} |
main(argc, argv); |
} |
void __exit(void) |
/branches/dd/uspace/lib/libc/generic/ipc.c |
---|
598,7 → 598,7 |
ipcarg_t newphid; |
int res; |
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
NULL, NULL, NULL, NULL, &newphid); |
if (res) |
return res; |
605,6 → 605,30 |
return newphid; |
} |
/** Ask through phone for a new connection to some service. |
* |
* If the connection is not available at the moment, the |
* call will block. |
* |
* @param phoneid Phone handle used for contacting the other side. |
* @param arg1 User defined argument. |
* @param arg2 User defined argument. |
* @param arg3 User defined argument. |
* |
* @return New phone handle on success or a negative error code. |
*/ |
int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3) |
{ |
ipcarg_t newphid; |
int res; |
res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, |
IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); |
if (res) |
return res; |
return newphid; |
} |
/** Hang up a phone. |
* |
* @param phoneid Handle of the phone to be hung up. |
666,6 → 690,23 |
arg2, mode); |
} |
int ipc_forward_slow(ipc_callid_t callid, int phoneid, int method, |
ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, |
int mode) |
{ |
ipc_call_t data; |
IPC_SET_METHOD(data, method); |
IPC_SET_ARG1(data, arg1); |
IPC_SET_ARG2(data, arg2); |
IPC_SET_ARG3(data, arg3); |
IPC_SET_ARG4(data, arg4); |
IPC_SET_ARG5(data, arg5); |
return __SYSCALL3(SYS_IPC_FORWARD_SLOW, callid, (sysarg_t) &data, mode); |
} |
/** Wrapper for making IPC_M_SHARE_IN calls. |
* |
* @param phoneid Phone that will be used to contact the receiving side. |
682,7 → 723,7 |
{ |
int res; |
sysarg_t tmp_flags; |
res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, |
res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, |
(ipcarg_t) size, arg, NULL, &tmp_flags); |
if (flags) |
*flags = tmp_flags; |
742,7 → 783,7 |
*/ |
int ipc_share_out_start(int phoneid, void *src, int flags) |
{ |
return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, |
return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, |
(ipcarg_t) flags); |
} |
803,7 → 844,7 |
*/ |
int ipc_data_read_start(int phoneid, void *dst, size_t size) |
{ |
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, |
return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, |
(ipcarg_t) size); |
} |
847,7 → 888,7 |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size) |
int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) |
{ |
return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) size); |
} |
860,9 → 901,9 |
* |
* @return Zero on success or a negative error code from errno.h. |
*/ |
int ipc_data_write_start(int phoneid, void *src, size_t size) |
int ipc_data_write_start(int phoneid, const void *src, size_t size) |
{ |
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, |
(ipcarg_t) size); |
} |
909,6 → 950,18 |
{ |
return ipc_answer_2(callid, EOK, (ipcarg_t) dst, (ipcarg_t) size); |
} |
#include <kernel/syscall/sysarg64.h> |
/** Connect to a task specified by id. |
*/ |
int ipc_connect_kbox(task_id_t id) |
{ |
sysarg64_t arg; |
arg.value = (unsigned long long) id; |
return __SYSCALL1(SYS_IPC_CONNECT_KBOX, (sysarg_t) &arg); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/udebug.c |
---|
0,0 → 1,103 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <udebug.h> |
#include <sys/types.h> |
#include <ipc/ipc.h> |
#include <async.h> |
int udebug_begin(int phoneid) |
{ |
return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_BEGIN); |
} |
int udebug_end(int phoneid) |
{ |
return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_END); |
} |
int udebug_set_evmask(int phoneid, udebug_evmask_t mask) |
{ |
return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_SET_EVMASK, |
mask); |
} |
int udebug_thread_read(int phoneid, void *buffer, size_t n, |
size_t *copied, size_t *needed) |
{ |
ipcarg_t a_copied, a_needed; |
int rc; |
rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_THREAD_READ, |
(sysarg_t)buffer, n, NULL, &a_copied, &a_needed); |
*copied = (size_t)a_copied; |
*needed = (size_t)a_needed; |
return rc; |
} |
int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n) |
{ |
return async_req_4_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_MEM_READ, |
(sysarg_t)buffer, addr, n); |
} |
int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer) |
{ |
return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_ARGS_READ, |
tid, (sysarg_t)buffer); |
} |
int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type, |
sysarg_t *val0, sysarg_t *val1) |
{ |
ipcarg_t a_ev_type; |
int rc; |
rc = async_req_2_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_GO, |
tid, &a_ev_type, val0, val1); |
*ev_type = a_ev_type; |
return rc; |
} |
int udebug_stop(int phoneid, thash_t tid) |
{ |
return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_STOP, |
tid); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/async.c |
---|
483,7 → 483,7 |
{ |
connection_t *conn; |
unsigned long key; |
conn = malloc(sizeof(*conn)); |
if (!conn) { |
if (callid) |
498,7 → 498,7 |
conn->call = *call; |
conn->wdata.active = 1; /* We will activate the fibril ASAP */ |
conn->cfibril = cfibril; |
conn->wdata.fid = fibril_create(connection_fibril, conn); |
if (!conn->wdata.fid) { |
free(conn); |
506,14 → 506,15 |
ipc_answer_0(callid, ENOMEM); |
return NULL; |
} |
/* Add connection to the connection hash table */ |
key = conn->in_phone_hash; |
futex_down(&async_futex); |
hash_table_insert(&conn_hash_table, &key, &conn->link); |
futex_up(&async_futex); |
fibril_add_ready(conn->wdata.fid); |
return conn->wdata.fid; |
} |
524,6 → 525,7 |
* |
* @param callid Hash of the incoming call. |
* @param call Data of the incoming call. |
* |
*/ |
static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
{ |
533,8 → 535,8 |
(*interrupt_received)(callid, call); |
_in_interrupt_handler = 0; |
return; |
} |
} |
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_CONNECT_ME_TO: |
/* Open new connection with fibril etc. */ |
542,11 → 544,11 |
client_connection); |
return; |
} |
/* Try to route the call through the connection hash table */ |
if (route_call(callid, call)) |
return; |
/* Unknown call from unknown phone - hang it up */ |
ipc_answer_0(callid, EHANGUP); |
} |
739,23 → 741,17 |
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot send asynchronous request in interrupt " |
"handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
msg->dataptr = dataptr; |
/* We may sleep in the next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, |
reply_received, 1); |
reply_received, !_in_interrupt_handler); |
return (aid_t) msg; |
} |
781,23 → 777,17 |
ipc_call_t *dataptr) |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot send asynchronous request in interrupt " |
"handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
msg->done = 0; |
msg->dataptr = dataptr; |
/* We may sleep in next method, but it will use its own mechanism */ |
msg->wdata.active = 1; |
ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, |
reply_received, 1); |
reply_received, !_in_interrupt_handler); |
return (aid_t) msg; |
} |
884,21 → 874,16 |
{ |
amsg_t *msg; |
if (_in_interrupt_handler) { |
printf("Cannot call async_usleep in interrupt handler.\n"); |
_exit(1); |
} |
msg = malloc(sizeof(*msg)); |
if (!msg) |
return; |
msg->wdata.fid = fibril_get_id(); |
msg->wdata.active = 0; |
gettimeofday(&msg->wdata.expires, NULL); |
tv_add(&msg->wdata.expires, timeout); |
futex_down(&async_futex); |
insert_timeout(&msg->wdata); |
/* Leave the async_futex locked when entering this function */ |
1012,4 → 997,3 |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/vfs/vfs.c |
---|
31,7 → 31,7 |
*/ |
/** @file |
*/ |
#include <vfs/vfs.h> |
#include <vfs/canonify.h> |
#include <stdlib.h> |
48,7 → 48,8 |
#include <futex.h> |
#include <errno.h> |
#include <string.h> |
#include "../../srv/vfs/vfs.h" |
#include <ipc/devmap.h> |
#include "../../../srv/vfs/vfs.h" |
int vfs_phone = -1; |
futex_t vfs_phone_futex = FUTEX_INITIALIZER; |
56,11 → 57,12 |
futex_t cwd_futex = FUTEX_INITIALIZER; |
DIR *cwd_dir = NULL; |
char *cwd_path = NULL; |
size_t cwd_len = 0; |
size_t cwd_len = 0; |
static char *absolutize(const char *path, size_t *retlen) |
char *absolutize(const char *path, size_t *retlen) |
{ |
char *ncwd_path; |
char *ncwd_path_nc; |
futex_down(&cwd_futex); |
size_t len = strlen(path); |
69,65 → 71,112 |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path = malloc(len + cwd_len + 1); |
if (!ncwd_path) { |
ncwd_path_nc = malloc(cwd_len + 1 + len + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
strcpy(ncwd_path, cwd_path); |
ncwd_path[cwd_len] = '/'; |
ncwd_path[cwd_len + 1] = '\0'; |
strcpy(ncwd_path_nc, cwd_path); |
ncwd_path_nc[cwd_len] = '/'; |
ncwd_path_nc[cwd_len + 1] = '\0'; |
} else { |
ncwd_path = malloc(len + 1); |
if (!ncwd_path) { |
ncwd_path_nc = malloc(len + 1); |
if (!ncwd_path_nc) { |
futex_up(&cwd_futex); |
return NULL; |
} |
ncwd_path[0] = '\0'; |
ncwd_path_nc[0] = '\0'; |
} |
strcat(ncwd_path, path); |
if (!canonify(ncwd_path, retlen)) { |
strcat(ncwd_path_nc, path); |
ncwd_path = canonify(ncwd_path_nc, retlen); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
free(ncwd_path); |
free(ncwd_path_nc); |
return NULL; |
} |
/* |
* We need to clone ncwd_path because canonify() works in-place and thus |
* the address in ncwd_path need not be the same as ncwd_path_nc, even |
* though they both point into the same dynamically allocated buffer. |
*/ |
ncwd_path = strdup(ncwd_path); |
free(ncwd_path_nc); |
if (!ncwd_path) { |
futex_up(&cwd_futex); |
return NULL; |
} |
futex_up(&cwd_futex); |
return ncwd_path; |
} |
static int vfs_connect(void) |
static void vfs_connect(void) |
{ |
if (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0); |
return vfs_phone; |
while (vfs_phone < 0) |
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0); |
} |
int mount(const char *fs_name, const char *mp, const char *dev) |
static int device_get_handle(const char *name, dev_handle_t *handle, |
const unsigned int flags) |
{ |
int phone; |
if (flags & IPC_FLAG_BLOCKING) |
phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
else |
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0); |
if (phone < 0) |
return phone; |
ipc_call_t answer; |
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0, |
&answer); |
ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1); |
if (retval != EOK) { |
async_wait_for(req, NULL); |
ipc_hangup(phone); |
return retval; |
} |
async_wait_for(req, &retval); |
if (handle != NULL) |
*handle = -1; |
if (retval == EOK) { |
if (handle != NULL) |
*handle = (dev_handle_t) IPC_GET_ARG1(answer); |
} |
ipc_hangup(phone); |
return retval; |
} |
int mount(const char *fs_name, const char *mp, const char *dev, |
const unsigned int flags) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
dev_handle_t dev_handle = 0; /* TODO */ |
dev_handle_t dev_handle; |
res = device_get_handle(dev, &dev_handle, flags); |
if (res != EOK) |
return res; |
size_t mpa_len; |
char *mpa = absolutize(mp, &mpa_len); |
if (!mpa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return res; |
} |
} |
req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name)); |
vfs_connect(); |
req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL); |
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_len); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
135,7 → 184,8 |
free(mpa); |
return (int) rc; |
} |
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len); |
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, strlen(fs_name)); |
if (rc != EOK) { |
async_wait_for(req, NULL); |
async_serialize_end(); |
143,16 → 193,17 |
free(mpa); |
return (int) rc; |
} |
async_wait_for(req, &rc); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(mpa); |
return (int) rc; |
} |
static int _open(const char *path, int lflag, int oflag, ...) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
164,15 → 215,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
186,6 → 230,9 |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
if (rc != EOK) |
return (int) rc; |
return (int) IPC_GET_ARG1(answer); |
} |
196,22 → 243,14 |
int close(int fildes) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
220,7 → 259,6 |
ssize_t read(int fildes, void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
227,14 → 265,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_READ, fildes, &answer); |
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
249,12 → 281,11 |
if (rc == EOK) |
return (ssize_t) IPC_GET_ARG1(answer); |
else |
return -1; |
return rc; |
} |
ssize_t write(int fildes, const void *buf, size_t nbyte) |
{ |
int res; |
ipcarg_t rc; |
ipc_call_t answer; |
aid_t req; |
261,14 → 292,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer); |
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte); |
if (rc != EOK) { |
288,23 → 313,15 |
off_t lseek(int fildes, off_t offset, int whence) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
off_t newoffs; |
vfs_connect(); |
ipcarg_t newoffs; |
rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence, |
(ipcarg_t)&newoffs); |
&newoffs); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
312,24 → 329,17 |
if (rc != EOK) |
return (off_t) -1; |
return newoffs; |
return (off_t) newoffs; |
} |
int ftruncate(int fildes, off_t length) |
{ |
int res; |
ipcarg_t rc; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
return res; |
} |
} |
vfs_connect(); |
rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length); |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
371,7 → 381,6 |
int mkdir(const char *path, mode_t mode) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
379,18 → 388,11 |
char *pa = absolutize(path, &pa_len); |
if (!pa) |
return ENOMEM; |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
409,7 → 411,6 |
static int _unlink(const char *path, int lflag) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
420,15 → 421,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(pa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_UNLINK, NULL); |
rc = ipc_data_write_start(vfs_phone, pa, pa_len); |
if (rc != EOK) { |
457,7 → 451,6 |
int rename(const char *old, const char *new) |
{ |
int res; |
ipcarg_t rc; |
aid_t req; |
475,16 → 468,8 |
futex_down(&vfs_phone_futex); |
async_serialize_start(); |
if (vfs_phone < 0) { |
res = vfs_connect(); |
if (res < 0) { |
async_serialize_end(); |
futex_up(&vfs_phone_futex); |
free(olda); |
free(newa); |
return res; |
} |
} |
vfs_connect(); |
req = async_send_0(vfs_phone, VFS_RENAME, NULL); |
rc = ipc_data_write_start(vfs_phone, olda, olda_len); |
if (rc != EOK) { |
537,6 → 522,7 |
cwd_path = pa; |
cwd_len = pa_len; |
futex_up(&cwd_futex); |
return EOK; |
} |
char *getcwd(char *buf, size_t size) |
/branches/dd/uspace/lib/libc/generic/vfs/canonify.c |
---|
36,6 → 36,7 |
*/ |
#include <stdlib.h> |
#include <vfs/canonify.h> |
/** Token types used for tokenization of path. */ |
typedef enum { |
125,6 → 126,7 |
static void set_first_slash(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
*tfsl = *t; |
*tlcomp = *t; |
} |
static void save_component(token_t *t, token_t *tfsl, token_t *tlcomp) |
{ |
/branches/dd/uspace/lib/libc/generic/mem.c |
---|
0,0 → 1,239 |
/* |
* Copyright (c) 2005 Martin Decky |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <mem.h> |
#include <stdlib.h> |
#include <sys/types.h> |
/** Fill memory block with a constant value. */ |
void *memset(void *dest, int b, size_t n) |
{ |
char *pb; |
unsigned long *pw; |
size_t word_size; |
size_t n_words; |
unsigned long pattern; |
size_t i; |
size_t fill; |
/* Fill initial segment. */ |
word_size = sizeof(unsigned long); |
fill = word_size - ((uintptr_t) dest & (word_size - 1)); |
if (fill > n) fill = n; |
pb = dest; |
i = fill; |
while (i-- != 0) |
*pb++ = b; |
/* Compute remaining size. */ |
n -= fill; |
if (n == 0) return dest; |
n_words = n / word_size; |
n = n % word_size; |
pw = (unsigned long *) pb; |
/* Create word-sized pattern for aligned segment. */ |
pattern = 0; |
i = word_size; |
while (i-- != 0) |
pattern = (pattern << 8) | (uint8_t) b; |
/* Fill aligned segment. */ |
i = n_words; |
while (i-- != 0) |
*pw++ = pattern; |
pb = (char *) pw; |
/* Fill final segment. */ |
i = n; |
while (i-- != 0) |
*pb++ = b; |
return dest; |
} |
struct along { |
unsigned long n; |
} __attribute__ ((packed)); |
static void *unaligned_memcpy(void *dst, const void *src, size_t n) |
{ |
int i, j; |
struct along *adst = dst; |
const struct along *asrc = src; |
for (i = 0; i < n / sizeof(unsigned long); i++) |
adst[i].n = asrc[i].n; |
for (j = 0; j < n % sizeof(unsigned long); j++) |
((unsigned char *) (((unsigned long *) dst) + i))[j] = |
((unsigned char *) (((unsigned long *) src) + i))[j]; |
return (char *) dst; |
} |
/** Copy memory block. */ |
void *memcpy(void *dst, const void *src, size_t n) |
{ |
size_t i; |
size_t mod, fill; |
size_t word_size; |
size_t n_words; |
const unsigned long *srcw; |
unsigned long *dstw; |
const uint8_t *srcb; |
uint8_t *dstb; |
word_size = sizeof(unsigned long); |
/* |
* Are source and destination addresses congruent modulo word_size? |
* If not, use unaligned_memcpy(). |
*/ |
if (((uintptr_t) dst & (word_size - 1)) != |
((uintptr_t) src & (word_size - 1))) |
return unaligned_memcpy(dst, src, n); |
/* |
* mod is the address modulo word size. fill is the length of the |
* initial buffer segment before the first word boundary. |
* If the buffer is very short, use unaligned_memcpy(), too. |
*/ |
mod = (uintptr_t) dst & (word_size - 1); |
fill = word_size - mod; |
if (fill > n) fill = n; |
/* Copy the initial segment. */ |
srcb = src; |
dstb = dst; |
i = fill; |
while (i-- != 0) |
*dstb++ = *srcb++; |
/* Compute remaining length. */ |
n -= fill; |
if (n == 0) return dst; |
/* Pointers to aligned segment. */ |
dstw = (unsigned long *) dstb; |
srcw = (const unsigned long *) srcb; |
n_words = n / word_size; /* Number of whole words to copy. */ |
n -= n_words * word_size; /* Remaining bytes at the end. */ |
/* "Fast" copy. */ |
i = n_words; |
while (i-- != 0) |
*dstw++ = *srcw++; |
/* |
* Copy the rest. |
*/ |
srcb = (const uint8_t *) srcw; |
dstb = (uint8_t *) dstw; |
i = n; |
while (i-- != 0) |
*dstb++ = *srcb++; |
return dst; |
} |
/** Move memory block with possible overlapping. */ |
void *memmove(void *dst, const void *src, size_t n) |
{ |
const uint8_t *sp; |
uint8_t *dp; |
/* Nothing to do? */ |
if (src == dst) |
return dst; |
/* Non-overlapping? */ |
if (dst >= src + n || src >= dst + n) { |
return memcpy(dst, src, n); |
} |
/* Which direction? */ |
if (src > dst) { |
/* Forwards. */ |
sp = src; |
dp = dst; |
while (n-- != 0) |
*dp++ = *sp++; |
} else { |
/* Backwards. */ |
sp = src + (n - 1); |
dp = dst + (n - 1); |
while (n-- != 0) |
*dp-- = *sp--; |
} |
return dst; |
} |
/** Compare two memory areas. |
* |
* @param s1 Pointer to the first area to compare. |
* @param s2 Pointer to the second area to compare. |
* @param len Size of the first area in bytes. Both areas must have |
* the same length. |
* @return If len is 0, return zero. If the areas match, return |
* zero. Otherwise return non-zero. |
*/ |
int bcmp(const char *s1, const char *s2, size_t len) |
{ |
for (; len && *s1++ == *s2++; len--) |
; |
return len; |
} |
/** @} |
*/ |
Property changes: |
Added: svn:mergeinfo |
/branches/dd/uspace/lib/libc/generic/smc.c |
---|
0,0 → 1,46 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <libc.h> |
#include <sys/types.h> |
#include <smc.h> |
int smc_coherence(void *address, size_t size) |
{ |
return __SYSCALL2(SYS_SMC_COHERENCE, (sysarg_t) address, |
(sysarg_t) size); |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/stdio.c |
---|
0,0 → 1,278 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** |
* @file |
* @brief ANSI C Stream I/O. |
*/ |
#include <stdlib.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <fcntl.h> |
#include <unistd.h> |
#include <errno.h> |
#include <bool.h> |
#include <stdio.h> |
FILE *stdin, *stdout, *stderr; |
/** |
* Open a stream. |
* |
* @param file_name Name of the file to open. |
* @param mode Mode string, (r|w|a)[b|t][+]. |
*/ |
FILE *fopen(const char *file_name, const char *mode) |
{ |
FILE *f; |
int flags; |
bool plus; |
const char *mp; |
/* Parse mode except first character. */ |
mp = mode; |
if (*mp++ == '\0') { |
errno = EINVAL; |
return NULL; |
} |
if (*mp == 'b' || *mp == 't') ++mp; |
if (*mp == '+') { |
++mp; |
plus = true; |
} else { |
plus = false; |
} |
if (*mp != '\0') { |
errno = EINVAL; |
return NULL; |
} |
/* Parse first character of mode and determine flags for open(). */ |
switch (mode[0]) { |
case 'r': |
flags = plus ? O_RDWR : O_RDONLY; |
break; |
case 'w': |
flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY); |
break; |
case 'a': |
/* TODO: a+ must read from beginning, append to the end. */ |
if (plus) { |
errno = ENOTSUP; |
return NULL; |
} |
flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY); |
default: |
errno = EINVAL; |
return NULL; |
} |
/* Open file. */ |
f = malloc(sizeof(FILE)); |
if (f == NULL) { |
errno = ENOMEM; |
return NULL; |
} |
f->fd = open(file_name, flags, 0666); |
if (f->fd < 0) { |
free(f); |
return NULL; /* errno was set by open() */ |
} |
f->error = 0; |
f->eof = 0; |
return f; |
} |
/** Close a stream. |
* |
* @param f Pointer to stream. |
* @return 0 on success, EOF on error. |
*/ |
int fclose(FILE *f) |
{ |
int rc; |
rc = close(f->fd); |
free(f); |
if (rc != 0) |
return EOF; /* errno was set by close() */ |
return 0; |
} |
/** Read from a stream. |
* |
* @param buf Destination buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to read. |
* @param f Pointer to the stream. |
*/ |
size_t fread(void *buf, size_t size, size_t nmemb, FILE *f) |
{ |
size_t left, done, n; |
left = size * nmemb; |
done = 0; |
while (left > 0 && !f->error && !f->eof) { |
n = read(f->fd, buf + done, left); |
if (n < 0) { |
f->error = 1; |
} else if (n == 0) { |
f->eof = 1; |
} else { |
left -= n; |
done += n; |
} |
} |
return done / size; |
} |
/** Write to a stream. |
* |
* @param buf Source buffer. |
* @param size Size of each record. |
* @param nmemb Number of records to write. |
* @param f Pointer to the stream. |
*/ |
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f) |
{ |
size_t left, done, n; |
left = size * nmemb; |
done = 0; |
while (left > 0 && !f->error) { |
n = write(f->fd, buf + done, left); |
if (n <= 0) { |
f->error = 1; |
} else { |
left -= n; |
done += n; |
} |
} |
return done / size; |
} |
/** Return the end-of-file indicator of a stream. */ |
int feof(FILE *f) |
{ |
return f->eof; |
} |
/** Return the error indicator of a stream. */ |
int ferror(FILE *f) |
{ |
return f->error; |
} |
/** Clear the error and end-of-file indicators of a stream. */ |
void clearerr(FILE *f) |
{ |
f->eof = 0; |
f->error = 0; |
} |
/** Read character from a stream. */ |
int fgetc(FILE *f) |
{ |
unsigned char c; |
size_t n; |
n = fread(&c, sizeof(c), 1, f); |
if (n < 1) return EOF; |
return (int) c; |
} |
/** Write character to a stream. */ |
int fputc(int c, FILE *f) |
{ |
unsigned char cc; |
size_t n; |
cc = (unsigned char) c; |
n = fwrite(&cc, sizeof(cc), 1, f); |
if (n < 1) return EOF; |
return (int) cc; |
} |
/** Write string to a stream. */ |
int fputs(const char *s, FILE *f) |
{ |
int rc; |
rc = 0; |
while (*s && rc >= 0) { |
rc = fputc(*s++, f); |
} |
if (rc < 0) return EOF; |
return 0; |
} |
/** Seek to position in stream. */ |
int fseek(FILE *f, long offset, int origin) |
{ |
off_t rc; |
rc = lseek(f->fd, offset, origin); |
if (rc == (off_t) (-1)) { |
/* errno has been set by lseek. */ |
return -1; |
} |
f->eof = 0; |
return 0; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/sprintf.c |
---|
48,7 → 48,6 |
va_start(args, fmt); |
ret = vsprintf(str, fmt, args); |
va_end(args); |
return ret; |
/branches/dd/uspace/lib/libc/generic/io/asprintf.c |
---|
0,0 → 1,79 |
/* |
* Copyright (c) 2006 Josef Cejka |
* Copyright (c) 2008 Jakub Jermar |
* 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** @file |
*/ |
#include <stdarg.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <io/printf_core.h> |
static int asprintf_prewrite(const char *str, size_t count, void *unused) |
{ |
return count; |
} |
/** Allocate and print to string. |
* |
* @param strp Address of the pointer where to store the address of |
* the newly allocated string. |
* @fmt Format strin. |
* |
* @return Number of characters printed or a negative error code. |
*/ |
int asprintf(char **strp, const char *fmt, ...) |
{ |
struct printf_spec ps = { |
asprintf_prewrite, |
NULL |
}; |
int ret; |
va_list args; |
va_start(args, fmt); |
ret = printf_core(fmt, &ps, args); |
va_end(args); |
if (ret > 0) { |
*strp = malloc(ret + 20); |
if (!*strp) |
return -1; |
va_start(args, fmt); |
vsprintf(*strp, fmt, args); |
va_end(args); |
} |
return ret; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/fprintf.c |
---|
0,0 → 1,69 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup libc |
* @{ |
*/ |
/** |
* @file |
* @brief fprintf, vfprintf |
*/ |
#include <stdio.h> |
#include <sys/types.h> |
#include <io/printf_core.h> |
static int vfprintf_write(const char *s, size_t count, void *f) |
{ |
return fwrite(s, 1, count, (FILE *) f); |
} |
int vfprintf(FILE *f, const char *fmt, va_list ap) |
{ |
struct printf_spec ps = { |
(int (*)(void *, size_t, void *)) vfprintf_write, |
(void *) f |
}; |
return printf_core(fmt, &ps, ap); |
} |
int fprintf(FILE *f, const char *fmt, ...) |
{ |
int rv; |
va_list args; |
va_start(args, fmt); |
rv = vfprintf(f, fmt, args); |
va_end(args); |
return rv; |
} |
/** @} |
*/ |
/branches/dd/uspace/lib/libc/generic/io/vsnprintf.c |
---|
38,22 → 38,27 |
#include <io/printf_core.h> |
struct vsnprintf_data { |
size_t size; /* total space for string */ |
size_t len; /* count of currently used characters */ |
char *string; /* destination string */ |
size_t size; /* total space for string */ |
size_t len; /* count of currently used characters */ |
char *string; /* destination string */ |
}; |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number |
* of characters that would have been written if enough space had been available. Hence the return value is not |
* number of really printed characters but size of input string. Number of really used characters |
* is stored in data->len. |
* @param str source string to print |
* @param count size of source string |
* @param data structure with destination string, counter of used space and total string size. |
* @return number of characters to print (not characters really printed!) |
* Write at most data->size characters including trailing zero. According to C99 |
* has snprintf to return number of characters that would have been written if |
* enough space had been available. Hence the return value is not number of |
* really printed characters but size of input string. Number of really used |
* characters is stored in data->len. |
* |
* @param str Source string to print. |
* @param count Size of the source string. |
* @param data Structure with destination string, counter of used space |
* and total string size. |
* @return Number of characters to print (not characters really |
* printed!) |
*/ |
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
static int |
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data) |
{ |
size_t i; |
i = data->size - data->len; |
63,7 → 68,10 |
} |
if (i == 1) { |
/* We have only one free byte left in buffer => write there trailing zero */ |
/* |
* We have only one free byte left in buffer => write there |
* trailing zero. |
*/ |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
70,17 → 78,23 |
} |
if (i <= count) { |
/* We have not enought space for whole string with the trailing zero => print only a part of string */ |
memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
/* |
* We have not enought space for whole string with the trailing |
* zero => print only a part of string. |
*/ |
memcpy((void *)(data->string + data->len), (void *)str, i - 1); |
data->string[data->size - 1] = 0; |
data->len = data->size; |
return count; |
} |
/* Buffer is big enought to print whole string */ |
memcpy((void *)(data->string + data->len), (void *)str, count); |
data->len += count; |
/* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */ |
/* |
* Put trailing zero at end, but not count it into data->len so it could |
* be rewritten next time. |
*/ |
data->string[data->len] = 0; |
return count; |
87,17 → 101,22 |
} |
/** Print formatted to the given buffer with limited size. |
* @param str buffer |
* @param size buffer size |
* @param fmt format string |
* @param str Buffer. |
* @param size Bffer size. |
* @param fmt Format string. |
* \see For more details about format string see printf_core. |
*/ |
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) |
{ |
struct vsnprintf_data data = {size, 0, str}; |
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data}; |
struct printf_spec ps = { |
(int(*)(void *, size_t, void *)) vsnprintf_write, |
&data |
}; |
/* Print 0 at end of string - fix the case that nothing will be printed */ |
/* |
* Print 0 at end of string - fix the case that nothing will be printed. |
*/ |
if (size > 0) |
str[0] = 0; |
/branches/dd/uspace/lib/libc/generic/io/printf_core.c |
---|
94,12 → 94,9 |
if (str == NULL) |
return printf_putnchars("(NULL)", 6, ps); |
for (count = 0; str[count] != 0; count++); |
count = strlen(str); |
if (ps->write((void *) str, count, ps->data) == count) |
return 0; |
return EOF; |
return ps->write((void *) str, count, ps->data); |
} |
/** Print one character to output |
/branches/dd/uspace/lib/libc/generic/io/stream.c |
---|
42,7 → 42,8 |
#include <ipc/ns.h> |
#include <ipc/fb.h> |
#include <ipc/services.h> |
#include <console.h> |
#include <ipc/console.h> |
#include <kbd/kbd.h> |
#include <unistd.h> |
#include <async.h> |
#include <sys/types.h> |
56,54 → 57,77 |
ssize_t read_stdin(void *buf, size_t count) |
{ |
ipcarg_t r0, r1; |
size_t i = 0; |
open_console(); |
if (console_phone >= 0) { |
kbd_event_t ev; |
int rc; |
size_t i = 0; |
while (i < count) { |
do { |
rc = kbd_get_event(&ev); |
if (rc < 0) return -1; |
} while (ev.c == 0 || ev.type == KE_RELEASE); |
while (i < count) { |
if (async_req_0_2(console_phone, CONSOLE_GETCHAR, &r0, |
&r1) < 0) { |
return -1; |
((char *) buf)[i++] = ev.c; |
} |
((char *) buf)[i++] = r0; |
return i; |
} else { |
return -1; |
} |
return i; |
} |
ssize_t write_stdout(const void *buf, size_t count) |
{ |
int i; |
for (i = 0; i < count; i++) |
async_msg_1(console_phone, CONSOLE_PUTCHAR, |
((const char *) buf)[i]); |
open_console(); |
if (console_phone >= 0) { |
int i; |
return count; |
for (i = 0; i < count; i++) |
async_msg_1(console_phone, CONSOLE_PUTCHAR, |
((const char *) buf)[i]); |
return count; |
} else |
return __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, count); |
} |
void open_stdin(void) |
void open_console(void) |
{ |
if (console_phone < 0) { |
while ((console_phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0)) < 0) { |
usleep(10000); |
} |
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_CONSOLE, 0, 0); |
if (phone >= 0) |
console_phone = phone; |
} |
} |
void open_stdout(void) |
void close_console(void) |
{ |
if (console_phone < 0) { |
while ((console_phone = ipc_connect_me_to(PHONE_NS, |
SERVICE_CONSOLE, 0, 0)) < 0) { |
usleep(10000); |
if (console_phone >= 0) { |
if (ipc_hangup(console_phone) == 0) { |
console_phone = -1; |
} |
} |
} |
int get_cons_phone(void) |
void klog_update(void) |
{ |
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0); |
} |
int get_console_phone(void) |
{ |
if (console_phone < 0) |
console_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_CONSOLE, 0, 0); |
return console_phone; |
} |
void console_wait(void) |
{ |
while (console_phone < 0) |
get_console_phone(); |
} |
/** @} |
*/ |