Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3491 → Rev 3492

/branches/sparc/uspace/app/bdsh/cmds/mknewcmd
120,8 → 120,8
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h
/* Entry points for the ${CMDNAME} command */
extern int * ${CMDENTRY}(char **);
extern void * ${HELPENTRY}(unsigned int);
extern int ${CMDENTRY}(char **);
extern void ${HELPENTRY}(unsigned int);
 
#endif /* ${defname}_ENTRY_H */
 
170,22 → 170,22
static char *cmdname = "${CMDNAME}";
 
/* Dispays help for ${CMDNAME} in various levels */
void * ${HELPENTRY}(unsigned int level)
void ${HELPENTRY}(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return CMD_VOID;
return;
}
 
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
/* Main entry point for ${CMDNAME}, accepts an array of arguments */
int * ${CMDENTRY}(char **argv)
int ${CMDENTRY}(char **argv)
EOF
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
/* Main entry point for ${CMDNAME}, accepts an array of arguments and a
* pointer to the cliuser_t structure */
int * ${CMDENTRY}(char **argv, cliuser_t *usr)
int ${CMDENTRY}(char **argv, cliuser_t *usr)
EOF
cat << EOF >> ${OUTDIR}/${CMDNAME}.c
{
/branches/sparc/uspace/app/bdsh/cmds/modules/quit/quit.c
39,15 → 39,15
extern volatile unsigned int cli_quit;
extern const char *progname;
 
void * help_cmd_quit(unsigned int level)
void help_cmd_quit(unsigned int level)
{
printf("Type `%s' to exit %s\n", cmdname, progname);
return CMD_VOID;
return;
}
 
/* Quits the program and returns the status of whatever command
* came before invoking 'quit' */
int * cmd_quit(char *argv[])
int cmd_quit(char *argv[])
{
/* Inform that we're outta here */
cli_quit = 1;
/branches/sparc/uspace/app/bdsh/cmds/modules/quit/entry.h
2,8 → 2,8
#define QUIT_ENTRY_H_
 
/* Entry points for the quit command */
extern void * help_cmd_quit(unsigned int);
extern int * cmd_quit(char *[]);
extern void help_cmd_quit(unsigned int);
extern int cmd_quit(char *[]);
 
#endif
 
/branches/sparc/uspace/app/bdsh/cmds/modules/touch/touch.c
48,7 → 48,7
static char *cmdname = "touch";
 
/* Dispays help for touch in various levels */
void * help_cmd_touch(unsigned int level)
void help_cmd_touch(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' updates access times for files\n", cmdname);
58,11 → 58,11
"created\n", cmdname);
}
 
return CMD_VOID;
return;
}
 
/* Main entry point for touch, accepts an array of arguments */
int * cmd_touch(char **argv)
int cmd_touch(char **argv)
{
unsigned int argc, i = 0, ret = 0;
int fd;
/branches/sparc/uspace/app/bdsh/cmds/modules/touch/entry.h
2,8 → 2,8
#define TOUCH_ENTRY_H
 
/* Entry points for the touch command */
extern int * cmd_touch(char **);
extern void * help_cmd_touch(unsigned int);
extern int cmd_touch(char **);
extern void help_cmd_touch(unsigned int);
 
#endif /* TOUCH_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cp/cp.c
0,0 → 1,73
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* 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.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "cp.h"
#include "cmds.h"
 
static char *cmdname = "cp";
 
/* Dispays help for cp in various levels */
void help_cmd_cp(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return;
}
 
/* Main entry point for cp, accepts an array of arguments */
int cmd_cp(char **argv)
{
unsigned int argc;
unsigned int i;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
 
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cp/cp_def.h
0,0 → 1,8
{
"cp",
"Copy files and directories",
&cmd_cp,
&help_cmd_cp,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cp/entry.h
0,0 → 1,9
#ifndef CP_ENTRY_H
#define CP_ENTRY_H
 
/* Entry points for the cp command */
extern int cmd_cp(char **);
extern void help_cmd_cp(unsigned int);
 
#endif /* CP_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cp/cp.h
0,0 → 1,8
#ifndef CP_H
#define CP_H
 
/* Prototypes for the cp command, excluding entry points */
 
 
#endif /* CP_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/mkdir/entry.h
2,8 → 2,8
#define MKDIR_ENTRY_H
 
/* Entry points for the mkdir command */
extern int * cmd_mkdir(char **);
extern void * help_cmd_mkdir(unsigned int);
extern int cmd_mkdir(char **);
extern void help_cmd_mkdir(unsigned int);
 
#endif /* MKDIR_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
60,7 → 60,7
};
 
 
void * help_cmd_mkdir(unsigned int level)
void help_cmd_mkdir(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' creates a new directory\n", cmdname);
79,7 → 79,7
cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
/* This is kind of clunky, but effective for now */
181,7 → 181,7
return ret;
}
 
int * cmd_mkdir(char **argv)
int cmd_mkdir(char **argv)
{
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
unsigned int verbose = 0;
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/entry.h
2,8 → 2,8
#define CAT_ENTRY_H
 
/* Entry points for the cat command */
extern int * cmd_cat(char **);
extern void * help_cmd_cat(unsigned int);
extern int cmd_cat(char **);
extern void help_cmd_cat(unsigned int);
 
#endif /* CAT_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/cat/cat.c
59,7 → 59,7
};
 
/* Dispays help for cat in various levels */
void * help_cmd_cat(unsigned int level)
void help_cmd_cat(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' shows the contents of files\n", cmdname);
78,7 → 78,7
cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
static unsigned int cat_file(const char *fname, size_t blen)
121,12 → 121,6
return 1;
}
 
/* Debug stuff, newline not added purposefully */
printf("** %s is a file with the size of %ld bytes\n",
fname, total);
printf( "** %d bytes were read in a buffer of %d bytes in %d reads\n",
count, blen, reads);
printf("** Read %s\n", count == total ? "Succeeded" : "Failed");
free(buff);
 
return 0;
133,7 → 127,7
}
 
/* Main entry point for cat, accepts an array of arguments */
int * cmd_cat(char **argv)
int cmd_cat(char **argv)
{
unsigned int argc, i, ret = 0, buffer = 0;
int c, opt_ind;
/branches/sparc/uspace/app/bdsh/cmds/modules/help/entry.h
2,7 → 2,7
#define HELP_ENTRY_H_
 
/* Entry points for the help command */
extern void * help_cmd_help(unsigned int);
extern int * cmd_help(char *[]);
extern void help_cmd_help(unsigned int);
extern int cmd_help(char *[]);
 
#endif
/branches/sparc/uspace/app/bdsh/cmds/modules/help/help.c
69,7 → 69,7
return HELP_IS_RUBBISH;
}
 
void *help_cmd_help(unsigned int level)
void help_cmd_help(unsigned int level)
{
if (level == HELP_SHORT) {
printf(
86,10 → 86,10
cmdname, cmdname, cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
int *cmd_help(char *argv[])
int cmd_help(char *argv[])
{
module_t *mod;
builtin_t *cmd;
/branches/sparc/uspace/app/bdsh/cmds/modules/sleep/entry.h
0,0 → 1,9
#ifndef SLEEP_ENTRY_H
#define SLEEP_ENTRY_H
 
/* Entry points for the sleep command */
extern int cmd_sleep(char **);
extern void help_cmd_sleep(unsigned int);
 
#endif /* SLEEP_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/sleep/sleep.c
0,0 → 1,73
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* 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.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "sleep.h"
#include "cmds.h"
 
static char *cmdname = "sleep";
 
/* Dispays help for sleep in various levels */
void help_cmd_sleep(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return;
}
 
/* Main entry point for sleep, accepts an array of arguments */
int cmd_sleep(char **argv)
{
unsigned int argc;
unsigned int i;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
 
return CMD_SUCCESS;
}
 
/branches/sparc/uspace/app/bdsh/cmds/modules/sleep/sleep_def.h
0,0 → 1,8
{
"sleep",
"Pause for given time interval (in seconds)",
&cmd_sleep,
&help_cmd_sleep,
0
},
 
/branches/sparc/uspace/app/bdsh/cmds/modules/sleep/sleep.h
0,0 → 1,8
#ifndef SLEEP_H
#define SLEEP_H
 
/* Prototypes for the sleep command, excluding entry points */
 
 
#endif /* SLEEP_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/pwd/entry.h
4,8 → 4,8
#include "scli.h"
 
/* Entry points for the pwd command */
extern void * help_cmd_pwd(unsigned int);
extern int * cmd_pwd(char **);
extern void help_cmd_pwd(unsigned int);
extern int cmd_pwd(char **);
 
#endif
 
/branches/sparc/uspace/app/bdsh/cmds/modules/pwd/pwd.c
39,13 → 39,13
 
static char * cmdname = "pwd";
 
void * help_cmd_pwd(unsigned int level)
void help_cmd_pwd(unsigned int level)
{
printf("`%s' prints your current working directory.\n", cmdname);
return CMD_VOID;
return;
}
 
int * cmd_pwd(char *argv[])
int cmd_pwd(char *argv[])
{
char *buff;
 
/branches/sparc/uspace/app/bdsh/cmds/modules/ls/ls.c
132,7 → 132,7
return;
}
 
void * help_cmd_ls(unsigned int level)
void help_cmd_ls(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' lists files and directories.\n", cmdname);
142,10 → 142,10
"working directory is used.\n", cmdname);
}
 
return CMD_VOID;
return;
}
 
int * cmd_ls(char **argv)
int cmd_ls(char **argv)
{
unsigned int argc;
unsigned int scope;
/branches/sparc/uspace/app/bdsh/cmds/modules/ls/entry.h
2,8 → 2,8
#define LS_ENTRY_H
 
/* Entry points for the ls command */
extern int * cmd_ls(char **);
extern void * help_cmd_ls(unsigned int);
extern int cmd_ls(char **);
extern void help_cmd_ls(unsigned int);
 
#endif /* LS_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/modules/modules.h
25,6 → 25,8
#include "touch/entry.h"
#include "ls/entry.h"
#include "pwd/entry.h"
#include "sleep/entry.h"
#include "cp/entry.h"
 
/* Each .def function fills the module_t struct with the individual name, entry
* point, help entry point, etc. You can use config.h to control what modules
39,6 → 41,8
#include "touch/touch_def.h"
#include "ls/ls_def.h"
#include "pwd/pwd_def.h"
#include "sleep/sleep_def.h"
#include "cp/cp_def.h"
{NULL, NULL, NULL, NULL}
};
 
/branches/sparc/uspace/app/bdsh/cmds/modules/rm/rm.c
144,7 → 144,7
}
 
/* Dispays help for rm in various levels */
void * help_cmd_rm(unsigned int level)
void help_cmd_rm(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' removes files and directories.\n", cmdname);
161,11 → 161,11
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
return CMD_VOID;
return;
}
 
/* Main entry point for rm, accepts an array of arguments */
int * cmd_rm(char **argv)
int cmd_rm(char **argv)
{
unsigned int argc;
unsigned int i, scope, ret = 0;
/branches/sparc/uspace/app/bdsh/cmds/modules/rm/entry.h
2,8 → 2,8
#define RM_ENTRY_H
 
/* Entry points for the rm command */
extern int * cmd_rm(char **);
extern void * help_cmd_rm(unsigned int);
extern int cmd_rm(char **);
extern void help_cmd_rm(unsigned int);
 
#endif /* RM_ENTRY_H */
 
/branches/sparc/uspace/app/bdsh/cmds/builtins/cd/cd.c
42,7 → 42,7
 
static char * cmdname = "cd";
 
void * help_cmd_cd(unsigned int level)
void help_cmd_cd(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' changes the current working directory.\n", cmdname);
53,12 → 53,12
cmdname, cmdname);
}
 
return CMD_VOID;
return;
}
 
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */
 
int * cmd_cd(char **argv, cliuser_t *usr)
int cmd_cd(char **argv, cliuser_t *usr)
{
int argc, rc = 0;
 
/branches/sparc/uspace/app/bdsh/cmds/builtins/cd/entry.h
4,8 → 4,8
#include "scli.h"
 
/* Entry points for the cd command */
extern void * help_cmd_cd(unsigned int);
extern int * cmd_cd(char **, cliuser_t *);
extern void help_cmd_cd(unsigned int);
extern int cmd_cd(char **, cliuser_t *);
 
#endif
 
/branches/sparc/uspace/app/bdsh/cmds/cmds.h
19,17 → 19,16
#define BUFF_SMALL 255
 
/* Return macros for int type entry points */
#define CMD_FAILURE (int*)1
#define CMD_FAILURE 1
#define CMD_SUCCESS 0
#define CMD_VOID (void *)NULL
 
/* Types for module command entry and help */
typedef int * (* mod_entry_t)(char **);
typedef void * (* mod_help_t)(unsigned int);
typedef int (* mod_entry_t)(char **);
typedef void (* mod_help_t)(unsigned int);
 
/* Built-in commands need to be able to modify cliuser_t */
typedef int * (* builtin_entry_t)(char **, cliuser_t *);
typedef void * (* builtin_help_t)(unsigned int);
typedef int (* builtin_entry_t)(char **, cliuser_t *);
typedef void (* builtin_help_t)(unsigned int);
 
/* Module structure */
typedef struct {
/branches/sparc/uspace/app/bdsh/config.h
1,15 → 1,18
/* Various things that are used in many files
* Various temporary port work-arounds are addressed in __HELENOS__ , this
* serves as a convenience and later as a guide to make "phony.h" for future
* ports */
/* Various things that are used in many places including a few
* tidbits left over from autoconf prior to the HelenOS port */
 
/* Specific port work-arounds : */
#ifndef PATH_MAX
#define PATH_MAX 255
#endif
 
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 0
#define EXIT_FAILURE 1
#endif
 
/* Work around for getenv() */
#define PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
#define PATH "/srv:/app"
#define PATH_DELIM ":"
 
/* Used in many places */
26,7 → 29,7
#define PACKAGE_BUGREPORT "echo@echoreply.us"
#define PACKAGE_NAME "bdsh"
#define PACKAGE_STRING "The brain dead shell"
#define PACKAGE_TARNAME "scli"
#define PACKAGE_TARNAME "bdsh"
#define PACKAGE_VERSION "0.0.1"
 
 
/branches/sparc/uspace/app/bdsh/README
57,12 → 57,12
They are typed as such (from cmds.h):
 
/* Types for module command entry and help */
typedef int * (* mod_entry_t)(char **);
typedef void * (* mod_help_t)(unsigned int);
typedef int (* mod_entry_t)(char **);
typedef void (* mod_help_t)(unsigned int);
 
/* Built-in commands need to be able to modify cliuser_t */
typedef int * (* builtin_entry_t)(char **, cliuser_t *);
typedef void * (* builtin_help_t)(unsigned int);
typedef int (* builtin_entry_t)(char **, cliuser_t *);
typedef void (* builtin_help_t)(unsigned int);
 
As you can see, both modular and builtin commands expect an array of
arguments, however bulitins also expect to be pointed to cliuser_t.
153,9 → 153,7
 
2: Change your "usage()" command as shown:
-- void usage(...)
++ void * help_cmd_foo(unsigned int level)
-- return;
++ retrn CMD_VOID;
++ void help_cmd_foo(unsigned int level)
 
'level' is either 0 or 1, indicating the level of help requested.
If the help / usage function currently exits based on how it is
163,33 → 161,19
 
3: Change the programs "main()" as shown:
-- int main(int argc, char **argv)
++ int * cmd_foo(char **argv)
++ int cmd_foo(char **argv)
-- return 1;
++ return CMD_FAILURE;
-- return 0;
++ return CMD_SUCCESS;
 
If main() returns an int that is not 1 or 0 (e.g. 127), cast it as
such:
 
-- return 127;
++ return (int *) 127;
 
NOTE: _ONLY_ the main and help entry points need to return int * or
void *, respectively. Also take note that argc has changed. The type
for entry points may soon change.
 
NOTE: If main is void, you'll need to change it and ensure that its
expecting an array of arguments, even if they'll never be read or
used. I.e.:
 
-- void main(void)
++ int * cmd_foo(char **argv)
++ int cmd_foo(char **argv)
 
Similararly, do not try to return CMD_VOID within the modules main
entry point. If somehow you escape the compiler yelling at you, you
will surely see pretty blue and yellow fireworks once its reached.
 
4: Don't expose more than the entry and help points:
-- void my_function(int n)
++ static void my_function(int n)
/branches/sparc/uspace/app/bdsh/util.c
70,125 → 70,6
return (char *) memcpy(ret, s1, len);
}
 
/*
* Take a previously allocated string (s1), re-size it to accept s2 and copy
* the contents of s2 into s1.
* Return -1 on failure, or the length of the copied string on success.
*/
int cli_redup(char **s1, const char *s2)
{
size_t len = strlen(s2) + 1;
 
if (! len)
return -1;
 
*s1 = realloc(*s1, len);
 
if (*s1 == NULL) {
cli_errno = CL_ENOMEM;
return -1;
}
 
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, s2, len);
cli_errno = CL_EOK;
return (int) len;
}
 
/* An asprintf() for formatting paths, similar to asprintf() but ensures
* the returned allocated string is <= PATH_MAX. On failure, an attempt
* is made to return the original string (if not null) unmodified.
*
* Returns: Length of the new string on success, 0 if the string was handed
* back unmodified, -1 on failure. On failure, cli_errno is set.
*
* We do not use POSIX_PATH_MAX, as it is typically much smaller than the
* PATH_MAX defined by the kernel.
*
* Use this like:
* if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) {
* cli_error(cli_errno, "Failed to format path");
* stop_what_your_doing_as_your_out_of_memory();
* }
*/
 
int cli_psprintf(char **s1, const char *fmt, ...)
{
va_list ap;
size_t needed, base = PATH_MAX + 1;
int skipped = 0;
char *orig = NULL;
char *tmp = (char *) malloc(base);
 
/* Don't even touch s1, not enough memory */
if (NULL == tmp) {
cli_errno = CL_ENOMEM;
return -1;
}
 
/* If re-allocating s1, save a copy in case we fail */
if (NULL != *s1)
orig = cli_strdup(*s1);
 
/* Print the string to tmp so we can determine the size that
* we actually need */
memset(tmp, 0, sizeof(tmp));
va_start(ap, fmt);
/* vsnprintf will return the # of bytes not written */
skipped = vsnprintf(tmp, base, fmt, ap);
va_end(ap);
 
/* realloc/alloc s1 to be just the size that we need */
needed = strlen(tmp) + 1;
*s1 = realloc(*s1, needed);
 
if (NULL == *s1) {
/* No string lived here previously, or we failed to
* make a copy of it, either way there's nothing we
* can do. */
if (NULL == *orig) {
cli_errno = CL_ENOMEM;
return -1;
}
/* We can't even allocate enough size to restore the
* saved copy, just give up */
*s1 = realloc(*s1, strlen(orig) + 1);
if (NULL == *s1) {
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return -1;
}
/* Give the string back as we found it */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, orig, strlen(orig) + 1);
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return 0;
}
 
/* Ok, great, we have enough room */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, tmp, needed);
free(tmp);
 
/* Free tmp only if s1 was reallocated instead of allocated */
if (NULL != orig)
free(orig);
 
if (skipped) {
/* s1 was bigger than PATH_MAX when expanded, however part
* of the string was printed. Tell the caller not to use it */
cli_errno = CL_ETOOBIG;
return -1;
}
 
/* Success! */
cli_errno = CL_EOK;
return (int) needed;
}
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * cli_strtok_r(char *s, const char *delim, char **last)
{
273,10 → 154,7
if (NULL == usr->cwd)
snprintf(usr->cwd, PATH_MAX, "(unknown)");
 
if (1 < cli_psprintf(&usr->prompt, "%s # ", usr->cwd)) {
cli_error(cli_errno, "Failed to set prompt");
return 1;
}
asprintf(&usr->prompt, "%s # ", usr->cwd);
 
return 0;
}
/branches/sparc/uspace/app/bdsh/util.h
5,8 → 5,6
 
/* Internal string handlers */
extern char * cli_strdup(const char *);
extern int cli_redup(char **, const char *);
extern int cli_psprintf(char **, const char *, ...);
extern char * cli_strtok_r(char *, const char *, char **);
extern char * cli_strtok(char *, const char *);
 
/branches/sparc/uspace/app/bdsh/exec.c
46,13 → 46,13
#include "errors.h"
 
/* FIXME: Just have find_command() return an allocated string */
char *found;
static char *found;
 
static char *find_command(char *);
static unsigned int try_access(const char *);
static int try_access(const char *);
 
/* work-around for access() */
static unsigned int try_access(const char *f)
static int try_access(const char *f)
{
int fd;
 
117,7 → 117,7
tmp = cli_strdup(find_command(cmd));
free(found);
 
tid = task_spawn((const char *)tmp, (const char **)argv);
tid = task_spawn((const char *)tmp, argv);
free(tmp);
 
if (tid == 0) {
/branches/sparc/uspace/app/bdsh/scli.c
53,8 → 53,8
const char *progname = PACKAGE_NAME;
 
/* These are not exposed, even to builtins */
static int cli_init(cliuser_t *usr);
static void cli_finit(cliuser_t *usr);
static int cli_init(cliuser_t *);
static void cli_finit(cliuser_t *);
 
/* Constructor */
static int cli_init(cliuser_t *usr)
/branches/sparc/uspace/app/bdsh/Makefile
64,6 → 64,8
cmds/modules/touch/ \
cmds/modules/ls/ \
cmds/modules/pwd/ \
cmds/modules/sleep/ \
cmds/modules/cp/ \
cmds/builtins/ \
cmds/builtins/cd/
 
76,6 → 78,8
cmds/modules/touch/touch.c \
cmds/modules/ls/ls.c \
cmds/modules/pwd/pwd.c \
cmds/modules/sleep/sleep.c \
cmds/modules/cp/cp.c \
cmds/builtins/cd/cd.c \
cmds/mod_cmds.c \
cmds/builtin_cmds.c \
/branches/sparc/uspace/app/init/init.c
104,15 → 104,15
return -1;
}
// FIXME: spawn("/sbin/pci");
//spawn("/sbin/fb");
spawn("/sbin/kbd");
spawn("/sbin/console");
// FIXME: spawn("/srv/pci");
//spawn("/srv/fb");
spawn("/srv/kbd");
spawn("/srv/console");
console_wait();
version_print();
spawn("/sbin/bdsh");
spawn("/app/bdsh");
return 0;
}
/branches/sparc/uspace/app/tester/tester.c
133,7 → 133,7
if (c == 'a')
break;
if (c > 'a')
if (test->name == NULL)
printf("Unknown test\n\n");
else
run_test(test);
147,6 → 147,8
}
}
 
return 0;
}
 
/** @}
/branches/sparc/uspace/app/tester/ipc/send_sync.c
35,7 → 35,6
{
int phoneid;
int res;
static int msgid = 1;
char c;
 
printf("Select phoneid to send msg: 2-9 (q to skip)\n");
/branches/sparc/uspace/app/trace/trace.c
0,0 → 1,806
/*
* 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 trace
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ipc/ipc.h>
#include <fibril.h>
#include <errno.h>
#include <udebug.h>
#include <async.h>
#include <task.h>
#include <loader/loader.h>
 
#include <libc.h>
 
// Temporary: service and method names
#include "proto.h"
#include <ipc/services.h>
#include "../../srv/vfs/vfs.h"
#include "../../srv/console/console.h"
 
#include "syscalls.h"
#include "ipcp.h"
#include "errors.h"
#include "trace.h"
 
#define THBUF_SIZE 64
uintptr_t thread_hash_buf[THBUF_SIZE];
int n_threads;
 
int next_thread_id;
 
int phoneid;
int abort_trace;
 
uintptr_t thash;
volatile int paused;
 
void thread_trace_start(uintptr_t thread_hash);
 
static proto_t *proto_console;
static task_id_t task_id;
static loader_t *task_ldr;
 
/** Combination of events/data to print. */
display_mask_t display_mask;
 
static int program_run_fibril(void *arg);
 
static void program_run(void)
{
fid_t fid;
 
fid = fibril_create(program_run_fibril, NULL);
if (fid == 0) {
printf("Error creating fibril\n");
exit(1);
}
 
fibril_add_ready(fid);
}
 
static int program_run_fibril(void *arg)
{
int rc;
 
/*
* This must be done in background as it will block until
* we let the task reply to this call.
*/
rc = loader_run(task_ldr);
if (rc != 0) {
printf("Error running program\n");
exit(1);
}
 
free(task_ldr);
task_ldr = NULL;
 
printf("program_run_fibril exiting\n");
return 0;
}
 
 
static int connect_task(task_id_t task_id)
{
int rc;
 
rc = ipc_connect_kbox(task_id);
 
if (rc == ENOTSUP) {
printf("You do not have userspace debugging support "
"compiled in the kernel.\n");
printf("Compile kernel with 'Support for userspace debuggers' "
"(CONFIG_UDEBUG) enabled.\n");
return rc;
}
 
if (rc < 0) {
printf("Error connecting\n");
printf("ipc_connect_task(%lld) -> %d ", task_id, rc);
return rc;
}
 
phoneid = rc;
 
rc = udebug_begin(phoneid);
if (rc < 0) {
printf("udebug_begin() -> %d\n", rc);
return rc;
}
 
rc = udebug_set_evmask(phoneid, UDEBUG_EM_ALL);
if (rc < 0) {
printf("udebug_set_evmask(0x%x) -> %d\n ", UDEBUG_EM_ALL, rc);
return rc;
}
 
return 0;
}
 
static int get_thread_list(void)
{
int rc;
size_t tb_copied;
size_t tb_needed;
int i;
 
rc = udebug_thread_read(phoneid, thread_hash_buf,
THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
if (rc < 0) {
printf("udebug_thread_read() -> %d\n", rc);
return rc;
}
 
n_threads = tb_copied / sizeof(uintptr_t);
 
printf("Threads:");
for (i = 0; i < n_threads; i++) {
printf(" [%d] (hash 0x%lx)", 1+i, thread_hash_buf[i]);
}
printf("\ntotal of %u threads\n", tb_needed / sizeof(uintptr_t));
 
return 0;
}
 
void val_print(sysarg_t val, val_type_t v_type)
{
switch (v_type) {
case V_VOID:
printf("<void>");
break;
 
case V_INTEGER:
printf("%ld", val);
break;
 
case V_HASH:
case V_PTR:
printf("0x%08lx", val);
break;
 
case V_ERRNO:
if (val >= -15 && val <= 0) {
printf("%ld %s (%s)", val,
err_desc[-val].name,
err_desc[-val].desc);
} else {
printf("%ld", val);
}
break;
case V_INT_ERRNO:
if (val >= -15 && val < 0) {
printf("%ld %s (%s)", val,
err_desc[-val].name,
err_desc[-val].desc);
} else {
printf("%ld", val);
}
break;
 
case V_CHAR:
if (val >= 0x20 && val < 0x7f) {
printf("'%c'", val);
} else {
switch (val) {
case '\a': printf("'\\a'"); break;
case '\b': printf("'\\b'"); break;
case '\n': printf("'\\n'"); break;
case '\r': printf("'\\r'"); break;
case '\t': printf("'\\t'"); break;
case '\\': printf("'\\\\'"); break;
default: printf("'\\x%02lX'", val); break;
}
}
break;
}
}
 
 
static void print_sc_retval(sysarg_t retval, val_type_t val_type)
{
printf(" -> ");
val_print(retval, val_type);
putchar('\n');
}
 
static void print_sc_args(sysarg_t *sc_args, int n)
{
int i;
 
putchar('(');
if (n > 0) printf("%ld", sc_args[0]);
for (i = 1; i < n; i++) {
printf(", %ld", sc_args[i]);
}
putchar(')');
}
 
static void sc_ipc_call_async_fast(sysarg_t *sc_args, sysarg_t sc_rc)
{
ipc_call_t call;
ipcarg_t phoneid;
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
return;
 
phoneid = sc_args[0];
 
IPC_SET_METHOD(call, sc_args[1]);
IPC_SET_ARG1(call, sc_args[2]);
IPC_SET_ARG2(call, sc_args[3]);
IPC_SET_ARG3(call, sc_args[4]);
IPC_SET_ARG4(call, sc_args[5]);
IPC_SET_ARG5(call, 0);
 
ipcp_call_out(phoneid, &call, sc_rc);
}
 
static void sc_ipc_call_async_slow(sysarg_t *sc_args, sysarg_t sc_rc)
{
ipc_call_t call;
int rc;
 
if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
return;
 
memset(&call, 0, sizeof(call));
rc = udebug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
 
if (rc >= 0) {
ipcp_call_out(sc_args[0], &call, sc_rc);
}
}
 
static void sc_ipc_call_sync_fast(sysarg_t *sc_args)
{
ipc_call_t question, reply;
int rc;
int phoneidx;
 
// printf("sc_ipc_call_sync_fast()\n");
phoneidx = sc_args[0];
 
IPC_SET_METHOD(question, sc_args[1]);
IPC_SET_ARG1(question, sc_args[2]);
IPC_SET_ARG2(question, sc_args[3]);
IPC_SET_ARG3(question, sc_args[4]);
IPC_SET_ARG4(question, 0);
IPC_SET_ARG5(question, 0);
 
// printf("memset\n");
memset(&reply, 0, sizeof(reply));
// printf("udebug_mem_read(phone=%d, buffer_ptr=%u, src_addr=%d, n=%d\n",
// phoneid, &reply.args, sc_args[5], sizeof(reply.args));
rc = udebug_mem_read(phoneid, &reply.args, sc_args[5], sizeof(reply.args));
// printf("dmr->%d\n", rc);
if (rc < 0) return;
 
// printf("call ipc_call_sync\n");
ipcp_call_sync(phoneidx, &question, &reply);
}
 
static void sc_ipc_call_sync_slow(sysarg_t *sc_args)
{
ipc_call_t question, reply;
int rc;
 
memset(&question, 0, sizeof(question));
rc = udebug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args));
printf("dmr->%d\n", rc);
if (rc < 0) return;
 
memset(&reply, 0, sizeof(reply));
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args));
printf("dmr->%d\n", rc);
if (rc < 0) return;
 
ipcp_call_sync(sc_args[0], &question, &reply);
}
 
static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc)
{
ipc_call_t call;
int rc;
 
if (sc_rc == 0) return;
 
memset(&call, 0, sizeof(call));
rc = udebug_mem_read(phoneid, &call, sc_args[0], sizeof(call));
// printf("udebug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n",
// phoneid, (int)&call, sc_args[0], sizeof(call), rc);
 
if (rc >= 0) {
ipcp_call_in(&call, sc_rc);
}
}
 
static void event_syscall_b(unsigned thread_id, uintptr_t thread_hash,
unsigned sc_id, sysarg_t sc_rc)
{
sysarg_t sc_args[6];
int rc;
 
/* Read syscall arguments */
rc = udebug_args_read(phoneid, thread_hash, sc_args);
 
async_serialize_start();
 
// printf("[%d] ", thread_id);
 
if (rc < 0) {
printf("error\n");
async_serialize_end();
return;
}
 
if ((display_mask & DM_SYSCALL) != 0) {
/* Print syscall name and arguments */
printf("%s", syscall_desc[sc_id].name);
print_sc_args(sc_args, syscall_desc[sc_id].n_args);
}
 
async_serialize_end();
}
 
static void event_syscall_e(unsigned thread_id, uintptr_t thread_hash,
unsigned sc_id, sysarg_t sc_rc)
{
sysarg_t sc_args[6];
int rv_type;
int rc;
 
/* Read syscall arguments */
rc = udebug_args_read(phoneid, thread_hash, sc_args);
 
async_serialize_start();
 
// printf("[%d] ", thread_id);
 
if (rc < 0) {
printf("error\n");
async_serialize_end();
return;
}
 
if ((display_mask & DM_SYSCALL) != 0) {
/* Print syscall return value */
rv_type = syscall_desc[sc_id].rv_type;
print_sc_retval(sc_rc, rv_type);
}
 
switch (sc_id) {
case SYS_IPC_CALL_ASYNC_FAST:
sc_ipc_call_async_fast(sc_args, sc_rc);
break;
case SYS_IPC_CALL_ASYNC_SLOW:
sc_ipc_call_async_slow(sc_args, sc_rc);
break;
case SYS_IPC_CALL_SYNC_FAST:
sc_ipc_call_sync_fast(sc_args);
break;
case SYS_IPC_CALL_SYNC_SLOW:
sc_ipc_call_sync_slow(sc_args);
break;
case SYS_IPC_WAIT:
sc_ipc_wait(sc_args, sc_rc);
break;
default:
break;
}
 
async_serialize_end();
}
 
static void event_thread_b(uintptr_t hash)
{
async_serialize_start();
printf("New thread, hash 0x%lx\n", hash);
async_serialize_end();
 
thread_trace_start(hash);
}
 
static int trace_loop(void *thread_hash_arg)
{
int rc;
unsigned ev_type;
uintptr_t thread_hash;
unsigned thread_id;
sysarg_t val0, val1;
 
thread_hash = (uintptr_t)thread_hash_arg;
thread_id = next_thread_id++;
 
printf("Start tracing thread [%d] (hash 0x%lx)\n", thread_id, thread_hash);
 
while (!abort_trace) {
 
/* Run thread until an event occurs */
rc = udebug_go(phoneid, thread_hash,
&ev_type, &val0, &val1);
 
// printf("rc = %d, ev_type=%d\n", rc, ev_type);
if (ev_type == UDEBUG_EVENT_FINISHED) {
/* Done tracing this thread */
break;
}
 
if (rc >= 0) {
switch (ev_type) {
case UDEBUG_EVENT_SYSCALL_B:
event_syscall_b(thread_id, thread_hash, val0, (int)val1);
break;
case UDEBUG_EVENT_SYSCALL_E:
event_syscall_e(thread_id, thread_hash, val0, (int)val1);
break;
case UDEBUG_EVENT_STOP:
printf("Stop event\n");
printf("Waiting for resume\n");
while (paused) {
usleep(1000000);
fibril_yield();
printf(".");
}
printf("Resumed\n");
break;
case UDEBUG_EVENT_THREAD_B:
event_thread_b(val0);
break;
case UDEBUG_EVENT_THREAD_E:
printf("Thread 0x%lx exited\n", val0);
abort_trace = 1;
break;
default:
printf("Unknown event type %d\n", ev_type);
break;
}
}
 
}
 
printf("Finished tracing thread [%d]\n", thread_id);
return 0;
}
 
void thread_trace_start(uintptr_t thread_hash)
{
fid_t fid;
 
thash = thread_hash;
 
fid = fibril_create(trace_loop, (void *)thread_hash);
if (fid == 0) {
printf("Warning: Failed creating fibril\n");
}
fibril_add_ready(fid);
}
 
static loader_t *preload_task(const char *path, char *const argv[],
task_id_t *task_id)
{
loader_t *ldr;
int rc;
 
/* Spawn a program loader */
ldr = loader_spawn();
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;
 
/* Success */
return ldr;
 
/* Error exit */
error:
loader_abort(ldr);
free(ldr);
return NULL;
}
 
static void trace_task(task_id_t task_id)
{
int i;
int rc;
int c;
 
ipcp_init();
 
/*
* User apps now typically have console on phone 3.
* (Phones 1 and 2 are used by the loader).
*/
ipcp_connection_set(3, 0, proto_console);
 
rc = get_thread_list();
if (rc < 0) {
printf("Failed to get thread list (error %d)\n", rc);
return;
}
 
abort_trace = 0;
 
for (i = 0; i < n_threads; i++) {
thread_trace_start(thread_hash_buf[i]);
}
 
while(1) {
c = getchar();
if (c == 'q') break;
if (c == 'p') {
paused = 1;
rc = udebug_stop(phoneid, thash);
printf("stop -> %d\n", rc);
}
if (c == 'r') {
paused = 0;
}
}
 
printf("\nTerminate debugging session...\n");
abort_trace = 1;
udebug_end(phoneid);
ipc_hangup(phoneid);
 
ipcp_cleanup();
 
printf("Done\n");
return;
}
 
static void main_init(void)
{
proto_t *p;
oper_t *o;
 
val_type_t arg_def[OPER_MAX_ARGS] = {
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER
};
 
val_type_t resp_def[OPER_MAX_ARGS] = {
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER
};
 
next_thread_id = 1;
paused = 0;
 
proto_init();
 
p = proto_new("vfs");
o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_READ, o);
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_WRITE, o);
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_TRUNCATE, o);
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_MOUNT, o);
/* o = oper_new("unmount", 0, arg_def);
proto_add_oper(p, VFS_UNMOUNT, o);*/
 
proto_register(SERVICE_VFS, p);
 
p = proto_new("console");
resp_def[0] = V_CHAR;
o = oper_new("getchar", 0, arg_def, V_INTEGER, 2, resp_def);
proto_add_oper(p, CONSOLE_GETCHAR, o);
 
arg_def[0] = V_CHAR;
o = oper_new("putchar", 1, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_PUTCHAR, o);
o = oper_new("clear", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_CLEAR, o);
 
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER;
o = oper_new("goto", 2, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_GOTO, o);
 
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
o = oper_new("getsize", 0, arg_def, V_INTEGER, 2, resp_def);
proto_add_oper(p, CONSOLE_GETSIZE, o);
o = oper_new("flush", 0, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_FLUSH, o);
 
arg_def[0] = V_INTEGER; arg_def[1] = V_INTEGER;
o = oper_new("set_style", 2, arg_def, V_INTEGER, 0, resp_def);
proto_add_oper(p, CONSOLE_SET_STYLE, o);
o = oper_new("cursor_visibility", 1, arg_def, V_VOID, 0, resp_def);
proto_add_oper(p, CONSOLE_CURSOR_VISIBILITY, o);
 
proto_console = p;
proto_register(SERVICE_CONSOLE, p);
}
 
static void print_syntax()
{
printf("Syntax:\n");
printf("\ttrace [+<events>] <executable> [<arg1> [...]]\n");
printf("or\ttrace [+<events>] -t <task_id>\n");
printf("Events: (default is +tp)\n");
printf("\n");
printf("\tt ... Thread creation and termination\n");
printf("\ts ... System calls\n");
printf("\ti ... Low-level IPC\n");
printf("\tp ... Protocol level\n");
printf("\n");
printf("Examples:\n");
printf("\ttrace +s /app/tetris\n");
printf("\ttrace +tsip -t 12\n");
}
 
static display_mask_t parse_display_mask(char *text)
{
display_mask_t dm;
char *c;
 
c = text;
 
while (*c) {
switch (*c) {
case 't': dm = dm | DM_THREAD; break;
case 's': dm = dm | DM_SYSCALL; break;
case 'i': dm = dm | DM_IPC; break;
case 'p': dm = dm | DM_SYSTEM | DM_USER; break;
default:
printf("Unexpected event type '%c'\n", *c);
exit(1);
}
 
++c;
}
 
return dm;
}
 
static int parse_args(int argc, char *argv[])
{
char *arg;
char *err_p;
 
task_id = 0;
 
--argc; ++argv;
 
while (argc > 0) {
arg = *argv;
if (arg[0] == '+') {
display_mask = parse_display_mask(&arg[1]);
} else if (arg[0] == '-') {
if (arg[1] == 't') {
/* Trace an already running task */
--argc; ++argv;
task_id = strtol(*argv, &err_p, 10);
task_ldr = NULL;
if (*err_p) {
printf("Task ID syntax error\n");
print_syntax();
return -1;
}
} else {
printf("Uknown option '%s'\n", arg[0]);
print_syntax();
return -1;
}
} else {
break;
}
 
--argc; ++argv;
}
 
if (task_id != 0) {
if (argc == 0) return 0;
printf("Extra arguments\n");
print_syntax();
return -1;
}
 
if (argc < 1) {
printf("Missing argument\n");
print_syntax();
return -1;
}
 
/* Preload the specified program file. */
printf("Spawning '%s' with arguments:\n", *argv);
{
char **cp = argv;
while (*cp) printf("'%s'\n", *cp++);
}
task_ldr = preload_task(*argv, argv, &task_id);
 
return 0;
}
 
int main(int argc, char *argv[])
{
int rc;
 
printf("System Call / IPC Tracer\n");
 
display_mask = DM_THREAD | DM_SYSTEM | DM_USER;
 
if (parse_args(argc, argv) < 0)
return 1;
 
main_init();
 
rc = connect_task(task_id);
if (rc < 0) {
printf("Failed connecting to task %lld\n", task_id);
return 1;
}
 
printf("Connected to task %lld\n", task_id);
 
if (task_ldr != NULL) {
program_run();
}
 
trace_task(task_id);
 
return 0;
}
 
/** @}
*/
/branches/sparc/uspace/app/trace/ipcp.c
0,0 → 1,375
/*
* 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 trace
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <libadt/hash_table.h>
 
#include "ipc_desc.h"
#include "proto.h"
#include "trace.h"
#include "ipcp.h"
 
#define IPCP_CALLID_SYNC 0
 
typedef struct {
ipcarg_t phone_hash;
ipc_call_t question;
oper_t *oper;
 
ipc_callid_t call_hash;
 
link_t link;
} pending_call_t;
 
typedef struct {
int server;
proto_t *proto;
} connection_t;
 
#define MAX_PHONE 64
connection_t connections[MAX_PHONE];
int have_conn[MAX_PHONE];
 
#define PCALL_TABLE_CHAINS 32
hash_table_t pending_calls;
 
/*
* Pseudo-protocols
*/
proto_t *proto_system; /**< Protocol describing system IPC methods. */
proto_t *proto_unknown; /**< Protocol with no known methods. */
 
static hash_index_t pending_call_hash(unsigned long key[]);
static int pending_call_compare(unsigned long key[], hash_count_t keys,
link_t *item);
static void pending_call_remove_callback(link_t *item);
 
hash_table_operations_t pending_call_ops = {
.hash = pending_call_hash,
.compare = pending_call_compare,
.remove_callback = pending_call_remove_callback
};
 
 
static hash_index_t pending_call_hash(unsigned long key[])
{
// printf("pending_call_hash\n");
return key[0] % PCALL_TABLE_CHAINS;
}
 
static int pending_call_compare(unsigned long key[], hash_count_t keys,
link_t *item)
{
pending_call_t *hs;
 
// printf("pending_call_compare\n");
hs = hash_table_get_instance(item, pending_call_t, link);
 
// FIXME: this will fail if sizeof(long) < sizeof(void *).
return key[0] == hs->call_hash;
}
 
static void pending_call_remove_callback(link_t *item)
{
// printf("pending_call_remove_callback\n");
}
 
 
void ipcp_connection_set(int phone, int server, proto_t *proto)
{
if (phone <0 || phone >= MAX_PHONE) return;
connections[phone].server = server;
connections[phone].proto = proto;
have_conn[phone] = 1;
}
 
void ipcp_connection_clear(int phone)
{
have_conn[phone] = 0;
connections[phone].server = 0;
connections[phone].proto = NULL;
}
 
static void ipc_m_print(proto_t *proto, ipcarg_t method)
{
oper_t *oper;
 
/* Try system methods first */
oper = proto_get_oper(proto_system, method);
 
if (oper == NULL && proto != NULL) {
/* Not a system method, try the user protocol. */
oper = proto_get_oper(proto, method);
}
 
if (oper != NULL) {
printf("%s (%ld)", oper->name, method);
return;
}
 
printf("%ld", method);
}
 
void ipcp_init(void)
{
ipc_m_desc_t *desc;
oper_t *oper;
 
val_type_t arg_def[OPER_MAX_ARGS] = {
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER,
V_INTEGER
};
 
/*
* Create a pseudo-protocol 'unknown' that has no known methods.
*/
proto_unknown = proto_new("unknown");
 
/*
* Create a pseudo-protocol 'system' defining names of system IPC
* methods.
*/
proto_system = proto_new("system");
 
desc = ipc_methods;
while (desc->number != 0) {
oper = oper_new(desc->name, OPER_MAX_ARGS, arg_def, V_INTEGER,
OPER_MAX_ARGS, arg_def);
proto_add_oper(proto_system, desc->number, oper);
 
++desc;
}
 
hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
}
 
void ipcp_cleanup(void)
{
proto_delete(proto_system);
hash_table_destroy(&pending_calls);
}
 
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
{
pending_call_t *pcall;
proto_t *proto;
unsigned long key[1];
oper_t *oper;
ipcarg_t *args;
int i;
 
if (have_conn[phone]) proto = connections[phone].proto;
else proto = NULL;
 
args = call->args;
 
if ((display_mask & DM_IPC) != 0) {
printf("Call ID: 0x%lx, phone: %d, proto: %s, method: ", hash,
phone, (proto ? proto->name : "n/a"));
ipc_m_print(proto, IPC_GET_METHOD(*call));
printf(" args: (%lu, %lu, %lu, %lu, %lu)\n", args[1], args[2],
args[3], args[4], args[5]);
}
 
 
if ((display_mask & DM_USER) != 0) {
 
if (proto != NULL) {
oper = proto_get_oper(proto, IPC_GET_METHOD(*call));
} else {
oper = NULL;
}
 
if (oper != NULL) {
 
printf("%s(%d).%s", (proto ? proto->name : "n/a"),
phone, (oper ? oper->name : "unknown"));
 
putchar('(');
for (i = 1; i <= oper->argc; ++i) {
if (i > 1) printf(", ");
val_print(args[i], oper->arg_type[i - 1]);
}
putchar(')');
 
if (oper->rv_type == V_VOID && oper->respc == 0) {
/*
* No response data (typically the task will
* not be interested in the response).
* We will not display response.
*/
putchar('.');
}
 
putchar('\n');
}
} else {
oper = NULL;
}
 
/* Store call in hash table for response matching */
 
pcall = malloc(sizeof(pending_call_t));
pcall->phone_hash = phone;
pcall->question = *call;
pcall->call_hash = hash;
pcall->oper = oper;
 
key[0] = hash;
 
hash_table_insert(&pending_calls, key, &pcall->link);
}
 
static void parse_answer(ipc_callid_t hash, pending_call_t *pcall,
ipc_call_t *answer)
{
ipcarg_t phone;
ipcarg_t method;
ipcarg_t service;
ipcarg_t retval;
proto_t *proto;
int cphone;
 
ipcarg_t *resp;
oper_t *oper;
int i;
 
// printf("parse_answer\n");
 
phone = pcall->phone_hash;
method = IPC_GET_METHOD(pcall->question);
retval = IPC_GET_RETVAL(*answer);
 
resp = answer->args;
 
if ((display_mask & DM_IPC) != 0) {
printf("Response to 0x%lx: retval=%ld, args = (%lu, %lu, %lu, %lu, %lu)\n",
hash, retval, IPC_GET_ARG1(*answer),
IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
}
 
if ((display_mask & DM_USER) != 0) {
oper = pcall->oper;
 
if (oper != NULL && (oper->rv_type != V_VOID || oper->respc > 0)) {
printf("->");
 
if (oper->rv_type != V_VOID) {
putchar(' ');
val_print(retval, oper->rv_type);
}
if (oper->respc > 0) {
putchar(' ');
putchar('(');
for (i = 1; i <= oper->respc; ++i) {
if (i > 1) printf(", ");
val_print(resp[i], oper->resp_type[i - 1]);
}
putchar(')');
}
 
putchar('\n');
}
}
 
if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
/* Connected to a service (through NS) */
service = IPC_GET_ARG1(pcall->question);
proto = proto_get_by_srv(service);
if (proto == NULL) proto = proto_unknown;
 
cphone = IPC_GET_ARG5(*answer);
if ((display_mask & DM_SYSTEM) != 0) {
printf("Registering connection (phone %d, protocol: %s)\n", cphone,
proto->name);
}
ipcp_connection_set(cphone, 0, proto);
}
}
 
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
{
link_t *item;
pending_call_t *pcall;
unsigned long key[1];
 
// printf("ipcp_call_in()\n");
 
if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
/* Not a response */
if ((display_mask & DM_IPC) != 0) {
printf("Not a response (hash 0x%lx)\n", hash);
}
return;
}
 
hash = hash & ~IPC_CALLID_ANSWERED;
key[0] = hash;
 
item = hash_table_find(&pending_calls, key);
if (item == NULL) return; // No matching question found
 
/*
* Response matched to question.
*/
pcall = hash_table_get_instance(item, pending_call_t, link);
hash_table_remove(&pending_calls, key, 1);
 
parse_answer(hash, pcall, call);
free(pcall);
}
 
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
{
ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
ipcp_call_in(answer, IPCP_CALLID_SYNC);
}
 
void ipcp_hangup(int phone, int rc)
{
if ((display_mask & DM_SYSTEM) != 0) {
printf("Hang phone %d up -> %d\n", phone, rc);
ipcp_connection_clear(phone);
}
}
 
/** @}
*/
/branches/sparc/uspace/app/trace/trace.h
0,0 → 1,71
/*
* 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 trace
* @{
*/
/** @file
*/
 
#ifndef TRACE_H_
#define TRACE_H_
 
#include <sys/types.h>
 
/**
* Classes of events that can be displayed. Can be or-ed together.
*/
typedef enum {
DM_THREAD = 1, /**< Thread creation and termination events */
DM_SYSCALL = 2, /**< System calls */
DM_IPC = 4, /**< Low-level IPC */
DM_SYSTEM = 8, /**< Sysipc protocol */
DM_USER = 16 /**< User IPC protocols */
 
} display_mask_t;
 
typedef enum {
V_VOID,
V_INTEGER,
V_PTR,
V_HASH,
V_ERRNO,
V_INT_ERRNO,
V_CHAR
} val_type_t;
 
/** Combination of events to print. */
extern display_mask_t display_mask;
 
void val_print(sysarg_t val, val_type_t v_type);
 
#endif
 
/** @}
*/
/branches/sparc/uspace/app/trace/syscalls.h
0,0 → 1,51
/*
* 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 trace
* @{
*/
/** @file
*/
 
#ifndef SYSCALLS_H_
#define SYSCALLS_H_
 
#include "trace.h"
 
typedef struct {
char *name;
int n_args;
val_type_t rv_type;
} sc_desc_t;
 
extern const sc_desc_t syscall_desc[];
 
#endif
 
/** @}
*/
/branches/sparc/uspace/app/trace/syscalls.c
0,0 → 1,80
/*
* 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 trace
* @{
*/
/** @file
*/
 
#include <kernel/syscall/syscall.h>
#include "syscalls.h"
#include "trace.h"
 
const sc_desc_t syscall_desc[] = {
[SYS_KLOG] ={ "klog", 3, V_INT_ERRNO },
[SYS_TLS_SET] = { "tls_set", 1, V_ERRNO },
[SYS_THREAD_CREATE] = { "thread_create", 3, V_ERRNO },
[SYS_THREAD_EXIT] = { "thread_exit", 1, V_ERRNO },
[SYS_THREAD_GET_ID] = { "thread_get_id", 1, V_ERRNO },
 
[SYS_TASK_GET_ID] = { "task_get_id", 1, V_ERRNO },
[SYS_FUTEX_SLEEP] = { "futex_sleep_timeout", 3, V_ERRNO },
[SYS_FUTEX_WAKEUP] = { "futex_wakeup", 1, V_ERRNO },
 
[SYS_AS_AREA_CREATE] = { "as_area_create", 3, V_ERRNO },
[SYS_AS_AREA_RESIZE] = { "as_area_resize", 3, V_ERRNO },
[SYS_AS_AREA_DESTROY] = { "as_area_destroy", 1, V_ERRNO },
 
[SYS_IPC_CALL_SYNC_FAST] = { "ipc_call_sync_fast", 6, V_ERRNO },
[SYS_IPC_CALL_SYNC_SLOW] = { "ipc_call_sync_slow", 3, V_ERRNO },
[SYS_IPC_CALL_ASYNC_FAST] = { "ipc_call_async_fast", 6, V_HASH },
[SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 2, V_HASH },
 
[SYS_IPC_ANSWER_FAST] = { "ipc_answer_fast", 6, V_ERRNO },
[SYS_IPC_ANSWER_SLOW] = { "ipc_answer_slow", 2, V_ERRNO },
[SYS_IPC_FORWARD_FAST] = { "ipc_forward_fast", 6, V_ERRNO },
[SYS_IPC_WAIT] = { "ipc_wait_for_call", 3, V_HASH },
[SYS_IPC_HANGUP] = { "ipc_hangup", 1, V_ERRNO },
[SYS_IPC_REGISTER_IRQ] = { "ipc_register_irq", 4, V_ERRNO },
[SYS_IPC_UNREGISTER_IRQ] = { "ipc_unregister_irq", 2, V_ERRNO },
 
[SYS_CAP_GRANT] = { "cap_grant", 2, V_ERRNO },
[SYS_CAP_REVOKE] = { "cap_revoke", 2, V_ERRNO },
[SYS_PHYSMEM_MAP] = { "physmem_map", 4, V_ERRNO },
[SYS_IOSPACE_ENABLE] = { "iospace_enable", 1, V_ERRNO },
[SYS_PREEMPT_CONTROL] = { "preempt_control", 1, V_ERRNO },
 
[SYS_SYSINFO_VALID] = { "sysinfo_valid", 2, V_HASH },
[SYS_SYSINFO_VALUE] = { "sysinfo_value", 2, V_HASH },
[SYS_DEBUG_ENABLE_CONSOLE] = { "debug_enable_console", 0, V_ERRNO },
[SYS_IPC_CONNECT_KBOX] = { "ipc_connect_kbox", 1, V_ERRNO }
};
 
/** @}
*/
/branches/sparc/uspace/app/trace/proto.c
0,0 → 1,236
/*
* 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 trace
* @{
*/
/** @file
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <ipc/ipc.h>
#include <libadt/hash_table.h>
 
#include "trace.h"
#include "proto.h"
 
#define SRV_PROTO_TABLE_CHAINS 32
#define METHOD_OPER_TABLE_CHAINS 32
 
hash_table_t srv_proto;
 
typedef struct {
int srv;
proto_t *proto;
link_t link;
} srv_proto_t;
 
typedef struct {
ipcarg_t method;
oper_t *oper;
link_t link;
} method_oper_t;
 
static hash_index_t srv_proto_hash(unsigned long key[]);
static int srv_proto_compare(unsigned long key[], hash_count_t keys,
link_t *item);
static void srv_proto_remove_callback(link_t *item);
 
hash_table_operations_t srv_proto_ops = {
.hash = srv_proto_hash,
.compare = srv_proto_compare,
.remove_callback = srv_proto_remove_callback
};
 
static hash_index_t method_oper_hash(unsigned long key[]);
static int method_oper_compare(unsigned long key[], hash_count_t keys,
link_t *item);
static void method_oper_remove_callback(link_t *item);
 
hash_table_operations_t method_oper_ops = {
.hash = method_oper_hash,
.compare = method_oper_compare,
.remove_callback = method_oper_remove_callback
};
 
static hash_index_t srv_proto_hash(unsigned long key[])
{
return key[0] % SRV_PROTO_TABLE_CHAINS;
}
 
static int srv_proto_compare(unsigned long key[], hash_count_t keys,
link_t *item)
{
srv_proto_t *sp;
 
sp = hash_table_get_instance(item, srv_proto_t, link);
 
return key[0] == sp->srv;
}
 
static void srv_proto_remove_callback(link_t *item)
{
}
 
static hash_index_t method_oper_hash(unsigned long key[])
{
return key[0] % METHOD_OPER_TABLE_CHAINS;
}
 
static int method_oper_compare(unsigned long key[], hash_count_t keys,
link_t *item)
{
method_oper_t *mo;
 
mo = hash_table_get_instance(item, method_oper_t, link);
 
return key[0] == mo->method;
}
 
static void method_oper_remove_callback(link_t *item)
{
}
 
 
void proto_init(void)
{
hash_table_create(&srv_proto, SRV_PROTO_TABLE_CHAINS, 1,
&srv_proto_ops);
}
 
void proto_cleanup(void)
{
hash_table_destroy(&srv_proto);
}
 
void proto_register(int srv, proto_t *proto)
{
srv_proto_t *sp;
unsigned long key;
 
sp = malloc(sizeof(srv_proto_t));
sp->srv = srv;
sp->proto = proto;
key = srv;
 
hash_table_insert(&srv_proto, &key, &sp->link);
}
 
proto_t *proto_get_by_srv(int srv)
{
unsigned long key;
link_t *item;
srv_proto_t *sp;
 
key = srv;
item = hash_table_find(&srv_proto, &key);
if (item == NULL) return NULL;
 
sp = hash_table_get_instance(item, srv_proto_t, link);
return sp->proto;
}
 
static void proto_struct_init(proto_t *proto, char *name)
{
proto->name = name;
hash_table_create(&proto->method_oper, SRV_PROTO_TABLE_CHAINS, 1,
&method_oper_ops);
}
 
proto_t *proto_new(char *name)
{
proto_t *p;
 
p = malloc(sizeof(proto_t));
proto_struct_init(p, name);
 
return p;
}
 
void proto_delete(proto_t *proto)
{
free(proto);
}
 
void proto_add_oper(proto_t *proto, int method, oper_t *oper)
{
method_oper_t *mo;
unsigned long key;
 
mo = malloc(sizeof(method_oper_t));
mo->method = method;
mo->oper = oper;
key = method;
 
hash_table_insert(&proto->method_oper, &key, &mo->link);
}
 
oper_t *proto_get_oper(proto_t *proto, int method)
{
unsigned long key;
link_t *item;
method_oper_t *mo;
 
key = method;
item = hash_table_find(&proto->method_oper, &key);
if (item == NULL) return NULL;
 
mo = hash_table_get_instance(item, method_oper_t, link);
return mo->oper;
}
 
static void oper_struct_init(oper_t *oper, char *name)
{
oper->name = name;
}
 
oper_t *oper_new(char *name, int argc, val_type_t *arg_types,
val_type_t rv_type, int respc, val_type_t *resp_types)
{
oper_t *o;
int i;
 
o = malloc(sizeof(oper_t));
oper_struct_init(o, name);
 
o->argc = argc;
for (i = 0; i < argc; i++)
o->arg_type[i] = arg_types[i];
 
o->rv_type = rv_type;
 
o->respc = respc;
for (i = 0; i < respc; i++)
o->resp_type[i] = resp_types[i];
 
return o;
}
 
/** @}
*/
/branches/sparc/uspace/app/trace/proto.h
0,0 → 1,85
/*
* 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 trace
* @{
*/
/** @file
*/
 
#ifndef PROTO_H_
#define PROTO_H_
 
#include <libadt/hash_table.h>
#include <ipc/ipc.h>
#include "trace.h"
 
#define OPER_MAX_ARGS (IPC_CALL_LEN - 1)
 
typedef struct {
char *name;
 
int argc;
val_type_t arg_type[OPER_MAX_ARGS];
 
val_type_t rv_type;
 
int respc;
val_type_t resp_type[OPER_MAX_ARGS];
} oper_t;
 
typedef struct {
/** Protocol name */
char *name;
 
/** Maps method number to operation */
hash_table_t method_oper;
} proto_t;
 
/* Maps service number to protocol */
extern hash_table_t srv_proto;
 
void proto_init(void);
void proto_cleanup(void);
 
void proto_register(int srv, proto_t *proto);
proto_t *proto_get_by_srv(int srv);
proto_t *proto_new(char *name);
void proto_delete(proto_t *proto);
void proto_add_oper(proto_t *proto, int method, oper_t *oper);
oper_t *proto_get_oper(proto_t *proto, int method);
 
oper_t *oper_new(char *name, int argc, val_type_t *arg_types,
val_type_t rv_type, int respc, val_type_t *resp_types);
 
 
 
#endif
 
/** @}
*/
/branches/sparc/uspace/app/trace/ipc_desc.h
0,0 → 1,48
/*
* 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 trace
* @{
*/
/** @file
*/
 
#ifndef IPC_DESC_H_
#define IPC_DESC_H_
 
typedef struct {
int number;
char *name;
} ipc_m_desc_t;
 
extern ipc_m_desc_t ipc_methods[];
 
#endif
 
/** @}
*/
/branches/sparc/uspace/app/trace/ipcp.h
0,0 → 1,55
/*
* 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 trace
* @{
*/
/** @file
*/
 
#ifndef IPCP_H_
#define IPCP_H_
 
#include <ipc/ipc.h>
#include "proto.h"
 
void ipcp_init(void);
void ipcp_cleanup(void);
 
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash);
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer);
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash);
void ipcp_hangup(int phone, int rc);
 
void ipcp_connection_set(int phone, int server, proto_t *proto);
void ipcp_connection_clear(int phone);
 
#endif
 
/** @}
*/
/branches/sparc/uspace/app/trace/errors.h
0,0 → 1,48
/*
* 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 trace
* @{
*/
/** @file
*/
 
#ifndef ERRORS_H_
#define ERRORS_H_
 
typedef struct {
char *name; /**< Error value name (Exx) */
char *desc; /**< Error description */
} err_desc_t;
 
extern const err_desc_t err_desc[];
 
#endif
 
/** @}
*/
/branches/sparc/uspace/app/trace/ipc_desc.c
0,0 → 1,58
/*
* 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 trace
* @{
*/
/** @file
*/
 
#include <stdlib.h>
#include <ipc/ipc.h>
#include "ipc_desc.h"
 
ipc_m_desc_t ipc_methods[] = {
/* System methods */
{ IPC_M_CONNECT_TO_ME, "CONNECT_TO_ME" },
{ IPC_M_CONNECT_ME_TO, "CONNECT_ME_TO" },
{ IPC_M_PHONE_HUNGUP, "PHONE_HUNGUP" },
{ IPC_M_SHARE_OUT, "SHARE_OUT" },
{ IPC_M_SHARE_IN, "SHARE_IN" },
{ IPC_M_DATA_WRITE, "DATA_WRITE" },
{ IPC_M_DATA_READ, "DATA_READ" },
{ IPC_M_DEBUG_ALL, "DEBUG_ALL" },
 
/* Well-known methods */
{ IPC_M_PING, "PING" },
 
/* Terminating entry */
{ 0, NULL }
};
 
/** @}
*/
/branches/sparc/uspace/app/trace/Makefile
0,0 → 1,78
#
# Copyright (c) 2005 Martin Decky
# 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.
#
 
## Setup toolchain
#
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
 
OUTPUT = trace
SOURCES = trace.c \
syscalls.c \
ipcp.c \
ipc_desc.c \
proto.c \
errors.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/sparc/uspace/app/trace/errors.c
0,0 → 1,61
/*
* 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 trace
* @{
*/
/** @file
*/
 
#include <errno.h>
#include "errors.h"
 
const err_desc_t err_desc[] = {
[-EOK] = { "EOK", "No error" },
[-ENOENT] = { "ENOENT", "No such entry" },
[-ENOMEM] = { "ENOMEM", "Not enough memory" },
[-ELIMIT] = { "ELIMIT", "Limit exceeded" },
[-EREFUSED] = { "EREFUSED", "Connection refused" },
 
[-EFORWARD] = { "EFORWARD", "Forward error" },
[-EPERM] = { "EPERM", "Permission denied" },
[-EHANGUP] = { "EHANGUP", "Answerbox closed connection" },
[-EEXISTS] = { "EEXISTS", "Entry already exists" },
[-EBADMEM] = { "EBADMEM", "Bad memory pointer" },
 
[-ENOTSUP] = { "ENOTSUP", "Not supported" },
[-EADDRNOTAVAIL] = { "EADDRNOTAVAIL", "Address not available." },
[-ETIMEOUT] = { "ETIMEOUT", "Timeout expired" },
[-EINVAL] = { "EINVAL", "Invalid value" },
[-EBUSY] = { "EBUSY", "Resource is busy" },
 
[-EOVERFLOW] = { "EOVERFLOW", "The result does not fit its size." }
};
 
/** @}
*/
/branches/sparc/uspace/lib/libfs/Makefile
57,7 → 57,7
find . -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
 
libfs.a: depend $(OBJECTS)
$(AR) rc libfs.a $(OBJECTS)
/branches/sparc/uspace/lib/softfloat/Makefile
66,7 → 66,7
find generic/ -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libsoftfloat.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libsoftfloat.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
/branches/sparc/uspace/lib/softint/Makefile
58,7 → 58,7
find generic/ -name '*.o' -follow -exec rm \{\} \;
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libsoftint.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libsoftint.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
/branches/sparc/uspace/lib/libc/include/string.h
64,6 → 64,9
extern long int strtol(const char *, char **, int);
extern unsigned long strtoul(const char *, char **, int);
 
extern char * strtok_r(char *, const char *, char **);
extern char * strtok(char *, const char *);
 
#endif
 
/** @}
/branches/sparc/uspace/lib/libc/include/syscall.h
32,15 → 32,28
/**
* @file
* @brief Syscall function declaration for architectures that don't
* inline syscalls.
* inline syscalls or architectures that handle syscalls
* according to the number of arguments.
*/
 
#ifndef LIBC_SYSCALL_H_
#define LIBC_SYSCALL_H_
 
#ifndef LIBARCH_SYSCALL_GENERIC
#error "You can't include this file directly."
#endif
 
#include <sys/types.h>
#include <kernel/syscall/syscall.h>
 
#define __syscall0 __syscall
#define __syscall1 __syscall
#define __syscall2 __syscall
#define __syscall3 __syscall
#define __syscall4 __syscall
#define __syscall5 __syscall
#define __syscall6 __syscall
 
extern sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2,
const sysarg_t p3, const sysarg_t p4, const sysarg_t p5, const sysarg_t p6,
const syscall_t id);
/branches/sparc/uspace/lib/libc/include/task.h
40,7 → 40,7
typedef uint64_t task_id_t;
 
extern task_id_t task_get_id(void);
extern task_id_t task_spawn(const char *path, const char *argv[]);
extern task_id_t task_spawn(const char *path, char *const argv[]);
 
#endif
 
/branches/sparc/uspace/lib/libc/include/libc.h
39,14 → 39,14
#include <kernel/syscall/syscall.h>
#include <libarch/syscall.h>
 
#define __SYSCALL0(id) __syscall(0, 0, 0, 0, 0, 0, id)
#define __SYSCALL1(id, p1) __syscall(p1, 0, 0, 0, 0, 0, id)
#define __SYSCALL2(id, p1, p2) __syscall(p1, p2, 0, 0, 0, 0, id)
#define __SYSCALL3(id, p1, p2, p3) __syscall(p1, p2, p3, 0, 0, 0, id)
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall(p1, p2, p3, p4, 0, 0, id)
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall(p1, p2, p3, p4, p5, 0, id)
#define __SYSCALL0(id) __syscall0(0, 0, 0, 0, 0, 0, id)
#define __SYSCALL1(id, p1) __syscall1(p1, 0, 0, 0, 0, 0, id)
#define __SYSCALL2(id, p1, p2) __syscall2(p1, p2, 0, 0, 0, 0, id)
#define __SYSCALL3(id, p1, p2, p3) __syscall3(p1, p2, p3, 0, 0, 0, id)
#define __SYSCALL4(id, p1, p2, p3, p4) __syscall4(p1, p2, p3, p4, 0, 0, id)
#define __SYSCALL5(id, p1, p2, p3, p4, p5) __syscall5(p1, p2, p3, p4, p5, 0, id)
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \
__syscall(p1, p2, p3, p4, p5, p6,id)
__syscall6(p1, p2, p3, p4, p5, p6, id)
 
extern void __main(void *pcb_ptr);
extern void __exit(void);
/branches/sparc/uspace/lib/libc/include/udebug.h
0,0 → 1,58
/*
* 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
*/
 
#ifndef LIBC_UDEBUG_H_
#define LIBC_UDEBUG_H_
 
#include <kernel/udebug/udebug.h>
#include <sys/types.h>
#include <libarch/types.h>
 
typedef sysarg_t thash_t;
 
int udebug_begin(int phoneid);
int udebug_end(int phoneid);
int udebug_set_evmask(int phoneid, udebug_evmask_t mask);
int udebug_thread_read(int phoneid, void *buffer, size_t n,
size_t *copied, size_t *needed);
int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n);
int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer);
int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
sysarg_t *val0, sysarg_t *val1);
int udebug_stop(int phoneid, thash_t tid);
 
#endif
 
/** @}
*/
/branches/sparc/uspace/lib/libc/include/loader/pcb.h
40,7 → 40,8
 
typedef void (*entry_point_t)(void);
 
/**
/** Program Control Block.
*
* Holds pointers to data passed from the program loader to the program
* and/or to the dynamic linker. This includes the program entry point,
* arguments, environment variables etc.
/branches/sparc/uspace/lib/libc/include/loader/loader.h
0,0 → 1,59
/*
* 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 fs
* @{
*/
/** @file
* @brief Program loader interface.
*/
 
#ifndef LIBC_LOADER_H_
#define LIBC_LOADER_H_
 
#include <task.h>
 
/** Abstraction of a loader connection */
typedef struct {
/** ID of the phone connected to the loader. */
int phone_id;
} loader_t;
 
extern loader_t *loader_spawn(void);
extern int loader_get_task_id(loader_t *, task_id_t *);
extern int loader_set_pathname(loader_t *, const char *);
extern int loader_set_args(loader_t *, char *const []);
extern int loader_load_program(loader_t *);
extern int loader_run(loader_t *);
extern void loader_abort(loader_t *);
 
#endif
 
/**
* @}
*/
/branches/sparc/uspace/lib/libc/include/ipc/ipc.h
283,11 → 283,16
extern int ipc_share_out_finalize(ipc_callid_t callid, void *dst);
extern int ipc_data_read_start(int phoneid, void *dst, size_t size);
extern int ipc_data_read_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_data_read_finalize(ipc_callid_t callid, void *src, size_t size);
extern int ipc_data_write_start(int phoneid, void *src, size_t size);
extern int ipc_data_read_finalize(ipc_callid_t callid, const void *src,
size_t size);
extern int ipc_data_write_start(int phoneid, const void *src, size_t size);
extern int ipc_data_write_receive(ipc_callid_t *callid, size_t *size);
extern int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size);
 
#include <task.h>
 
extern int ipc_connect_kbox(task_id_t id);
 
#endif
 
/** @}
/branches/sparc/uspace/lib/libc/include/ipc/loader.h
32,15 → 32,17
/** @file
*/
 
#ifndef LIBC_LOADER_H_
#define LIBC_LOADER_H_
#ifndef LIBC_IPC_LOADER_H_
#define LIBC_IPC_LOADER_H_
 
#include <ipc/ipc.h>
 
typedef enum {
LOADER_HELLO = IPC_FIRST_USER_METHOD,
LOADER_GET_TASKID,
LOADER_SET_PATHNAME,
LOADER_SET_ARGS,
LOADER_LOAD,
LOADER_RUN
} fb_request_t;
 
/branches/sparc/uspace/lib/libc/Makefile.toolchain
27,7 → 27,7
#
 
DEFS = -DARCH=$(ARCH)
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include
CFLAGS = -fno-builtin -Wall -Werror-implicit-function-declaration -Wmissing-prototypes -O3 -nostdlib -nostdinc -I$(LIBC_PREFIX)/include -pipe
LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS =
#-Werror
/branches/sparc/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/sparc/uspace/lib/libc/generic/task.c
34,14 → 34,10
*/
 
#include <task.h>
#include <ipc/ipc.h>
#include <ipc/loader.h>
#include <libc.h>
#include <string.h>
#include <stdlib.h>
#include <async.h>
#include <errno.h>
#include <vfs/vfs.h>
#include <loader/loader.h>
 
task_id_t task_get_id(void)
{
52,134 → 48,62
return task_id;
}
 
static int task_spawn_loader(void)
{
int phone_id, rc;
 
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
if (rc != 0)
return rc;
 
return phone_id;
}
 
static int loader_set_args(int phone_id, const char *argv[])
{
aid_t req;
ipc_call_t answer;
ipcarg_t rc;
 
const char **ap;
char *dp;
char *arg_buf;
size_t buffer_size;
size_t len;
 
/*
* 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(phone_id, LOADER_SET_ARGS, &answer);
rc = ipc_data_write_start(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;
}
 
/** Create a new task by running an executable from VFS.
/** 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, const char *argv[])
task_id_t task_spawn(const char *path, char *const argv[])
{
int phone_id;
ipc_call_t answer;
aid_t req;
loader_t *ldr;
task_id_t task_id;
int rc;
ipcarg_t retval;
 
char *pa;
size_t pa_len;
 
pa = absolutize(path, &pa_len);
if (!pa)
/* Spawn a program loader. */
ldr = loader_spawn();
if (ldr == NULL)
return 0;
 
/* Spawn a program loader */
phone_id = task_spawn_loader();
if (phone_id < 0)
return 0;
/* Get task ID. */
rc = loader_get_task_id(ldr, &task_id);
if (rc != EOK)
goto error;
 
/*
* Say hello so that the loader knows the incoming connection's
* phone hash.
*/
rc = async_req_0_0(phone_id, LOADER_HELLO);
/* Send program pathname. */
rc = loader_set_pathname(ldr, path);
if (rc != EOK)
return 0;
goto error;
 
/* Send program pathname */
req = async_send_0(phone_id, LOADER_SET_PATHNAME, &answer);
rc = ipc_data_write_start(phone_id, (void *)pa, pa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
return 1;
}
 
async_wait_for(req, &retval);
if (retval != EOK)
/* Send arguments. */
rc = loader_set_args(ldr, argv);
if (rc != EOK)
goto error;
 
/* Send arguments */
rc = loader_set_args(phone_id, argv);
/* Load the program. */
rc = loader_load_program(ldr);
if (rc != EOK)
goto error;
 
/* Request loader to start the program */
rc = async_req_0_0(phone_id, LOADER_RUN);
/* Run it. */
/* Load the program. */
rc = loader_run(ldr);
if (rc != EOK)
goto error;
 
/* Success */
ipc_hangup(phone_id);
return 1;
 
free(ldr);
return task_id;
 
/* Error exit */
error:
ipc_hangup(phone_id);
loader_abort(ldr);
free(ldr);
 
return 0;
}
 
/branches/sparc/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/sparc/uspace/lib/libc/generic/string.c
1,5 → 1,7
/*
* Copyright (c) 2005 Martin Decky
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com>
* Copyright (c) 1988, 1993 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
396,5 → 398,52
return (char *) memcpy(ret, s1, len);
}
 
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * strtok_r(char *s, const char *delim, char **last)
{
char *spanp, *tok;
int c, sc;
 
if (s == NULL && (s = *last) == NULL)
return (NULL);
 
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
 
if (c == 0) { /* no non-delimiter characters */
*last = NULL;
return (NULL);
}
 
tok = s - 1;
 
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = '\0';
*last = s;
return (tok);
}
} while (sc != 0);
}
}
 
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * strtok(char *s, const char *delim)
{
static char *last;
 
return (strtok_r(s, delim, &last));
}
 
/** @}
*/
/branches/sparc/uspace/lib/libc/generic/loader.c
0,0 → 1,267
/*
* 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 <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.
* @return Pointer to the loader connection structure (should be
* de-allocated using free() after use).
*/
loader_t *loader_spawn(void)
{
int phone_id, rc;
loader_t *ldr;
 
/*
* Ask kernel to spawn a new loader task.
*/
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
if (rc != 0)
return NULL;
 
/*
* Say hello so that the loader knows the incoming connection's
* phone hash.
*/
rc = async_req_0_0(phone_id, LOADER_HELLO);
if (rc != EOK)
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/sparc/uspace/lib/libc/generic/ipc.c
847,7 → 847,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,7 → 860,7
*
* @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 async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
(ipcarg_t) size);
909,6 → 909,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/sparc/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/sparc/uspace/lib/libc/generic/vfs/vfs.c
116,7 → 116,7
return vfs_phone;
}
 
static int device_get_handle(char *name, dev_handle_t *handle)
static int device_get_handle(const char *name, dev_handle_t *handle)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
0);
364,9 → 364,9
}
}
off_t newoffs;
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);
374,7 → 374,7
if (rc != EOK)
return (off_t) -1;
return newoffs;
return (off_t) newoffs;
}
 
int ftruncate(int fildes, off_t length)
599,6 → 599,7
cwd_path = pa;
cwd_len = pa_len;
futex_up(&cwd_futex);
return EOK;
}
 
char *getcwd(char *buf, size_t size)
/branches/sparc/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 {
/branches/sparc/uspace/lib/libc/generic/smc.c
34,6 → 34,7
 
#include <libc.h>
#include <sys/types.h>
#include <smc.h>
 
int smc_coherence(void *address, size_t size)
{
/branches/sparc/uspace/lib/libc/Makefile
71,6 → 71,7
generic/sysinfo.c \
generic/ipc.c \
generic/async.c \
generic/loader.c \
generic/getopt.c \
generic/libadt/list.o \
generic/libadt/hash_table.o \
78,6 → 79,7
generic/err.c \
generic/stdlib.c \
generic/mman.c \
generic/udebug.c \
generic/vfs/vfs.c \
generic/vfs/canonify.c
 
104,7 → 106,7
find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \;
 
depend: kerninc
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
/branches/sparc/uspace/lib/libc/arch/sparc64/include/syscall.h
38,6 → 38,14
#include <sys/types.h>
#include <kernel/syscall/syscall.h>
 
#define __syscall0 __syscall
#define __syscall1 __syscall
#define __syscall2 __syscall
#define __syscall3 __syscall
#define __syscall4 __syscall
#define __syscall5 __syscall
#define __syscall6 __syscall
 
static inline sysarg_t
__syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3,
const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, const syscall_t id)
/branches/sparc/uspace/lib/libc/arch/ia64/include/syscall.h
36,6 → 36,8
#ifndef LIBC_ia64_SYSCALL_H_
#define LIBC_ia64_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/sparc/uspace/lib/libc/arch/arm32/include/syscall.h
30,12 → 30,14
* @{
*/
/** @file
* @brief Empty.
* @brief
*/
 
#ifndef LIBC_arm32_SYSCALL_H_
#define LIBC_arm32_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/sparc/uspace/lib/libc/arch/ppc32/include/syscall.h
36,6 → 36,8
#ifndef LIBC_ppc32_SYSCALL_H_
#define LIBC_ppc32_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/sparc/uspace/lib/libc/arch/amd64/include/syscall.h
36,6 → 36,8
#ifndef LIBC_amd64_SYSCALL_H_
#define LIBC_amd64_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/sparc/uspace/lib/libc/arch/ppc64/include/syscall.h
36,6 → 36,8
#ifndef LIBC_ppc64_SYSCALL_H_
#define LIBC_ppc64_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/sparc/uspace/lib/libc/arch/mips32/include/syscall.h
36,6 → 36,8
#ifndef LIBC_mips32_SYSCALL_H_
#define LIBC_mips32_SYSCALL_H_
 
#define LIBARCH_SYSCALL_GENERIC
 
#include <syscall.h>
 
#endif
/branches/sparc/uspace/lib/libc/arch/ia32/include/syscall.h
36,8 → 36,25
#ifndef LIBC_ia32_SYSCALL_H_
#define LIBC_ia32_SYSCALL_H_
 
#include <syscall.h>
#include <sys/types.h>
#include <kernel/syscall/syscall.h>
 
#define __syscall0 __syscall_sysenter
#define __syscall1 __syscall_sysenter
#define __syscall2 __syscall_sysenter
#define __syscall3 __syscall_sysenter
#define __syscall4 __syscall_sysenter
#define __syscall5 __syscall_int
#define __syscall6 __syscall_int
 
extern sysarg_t
__syscall_sysenter(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
const sysarg_t, const sysarg_t, const syscall_t);
 
extern sysarg_t
__syscall_int(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
const sysarg_t, const sysarg_t, const syscall_t);
 
#endif
 
/** @}
/branches/sparc/uspace/lib/libc/arch/ia32/src/syscall.S
28,14 → 28,14
 
.text
 
/** Syscall wrapper.
/** Syscall wrapper - INT $0x30 version.
*
* Mind the order of arguments. First two arguments and the syscall number go to
* scratch registers. An optimized version of this wrapper for fewer arguments
* could benefit from this and not save unused registers on the stack.
*/
.global __syscall
__syscall:
.global __syscall_int
__syscall_int:
pushl %ebx
pushl %esi
pushl %edi
53,3 → 53,38
popl %esi
popl %ebx
ret
 
 
/** Syscall wrapper - SYSENTER version.
*
* This is an optimized version of syscall for four or less arguments. Note
* that EBP and EDI are used to remember user stack address and the return
* address. The kernel part doesn't save DS, ES and FS so the handler restores
* these to the selector immediately following CS (it must be the flat data
* segment, otherwise the SYSENTER wouldn't work in the first place).
*/
.global __syscall_sysenter
__syscall_sysenter:
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
mov %esp, %ebp
lea ra, %edi
movl 20(%esp), %edx # First argument.
movl 24(%esp), %ecx # Second argument.
movl 28(%esp), %ebx # Third argument.
movl 32(%esp), %esi # Fourth argument.
movl 44(%esp), %eax # Syscall number.
sysenter
ra:
movw %cs, %cx
addw $8, %cx
movw %cx, %ds
movw %cx, %es
movw %cx, %fs
popl %ebp
popl %edi
popl %esi
popl %ebx
ret
/branches/sparc/uspace/srv/loader/main.c
46,6 → 46,7
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bool.h>
#include <fcntl.h>
#include <sys/types.h>
#include <ipc/ipc.h>
77,6 → 78,33
/** Buffer holding all arguments */
static char *arg_buf = NULL;
 
static elf_info_t prog_info;
static elf_info_t interp_info;
 
static bool is_dyn_linked;
 
 
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
task_id_t task_id;
size_t len;
 
task_id = task_get_id();
 
if (!ipc_data_read_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (len > sizeof(task_id)) len = sizeof(task_id);
 
ipc_data_read_finalize(callid, &task_id, len);
ipc_answer_0(rid, EOK);
}
 
 
/** Receive a call setting pathname of the program to execute.
*
* @param rid
191,20 → 219,16
argv[n] = NULL;
}
 
 
/** Load and run the previously selected program.
/** Load the previously selected program.
*
* @param rid
* @param request
* @return 0 on success, !0 on error.
*/
static int loader_run(ipc_callid_t rid, ipc_call_t *request)
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
 
elf_info_t prog_info;
elf_info_t interp_info;
 
// printf("Load program '%s'\n", pathname);
 
rc = elf_load_file(pathname, 0, &prog_info);
224,9 → 248,8
/* Statically linked program */
// printf("Run statically linked program\n");
// printf("entry point: 0x%llx\n", prog_info.entry);
is_dyn_linked = false;
ipc_answer_0(rid, EOK);
close_console();
elf_run(&prog_info, &pcb);
return 0;
}
 
244,17 → 267,40
pcb.rtld_dynamic = interp_info.dynamic;
pcb.rtld_bias = RTLD_BIAS;
 
printf("run dynamic linker\n");
printf("entry point: 0x%llx\n", interp_info.entry);
close_console();
 
is_dyn_linked = true;
ipc_answer_0(rid, EOK);
elf_run(&interp_info, &pcb);
 
/* Not reached */
return 0;
}
 
 
/** Run the previously loaded program.
*
* @param rid
* @param request
* @return 0 on success, !0 on error.
*/
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
{
if (is_dyn_linked == true) {
/* Dynamically linked program */
printf("run dynamic linker\n");
printf("entry point: 0x%llx\n", interp_info.entry);
close_console();
 
ipc_answer_0(rid, EOK);
elf_run(&interp_info, &pcb);
 
} else {
/* Statically linked program */
close_console();
ipc_answer_0(rid, EOK);
elf_run(&prog_info, &pcb);
}
 
/* Not reached */
}
 
/** Handle loader connection.
*
* Receive and carry out commands (of which the last one should be
271,18 → 317,23
 
while (1) {
callid = async_get_call(&call);
// printf("received call from phone %d, method=%d\n",
// call.in_phone_hash, IPC_GET_METHOD(call));
 
switch (IPC_GET_METHOD(call)) {
case LOADER_GET_TASKID:
loader_get_taskid(callid, &call);
continue;
case LOADER_SET_PATHNAME:
loader_set_pathname(callid, &call);
continue;
case LOADER_SET_ARGS:
loader_set_args(callid, &call);
continue;
case LOADER_LOAD:
loader_load(callid, &call);
continue;
case LOADER_RUN:
loader_run(callid, &call);
exit(0);
continue;
/* Not reached */
default:
retval = ENOENT;
break;
/branches/sparc/uspace/srv/vfs/vfs.c
49,8 → 49,6
 
#define NAME "vfs"
 
#define dprintf(...) printf(__VA_ARGS__)
 
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
{
bool keep_on_going = 1;
/branches/sparc/uspace/srv/vfs/vfs_ops.c
153,7 → 153,7
return;
}
/* Allocate buffer for the mount point data being received. */
uint8_t *buf;
char *buf;
buf = malloc(size + 1);
if (!buf) {
ipc_answer_0(callid, ENOMEM);
/branches/sparc/uspace/Makefile
48,6 → 48,7
srv/devmap \
app/tetris \
app/tester \
app/trace \
app/klog \
app/init \
app/bdsh