Commit bf73a988 authored by Seblu's avatar Seblu

--no commit message

--no commit message
parent 30a57534
......@@ -32,6 +32,7 @@ bin_PROGRAMS=42sh
src/exec/exec_node.c \
src/exec/exec_or.c \
src/exec/exec_if.c \
src/exec/exec_red.c \
src/exec/exec_sep.c \
src/exec/exec_sepand.c \
src/exec/exec_while.c \
......
/*
** builtin.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Tue Apr 11 00:22:44 2006 Seblu
** Last update Sun Nov 12 16:47:59 2006 Seblu
*/
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "builtin.h"
#include "../main/42sh.h"
#include "../ast/ast.h"
#include "../opt/opt.h"
#define BUILTIN_NUMBER 7
#define BUILTIN_BONUS_NUMBER 7
static const char *builtin_name[BUILTIN_NUMBER] =
{
"cd",
"echo",
"exit",
"shopt",
"source",
"unset",
"export"
};
static const char *builtin_bonus_name[BUILTIN_BONUS_NUMBER] =
{
".",
"..",
"set",
"varlist",
"funclist",
"exec",
"history"
};
static const t_func_builtin builtin_function[BUILTIN_NUMBER] =
{
builtin_cd,
builtin_echo,
builtin_exit,
builtin_shopt,
builtin_source,
builtin_unset,
builtin_export
};
static const t_func_builtin builtin_bonus_function[BUILTIN_BONUS_NUMBER] =
{
builtin_simpledot,
builtin_doubledot,
builtin_set,
builtin_varlist,
builtin_funclist,
builtin_exec,
builtin_history
};
/*!
** test if a command is a builtin
**
** @param name The name of the command
** @return 1 if \a name is a builtin, else 0
*/
int is_a_builtin(const char *name, struct s_42sh *sh)
{
register int i;
for (i = 0; i < BUILTIN_NUMBER; ++i)
if (!strcmp(name, builtin_name[i]))
return 1;
if (opt_isset("bonus", sh->opt))
for (i = 0; i < BUILTIN_BONUS_NUMBER; ++i)
if (!strcmp(name, builtin_bonus_name[i]))
return 1;
return 0;
}
/*!
** execute a shell builtin
**
** @param builtin_name The name of the builtin
** @param argv The builtin arguments, terminate by NULL, argv[0] = builtin_name
** @return The return value of the builtin
*/
int exec_builtin(struct s_cmd *cmd, struct s_42sh *sh)
{
register int i;
for (i = 0; i < BUILTIN_NUMBER; ++i)
if (!strcmp(cmd->argv[0], builtin_name[i]))
return builtin_function[i](cmd->argv, sh);
if (opt_isset("bonus", sh->opt))
for (i = 0; i < BUILTIN_BONUS_NUMBER; ++i)
if (!strcmp(cmd->argv[0], builtin_bonus_name[i]))
return builtin_bonus_function[i](cmd->argv, sh);
return 0;
}
/*
** builtin.h for 42sh in /home/seblu/svn/42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Nov 12 16:46:24 2006 Seblu
** Last update Sun Nov 12 16:47:03 2006 Seblu
*/
#ifndef BUILTIN_H_
# define BUILTIN_H_
struct s_42sh;
struct s_cmd;
typedef int (*t_func_builtin)(char *argv[], struct s_42sh *sh);
int is_a_builtin(const char *name, struct s_42sh *sh);
int exec_builtin(struct s_cmd *cmd, struct s_42sh *sh);
/*
** Regular builtin
*/
int builtin_cd(char *argv[], struct s_42sh *sh);
int builtin_echo(char *argv[], struct s_42sh *sh);
int builtin_shopt(char *argv[], struct s_42sh *sh);
int builtin_exit(char *argv[], struct s_42sh *sh);
int builtin_source(char *argv[], struct s_42sh *sh);
int builtin_unset(char *argv[], struct s_42sh *sh);
int builtin_export(char *argv[], struct s_42sh *sh);
/*
** Bonus builtin
*/
int builtin_simpledot(char *argv[], struct s_42sh *sh);
int builtin_doubledot(char *argv[], struct s_42sh *sh);
int builtin_set(char *argv[], struct s_42sh *sh);
int builtin_varlist(char *argv[], struct s_42sh *sh);
int builtin_funclist(char *argv[], struct s_42sh *sh);
int builtin_exec(char *argv[], struct s_42sh *sh);
int builtin_history(char *argv[], struct s_42sh *sh);
#endif /* ! BUILTIN_H_ */
/*
** builtin_cd.c for 42sh in /home/seblu/devel/c/42sh/src/execution
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Tue Apr 11 00:23:47 2006 Seblu
** Last update Sun May 21 19:17:53 2006 Seblu
*/
#include <ctype.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "../main/42sh.h"
#include "builtin.h"
#include "../var/var.h"
#include "mem.h"
static int cd_var(struct s_42sh *sh, const char *name);
static int cd_minus(struct s_42sh *sh);
static int secure_chdir(const char *path);
/*!
** Builtin cd.
** @param argv The tab of args: terminated by NULL, argv[0] = "cd"
** @param sh The 42sh structure
*/
int builtin_cd(char **argv, struct s_42sh *sh)
{
assert(sh && argv && argv[0]);
if (!argv[1])
return cd_var(sh, "HOME");
if (!strcmp("-", argv[1]))
return cd_minus(sh);
return secure_chdir(argv[1]);
}
/*!
** Change directory to home directory
**
** @param sh shell env
** @param name env var
**
** @return exit status
*/
static int cd_var(struct s_42sh *sh, const char *name)
{
const char *new_dir;
if (!(new_dir = var_get(sh->vars, name)))
{
fprintf(stderr, "42sh: cd: %s not set\n", name);
return 1;
}
return secure_chdir(new_dir);
}
/*!
** Return in previous directory
**
** @param sh shell info
**
** @return return status
*/
static int cd_minus(struct s_42sh *sh)
{
if (cd_var(sh, "OLDPWD"))
return 1;
return 0;
}
/*!
** Change of directory and on error, print good error.
**
** @param path new path
**
** @return error status with error code (0 is good)
*/
static int secure_chdir(const char *path)
{
const char *errormsg = "";
char *tmp;
errno = 0;
if (chdir(path))
{
if (errno == ENOENT)
errormsg = "No such file or directory";
else if (errno == EACCES)
errormsg = "Permission denied";
else if (errno == ENAMETOOLONG)
errormsg = "File name too long";
else if (errno == ENOTDIR)
errormsg = "Not a directory";
else if (errno == ELOOP)
errormsg = "Too many levels of symbolic links";
else
assert(0);
fprintf(stderr, "42sh: cd %s: %s\n", path, errormsg);
return 1;
}
if ((tmp = getenv("PWD")))
var_setenv("OLDPWD", tmp, !0);
var_setenv("PWD", (tmp = var_getcwd()), !0);
free(tmp);
return 0;
}
/*
** builtin_doubledot.c for 42sh in /home/seblu/devel/c/towork/42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Apr 8 18:02:31 2006 Seblu
** Last update Sun Apr 9 12:38:38 2006 SIGOURE Benoit
*/
#include <stddef.h>
#include "builtin.h"
#include "mem.h"
/*!
** Builtin double dot, allow you to cdup
**
** @param argv argv vector
** @param sh sh data
**
** @return builtin return success
*/
int builtin_doubledot(char *argv[], struct s_42sh *sh)
{
char *argv2[3];
argv2[0] = "cd";
argv2[1] = "..";
argv2[2] = NULL;
return builtin_cd(argv2, sh);
argv = argv;
}
/*
** builtin_echo.c for 42sh in /goinfre/seblu/builtins
**
** Made by Seblu
** Login <luttri_s@epita.fr>
**
** Started on Tue Mar 14 20:57:07 2006 Seblu
** Last update Wed Apr 12 02:02:07 2006 Seblu
*/
#include <ctype.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "../main/42sh.h"
#include "../opt/opt.h"
#include "mem.h"
#define isoctale(x) (((x) >= '0' && (x) <= '7') ? 1 : 0)
static int builtin_echo_ext(const char *);
static void builtin_echo_ext2(const char **, int *);
static void print_hex(const char **);
static void print_oct(const char **);
static void getoption(char *argv[], int *argp, int *line, int *ext);
static int fisdigit(const int c);
static int fisxdigit(const int c);
/*!
** Echo show all element on her line
**
** @param argc number of argument given
** @param argv vector to argument
** @param shopt option structure of shell
**
** @return sucess status
*/
int builtin_echo(char *argv[], struct s_42sh *sh)
{
int argp;
int ext = 0;
int line = 1;
int first;
assert(argv && argv[0] && sh);
ext = opt_isset("xpg_echo", sh->opt);
for (getoption(argv, &argp, &line, &ext), first = argp; argv[argp]; ++argp)
{
if (first != argp)
printf(" ");
if (ext)
{
if (!builtin_echo_ext(argv[argp]))
return fflush(stdout);
}
else
printf("%s", argv[argp]);
}
if (line)
printf("\n");
return fflush(stdout);
}
/*!
** Retreinve command line option
**
** @param argv argument vector
** @param argp argument position
** @param line line flag
** @param ext extended flag
*/
static void getoption(char *argv[], int *argp, int *line, int *ext)
{
char *carg;
for (*argp = 1; (carg = argv[*argp]); ++*argp)
if (*carg == '-')
for (++carg; *carg; ++carg)
if (*carg == 'e')
*ext = 1;
else if (*carg == 'E')
*ext = 0;
else if (*carg == 'n')
*line = 0;
else
return;
else
return;
}
/*!
** Interpreter for special char
**
** @param msg
*/
static int builtin_echo_ext(const char *msg)
{
int backed = 0;
for (; *msg; ++msg)
if (*msg == '\\' && !backed && (backed = 1))
continue;
else if (backed && *msg == 'a' && !(backed = 0))
putchar('\a');
else if (backed && *msg == 'b' && !(backed = 0))
putchar('\b');
else if (backed && *msg == 'c')
return 0;
else if (backed && *msg == 'e' && !(backed = 0))
putchar(0x1b);
else if (backed && *msg == 'f' && !(backed = 0))
putchar('\f');
else if (backed && *msg == 'n' && !(backed = 0))
putchar('\n');
else if (backed && *msg == 'r' && !(backed = 0))
putchar('\r');
else if (backed && *msg == 't' && !(backed = 0))
putchar('\t');
else
builtin_echo_ext2(&msg, &backed);
return 1;
}
/*!
** End of function builtin_echo_ext due to an stupid norme limitation.
**
** @param msg message to print
** @param backed if a backed char
*/
static void builtin_echo_ext2(const char **msg, int *backed)
{
if (*backed && **msg == '\\' && !(*backed = 0))
putchar('\\');
else if (*backed && **msg == 'v' && !(*backed = 0))
putchar('\v');
else if (*backed && fisdigit(**msg) && !(*backed = 0))
print_oct(msg);
else if (*backed && **msg == 'x' && !(*backed = 0) && (++*msg))
print_hex(msg);
else if (*backed && !(backed = 0))
printf("\\%c", **msg);
else
putchar(**msg);
}
/*!
** Print hexa number on stdout a number
**
** @param msg message to print
** @param base base of the number
*/
static void print_hex(const char **msg)
{
char buf[4];
char *end;
long n;
unsigned char c;
int i;
if (!fisxdigit(**msg))
return;
for (i = 0; fisxdigit(**msg) && i < 2; ++*msg, ++i)
buf[i] = **msg;
buf[i] = 0;
--*msg;
n = strtoul(buf, &end, 16);
printf("%c", (c = n));
}
/*!
** Print oct number on stdout a number
**
** @param msg message to print
** @param base base of the number
*/
static void print_oct(const char **msg)
{
char buf[5];
char *end;
unsigned long n;
unsigned char c;
int i;
int max;
if (!isoctale(**msg))
return;
max = (**msg == '0') ? 4 : 3;
for (i = 0; isoctale(**msg) && i < max; ++*msg, ++i)
buf[i] = **msg;
buf[i] = 0;
--*msg;
n = strtoul(buf, &end, 8);
printf("%c", (c = n));
}
/*!
** Function to say if c is a digit or not.
** It use macro isdigit, but due to epita coding style
** restriction about cast, it's impossible to call
** a macro wrote with int with char, because cast is forbidden
** and macro call, dont have the same right about parameter
** implicit cast (on netBSD)
**
** @param c character
**
** @return if \param c is a digit
*/
static int fisdigit(const int c)
{
return isdigit(c);
}
/*!
** Function to say if c is a digit or not.
** It use macro isdigit, but due to epita coding style
** restriction about cast, it's impossible to call
** a macro wrote with int with char, because cast is forbidden
** and macro call, dont have the same right about parameter
** implicit cast (on netBSD)
**
** @param c character
**
** @return if \param c is a hexa digit
*/
static int fisxdigit(const int c)
{
return isxdigit(c);
}
/*
** builtin_exec.c for 42sh in /goinfre/seblu/42sh/src/builtin
**
** Made by Seblu
** Login <luttri_s@epita.fr>
**
** Started on Thu May 11 10:00:36 2006 Seblu
** Last update Sun May 21 18:42:29 2006 Seblu
*/
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include "builtin.h"
#include "../main/42sh.h"
/*!
** Replace current process by which is given in arg
**
** @param argv arg vector
** @param sh shell struct
**
** @return success status
*/
int builtin_exec(char *argv[], struct s_42sh *sh)
{
assert(sh && argv);
if (!argv[1])
return 0;
if (execvp(argv[1], argv + 1) == -1)
{
perror("42sh: exec");
return 127;
}
return 0;
argv = argv;
sh = sh;
}
/*
** builtin_exit.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Nov 12 16:48:50 2006 Seblu
** Last update Sun Nov 12 16:49:42 2006 Seblu
*/
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include "builtin.h"
#include "../main/42sh.h"
/*!
** Terminate program
**
** @param argv vector to argument
** @param shopt option structure of shell
**
** @return
*/
int builtin_exit(char *argv[])
{
long i;
char *endptr;
assert(argv && argv[0]);
if (!argv[1])
{
/* if (isatty(fileno(stdin))) */
/* printf("exit\n"); */
i = sh->last_status;
sh_destroy(sh);
exit(i);
}
if (argv[2])
{
fprintf(stderr, "42sh : exit : too many arguments\n");
fflush(stderr);
return 1;
}
i = strtol(argv[1], &endptr, 10);
/* if (isatty(fileno(stdin))) */
/* printf("exit\n"); */
if (*endptr)
fprintf(stderr, "42sh: exit: %s: numeric argument required\n", argv[1]);
sh_destroy(sh);
exit((!*endptr) ? i : 255);
return 1;
}
/*
** builtin_export.c for 42sh in /goinfre/seblu/42sh/src/builtin
**
** Made by Seblu
** Login <luttri_s@epita.fr>
**
** Started on Thu May 11 09:32:30 2006 Seblu
** Last update Thu May 11 09:41:01 2006 Seblu
*/
#include <stdio.h>
#include "builtin.h"
int builtin_export(char *argv[], struct s_42sh *sh)
{
printf("export: not yet implemeted\n");
sh = sh;
argv = argv;
return 1;
}
/*
** builtin_funclist.c for 42sh in /goinfre/seblu/42sh/src/builtin
**
** Made by Seblu
** Login <luttri_s@epita.fr>
**
** Started on Thu May 11 10:00:36 2006 Seblu
** Last update Sun May 21 18:40:33 2006 Seblu
*/
#include <assert.h>
#include <stdio.h>
#include "builtin.h"
#include "../func/function.h"
#include "../main/42sh.h"
int builtin_funclist(char *argv[], struct s_42sh *sh)
{
assert(sh);
/* FIXME
func_print(sh->funcs);
*/
printf("Not yet implemented !\n");
return 0;
argv = argv;
sh = sh;
}
/*
** builtin_history.c for in /home/joel/42sh
**
** Made by joel
** Login <joel@epita.fr>
**
** Started on Wed May 17 12:28:30 2006 joel
** Last update Sun May 21 18:44:31 2006 Seblu
*/
#include <assert.h>
#include <stdio.h>
#include "../main/42sh.h"
#include "../history/history.h"
#include "builtin.h"
/*!
** Builtin history.
** @param argv The tab of args: terminated by NULL, argv[0] = "cd"
** @param sh The 42sh structure
*/
int builtin_history(char **argv, struct s_42sh *sh)
{
struct s_my_dlist *list;
char *elem;
int count = 1;
assert(sh && argv && argv[0]);
if (!sh->history->list)
return 0;
for (list = sh->history->list; list->next != NULL; list = list->next)
;
for (; list; list = list->prev, ++count)
fprintf(stdout, " %i %s\n", count, elem = list->elem);
return 0;
argv = argv;
}
/*
** builtin_set.c for 42sh in /goinfre/seblu/42sh/src/builtin
**
** Made by Seblu
** Login <luttri_s@epita.fr>
**
** Started on Thu May 11 09:32:30 2006 Seblu
** Last update Thu May 11 09:38:54 2006 Seblu
*/
#include <stdio.h>
#include "builtin.h"
int builtin_set(char *argv[], struct s_42sh *sh)
{
printf("set: not yet implemeted\n");
sh = sh;
argv = argv;
return 1;
}
/*
** builtin_shopt.c for 42sh in /goinfre/seblu/42sh/src