How can I get csh to source a file and then go interactive?
Asked Answered
csh
P

5

8

BRIEF

how do I (1) start a new csh, (2) force it to execute a few commands that are NOT in any .cshrc (although I could arrange for them to be in a non-standard location to be source'ed) and (3) then go interactive?

E.g. is there any way to get csh or tcsh to sue alternate startup files other than those described at http://www.manpagez.com/man/1/tcsh/, which says

I already know about

Startup and shutdown A login shell begins by executing commands from the system files /etc/csh.cshrc and /etc/csh.login. It then executes commands from files in the user's home directory: first ~/.tcshrc (+) or, if ~/.tcshrc is not found, ~/.cshrc, then ~/.history (or the value of the histfile shell variable), then ~/.login, and finally ~/.cshdirs (or the value of the dirsfile shell variable) (+). The shell may read /etc/csh.login before instead of after /etc/csh.cshrc, and ~/.login before instead of after ~/.tcshrc or ~/.cshrc and ~/.history, if so compiled; see the version shell variable. (+)

   Non-login  shells read only /etc/csh.cshrc and ~/.tcshrc or ~/.cshrc

DETAIL

I'm a bash user. But I work at a hardware company, where (1) many people are csh users, and (2) many of the CAD tools depend on stuff in the environment, such as the modules system.

Many recipes - e.g. internal wiki pages where people explain how to do things - start off something like

start a new shell or xterm
source /proj/Foo/setup.proj
source ~some_engineer/env/setup-for-this-tool
now run the tool

Oftentimes the environment variables conflict; sometimes I have to delete all of my ~/.* files, ssh in afresh, etc.

I would like to automate many of these. Indeed, I have automated many of these. However, I had to automate them by using expect (actually, Perl CPAN Expect), to fake out being an interactive user.

Along the way, I have my own script clear-env that I often use to start a shell with almost no environment variables. Used thusly:

clear-env -keep HOME -- csh
and then either pipe commands in through expect
or run interactively

This works for automation. But sometimes I really do need to be interactive - but only after I have loaded several lines of long source script names.

I would like to be able to load thes source files, and then fall back to interactive.

E.g. I have tried

clear-env -keep HOME -- csh -c 'source filename' -i
...

or, without my clear-env

csh -c 'source filename' -i
...

hoping that it would execute the -c command and then become interactive. But it only executes the -c command.

I have been able to feed commands to csh via expect in a perl script of my own, that reads my tty, and then pipes the command into the csh via expect. However, then I lose the interactive features of csh.

Is there any better way? Some way of saying "From this point on, I want you to reconnect youir controlling terminal to this other terminal?"

Thanks.

By the way, this would be useful for other shells as well. However, it has been my experience that csh users are the most prone to writing recipes that must be manually executed.

--

Perhaps I am not being clear:

I know about

 exec tcsh -c "source stuff ; exec bash"

and exec csh -c "source stuff ; exec csh"

The situation is that I have already driven the tool, the script, a long way using "interactive" commands via Expect.

Now, after I have done that pseudo-interactive setup, finally I want to return to being truly interactive. Basically, changing the controlling terminal for the shell from the pty that Expect was using, to a real pty.

I have been able to do this by creating a forwarding process.

But I was hoping that I could switch. Or do something like

... long
... sequence
... of expect commands
exec csh -i < /dev/my-pty ...
Percussive answered 24/1, 2012 at 5:12 Comment(6)
does alias srcMyStuff "source /path/to/my/special/stuff/.anyOldName_cshrc" help at all? (You might need an equal sign in there). Did you try the '-i' before the '-c'? (I don't think it will work, but options after '-c' will never work.) Also try '&' at appended to end-of-cmd to run the cmd in the background (Might help). I don't have access to a csh to test now. Good luck.Copley
I have been creating a succession of files to source in each of these different csh. It's getting a bit tiresome. Hmm, maybe I should just do the csh howsoever, and then create a program that figures out which of the many, many, soource files I nee to pull in.Percussive
that is a common approach, and it has the benefit of being testable. Good luck.Copley
(1) It's just annoying ti have to do this, since I already have the expect scripts that automate this. I'd like to share the existing automation code, and say "Now go off and be interactive." (2) In what way would csh -c 'source foo' -i be less testable, if it worked?Percussive
I guess it was wishful thinking on my part about better testing. Going back to your #2 'force it to execute a few commands that are NOT in any .cshrc (although ....', While it requires more fixing, it seems like you could do conditional tests if ( -f /path/2/nonstd/rc ) ; then source /path/2/nonstd/rc ; endif (Sorry my csh is rusty). Hopefully you get the idea. Maybe you are really looking for something that is provided by larger-scale build/test/deploy tools? Good luck.Copley
You could also do a survey of the ' many people are csh users,' to see if they would even notice if you switched everything to bash. (Just thinking outside of the box). Good luck.Copley
G
3

You were on the right track. You can use expect to do this. The key is the statement interact.

#!/usr/bin/env expect

spawn tcsh

expect {
  > {
    send "cd /some/path/foobar\n"
  }
}
interact

... if > is in your prompt, of course. This is the main problem with using expect, but sometimes you're trapped in a situation with no other way out.

Also, you might want to take steps to not pollute your .history file with scripted commands, but you're probably already aware of that.

Gudrun answered 8/9, 2015 at 9:28 Comment(1)
This works great, except if the send command has something like ` > /dev/null` in it. So this is my solution: Use $ to expect the > to be at the end of the input: expect "> $". Still testing, but I think it works. From Exploring Expect, Ch. 3: Anchoring: "Patterns that use the ^ or $ are said to be anchored. Some programs, such as sed, define anchoring in terms of the beginning of a line. This makes sense for sed, but not for expect. expect anchors at the beginning of whatever input it has received without regard to line boundaries."Vorlage
H
2

I had the same problem. I'm using bash, and have a software package that only works if you are at a csh prompt and source a file called nemo_start. This is the solution:

me@machine:~/nemo$ csh -c "source nemo_start; csh" # This is bash.
FALCON set to /home/me/nemo/usr/dehnen/falcON
machine:~/nemo% tsf                                # This is csh already.
Insufficient parameters, try 'help=', 'help=?' or 'help=h' or 'man tsf',
Usage: tsf in=??? ...
type contents of a (binary) structured file

This tsf command would not have been available unless the file was sourced properly and environmental variables and aliases kept.

Halophyte answered 22/1, 2013 at 10:19 Comment(0)
E
1

I have managed to do this by setting $HOME to some other directory, and put a .cshrc in that new $HOME which does what you want, then sets $HOME back to ~$USER and manually sources $HOME/.cshrc.

It feels awfully nasty but seems to work. Beware other dotfiles like .history may be broken depending on the startup sequence within the shell, but it's an idea to explore if you're desperate and want to avoid using expect.

I've started using this to share my own user's .cshrc when logging in to a shared test account, using something like this:

xterm -e "setenv HOME ~spickup; exec csh -l" &

(Of course in this case you need open permissions between accounts, so don't do this on a secure system.)

Similar principles could presumably be applied to bash or other shells.

Expert answered 16/5, 2017 at 9:42 Comment(0)
P
0

This may not solve your problem, but if your goal is to automate a "source", then you can put it in an alias:

~/.aliases

alias mysource 'source /path/to/source/file.rc'
Psychosurgery answered 16/2, 2018 at 0:47 Comment(0)
C
-1
exec tcsh -c "source stuff ; exec bash"

Where 'source stuff' should be replaced with a (csh) shell script, this leaves you in a bash shell that inherits the environment set up in the tcsh by 'source stuff'. The 'exec's mean you don't end up with nested shell processes.

Chromonema answered 15/6, 2012 at 11:53 Comment(1)
But it doesn't go interactive with whatever aliases have been created.Percussive

© 2022 - 2024 — McMap. All rights reserved.