Implement profile(5) and shrc(5) in sh(1).
This commit is contained in:
parent
c6af3bc074
commit
159415c3b1
|
@ -214,13 +214,16 @@ bool login(const char* username)
|
||||||
int pipe_fds[2];
|
int pipe_fds[2];
|
||||||
if ( pipe2(pipe_fds, O_CLOEXEC) < 0 )
|
if ( pipe2(pipe_fds, O_CLOEXEC) < 0 )
|
||||||
return false;
|
return false;
|
||||||
|
char* login_shell;
|
||||||
|
if ( asprintf(&login_shell, "-%s", pwd->pw_shell) < 0 )
|
||||||
|
return close(pipe_fds[0]), close(pipe_fds[1]), false;
|
||||||
sigset_t oldset, sigttou;
|
sigset_t oldset, sigttou;
|
||||||
sigemptyset(&sigttou);
|
sigemptyset(&sigttou);
|
||||||
sigaddset(&sigttou, SIGTTOU);
|
sigaddset(&sigttou, SIGTTOU);
|
||||||
sigprocmask(SIG_BLOCK, &sigttou, &oldset);
|
sigprocmask(SIG_BLOCK, &sigttou, &oldset);
|
||||||
pid_t child_pid = fork();
|
pid_t child_pid = fork();
|
||||||
if ( child_pid < 0 )
|
if ( child_pid < 0 )
|
||||||
return close(pipe_fds[0]), close(pipe_fds[1]), false;
|
return free(login_shell), close(pipe_fds[0]), close(pipe_fds[1]), false;
|
||||||
if ( child_pid == 0 )
|
if ( child_pid == 0 )
|
||||||
{
|
{
|
||||||
sigdelset(&oldset, SIGINT);
|
sigdelset(&oldset, SIGINT);
|
||||||
|
@ -253,10 +256,11 @@ bool login(const char* username)
|
||||||
errno != ENOENT && errno != EACCES) ||
|
errno != ENOENT && errno != EACCES) ||
|
||||||
(execlp("/etc/session", "/etc/session", (const char*) NULL) < 0 &&
|
(execlp("/etc/session", "/etc/session", (const char*) NULL) < 0 &&
|
||||||
errno != ENOENT && errno != EACCES) ||
|
errno != ENOENT && errno != EACCES) ||
|
||||||
execlp(pwd->pw_shell, pwd->pw_shell, (const char*) NULL));
|
execlp(pwd->pw_shell, login_shell, (const char*) NULL));
|
||||||
write(pipe_fds[1], &errno, sizeof(errno));
|
write(pipe_fds[1], &errno, sizeof(errno));
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
|
free(login_shell);
|
||||||
close(pipe_fds[1]);
|
close(pipe_fds[1]);
|
||||||
int errnum;
|
int errnum;
|
||||||
if ( readall(pipe_fds[0], &errnum, sizeof(errnum)) < (ssize_t) sizeof(errnum) )
|
if ( readall(pipe_fds[0], &errnum, sizeof(errnum)) < (ssize_t) sizeof(errnum) )
|
||||||
|
|
|
@ -29,7 +29,9 @@ install: all
|
||||||
cp sh.1 $(DESTDIR)$(MANDIR)/man1/sh.1
|
cp sh.1 $(DESTDIR)$(MANDIR)/man1/sh.1
|
||||||
ln -sf sh.1 $(DESTDIR)$(MANDIR)/man1/sortix-sh.1
|
ln -sf sh.1 $(DESTDIR)$(MANDIR)/man1/sortix-sh.1
|
||||||
mkdir -p $(DESTDIR)$(MANDIR)/man5
|
mkdir -p $(DESTDIR)$(MANDIR)/man5
|
||||||
|
cp profile.5 $(DESTDIR)$(MANDIR)/man5/profile.5
|
||||||
cp proper-sh.5 $(DESTDIR)$(MANDIR)/man5/proper-sh.5
|
cp proper-sh.5 $(DESTDIR)$(MANDIR)/man5/proper-sh.5
|
||||||
|
cp shrc.5 $(DESTDIR)$(MANDIR)/man5/shrc.5
|
||||||
|
|
||||||
sortix-sh: $(SORTIX_SH_SRCS) *.h
|
sortix-sh: $(SORTIX_SH_SRCS) *.h
|
||||||
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $(SORTIX_SH_SRCS) -o $@
|
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $(SORTIX_SH_SRCS) -o $@
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
.Dd November 9, 2022
|
||||||
|
.Dt PROFILE 5
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm profile
|
||||||
|
.Nd login shell startup
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm ~/.profile
|
||||||
|
.Nm /etc/profile
|
||||||
|
.Nm /etc/default/profile
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
Interactive login shell sessions in
|
||||||
|
.Xr sh 1
|
||||||
|
execute the commands in the
|
||||||
|
.Nm
|
||||||
|
script upon startup, searching for the user's script at
|
||||||
|
.Pa ~/.profile ,
|
||||||
|
any system administrator provided script at
|
||||||
|
.Pa /etc/profile ,
|
||||||
|
or any operating system provided script at
|
||||||
|
.Pa /etc/default/profile ,
|
||||||
|
whichever exists first.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Xr shrc 5
|
||||||
|
script is run instead in interactive non-login shell sessions.
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width "/etc/default/profile" -compact
|
||||||
|
.It Pa ~/.profile
|
||||||
|
The user's
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
.It Pa /etc/profile
|
||||||
|
The system administor provided
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
.It Pa /etc/default/profile
|
||||||
|
The operating system provided
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
.El
|
||||||
|
.Sh EXAMPLES
|
||||||
|
To portably run the
|
||||||
|
.Xr shrc 5
|
||||||
|
script upon startup of non-login interactive shells in all shells:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
export ENV="$HOME/.shrc"
|
||||||
|
.Ed
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr dash 1 ,
|
||||||
|
.Xr sh 1 ,
|
||||||
|
.Xr shrc 5
|
||||||
|
.Sh BUGS
|
||||||
|
.Xr sh 1
|
||||||
|
is currently primitive and cannot execute most scripts.
|
||||||
|
Beware of sharing the
|
||||||
|
.Nm
|
||||||
|
script between it and other shells such as
|
||||||
|
.Xr dash 1 .
|
|
@ -42,6 +42,7 @@ static bool is_supported(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
case 'e': break;
|
case 'e': break;
|
||||||
case 'i': break;
|
case 'i': break;
|
||||||
|
case 'l': break;
|
||||||
case 's': break;
|
case 's': break;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
|
|
30
sh/sh.1
30
sh/sh.1
|
@ -6,10 +6,10 @@
|
||||||
.Nd shell command interpreter
|
.Nd shell command interpreter
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm sh
|
.Nm sh
|
||||||
.Op Fl ceis
|
.Op Fl ceils
|
||||||
.Op Ar script Oo argument ... Oc
|
.Op Ar script Oo argument ... Oc
|
||||||
.Nm sortix-sh
|
.Nm sortix-sh
|
||||||
.Op Fl ceis
|
.Op Fl ceils
|
||||||
.Op Ar script Oo argument ... Oc
|
.Op Ar script Oo argument ... Oc
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -50,6 +50,15 @@ argument contains the script's text instead of a path to the script file.
|
||||||
Exit if any command exit non-zero.
|
Exit if any command exit non-zero.
|
||||||
.It Fl i
|
.It Fl i
|
||||||
Interactively read and execute commands.
|
Interactively read and execute commands.
|
||||||
|
.It Fl l
|
||||||
|
The shell is a login shell.
|
||||||
|
Interactive shells run the
|
||||||
|
.Xr profile 5
|
||||||
|
script on startup instead of the
|
||||||
|
.Xr shrc
|
||||||
|
script.
|
||||||
|
This option is set if the shell is invoked by a name starting with a dash
|
||||||
|
.Sq - .
|
||||||
.It Fl s
|
.It Fl s
|
||||||
Read commands from the standard input (the default).
|
Read commands from the standard input (the default).
|
||||||
This option can be combined with the
|
This option can be combined with the
|
||||||
|
@ -62,6 +71,12 @@ argument before reading normally from the standard input
|
||||||
.Nm
|
.Nm
|
||||||
uses environment these variables:
|
uses environment these variables:
|
||||||
.Bl -tag -width "HISTFILE"
|
.Bl -tag -width "HISTFILE"
|
||||||
|
.It Ev ENV
|
||||||
|
File to execute on non-login interactive startup instead of
|
||||||
|
.Pa ~/.shrc
|
||||||
|
per
|
||||||
|
.Xr shrc 5 .
|
||||||
|
This variable is subject to path expansion.
|
||||||
.It Ev HISTFILE
|
.It Ev HISTFILE
|
||||||
Save the shell history in this file.
|
Save the shell history in this file.
|
||||||
The default is
|
The default is
|
||||||
|
@ -93,6 +108,9 @@ This variable takes precedence over
|
||||||
.El
|
.El
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "/etc/proper-sh" -compact
|
.Bl -tag -width "/etc/proper-sh" -compact
|
||||||
|
.It Pa ~/.profile , /etc/profile , /etc/default/profile
|
||||||
|
.Xr profile 5
|
||||||
|
script whose commands are run on non-login interactive shell startup.
|
||||||
.It Pa /etc/proper-sh
|
.It Pa /etc/proper-sh
|
||||||
Name of a better shell to use for non-interactive use per
|
Name of a better shell to use for non-interactive use per
|
||||||
.Xr proper-sh 5 .
|
.Xr proper-sh 5 .
|
||||||
|
@ -106,6 +124,12 @@ The saved shell history.
|
||||||
This location is controlled by the
|
This location is controlled by the
|
||||||
.Ev HISTFILE
|
.Ev HISTFILE
|
||||||
environment variable.
|
environment variable.
|
||||||
|
.It Pa ~/.shrc , /etc/shrc , /etc/default/shrc
|
||||||
|
.Xr shrc 5
|
||||||
|
script whose commands are run on login interactive shell startup.
|
||||||
|
The
|
||||||
|
.Ev ENV
|
||||||
|
environment variable overrides the search for the script if set.
|
||||||
.El
|
.El
|
||||||
.Sh EXIT STATUS
|
.Sh EXIT STATUS
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -113,6 +137,8 @@ exits with the same exit status as the last run command, or 0 if no command has
|
||||||
been run.
|
been run.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr dash 1 ,
|
.Xr dash 1 ,
|
||||||
|
.Xr profile 5 ,
|
||||||
.Xr proper-sh 5 ,
|
.Xr proper-sh 5 ,
|
||||||
.Xr session 5 ,
|
.Xr session 5 ,
|
||||||
|
.Xr shrc 5 ,
|
||||||
.Xr login 8
|
.Xr login 8
|
||||||
|
|
75
sh/sh.c
75
sh/sh.c
|
@ -2079,36 +2079,81 @@ static int run(FILE* fp,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char* find_rc(bool login)
|
||||||
|
{
|
||||||
|
const char* env = getenv("ENV");
|
||||||
|
if ( !login && env )
|
||||||
|
{
|
||||||
|
// TODO: Path expansion.
|
||||||
|
char* result = strdup(env);
|
||||||
|
if ( !result )
|
||||||
|
err(1, "malloc");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const char* home = getenv("HOME");
|
||||||
|
const char* rcname = login ? "profile" : "shrc";
|
||||||
|
const char* dirs[] = { home, "/etc", "/etc/default" };
|
||||||
|
bool found = false;
|
||||||
|
for ( size_t i = 0; !found && i < sizeof(dirs) / sizeof(dirs[0]); i++ )
|
||||||
|
{
|
||||||
|
char* rc;
|
||||||
|
if ( asprintf(&rc, "%s%s%s", dirs[i], i ? "/" : "/.", rcname) < 0 )
|
||||||
|
err(1, "malloc");
|
||||||
|
if ( (found = !access(rc, F_OK)) )
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int top(FILE* fp,
|
static int top(FILE* fp,
|
||||||
const char* fp_name,
|
const char* fp_name,
|
||||||
bool interactive,
|
bool interactive,
|
||||||
bool exit_on_error,
|
bool exit_on_error,
|
||||||
|
bool login,
|
||||||
bool* script_exited,
|
bool* script_exited,
|
||||||
int status)
|
int status)
|
||||||
{
|
{
|
||||||
if ( interactive )
|
if ( interactive )
|
||||||
{
|
{
|
||||||
const char* home;
|
const char* home = getenv("HOME");
|
||||||
const char* histfile = getenv("HISTFILE");
|
const char* histfile = getenv("HISTFILE");
|
||||||
if ( !histfile && (home = getenv("HOME")) )
|
if ( !histfile && home )
|
||||||
{
|
{
|
||||||
char* path;
|
char* path;
|
||||||
if ( asprintf(&path, "%s/.sh_history", home) < 0 ||
|
if ( asprintf(&path, "%s/.sh_history", home) < 0 ||
|
||||||
setenv("HISTFILE", path, 1) < 0 )
|
setenv("HISTFILE", path, 1) < 0 )
|
||||||
err(1, "malloc");
|
err(1, "malloc");
|
||||||
free(path);
|
free(path);
|
||||||
histfile = getenv("HISTFILE");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_line_history_load(&edit_state, histfile);
|
char* rc = find_rc(login);
|
||||||
|
if ( rc )
|
||||||
|
{
|
||||||
|
FILE* rcfp = fopen(rc, "r");
|
||||||
|
if ( !rcfp )
|
||||||
|
warn("%s", rc);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = run(rcfp, rc, false, exit_on_error, script_exited,
|
||||||
|
status);
|
||||||
|
fclose(rcfp);
|
||||||
|
}
|
||||||
|
free(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = run(fp, fp_name, interactive, exit_on_error, script_exited, status);
|
if ( *script_exited || (status != 0 && exit_on_error) )
|
||||||
|
return status;
|
||||||
|
|
||||||
|
edit_line_history_load(&edit_state, getenv("HISTFILE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = run(fp, fp_name, interactive, exit_on_error, script_exited,
|
||||||
|
status);
|
||||||
|
|
||||||
if ( interactive )
|
if ( interactive )
|
||||||
edit_line_history_save(&edit_state, getenv("HISTFILE"));
|
edit_line_history_save(&edit_state, getenv("HISTFILE"));
|
||||||
|
|
||||||
return r;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compact_arguments(int* argc, char*** argv)
|
static void compact_arguments(int* argc, char*** argv)
|
||||||
|
@ -2186,8 +2231,10 @@ int main(int argc, char* argv[])
|
||||||
bool flag_c_first_operand_is_command = false;
|
bool flag_c_first_operand_is_command = false;
|
||||||
bool flag_e_exit_on_error = false;
|
bool flag_e_exit_on_error = false;
|
||||||
bool flag_i_interactive = false;
|
bool flag_i_interactive = false;
|
||||||
|
bool flag_l_login = argv[0][0] == '-';
|
||||||
bool flag_s_stdin = false;
|
bool flag_s_stdin = false;
|
||||||
|
|
||||||
|
// The well implemented options are recognized in proper-sh.c.
|
||||||
const char* argv0 = argv[0];
|
const char* argv0 = argv[0];
|
||||||
for ( int i = 1; i < argc; i++ )
|
for ( int i = 1; i < argc; i++ )
|
||||||
{
|
{
|
||||||
|
@ -2205,6 +2252,7 @@ int main(int argc, char* argv[])
|
||||||
case 'c': flag_c_first_operand_is_command = false; break;
|
case 'c': flag_c_first_operand_is_command = false; break;
|
||||||
case 'e': flag_e_exit_on_error = false; break;
|
case 'e': flag_e_exit_on_error = false; break;
|
||||||
case 'i': flag_i_interactive = false; break;
|
case 'i': flag_i_interactive = false; break;
|
||||||
|
case 'l': flag_l_login = false; break;
|
||||||
case 's': flag_s_stdin = false; break;
|
case 's': flag_s_stdin = false; break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
||||||
|
@ -2220,6 +2268,7 @@ int main(int argc, char* argv[])
|
||||||
case 'c': flag_c_first_operand_is_command = true; break;
|
case 'c': flag_c_first_operand_is_command = true; break;
|
||||||
case 'e': flag_e_exit_on_error = true; break;
|
case 'e': flag_e_exit_on_error = true; break;
|
||||||
case 'i': flag_i_interactive = true; break;
|
case 'i': flag_i_interactive = true; break;
|
||||||
|
case 'l': flag_l_login = true; break;
|
||||||
case 's': flag_s_stdin = true; break;
|
case 's': flag_s_stdin = true; break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
||||||
|
@ -2261,7 +2310,7 @@ int main(int argc, char* argv[])
|
||||||
char ppidstr[3 * sizeof(pid_t)];
|
char ppidstr[3 * sizeof(pid_t)];
|
||||||
snprintf(pidstr, sizeof(pidstr), "%ji", (intmax_t) getpid());
|
snprintf(pidstr, sizeof(pidstr), "%ji", (intmax_t) getpid());
|
||||||
snprintf(ppidstr, sizeof(ppidstr), "%ji", (intmax_t) getppid());
|
snprintf(ppidstr, sizeof(ppidstr), "%ji", (intmax_t) getppid());
|
||||||
setenv("SHELL", argv[0], 1);
|
setenv("SHELL", argv[0] + (argv[0][0] == '-'), 1);
|
||||||
setenv("$", pidstr, 1);
|
setenv("$", pidstr, 1);
|
||||||
setenv("PPID", ppidstr, 1);
|
setenv("PPID", ppidstr, 1);
|
||||||
setenv("?", "0", 1);
|
setenv("?", "0", 1);
|
||||||
|
@ -2291,7 +2340,7 @@ int main(int argc, char* argv[])
|
||||||
error(2, errno, "fmemopen");
|
error(2, errno, "fmemopen");
|
||||||
|
|
||||||
status = top(fp, "<command-line>", false, flag_e_exit_on_error,
|
status = top(fp, "<command-line>", false, flag_e_exit_on_error,
|
||||||
&script_exited, status);
|
flag_l_login, &script_exited, status);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
@ -2302,7 +2351,7 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
bool is_interactive = flag_i_interactive || isatty(fileno(stdin));
|
bool is_interactive = flag_i_interactive || isatty(fileno(stdin));
|
||||||
status = top(stdin, "<stdin>", is_interactive, flag_e_exit_on_error,
|
status = top(stdin, "<stdin>", is_interactive, flag_e_exit_on_error,
|
||||||
&script_exited, status);
|
flag_l_login, &script_exited, status);
|
||||||
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
@ -2318,7 +2367,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
bool is_interactive = flag_i_interactive || isatty(fileno(stdin));
|
bool is_interactive = flag_i_interactive || isatty(fileno(stdin));
|
||||||
status = top(stdin, "<stdin>", is_interactive, flag_e_exit_on_error,
|
status = top(stdin, "<stdin>", is_interactive, flag_e_exit_on_error,
|
||||||
&script_exited, status);
|
flag_l_login, &script_exited, status);
|
||||||
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
@ -2335,8 +2384,8 @@ int main(int argc, char* argv[])
|
||||||
FILE* fp = fopen(path, "r");
|
FILE* fp = fopen(path, "r");
|
||||||
if ( !fp )
|
if ( !fp )
|
||||||
error(127, errno, "%s", path);
|
error(127, errno, "%s", path);
|
||||||
status = top(fp, path, false, flag_e_exit_on_error, &script_exited,
|
status = top(fp, path, false, flag_e_exit_on_error, flag_l_login,
|
||||||
status);
|
&script_exited, status);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
||||||
exit(status);
|
exit(status);
|
||||||
|
@ -2345,7 +2394,7 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
bool is_interactive = flag_i_interactive || isatty(fileno(stdin));
|
bool is_interactive = flag_i_interactive || isatty(fileno(stdin));
|
||||||
status = top(stdin, "<stdin>", is_interactive, flag_e_exit_on_error,
|
status = top(stdin, "<stdin>", is_interactive, flag_e_exit_on_error,
|
||||||
&script_exited, status);
|
flag_l_login, &script_exited, status);
|
||||||
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
if ( script_exited || (status != 0 && flag_e_exit_on_error) )
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
.Dd November 9, 2022
|
||||||
|
.Dt SHRC 5
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm shrc
|
||||||
|
.Nd login shell startup
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm $ENV
|
||||||
|
.Nm ~/.shrc
|
||||||
|
.Nm /etc/shrc
|
||||||
|
.Nm /etc/default/shrc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
Interactive non-login shell sessions in
|
||||||
|
.Xr sh 1
|
||||||
|
execute the commands in the
|
||||||
|
.Nm
|
||||||
|
script upon startup, using the
|
||||||
|
.Pa ENV
|
||||||
|
environment variable with path expansion if set, and otherwise searching for the
|
||||||
|
user's script at
|
||||||
|
.Pa ~/.shrc ,
|
||||||
|
any system administrator provided script at
|
||||||
|
.Pa /etc/shrc ,
|
||||||
|
or any operating system provided script at
|
||||||
|
.Pa /etc/default/shrc ,
|
||||||
|
whichever exists first.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Xr profile 5
|
||||||
|
script is run instead in interactive login shell sessions.
|
||||||
|
.Sh ENVIRONMENT
|
||||||
|
.Bl -tag -width "ENV"
|
||||||
|
.It Ev ENV
|
||||||
|
File to execute on non-login interactive startup instead of searching the
|
||||||
|
standard paths for the
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
This variable is subject to path expansion.
|
||||||
|
.El
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width "/etc/default/shrc" -compact
|
||||||
|
.It Pa ~/.shrc
|
||||||
|
The user's
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
.It Pa /etc/shrc
|
||||||
|
The system administor provided
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
.It Pa /etc/default/shrc
|
||||||
|
The operating system provided
|
||||||
|
.Nm
|
||||||
|
script.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr dash 1 ,
|
||||||
|
.Xr sh 1 ,
|
||||||
|
.Xr shrc 5
|
||||||
|
.Sh CAVEATS
|
||||||
|
.Xr dash
|
||||||
|
does not use the
|
||||||
|
.Nm
|
||||||
|
script, but instead only uses the
|
||||||
|
.Ev ENV
|
||||||
|
environment variable.
|
||||||
|
To invoke the
|
||||||
|
.Nm
|
||||||
|
script portably across all standard shells upon startup of non-interactive login
|
||||||
|
sells, set the
|
||||||
|
.Ev ENV
|
||||||
|
variable to the user's
|
||||||
|
.Nm
|
||||||
|
script per the example in
|
||||||
|
.Xr profile 5 .
|
||||||
|
.Sh BUGS
|
||||||
|
.Xr sh 1
|
||||||
|
is currently primitive and cannot execute most scripts.
|
||||||
|
Beware of sharing the
|
||||||
|
.Nm
|
||||||
|
script between it and other shells such as
|
||||||
|
.Xr dash 1 .
|
|
@ -6,4 +6,4 @@ need tty
|
||||||
|
|
||||||
cd "$HOME"
|
cd "$HOME"
|
||||||
exit-code-meaning poweroff-reboot
|
exit-code-meaning poweroff-reboot
|
||||||
exec "$SHELL"
|
exec "$SHELL" -l
|
||||||
|
|
Loading…
Reference in New Issue