nuta / nsh Goto Github PK
View Code? Open in Web Editor NEWA command-line shell like fish, but POSIX compatible.
A command-line shell like fish, but POSIX compatible.
It can be helpful in attracting new contributors. More info here.
To do so, it should be sufficient to add the hacktoberfest
label to the GitHub repository.
When compiling via cargo install --path .
, I get the following:
Compiling nsh v0.4.0 (/usr/home/kts/Develop/nsh)
warning: use of deprecated associated function `nix::errno::<impl nix::errno::Errno>::Sys`: Use Errno::... instead
--> src/process.rs:319:13
|
319 | Err(nix::Error::Sys(nix::errno::Errno::ECHILD)) | Ok(WaitStatus::StillAlive) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
error[E0164]: expected tuple struct or tuple variant, found associated function `nix::Error::Sys`
--> src/process.rs:319:13
|
319 | Err(nix::Error::Sys(nix::errno::Errno::ECHILD)) | Ok(WaitStatus::StillAlive) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
|
= help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
warning: use of deprecated associated function `nix::errno::<impl nix::errno::Errno>::Sys`: Use Errno::... instead
--> src/process.rs:475:21
|
475 | Err(nix::Error::Sys(nix::errno::Errno::EACCES)) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0164]: expected tuple struct or tuple variant, found associated function `nix::Error::Sys`
--> src/process.rs:475:21
|
475 | Err(nix::Error::Sys(nix::errno::Errno::EACCES)) => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
|
= help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
error: aborting due to 2 previous errors; 2 warnings emitted
I would fix this myself but I do not know Rust nor its ecosystem (and as such, don't know if it is an expected Rust version mismatch or otherwise).
error[E0432]: unresolved imports `nix::unistd::fork`, `nix::unistd::setpgid`, `nix::unistd::ForkResult`, `nix::unistd::Pid`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/eval.rs:13:26
|
13 | use nix::unistd::{close, fork, pipe, setpgid, ForkResult, Pid};
| ^^^^ ^^^^^^^ ^^^^^^^^^^ ^^^ no `Pid` in `unistd`
| | | |
| | | no `ForkResult` in `unistd`
| | no `setpgid` in `unistd`
| no `fork` in `unistd`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:291:15
|
291 | pub unsafe fn fork() -> Result<ForkResult> {
| ^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:331:8
|
331 | pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
| ^^^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:227:10
|
227 | pub enum ForkResult {
| ^^^^^^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:183:12
|
183 | pub struct Pid(pid_t);
| ^^^
= note: the item is gated behind the `process` feature
error[E0432]: unresolved imports `nix::sys::signal::kill`, `nix::sys::signal::sigaction`, `nix::sys::signal::SaFlags`, `nix::sys::signal::SigAction`, `nix::sys::signal::SigHandler`, `nix::sys::signal::SigSet`, `nix::sys::signal::Signal`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/process.rs:10:24
|
10 | use nix::sys::signal::{kill, sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
| ^^^^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^ ^^^^^^ no `Signal` in `sys::signal`
| | | | | | |
| | | | | | no `SigSet` in `sys::signal`
| | | | | no `SigHandler` in `sys::signal`
| | | | no `SigAction` in `sys::signal`
| | | no `SaFlags` in `sys::signal`
| | no `sigaction` in `sys::signal`
| no `kill` in `sys::signal`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:974:8
|
974 | pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
| ^^^^
= note: the item is gated behind the `signal` feature
= help: consider importing this struct instead:
libc::sigaction
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:810:15
|
810 | pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
| ^^^^^^^^^
= note: the item is gated behind the `signal` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:679:12
|
679 | pub struct SigAction {
| ^^^^^^^^^
= note: the item is gated behind the `signal` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:663:10
|
663 | pub enum SigHandler {
| ^^^^^^^^^^
= note: the item is gated behind the `signal` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:490:12
|
490 | pub struct SigSet {
| ^^^^^^
= note: the item is gated behind the `signal` feature
= help: consider importing this variant instead:
signal_hook::iterator::backend::PollResult::Signal
error[E0433]: failed to resolve: could not find `termios` in `sys`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/process.rs:11:15
|
11 | use nix::sys::termios::{tcgetattr, tcsetattr, SetArg::TCSADRAIN, Termios};
| ^^^^^^^ could not find `termios` in `sys`
error[E0432]: unresolved import `nix::sys::termios`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/process.rs:11:15
|
11 | use nix::sys::termios::{tcgetattr, tcsetattr, SetArg::TCSADRAIN, Termios};
| ^^^^^^^ could not find `termios` in `sys`
error[E0432]: unresolved import `nix::sys::wait`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/process.rs:12:15
|
12 | use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
| ^^^^ could not find `wait` in `sys`
error[E0432]: unresolved imports `nix::unistd::dup2`, `nix::unistd::execv`, `nix::unistd::fork`, `nix::unistd::getpid`, `nix::unistd::setpgid`, `nix::unistd::tcsetpgrp`, `nix::unistd::ForkResult`, `nix::unistd::Pid`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/process.rs:13:26
|
13 | use nix::unistd::{close, dup2, execv, fork, getpid, setpgid, tcsetpgrp, ForkResult, Pid};
| ^^^^ ^^^^^ ^^^^ ^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^ ^^^ no `Pid` in `unistd`
| | | | | | | |
| | | | | | | no `ForkResult` in `unistd`
| | | | | | no `tcsetpgrp` in `unistd`
| | | | | no `setpgid` in `unistd`
| | | | no `getpid` in `unistd`
| | | no `fork` in `unistd`
| | no `execv` in `unistd`
| no `dup2` in `unistd`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:440:8
|
440 | pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
| ^^^^
= note: the item is gated behind the `fs` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:824:8
|
824 | pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
| ^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:291:15
|
291 | pub unsafe fn fork() -> Result<ForkResult> {
| ^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:307:8
|
307 | pub fn getpid() -> Pid {
| ^^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:331:8
|
331 | pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
| ^^^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:379:8
|
379 | pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> {
| ^^^^^^^^^
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:227:10
|
227 | pub enum ForkResult {
| ^^^^^^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:183:12
|
183 | pub struct Pid(pid_t);
| ^^^
= note: the item is gated behind the `process` feature
error[E0432]: unresolved import `nix::sys::termios`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/shell.rs:8:15
|
8 | use nix::sys::termios::{tcgetattr, Termios};
| ^^^^^^^ could not find `termios` in `sys`
error[E0432]: unresolved imports `nix::unistd::getpid`, `nix::unistd::Pid`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/shell.rs:9:19
|
9 | use nix::unistd::{getpid, Pid};
| ^^^^^^ ^^^ no `Pid` in `unistd`
| |
| no `getpid` in `unistd`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:307:8
|
307 | pub fn getpid() -> Pid {
| ^^^^^^
= note: the item is gated behind the `process` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:183:12
|
183 | pub struct Pid(pid_t);
| ^^^
= note: the item is gated behind the `process` feature
error[E0432]: unresolved imports `nix::sys::signal::sigaction`, `nix::sys::signal::SaFlags`, `nix::sys::signal::SigAction`, `nix::sys::signal::SigHandler`, `nix::sys::signal::SigSet`, `nix::sys::signal::Signal`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/main.rs:48:24
|
48 | use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
| ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^ ^^^^^^ no `Signal` in `sys::signal`
| | | | | |
| | | | | no `SigSet` in `sys::signal`
| | | | no `SigHandler` in `sys::signal`
| | | no `SigAction` in `sys::signal`
| | no `SaFlags` in `sys::signal`
| no `sigaction` in `sys::signal`
|
= help: consider importing this struct instead:
libc::sigaction
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:810:15
|
810 | pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
| ^^^^^^^^^
= note: the item is gated behind the `signal` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:679:12
|
679 | pub struct SigAction {
| ^^^^^^^^^
= note: the item is gated behind the `signal` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:663:10
|
663 | pub enum SigHandler {
| ^^^^^^^^^^
= note: the item is gated behind the `signal` feature
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/sys/signal.rs:490:12
|
490 | pub struct SigSet {
| ^^^^^^
= note: the item is gated behind the `signal` feature
= help: consider importing this variant instead:
signal_hook::iterator::backend::PollResult::Signal
error[E0425]: cannot find function `isatty` in module `nix::unistd`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/macros.rs:4:22
|
4 | nix::unistd::isatty(std::io::stdout().as_raw_fd()).unwrap_or(false)
| ^^^^^^ not found in `nix::unistd`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:1264:8
|
1264 | pub fn isatty(fd: RawFd) -> Result<bool> {
| ^^^^^^
= note: the item is gated behind the `fs` feature
help: consider importing this function
|
1 + use libc::isatty;
|
help: if you import `isatty`, refer to it directly
|
4 - nix::unistd::isatty(std::io::stdout().as_raw_fd()).unwrap_or(false)
4 + isatty(std::io::stdout().as_raw_fd()).unwrap_or(false)
|
error[E0425]: cannot find function `gethostname` in module `unistd`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/prompt.rs:131:33
|
131 | let hostname_cstr = unistd::gethostname(&mut hostname_buf).expect("failed to get hostname");
| ^^^^^^^^^^^ not found in `unistd`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:1056:8
|
1056 | pub fn gethostname() -> Result<OsString> {
| ^^^^^^^^^^^
= note: the item is gated behind the `hostname` feature
help: consider importing one of these items
|
1 + use crate::prompt::libc::gethostname;
|
1 + use libc::gethostname;
|
help: if you import `gethostname`, refer to it directly
|
131 - let hostname_cstr = unistd::gethostname(&mut hostname_buf).expect("failed to get hostname");
131 + let hostname_cstr = gethostname(&mut hostname_buf).expect("failed to get hostname");
|
error[E0425]: cannot find function `fsync` in module `unistd`
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nsh-0.4.2/src/utils.rs:57:17
|
57 | unistd::fsync(self.fd).ok();
| ^^^^^ not found in `unistd`
|
note: found an item that was configured out
--> /home/danish/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nix-0.27.1/src/unistd.rs:1410:8
|
1410 | pub fn fsync(fd: RawFd) -> Result<()> {
| ^^^^^
= note: the item is gated behind the `fs` feature
help: consider importing this function
|
1 + use libc::fsync;
|
help: if you import `fsync`, refer to it directly
|
57 - unistd::fsync(self.fd).ok();
57 + fsync(self.fd).ok();
|
PS: Please keep in mind that I know I am not a dev, I just a noob EndeavourOS (ArchLinux) user who just wants to use this shell so clear instructions on how to get logs or more/better error messages would be appreciated. Because of that I might have included something other than the error messages in the code. Sorry for that if I did.
Bash has the problem of most shells: >100k LOC with not offering proper error handling or being able to do basic safety checks.
Most of them are due to POSIX being underspecified.
Necessary functionality
Hi
Thanks for your shell, I'm just beginning to test !
I was wondering if you could use $XDG_CONFIG_HOME like ~/.config/nsh instead of .nshrc
Thanks !
Raphaël
Hi,
As I saw some updates, I tried to build nsh on two machines, with same ending, building fails :
Compiling textwrap v0.11.0
Compiling heck v0.3.1
Compiling proc-macro-error-attr v0.4.11
Compiling proc-macro-error v0.4.11
Compiling pest_meta v2.1.3
Compiling quote v1.0.3
Compiling atty v0.2.14
Compiling signal-hook-registry v1.2.0
Compiling dirs v1.0.5
Compiling termion v1.5.5
Compiling rand_core v0.5.1
Compiling clap v2.33.0
Compiling signal-hook v0.1.13
Compiling rand_chacha v0.2.1
Compiling rand_pcg v0.2.1
Compiling rand v0.7.3
Compiling syn-mid v0.5.0
Compiling synstructure v0.12.3
Compiling pest_generator v2.1.2
Compiling phf_generator v0.8.0
Compiling backtrace-sys v0.1.33
Compiling backtrace v0.3.45
Compiling proc-macro-hack v0.5.11
Compiling pest_derive v2.1.0
error[E0433]: failed to resolve: could not find `__rt` in `quote`
--> /home/rsalle/.cargo/registry/src/github.com-1ecc6299db9ec823/failure_derive-0.1.6/src/lib.rs:107:70
|
107 | fn display_body(s: &synstructure::Structure) -> Result<Option<quote::__rt::TokenStream>, Error> {
| ^^^^ could not find `__rt` in `quote`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
error: could not compile `failure_derive`.
warning: build failed, waiting for other jobs to finish...
error: failed to compile `nsh v0.3.0`, intermediate artifacts can be found at `/tmp/cargo-installwDSerl`
Caused by:
build failed
and rustc --explain E0433 gives :
An undeclared type or module was used.
Erroneous code example:
let map = HashMap::new();
// error: failed to resolve: use of undeclared type or module `HashMap`
Please verify you didn't misspell the type/module's name or that you didn't
forget to import it:
use std::collections::HashMap; // HashMap has been imported.
let map: HashMap<u32, u32> = HashMap::new(); // So it can be used!
Thanks
rustc 1.48.0 (7eac88abb 2020-11-16)
Linux lptp 5.9.11-arch2-1 #1 SMP PREEMPT Sat, 28 Nov 2020 02:07:22 +0000 x86_64 GNU/Linux
I get this error while compiling nsh:
error[E0277]: `&SignalsInfo` is not an iterator
--> src/mainloop.rs:137:27
|
137 | for signal in &signals {
| ^^^^^^^^ `&SignalsInfo` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&SignalsInfo`
= note: required by `into_iter`
Vim mode/binding would be aweosome
I'm in the habit of inserting the EOT special character with ctrl+d to quit command-line programs. If I do that in nsh, I get the follwoing error:
nsh: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/eliminmax/.local/lib/rust/cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
nsh: 0: 0x55cbf52482a7 - <unknown>
1: 0x55cbf5237d95 - <unknown>
2: 0x55cbf51dd51e - <unknown>
3: 0x55cbf52cf904 - <unknown>
4: 0x55cbf52cf5b7 - <unknown>
5: 0x55cbf52cd324 - <unknown>
Hi. I just founded nsh.
Can you add nsh to Arch Linux?
https://wiki.archlinux.org/title/Arch_package_guidelines
Compiling nsh v0.4.2
error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/prompt.rs:131:25
|
131 | let hostname_cstr = unistd::gethostname(&mut hostname_buf).expect("failed to get hostname");
| ^^^^^^^^^^^^^^^^^^^ ----------------- argument of type `&mut [u8; 128]` unexpected
|
note: function defined here
--> /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.26.1/src/unistd.rs:1020:8
|
1020 | pub fn gethostname() -> Result<OsString> {
| ^^^^^^^^^^^
help: remove the extra argument
|
131 | let hostname_cstr = unistd::gethostname().expect("failed to get hostname");
|
[edit]
Apologies. The hang only occurs when sshing in with Paramiko, a Python library. This bug is an even smaller niche, and even lower priority for you guys therefore, but I'll leave it up for posterity.
Hi there,
I've been running some tests, ssh-ing into a local Docker container from Python, using multiple shells. When I try as a user whose shell is nsh, the test script hangs.
It's entirely possible I've misconfigured nsh, or encountered one of those strange Musl Alpine bugs. And it's even more likely, there's an issue in my Python code.
However I can successfully connect with Paramiko, as users whose shells are: bash , dash , fish , zsh , ion-shell , tcsh , oksh , loksh , yash, and from edge/testing: elvish , xonsh , mrsh and imrsh (and csh, ksh, rc, and a source build of heirloom-sh on Debian).
I first thought this was a general ssh issue, but it only occurs in my script. It would be above and beyond the call of duty for someone to debug my Python code, especially on a great repo you could all be working on anyway, that uses a different language. But nonetheless, I wondered why I've been unable to get the script to work for nsh, (I've had no joy with hilbish or nushell either).
To reproduce (some shells not installed for brevity):
Dockerfile:
ARG base_image=alpine
ARG base_tag=edge
FROM "${base_image}:${base_tag}" as runner
ENV LANG=C.UTF8
RUN apk add --no-cache \
openssh \
bash \
yash
RUN apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing/ \
elvish \
mrsh \
nsh
# Do not hardcode important passwords into Dockerfiles (and do not
# set trivially guessable passwords), as I have done below!
#
# Use secrets, or at least environment variables.
#
# This Dockerfile is intended to define a local testing server,
# remote connections to which are prevented by other means.
#
RUN echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config && \
adduser -h /home/sh -s /bin/sh -D sh && \
echo -n 'sh:sh' | chpasswd && \
adduser -h /home/ash -s /bin/ash -D ash && \
echo -n 'ash:ash' | chpasswd && \
adduser -h /home/bash -s /bin/bash -D bash && \
echo -n 'bash:bash' | chpasswd && \
adduser -h /home/yash -s /usr/bin/yash -D yash && \
echo -n 'yash:yash' | chpasswd && \
adduser -h /home/elvish -s /usr/bin/elvish -D elvish && \
echo -n 'elvish:elvish' | chpasswd && \
adduser -h /home/mrsh -s /usr/bin/mrsh -D mrsh && \
echo -n 'mrsh:mrsh' | chpasswd && \
adduser -h /home/nsh -s /usr/bin/nsh -D nsh && \
echo -n 'nsh:nsh' | chpasswd
RUN ssh-keygen -A
# Start SSH daemon to listen for log ins.
CMD ["/usr/sbin/sshd", "-D", "-e"]
EXPOSE 22
Build image:
docker build -t alpine_nsh
Run container (blocks process to show output from server):
docker run -p 22:22 --rm alpine_nsh
Install paramiko, preferably after first making and activating a venv (requires Python).
pip install paramiko
Run test script:
import sys
import paramiko
shells = sys.argv[1:] or ['sh', 'ash', 'bash', 'yash', 'elvish', 'nsh']
for shell in shells:
input(f'Press Enter to test: {shell} ')
con = paramiko.SSHClient()
con.set_missing_host_key_policy(paramiko.AutoAddPolicy())
con.connect('localhost', username=shell, password=shell)
con_chann = con.invoke_shell()
con_in = con_chann.makefile('wt')
con_out = con_chann.makefile('rb')
con_in.write('''\
echo "Hello World"
exit
''')
print(con_out.read().decode())
con_out.close()
con_in.close()
con.close()
I know I can just docker exec in instead. It's a long story, and besides the point, why I want to ssh to containers. But lets do that, to show nsh is otherwise working, and to check the path of the nsh binary:
docker ps
remember some characters from the start of the container_id, then the following commands:
docker exec -it container_id nsh
ls /usr/bin/nsh -l
nsh --version
respectively produce:
-rwxr-xr-x 1 root root 1314456 May 23 2023 /usr/bin/nsh
0.4.2
To kill the container when done:
docker kill container_id
Nsh already checks if aliases exist and highlights them with a green color accordingly. The same thing doesn't work for functions though.
alias l="ls -la"
works, while
l () {
ls -la
}
doesn't.
IIRC, this shell is implemented as my first step in Rust long long ago, and it has some faults:
Mainloop
is fatThis issue aims to deal with these problems by rewriting nsh when I have time (hopefully Q1 2022).
For validation, we could use something like grok.sh
or https://stackoverflow.com/a/67261832.
Run code as nsh -c '<code>'
, e.g.: nsh -c 'var='
.
Empty variable assignment
#!/bin/sh
var=
nsh: parse error: --> 2:5
|
2 | var=␊
| ^---
|
= expected literal_span, tilde_span, any_string_span, any_char_span, command_span, proc_subst_direction, backtick_span, expr_span, param_ex_span, param_span, double_quoted_span, single_quoted_span, or initializer
␊
is shown when there's a newline.Default value substitution with whitespace
echo "${var:- }"
nsh: parse error: --> 1:14
|
1 | echo "${var:- }"
| ^---
|
= expected word
Default value initialization
: "${var:=def}"
nsh: command not found `:'
Get name without extension
echo ${FILENAME%.*}
nsh: parse error: --> 1:16
|
1 | echo ${FILENAME%.*}
| ^---
|
= expected param_op
Get extension
echo ${FILENAME##*.}
nsh: parse error: --> 1:16
|
1 | echo ${FILENAME##*.}
| ^---
|
= expected param_op
Get directory name
echo ${PATHNAME%/*}
nsh: parse error: --> 1:16
|
1 | echo ${PATHNAME%/*}
| ^---
|
= expected param_op
Get file name
echo ${PATHNAME##*/}
nsh: parse error: --> 1:16
|
1 | echo ${PATHNAME##*/}
| ^---
|
= expected param_op
For reference, here is the expansion table:
parameter expansion | var set |
var empty |
var unset |
---|---|---|---|
${var-default} |
$var |
"" |
default |
${var=default} |
$var |
"" |
default |
${var?default} |
$var |
"" |
exit 127 |
${var+default} |
default |
default |
"" |
${var:-default} |
$var |
default |
default |
${var:=default} |
$var |
default |
default |
${var:?default} |
$var |
exit 127 |
exit 127 |
${var:+default} |
default |
"" |
"" |
For POSIX parameter expansion, see: POSIX.1-2017: Parameter Expansion.
For other applications of parameter expansion, see: The Bash Hackers Wiki: Parameter Expansion.
For a more historical reference, see: The Traditional Bourne Shell Family.
In ZSH (and I believe other shells as well) something like the following is possible (example):
alias ls="exa"
alias l="ls -la"
which will both execute exa
since the first alias remaps the default unix ls
to exa
.
In Nsh, this doesn't work. The second alias runs the default ls
instead.
What would be the scope of this change? What would need to be done?
The following snippets crash nsh:
$(printf '\xff')
.A=$'\xff' ./target/release/nsh
.true $(printf '\x00')
.Possible fix to 1 and 2: store strings in Vec<u8>
, OsString
, or bstr
rather than String
which forces strings to be valid UTF-8.
Proper behavior for 3 is not specified for POSIX sh; other shells treat it differently.
So, this is probably user error, but it told me to report this and I will.
I saw nsh
was in brew and I'm always up for trying new shells (including nushell. So I brew install nsh
, ran nsh
from my usual zsh
and then when I run ls
, it lists files and then:
nsh: panicked at 'failed to tcsetpgrp: EINVAL', src/process.rs:193:24
nsh: 0: 0x10e69039b - backtrace::capture::Backtrace::new::h94e01dcc48b96db5
1: 0x10e65699f - nsh::main::{{closure}}::h041e738f2aeec958
2: 0x10e708492 - std::panicking::rust_panic_with_hook::h32f3432eccbbcf03
3: 0x10e70f00a - std::panicking::begin_panic_handler::{{closure}}::heec496a5329a15c8
4: 0x10e70ef78 - std::sys_common::backtrace::__rust_end_short_backtrace::h9ba91ee04b4386bb
5: 0x10e707e60 - _rust_begin_unwind
6: 0x10e73e5cf - core::panicking::panic_fmt::h2b293e6c03a76160
7: 0x10e73ec65 - core::result::unwrap_failed::hed5438487a4f03df
8: 0x10e6487f8 - nsh::process::run_in_foreground::hb1058e5c4336dabf
9: 0x10e6164cc - nsh::eval::run_terms::h94c52fd4b9b5a554
10: 0x10e64fd28 - nsh::shell::Shell::run_str::h56b5f07065e1fbf4
11: 0x10e626029 - nsh::mainloop::Mainloop::handle_key_event::hbe974f26d5dfc811
12: 0x10e623cef - nsh::mainloop::Mainloop::handle_event::hcba2b4fd18674129
13: 0x10e6203df - nsh::mainloop::Mainloop::run::h0669bafc547fbc4e
14: 0x10e6537bf - nsh::shell_main::h70b80c33723cca7e
15: 0x10e6563bc - nsh::main::ha6ee95719b18a463
16: 0x10e5bf87a - std::sys_common::backtrace::__rust_begin_short_backtrace::hb608f8487b3c3a45
17: 0x10e671716 - _main
nsh: Something went wrong. Check out ~/.nsh.log and please file this bug on GitHub: https://github.com/nuta/nsh/issues
I broke things! 😄
Hi.
After reading docs/completion.md
it isn't clear to me whether that also includes auto suggestions based on .nsh_history
. As far as I can tell, such auto suggestions would in essence be the same functionality provides by CTRL+r, but then inline on the prompt.
Here's what I'm referring to (in fish):
(arrow up searches the history based on the command I've already typed.)
Thanks for your time and for nsh!
I just ported nsh to FreeBSD:
https://www.freshports.org/shells/nsh/
To install in FreeBSD:
pkg install shells/nsh
or
pkg install nsh
Maybe something for the documentation?
Hi
I tried to install your project with Termux on Android, and got a huge error output:
Any advice?
Cheers
Beauford
the shell is known as git-shell not nsh
When trying to install nsh through cargo I get the following error
error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> .../.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/prompt.rs:131:25
|
131 | let hostname_cstr = unistd::gethostname(&mut hostname_buf).expect("failed to get hostname");
| ^^^^^^^^^^^^^^^^^^^ ----------------- argument unexpected
|
note: function defined here
--> .../.cargo/registry/src/github.com-1ecc6299db9ec823/nix-0.25.0/src/unistd.rs:1020:8
|
1020 | pub fn gethostname() -> Result<OsString> {
| ^^^^^^^^^^^
help: remove the extra argument
|
131 | let hostname_cstr = unistd::gethostname().expect("failed to get hostname");
| ~~~~~~~~~~~~~~~~~~~~~
For more information about this error, try `rustc --explain E0061`.
error: could not compile `nsh` due to previous error
error: failed to compile `nsh v0.4.2`, intermediate artifacts can be found at `/var/folders/dt/97jrrt3s3yn7z7bgr3rv0wy40000gn/T/cargo-installHlVCo7`
On macOS Monterey 12.5
foo=
{ :; } >&2
case x in
x) foo
esac
case x in
(x) foo ;;
esac
foo=bar
echo ${foo#}
-c
, the shell doesn't accept positional parameters:
nsh -c '' nsh 1 2 3
I didn't test any further than this.
I was trying out nsh on my macbook and encountered this. (might be related to #14 ?)
[ERROR ] /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
[ERROR ] /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'index out of bounds: the len is 20 but the index is 53', /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs:1153:13
[ERROR ] /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: 0: 0x102083c18 - backtrace::capture::Backtrace::new::hba9adf1e5b3c7a91
1: 0x10204a7d8 - nsh::main::{{closure}}::h67739294c6afee12
2: 0x1020ffe9d - std::panicking::rust_panic_with_hook::hae2b05f08a320721
3: 0x10211dc5c - std::panicking::begin_panic_handler::{{closure}}::h72d68d3a77e0b718
4: 0x10211dc27 - std::sys_common::backtrace::__rust_end_short_backtrace::h7c5e286792f94edb
5: 0x10211dbe0 - _rust_begin_unwind
6: 0x102136d9f - core::panicking::panic_fmt::h1b194bb80d76fb10
7: 0x102136d66 - core::panicking::panic_bounds_check::hde7f7e34704d5da2
8: 0x102016118 - nsh::mainloop::Mainloop::handle_key_event::h72f2fc3ed6d69a71
9: 0x1020119ae - nsh::mainloop::Mainloop::handle_event::h98f98893dfe246aa
10: 0x10200e02f - nsh::mainloop::Mainloop::run::hd7a071cbdcd9cbdc
11: 0x1020466e2 - nsh::shell_main::ha315b12f85f157a9
12: 0x102049ff9 - nsh::main::h367ea8887b771698
13: 0x101fa32aa - std::sys_common::backtrace::__rust_begin_short_backtrace::hde4e21082195018a
14: 0x102060794 - _main
[ERROR ] /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /Users/$USER/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
I'm in a LANG=ja_JP.UTF-8 environment, and nsh was acting weird in a directory with a name consisting multibyte letters. (The left prompt and the actual input area were separated way apart)
The actual crash occurred when trying to type a letter after completing a multibyte directory name.
PoC:
nsh
$ mkdir ぴーおーしー
$ cd <TAB> <select ぴーおーしー> <return> <type any letter>
(sidenote: ぴーおーしー
is "PoC" in Japanese hiragana representation and doesn't mean anything)
In other shells like bash or zsh and pretty much any text editor if you press ctrl + left or right arrow key it will go to the next word on that side. In nsh if you press ctrl + an arrow key it doesnt move at all. Its a little quality of life feature I would appreciate being added. If it does get added could you please show me the commit as id like to learn.
First of all, impressive work - great experience to use it so far!
I just hit a panic when I pressed Ctrl-W (I think) when editing a line from the front.
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: SHIFT }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: SHIFT }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Right, modifiers: ALT }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Right, modifiers: ALT }
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: BackTab, modifiers: SHIFT }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'byte index 18446744073709551615 is out of bounds of ` <(cat ho)`', /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/alloc/src/string.rs:1250:24
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: 0: 0x55e00df2c34e - backtrace::backtrace::libunwind::trace::ha92b05c3835a19b3
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.62/src/backtrace/libunwind.rs:93:5
backtrace::backtrace::trace_unsynchronized::h5bd46d966599ad53
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.62/src/backtrace/mod.rs:66:5
backtrace::backtrace::trace::hc0cd2fe75e0630e9
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.62/src/backtrace/mod.rs:53:14
backtrace::capture::Backtrace::create::hbe88d678c6254fcc
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.62/src/capture.rs:176:9
backtrace::capture::Backtrace::new::h55226a7eaa89bbb3
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.62/src/capture.rs:140:22
1: 0x55e00def63aa - nsh::main::{{closure}}::hbdf33c6259b88669
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs:190:25
2: 0x55e00dfa04d6 - std::panicking::rust_panic_with_hook::h32c44b1364c1c247
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/std/src/panicking.rs:628:17
3: 0x55e00dfc1c78 - std::panicking::begin_panic_handler::{{closure}}::he2e5f48fb16982d1
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/std/src/panicking.rs:521:13
4: 0x55e00dfc1bf6 - std::sys_common::backtrace::__rust_end_short_backtrace::haea54a33f9e18aba
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/std/src/sys_common/backtrace.rs:141:18
5: 0x55e00dfc1bb2 - rust_begin_unwind
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/std/src/panicking.rs:517:5
6: 0x55e00de5fcb0 - core::panicking::panic_fmt::h824e0febbdf5e655
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/core/src/panicking.rs:101:14
7: 0x55e00de601ac - core::str::slice_error_fail::h416bbb3b8269e469
8: 0x55e00decd3cc - nsh::mainloop::UserInput::remove_until_word_start::hcfc8b7422d12c885
nsh::mainloop::Mainloop::handle_key_event::hc2d9e41aad7e6c31
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs:383:17
9: 0x55e00dec911f - nsh::mainloop::Mainloop::handle_event::h9da7cc13584b9546
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs:267:44
10: 0x55e00dec591e - nsh::mainloop::Mainloop::run::h89f95d1cb82c50be
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs:161:29
11: 0x55e00def3a50 - nsh::interactive_mode::hcbcb561b5dd1dbc9
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs:68:5
nsh::shell_main::hc8f90789de9f5633
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs:124:13
12: 0x55e00def608d - nsh::main::hd9825816e817867a
at /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs:203:5
13: 0x55e00de67953 - core::ops::function::FnOnce::call_once::h049cc098aa9d1397
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/core/src/ops/function.rs:227:5
std::sys_common::backtrace::__rust_begin_short_backtrace::hc50c39f301db3c0e
at /rustc/09c42c45858d5f3aedfa670698275303a3d19afa/library/std/src/sys_common/backtrace.rs:125:18
14: 0x55e00df0fbf4 - main
15: 0x7fd1f9401e4a - __libc_start_main
at ./csu/../csu/libc-start.c:314:16
16: 0x55e00de6582a - _start
17: 0x0 - <unknown>
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[WARN ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/mainloop.rs: unsupported key event: KeyEvent { code: Left, modifiers: CONTROL }
[ERROR ] /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/main.rs: panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/kai/.cargo/registry/src/github.com-1ecc6299db9ec823/nsh-0.4.2/src/bash_server.rs:26:33
Running Homebrew's shellenv
script (necessary to use packages installed via Homebrew) by running
eval "$(/opt/homebrew/bin/brew shellenv)"
results in an error:
nsh: parse error: --> 4:56
|
4 | export PATH="/opt/homebrew/bin:/opt/homebrew/sbin${PATH+:$PATH}";␊
| ^---
|
= expected param_op
Which corresponds to line 48 in the aforementioned script.
Is this POSIX-compliant syntax? If so, an implementation for this seems to be missing.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.