# print timeout for user input in csh



## srchi (Mar 8, 2021)

I'm trying create a csh script.
requirement:
When a script runs it asks for user input. Prompt should wait for 10secs. If not then exit the script. And please also suggest me secure prompt since password should not display in plain text (ex in bash script read -s "")
I have solution for bash script where I can use `read -t 10 username` but I want same in csh


```
#!/bin/csh
echo -n "username:"
set req = $< 
echo "username is $req"
sed -i.bak "/rootpw/s/edjos/$req/" /boot/loader.conf
```

And for advance level, the message should look like "prompts end in 10(this number should decrease and lively should visible the timeout secs)"


----------



## SirDice (Mar 8, 2021)

Don't use csh(1) for scripting. Use sh(1). Or, if you really, really want to use bash, install shells/bash. 



			Csh Programming Considered Harmful


----------



## zirias@ (Mar 8, 2021)

srchi said:


> Im trying create a csh script.


Don't. If there's one thing worse than a "bash" script, it's a "csh" script. Always use the default POSIX shell /bin/sh for scripting.
(edit: Ok, I see this was already addressed)

Some of the things you want can be accomplished in a script, here's a little example:

```
#!/bin/sh

trap 'echo timeout.; exit 1' HUP
trap 'stty echo' 0

echo -n "password: "
stty -echo
(sleep 5; kill -HUP $$ 2>/dev/null) &
read TEST
echo
echo $TEST
```

`stty -echo` suppresses terminal echo, the subshell sends a HUP signal after 5 seconds which interrupts the read, the first trap handles this signal, the second trap makes sure echoing is re-enabled on exit.

In this simple example, the `kill -HUP` will also be executed after the `read` finished successfully, creating a little race condition with any code following, so you probably want to fix this for production use.

But given all you'd like to have, you should probably try e.g. C instead of scripting.


----------



## srchi (Mar 8, 2021)

I'm able to achieve. But another issue is value is not storing in a variable($req). Since its secured. How can I store the value in variable?

```
#!/bin/csh
set pass=`cat file | grep rootpw | grep -o '".*"' | sed 's/"//g'`
if ( "$pass" == "edjos" ) then
   echo  "You are at default password. kindly change the password in 10secs……."
set req=`bash -c 'read -s -t 10'`
echo $req
     if ( "$req" == "" ) then
       echo "No password entered. So continuing with default password"
    else
      sed -i.bak "/rootpw/s/edjos/$req/"  file
   endif
endif
```


----------



## srchi (Mar 8, 2021)

Finally it's working.

```
#!/bin/csh
set pass=`grep rootpw file| grep -o '".*"' | sed 's/"//g'`
if ( "$pass" == "edjos" ) then
   echo  "You are at default password. kindly change the password in 10secs……."
set req=`bash -c 'read -s -t 10 ;echo "${REPLY}"'`
if ( "$req" == "" ) then
       echo "No password entered. So continuing with default password"
    else
      sed -i.bak "/rootpw/s/edjos/$req/"  file
     echo "password updated successfully"
   endif
endif
```


----------



## zirias@ (Mar 8, 2021)

Now you have a script that needs both csh and bash. Congratulations, this is a new level.


----------



## SirDice (Mar 8, 2021)

Zirias said:


> Congratulations, this is a new level.


It could be worse. I've seen people use a shell script to start a perl script that uses a python module 

Yeah, not the best way to do it.


----------



## Deleted member 66267 (Mar 8, 2021)

BTW, I did see people used csh for scripts, it's on Q4OS. Don't know if it's really csh scripts or not, but the extension is .csh as I recall.


----------



## Deleted member 66267 (Mar 8, 2021)

also-ran said:


> BTW, I did see people used csh for scripts, it's on Q4OS. Don't know if it's really csh scripts or not, but the extension is .csh as I recall.


Turned out I was wrong everyone. The extension is .esh, not .csh and they seemed to be dash scripts, not csh scripts.


----------



## a6h (Mar 8, 2021)

File extension in UNIX is irrelevant. Here we're talking magic number, so forth and so on. STFW 4 shebang & "_exec"_ syscall(s).


----------



## zirias@ (Mar 8, 2021)

Well, you DON'T write a shell script that needs a special shell. The only shell guaranteed to be present on any system is the POSIX /bin/sh, with well-defined behavior, so THIS is the shell you use for scripts.

Using "bash" instead ist somewhat widespread among Linux users and often enough, these scripts won't work correctly with /bin/sh. But at least, bash is a superset of the standard POSIX shell, so there's a chance you can port these scripts with a few changes. Using "csh" is another circle of hell, because it is outright incompatible. And then, on top, you might run into weird bugs as shown in this nice old document mentioned in the 2nd post  Yes, on FreeBSD(!), /bin/csh is "tcsh" with probably a lot fewer bugs, but of course that's another thing not guaranteed about any other system.


----------



## a6h (Mar 8, 2021)

Csh Programming Considered Harmful | cat-v.org


----------



## zirias@ (Mar 8, 2021)

Oh and of course, tcsh can be disabled when building FreeBSD base, because it isn't required for a "complete" system. My FreeBSD installations don't have any C shell.  If "pkg-base" gets anywhere, it might be possible that also users not compiling themselves might leave out tcsh when they're not interested in C shells.


----------



## SirDice (Mar 8, 2021)

Tcsh/csh is a nice _interactive_ shell. Scripting however should not be done with it, simple as that, use sh(1) for that. If you can't hack it with sh(1) use a proper scripting language like Perl, Python, Ruby, etc.


----------



## srchi (Mar 8, 2021)

i want to use only csh script. i need secure prompt of user input and should store in a variable. any possibilities?


----------



## zirias@ (Mar 8, 2021)

csh can't do that. Maybe tcsh has a way, I doubt it and don't know. You basically insist on shooting your foot, so, may I at least ask: why?


----------



## Deleted member 66267 (Mar 8, 2021)

srchi said:


> i want to use only csh script. i need secure prompt of user input and should store in a variable. any possibilities?


Better go with bash my friend. You invoked bash anyway.


----------



## zirias@ (Mar 8, 2021)

also-ran said:


> Better go with bash my friend. You invoked bash anyway.


That's only *slightly* better. As mentioned often enough, THE shell to use for scripting is /bin/sh.

If you can't achieve your goal in a sane way with that, it's time to switch to something different – depending on the nature of the problem, this might be C, or some full-featured scripting language like perl etc.


----------



## srchi (Mar 9, 2021)

as future concern im converting my script  from /bin/csh to /bin/sh.

but here my goal is, currently the password change happening in plain text in the loader.conf file. but i need, convert to hash format(sha512) in loader.conf file at
mfsbsd.rootpwhash="". 

```
#!/bin/sh
boot=$(ls /bootpool | grep boot | awk 'NR==1{print $1}')
data=$(ls /datapool | grep boot | awk 'NR==1{print $1}')
if [ "$boot" == "boot" ] 
then
   pass=$(grep rootpw /bootpool/boot/loader.conf| grep -o '".*"' | sed 's/"//g' | awk 'BEGIN { ORS = " " } { print }')
elif [ "$data" == "boot" ]
then
    pass=$(grep rootpw /datapool/boot/loader.conf| grep -o '".*"' | sed 's/"//g' | awk 'BEGIN { ORS = " " } { print }')
fi
if [ $pass == edjos ]
then
   echo  "You are at default password. kindly change the password"

stty -echo

read -p  "Password: " req

stty echo
if [ "$req" == "" ]
then
       echo "No password entered. So continuing with default password"
    else
    if [ "$boot" == "boot" ]
         then
              sed -i.bak "/rootpw/s/edjos/$req/" /bootpool/boot/loader.conf
              echo "Great! password updated successfully"
   fi
    if [ "$data" == "boot" ]
       then
         sed -i.bak "/rootpw/s/edjos/$req/" /datapool/boot/loader.conf
         echo "Great! password updated successfully"
     fi
 fi
else
   echo "Great! you are having authorised password"
fi
```
this script is updating in loader.conf as mfsbsd.rootpw="mypass" here password is visible but i need this in hash format and when user is trying to login he can able to login with his plain password


----------



## zirias@ (Mar 9, 2021)

No shell I know about has a feature for hashing, so you need to call a tool if you want to do that in a shellscript, e.g.:

```
$ echo -n test | sha256
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
```

Again, doing it in csh first is even worse than doing it in bash first. Bash is a superset of a POSIX shell, csh is completely different (and incompatible). By moving to csh, you're making the problem to later port it to standard POSIX shell worse.


----------



## srchi (Mar 9, 2021)

im using shell script only,
as you said use $ echo -n test | sha256 but this is already tried but i need to update this in master.passw. i'm unable to understand what is the encrypt algorithm it is using(freebsd website says md5 format but i dont think so md5 should have this much length would have). please suggest how can i fix this
this is the format of user in master.passwd
myuser:$6$z589PFtDjmVXcmho$SRIvZSfYvxSFeWsrduwMX.YoGIIE9YfvRInYdtK2FQPKSXQBIEQHrZ1EVhkKEtC4Dhov0B7sWMPAA46FV8XHQ1:1051:1601::0:0:myuser:/home/myuser:/bin/sh


----------



## zirias@ (Mar 9, 2021)

This is not just sha512, but it's the "modular crypt" format which also includes a salt, see crypt(3).
I don't know any shell utility for this function. Perl could use it, or you start using C directly. Of course if you want to TEST for a specific password, you can't do simple string comparison as well, you need the salt.

edit: this function is normally only used by the UNIX module of PAM, see here for example the code for setting a new password: https://github.com/freebsd/freebsd-src/blob/main/lib/libpam/modules/pam_unix/pam_unix.c#L401


----------

