Builtins
Header for builtin function registry and declarations.
Defines the t_builtin_fn type and declares builtin functions. Also includes the builtin lookup function.
- Author
zweng, jguillem, pulgamecanica
Typedefs
-
typedef struct s_shell t_shell
Forward declaration to avoid circular dependency with 42sh.h
-
typedef int (*t_builtin_fn)(struct s_shell *shell, int argc, char **argv)
Builtin function type.
Every builtin shares this signature.
argv[0]is the builtin name itself,argv[argc]isNULL. Return value is the exit status the shell should observe.- Param shell:
Pointer to the central shell state, for accessing variables, jobs, etc.
- Param argc:
Argument count (number of elements in
argv).- Param argv:
Argument vector (
argv[0]is the command name).- Return:
Exit status code (0 for success, non-zero for failure).
Functions
-
t_builtin_fn builtin_get(const char *name)
Look up a builtin function by name.
- Parameters:
name – Name of the builtin function to retrieve
- Returns:
Pointer to the builtin function, or
NULLifnameis not a registered builtin.- Returns:
Pointer to the builtin function, or NULL if not found
-
int builtin_is_builtin(const char *name)
Test whether
nameis a registered builtin.- Returns:
Non-zero if
nameis a builtin, 0 otherwise.
-
int builtin_echo(struct s_shell *shell, int argc, char **argv)
Print arguments separated by spaces, followed by a newline.
Usage:
echo [-neE] [arg ...]Options may be combined (e.g.
-nE). Unknown letters disable option parsing for that token, so-xis printed literally.Option
Effect
-nSuppress the trailing newline.
-eInterpret backslash escapes (
\n,\t,\xNN, …).-EDisable backslash interpretation (default).
Examples:
echo hello world # hello world echo -n no-newline # no-newline echo -e 'a\tb\nc' # a<TAB>b<NEWLINE>c echo -E 'literal\\n' # literal\n
- Returns:
Always 0.
-
int builtin_cd(struct s_shell *shell, int argc, char **argv)
Change the shell’s current working directory.
Usage:
cd [-L|-P] [--] [dir]With no argument, changes to
$HOME. The argument-switches to the previous directory ($OLDPWD) and prints the new path.--ends option parsing so a directory literally named-foocan be reached.Option
Effect
-LLogical: keep symlinks in
PWD(default).-PPhysical: resolve symlinks via
realpath.After a successful change,
OLDPWDis set to the previousPWDandPWDis updated.Examples:
cd # go to $HOME cd /tmp # absolute path cd .. # parent directory cd - # back to previous directory, prints it cd -P /var/run # follow symlinks cd -- -weird-dir-name # directory whose name starts with '-'
- Returns:
0 on success, 1 on filesystem error (no such directory, not a directory, permission denied, name too long,
HOME/OLDPWDunset), 2 on usage error (invalid option, too many arguments).
-
int builtin_pwd(struct s_shell *shell, int argc, char **argv)
Print the current working directory.
Usage:
pwd [-L|-P]Option
Effect
-LLogical: print
$PWD(default).-PPhysical: print
getcwd(3)output (symlinks resolved).The default
-Lform is what makescd /bin; pwdreport/bineven when/binis a symlink to/usr/bin— the shell tracks the logical path the user typed, not what the kernel resolved.- Returns:
0 on success, 1 on getcwd failure or usage error.
-
int builtin_exit(struct s_shell *shell, int argc, char **argv)
Exit the shell.
Usage:
exit [n]If
nis supplied, the shell exits with statusn & 0xFF(POSIX truncation to 8 bits). With no argument, exits with the status of the most recently executed command ($?).Examples:
exit # exit with $? exit 0 # exit success exit 42 # exit with status 42 exit -1 # exit with status 255 (-1 & 0xFF) exit foo # error: "numeric argument required", exit 2 exit 1 2 # error: "too many arguments", returns 1
- Returns:
On success the shell terminates and never returns to the caller. On usage error: 2 (non-numeric argument) or 1 (more than one argument — the shell is not exited in this case).
-
int builtin_type(struct s_shell *shell, int argc, char **argv)
Describe how each name would be interpreted as a command.
Usage:
type [-tpa] name [name ...]Option
Effect
(none)
name is a shell builtin/name is /path/name not found-tPrint one word:
builtinorfile(nothing if not found).-pPrint the
$PATHresolution of a disk command only.-aPrint the builtin entry and every
$PATHmatch.Options may be combined (
-ta);--ends option parsing. An unknown option is reported on stderr and yields exit status 2.Examples:
type cd ls bogus # cd is a shell builtin # ls is /usr/bin/ls # bogus not found type -t ls # file type -p ls # /usr/bin/ls
- Returns:
0 if every name was identified, 1 if any name was not found, 2 on an invalid option.
-
int builtin_jobs(struct s_shell *shell, int argc, char **argv)
List active jobs known to the shell.
Usage:
jobsOutput format, one line per job:
[<id>] <marker> <status>\t<command-line>
<marker>is+for the current job and a space otherwise.<status>isRunning,Stopped, orDone. Listing a job clears its pending notification flag.Example:
sleep 100 & sleep 200 & jobs # [1] Running sleep 100 # [2] + Running sleep 200
- Returns:
Always 0.
-
int builtin_fg(struct s_shell *shell, int argc, char **argv)
Resume a job in the foreground.
Usage:
fg [job_spec]Brings the selected job to the foreground, prints its command line, and waits for it to finish or stop. With no argument, acts on the current job (
%+).job_specaccepts:Spec
Meaning
(omitted)
The current job.
%,%%,%+The current job.
%-The previous current job.
%<n>Job whose id is
<n>(the number in[ ]).%<str>Most recent job whose command line begins with
<str>.Examples:
sleep 100 & # [1] 12345 fg %1 # resume job 1 in foreground fg # resume the current job fg %sleep # resume job whose command begins with "sleep"
- Returns:
Exit status of the resumed job, or 1 if no matching job exists.
-
int builtin_bg(struct s_shell *shell, int argc, char **argv)
Resume a stopped job in the background.
Usage:
bg [job_spec]Sends
SIGCONTto the selected job and lets it continue without occupying the terminal. The job spec syntax is identical tofg(see builtin_fg). With no argument, acts on the current job.Examples:
sleep 100 # ... press Ctrl-Z # [1]+ Stopped sleep 100 bg # resume in background bg %1 # same, by job id
- Returns:
0 on success, 1 if no matching job exists.
-
int builtin_kill(struct s_shell *shell, int argc, char **argv)
Send a signal to processes or
jobspecjobs.Usage:
kill [-l] [-s sig | -sig | -signum] pid|jobspec ...-lwith no further argument lists every recognised signal name. Without-s/-signal/-signum, the default signal isSIGTERM(15).jobspecresolves throughjob_find_by_specand signals the whole process group (-pgid). Numeric arguments are passed verbatim tokill(2).- Returns:
0 if every target was signalled, 1 if any failed (no such job, invalid signal, unreachable pid).
-
int builtin_history(struct s_shell *shell, int argc, char **argv)
Print the command history.
Usage:
history [n]With no argument, prints every entry currently held by readline. With a positive integer
n, prints only the lastnentries. Non-positivenprints nothing. Each line is<index> <command>where<index>starts athistory_base(typically 1).Examples:
history # print full history history 5 # print last 5 commands
- Returns:
Always 0.
-
int builtin_set(struct s_shell *shell, int argc, char **argv)
The set builtin command.
Usage:
set [NAME=VALUE ...]With no arguments, displays all variables in
NAME=VALUEformat.Each
NAME=VALUEargument sets a variable.
Examples:
set # display all variables set var1=value1 # set a variable set x=10 y=hello # set multiple variables
- Parameters:
shell – Pointer to the shell state
argc – Argument count
argv – Argument vector
- Returns:
0 on success, 1 on error
-
int builtin_unset(struct s_shell *shell, int argc, char **argv)
The unset builtin command.
Usage:
unset name [name ...]Removes one or more variables by name. Each argument should be a valid variable name (identifier). If a name is not found, unset succeeds silently (POSIX behavior).
Examples:
unset var1 # remove a variable unset x y z # remove multiple variables unset nonexistent # succeeds silently
- Parameters:
shell – Pointer to the shell state
argc – Argument count
argv – Argument vector
- Returns:
0 on success, 1 on error (invalid identifier)
-
int builtin_export(struct s_shell *shell, int argc, char **argv)
The export builtin command.
Usage:
export [name] [name=value ...]With no arguments, displays all exported variables in exportable format.
With
name(identifier), marks the variable for export to child processes.With
NAME=VALUEargument, sets the variable and marks it for export.
Examples:
export # display all exported variables export PATH # export existing PATH variable export var1=value1 # set and export a variable export x=10 MYVAR=hello # set and export multiple variables
- Parameters:
shell – Pointer to the shell state
argc – Argument count
argv – Argument vector
- Returns:
0 on success, 1 on error
-
int builtin_hash(struct s_shell *shell, int argc, char **argv)
Manage the shell’s PATH-lookup cache.
Usage:
hash [-r] [-p path] [-dt] [name ...]Form
Effect
(no args)
Print cached entries (
hits<TAB>command).name [name ...]Resolve each name through
$PATHand cache it.-rForget every cached entry.
-d name [name ...]Forget specific entries.
-p path nameCache
name -> pathwithout consulting$PATH.-t name [name ...]Print the cached path for each name.
The cache powers
find_command, which consults this table before walking$PATH- so a frequent command costs one strcmp instead of a directory scan.- Returns:
0 on success, 1 on lookup failure (unknown name to resolve, delete, or print), 2 on usage error (unknown flag, missing operand, mutually-exclusive flags).
-
int builtin_alias(struct s_shell *shell, int argc, char **argv)
The alias builtin command.
Usage:
alias [name[=value] ...]With no arguments, lists every alias as alias name=’value
, sorted by name, with embedded single quotes escaped as’’’.Withname=value, defines or redefines an alias.Withname`, prints that alias, or reports it as not found.
- Returns:
0 on success, 1 if a queried name is not an alias.
-
int builtin_unalias(struct s_shell *shell, int argc, char **argv)
The unalias builtin command.
Usage:
unalias [-a] name [name ...]-aremoves every alias.Each
nameremoves one alias; an unknown name is reported on stderr.
- Returns:
0 on success, 1 if a name was not an alias or on usage error.
-
int builtin_test(struct s_shell *shell, int argc, char **argv)
Execute the shell builtin
test.- Parameters:
shell – Pointer to the current shell state.
argc – Number of arguments in argv.
argv – Array of argument strings.
- Returns:
Exit status for the builtin command.
-
struct t_test_context
- #include <builtins.h>
t_test_context - Context structure for test command execution @argc: Argument count for the test command @argv: Argument vector containing test command arguments @pos: Current position or index within the argument parsing
This structure maintains the state and arguments needed to execute and parse test builtin commands in the shell.
registry
Builtin function registry and implementations.
- Author
pulgamecanica
Functions
-
t_builtin_fn builtin_get(const char *name)
Look up a builtin function by name.
- Parameters:
name – Name of the builtin function to retrieve
- Returns:
Pointer to the builtin function, or NULL if not found
-
int builtin_is_builtin(const char *name)
Test whether
nameis a registered builtin.- Returns:
Non-zero if
nameis a builtin, 0 otherwise.
Variables
- static const t_builtin_entry g_builtins [] = {{"history",builtin_history},{"echo",builtin_echo},{"cd",builtin_cd},{"pwd",builtin_pwd},{"jobs",builtin_jobs},{"fg",builtin_fg},{"bg",builtin_bg},{"kill",builtin_kill},{"exit",builtin_exit},{"type",builtin_type},{"set",builtin_set},{"unset",builtin_unset},{"export",builtin_export},{"hash",builtin_hash},{"alias",builtin_alias},{"unalias",builtin_unalias},{"test",builtin_test},{"[",builtin_test},{NULL, NULL}}
Builtin lookup table.
-
struct t_builtin_entry
bg
bg [spec] - resume a stopped job in the background.
- Author
pulgamecanica
cd
Implementation of the cd builtin command for the 42sh shell.
- Author
jguillem
Functions
-
static char *join_paths(char *old_path, char *relative)
Join a base path with a relative path, ensuring proper ‘/’ separation.
- Parameters:
old_path – : the base path
relative – : the relative path to append
- Returns:
The newly allocated combined path
-
static char *concatenate(char *base, char *add)
Concatenate two paths, inserting ‘/’ when needed and freeing base.
- Parameters:
base – : the base string
add – : the string to append
- Returns:
The resulting concatenated string
-
static int resolve_path(char **path)
Normalize a path by resolving ‘.’, ‘..’ and redundant separators.
- Parameters:
path – : pointer to the path string to resolve
- Returns:
0 on success, 1 if an error occurs (e.g. path too long)
-
static int access_failure(char *directory, char *path, char *oldpwd, char *msg)
Print a cd error message and free allocated resources.
- Parameters:
directory – : the directory argument provided by the user
path – : the resolved path
oldpwd – : the previous working directory
msg – : the error message to display
- Returns:
1 (failure)
-
static int no_such_file_or_directory(char *directory, char *path, char *oldpwd)
Handle No such file or directory error.
- Parameters:
directory – : the directory argument provided by the user
path – : the resolved path
oldpwd – : the previous working directory
- Returns:
1 (failure)
-
static int not_a_directory(char *directory, char *path, char *oldpwd)
Handle Not a directory error.
- Parameters:
directory – : the directory argument provided by the user
path – : the resolved path
oldpwd – : the previous working directory
- Returns:
1 (failure)
-
static int permission_denied(char *directory, char *path, char *oldpwd)
Handle Permission denied error.
- Parameters:
directory – : the directory argument provided by the user
path – : the resolved path
oldpwd – : the previous working directory
- Returns:
1 (failure)
-
static int filename_too_long(char *directory, char *path, char *oldpwd)
Handle File name too long error.
- Parameters:
directory – : the directory argument provided by the user
path – : the resolved path
oldpwd – : the previous working directory
- Returns:
1 (failure)
-
static int is_invalid_path(char *directory, char *path, char *oldpwd)
Validate the path (length, type, permissions)
- Parameters:
directory – : the directory argument provided by the user
path – : the resolved path
oldpwd – : the previous working directory
- Returns:
0 if valid, 1 if an error occurs
-
static void publish_pwd(t_shell *shell, const char *new_pwd, const char *oldpwd)
Update PWD/OLDPWD in the shell variable table and mark exported.
Using var_set (instead of setenv) is what makes
$PWDvisible to subsequent expansions and to the rebuilt child environ. var_set preserves the existing ‘exported’ flag, but PWD/OLDPWD may not have been inherited from the parent environment, so we call var_export to be safe.
-
static int change_directory(t_shell *shell, char *target, int argc, int physical)
Resolve and change the current working directory, updating PWD/OLDPWD.
- Parameters:
target – : the target directory argument
argc – : number of remaining arguments
physical – : flag indicating physical (-P) or logical (-L) resolution
- Returns:
0 on success, 1 on failure
-
static int detect_option(char *option)
detect if the string correspond to an option
- Parameters:
option – : a string from *argv
- Returns:
0 | 1
-
int builtin_cd(struct s_shell *shell, int argc, char **argv)
Change the shell’s current working directory.
Usage:
cd [-L|-P] [--] [dir]With no argument, changes to
$HOME. The argument-switches to the previous directory ($OLDPWD) and prints the new path.--ends option parsing so a directory literally named-foocan be reached.Option
Effect
-LLogical: keep symlinks in
PWD(default).-PPhysical: resolve symlinks via
realpath.After a successful change,
OLDPWDis set to the previousPWDandPWDis updated.Examples:
cd # go to $HOME cd /tmp # absolute path cd .. # parent directory cd - # back to previous directory, prints it cd -P /var/run # follow symlinks cd -- -weird-dir-name # directory whose name starts with '-'
- Returns:
0 on success, 1 on filesystem error (no such directory, not a directory, permission denied, name too long,
HOME/OLDPWDunset), 2 on usage error (invalid option, too many arguments).
echo
Implementation of the echo builtin command for the 42sh shell.
- Author
jguillem
Functions
-
static int is_valid_option(char *token, int *nl, int *escape)
check if the option is -e, -E, -N or a combination thereof
- Parameters:
token – : the token to analyze
nl – : pointer to int to know the trailing newline status
escape – : pointer to int to know the backslash interpretation status
- Returns:
1 | 0
-
static int is_valid_symbol(char c, char symbols[])
check if the symbol c own to the symbols list
- Parameters:
c – : symbol to check
symbols – : list of valid symbols
- Returns:
0 | 1
-
static void display_base(char **scout, int base)
: display the char corresponding to the base number given
- Parameters:
scout – : the pointer of pointer on the number
base – : the input base
-
static int display_token(char *token, int last, int escape)
display the token
- Parameters:
token – : char *
last – : flag to know if a trailing space is necessary
escape – : flag to know if there is a backslash interpretation
- Returns:
0 | 1
-
static int report_write_error(void)
Force buffered output to fd 1 and report any write failure.
Bash-posix-compatible behaviour: fd 1 may have been closed by a
>&-redirection, in which case the buffered stdio writes only surface as errors once we flush. clearerr() resets the stream so a later builtin (after the redirection is restored) can write again.- Returns:
0 on success, 1 if a write error was detected.
-
int builtin_echo(struct s_shell *shell, int argc, char **argv)
Print arguments separated by spaces, followed by a newline.
Usage:
echo [-neE] [arg ...]Options may be combined (e.g.
-nE). Unknown letters disable option parsing for that token, so-xis printed literally.Option
Effect
-nSuppress the trailing newline.
-eInterpret backslash escapes (
\n,\t,\xNN, …).-EDisable backslash interpretation (default).
Examples:
echo hello world # hello world echo -n no-newline # no-newline echo -e 'a\tb\nc' # a<TAB>b<NEWLINE>c echo -E 'literal\\n' # literal\n
- Returns:
Always 0.
exit
Implementation of the exit builtin command for the 42sh shell.
- Author
zweng
Functions
-
static int is_numeric(const char *str)
Check if a string is a valid numeric argument.
Allows optional leading ‘+’ or ‘-’, followed by digits only. Also rejects values that overflow long.
- Parameters:
str – The string to check.
- Returns:
1 if numeric, 0 otherwise.
-
int builtin_exit(struct s_shell *shell, int argc, char **argv)
Exit the shell.
Usage:
exit [n]If
nis supplied, the shell exits with statusn & 0xFF(POSIX truncation to 8 bits). With no argument, exits with the status of the most recently executed command ($?).Examples:
exit # exit with $? exit 0 # exit success exit 42 # exit with status 42 exit -1 # exit with status 255 (-1 & 0xFF) exit foo # error: "numeric argument required", exit 2 exit 1 2 # error: "too many arguments", returns 1
- Returns:
On success the shell terminates and never returns to the caller. On usage error: 2 (non-numeric argument) or 1 (more than one argument — the shell is not exited in this case).
fg
fg [spec] - resume a stopped job in the foreground.
- Author
pulgamecanica
Functions
-
static void no_such_job(const char *spec)
-
int builtin_fg(t_shell *shell, int argc, char **argv)
history
Implementation of the history builtin command for the 42sh shell.
- Author
pulgamecanica
Functions
-
static void print_entries(HIST_ENTRY **list, int start, int end)
Print the command history list.
Prints all entries of the history
- Parameters:
list – The list of history entries obtained from readline’s history_list()
start – The starting index in the history list to print from
end – The ending index in the history list to print to (exclusive)
-
int builtin_history(struct s_shell *shell, int argc, char **argv)
Print the command history.
Usage:
history [n]With no argument, prints every entry currently held by readline. With a positive integer
n, prints only the lastnentries. Non-positivenprints nothing. Each line is<index> <command>where<index>starts athistory_base(typically 1).Examples:
history # print full history history 5 # print last 5 commands
- Returns:
Always 0.
jobs
jobs builtin - list active background jobs.
- Author
pulgamecanica
Functions
-
int builtin_jobs(t_shell *shell, int argc, char **argv)
type
Implementation of the type builtin command for the 42sh shell.
- Author
zweng
Functions
-
static void type_invalid_option(char opt)
Report an unrecognised option letter on stderr.
-
static int parse_type_opts(int argc, char **argv, int *flags)
Parse leading -t/-p/-a options (combinable;
--ends parsing).- Parameters:
argc – Argument count.
argv – Argument vector.
flags – Out: bitmask of TYPE_F_* for the options seen.
- Returns:
Index of the first name argument, or -1 on an invalid option.
-
static void type_free_dirs(char **dirs)
Free a NULL-terminated string array.
-
static char *type_join(const char *dir, const char *name)
Build “dir/name”. Caller frees the result.
-
static int type_path_matches(t_shell *shell, const char *name)
Print every location holding an executable
name.A name containing ‘/’ is probed directly; otherwise every $PATH directory is walked and each match printed.
- Returns:
1 if at least one match was printed, 0 otherwise.
-
static int type_kind(t_shell *shell, const char *name)
type -t: print the one-word category (builtin/file).
-
static int type_path(t_shell *shell, const char *name)
type -p: print the resolved path of a disk command only.
-
static int type_all(t_shell *shell, const char *name)
type -a: print the builtin entry and every PATH match.
-
static int type_default(t_shell *shell, const char *name)
Default form: “<name> is a shell builtin” / “<name> is <path>”.
-
static int type_dispatch(t_shell *shell, const char *name, int flags)
Route one name to the handler selected by the parsed flags.
-
int builtin_type(struct s_shell *shell, int argc, char **argv)
Describe how each name would be interpreted as a command.
Usage:
type [-tpa] name [name ...]Option
Effect
(none)
name is a shell builtin/name is /path/name not found-tPrint one word:
builtinorfile(nothing if not found).-pPrint the
$PATHresolution of a disk command only.-aPrint the builtin entry and every
$PATHmatch.Options may be combined (
-ta);--ends option parsing. An unknown option is reported on stderr and yields exit status 2.Examples:
type cd ls bogus # cd is a shell builtin # ls is /usr/bin/ls # bogus not found type -t ls # file type -p ls # /usr/bin/ls
- Returns:
0 if every name was identified, 1 if any name was not found, 2 on an invalid option.