How to use xterm with -S option? - xterm

I am trying to automate xterm and it mainly relies on the -S option while launching the xterm.
From man page
-Sccn
This option allows xterm to be used as an input and output
channel for an existing program and is sometimes used in spe‐
cialized applications. The option value specifies the last few
letters of the name of a pseudo-terminal to use in slave mode, plus
the number of the inherited file descriptor. If the option
contains a “/” character, that delimits the characters used for
the pseudo-terminal name from the file descriptor. Otherwise,
exactly two characters are used from the option for the
pseudo-terminal name, the remainder is the file descriptor. Examples
(the first two are equivalent since the descriptor follows the
last “/”):
-S/dev/pts/123/45
-S123/45
-Sab34
Note that xterm does not close any file descriptor which it did not
open for its own use. It is possible (though probably not portable)
to have an application which passes an open file descriptor down
to xterm past the initialization or the -S option to a process
running in the xterm.
I hope this option is to make use of the input and output channels of xterm and can be customized.
How to use this option ?

"How to use" is pretty broad. There are a few examples of its use: a Tcl/Tk script multixterm written a while back, and the ditto program which is part of ncurses-examples.
The latter is mentioned here:
Get output from Ncurses app on a separate terminal (with screenshots)
Sending curses input to another terminal in C via a fifo
Multiple xterm pseudoterminals used as output only from multiple threads
The option is not much used; there was some problem a few years ago which was repaired in patch #314 (newer versions should work as shown).

Related

Detect prompt with xterm.js

TLDR: I want know how to detect from the output of a shell (e.g. zsh, bash) the location of the prompts (e.g. user#machine /etc % ).
Details
I have made a working shell frontend in the browser based on xtermjs. It is now equivalent feature-wise to e.g. the default macOS terminal application with zsh, bash and powershell. In a nutshell, it works by executing a shell process (e.g. zsh) as the child of a parent process that pipes the input/output from/to the browser via web sockets.
I want now to step up and implement a "collapse" functionality that hides the output of the selected commands in the history (like Visual Studio Code does now).
To this end, I need to detect the location of the prompts from the terminal output: the collapse function would then hide the characters between two consecutive prompts.
I know I can use the approaches below:
detect the prompt with a regular expression (I would need to parse the PS1 variable)
inject some special character sequence before and after the prompt (e.g. in variable PS1)
But both do not seem very robust, and may not work with some specific command interpreter. I could not find yet the location where this functionality is implemented in the source code of Visual Studio Code.
My question is: is there a robust way to achieve this functionality for at least zsh, bash and powershell (it is fine if it is specific to xterm.js)
Edit 1
This SO question is related: ANSI escape sequence for collapsing/folding text (maybe hierarchically)
It links to this interesting thread: https://github.com/PerBothner/DomTerm/issues/54
It appears that DomTerm uses escapes sequences at folding points (my solution 2).
Yet I don't see how to inject them into the terminal, besides hacking the PS1 env var.
Edit 2
While parsing iTerm's documentation I found out that it takes advantage of the hooks provided by the shell (e.g. for zsh) in order to print some special escape sequence at various locations, including before showing the prompt.
For example, in zsh, I can print string "🐮" before each prompt be executing precmd() { echo '🐮' }. Then when I execute e.g. ls I get
$> ls
[...]
🐮
$>
There is a more extensive explanation of the various available hooks for various shells here.
It looks like PowerShell uses a very different system though.

problems in Perl script with localized user name on Windows

I have a perl script to start a script file with default program.
system("Start C:\\Temp\\test.jsx");
It works file with English user names but when I change user name to ai𥹖Ц中 it doesn't work.
Also no error message appears to I'm not able to debug.
perl on Windows uses so called ANSI functions to interface with the outside world. That means, if you use interesting characters (for example, certain Turkish letters on a US-English Windows install), perl cannot see them. As I wrote on my blog:
You can't pass characters that are outside of the Windows code page to perl on the command line. It doesn't matter whether you have set the code page to 65001 and use the -CA command line argument to perl: Because perl uses main instead of wmain as the entry point, it never sees anything other than characters in the ANSI code page.
For example:
$ chcp 65001
$ perl -CAS -E "say for #ARGV" şey
sey
That's because ş does not appear in CP 437 which is what my laptop is using. By the time it reaches the internals of perl, it has already become s.
So, there is not much you can do with a stock perl. I was working on a set of patches, but things intervened. I may still get around to it this summer.
Now, in your case, you are passing "interesting characters" to an external program via system. The same problem applies. Because perl is using the ANSI versions of functions used to spawn processes etc, the program spawned will not see a Unicode environment. So, if you are trying to use Korean or Japanese programs with a system code page that does not include them, I am not sure what will happen.
There is not much you can do once perl is running. The environment, command line arguments, everything lives in the ANSI world from that point on. There may be funky work-arounds, but for that one would need to know exactly how 'ai𥹖Ц中' gets from your perl program to the external program.

When data is piped from one program via | is there a way to detect what that program was from the second program?

Say you have a shell command like
cat file1 | ./my_script
Is there any way from inside the 'my_script' command to detect the command run first as the pipe input (in the above example cat file1)?
I've been digging into it and so far I've not found any possibilities.
I've been unable to find any environment variables set in the process space of the second command recording the full command line, the command data the my_script commands sees (via /proc etc) is just _./my_script_ and doesn't include any information about it being run as part of a pipe. Checking the process list from inside the second command even doesn't seem to provide any data since the first process seems to exit before the second starts.
The best information I've been able to find suggests in bash in some cases you can get the exit codes of processes in the pipe via PIPESTATUS, unfortunately nothing similar seems to be present for the name of commands/files in the pipe. My research seems to be saying it's impossible to do in a generic manner (I can't control how people decide to run my_script so I can't force 3rd party pipe replacement tools to be used over build in shell pipes) but it just at the same time doesn't seem like it should be impossible since the shell has the full command line present as the command is run.
(update adding in later information following on from comments below)
I am on Linux.
I've investigated the /proc/$$/fd data and it almost does the job. If the first command doesn't exit for several seconds while piping data to the second command can you read /proc/$$/fd/0 to see the value pipe:[PIPEID] that it symlinks to. That can then be used to search through the rest of the /proc//fd/ data for other running processes to find another process with a pipe open using the same PIPEID which gives you the first process pid.
However in most real world tests I've done of piping you can't trust that the first command will stay running long enough for the second one to have time to locate it's pipe fd in /proc before it exits (which removes the proc data preventing it being read). So if this method will return any information is something I can't rely on.

Why does `ls | cat` != `ls`?

Why is there a difference in output between these two commands:
ls | cat
ls
The first one seems to separate filenames with a newline.
This also applies to commands suc has ls > outfile, and similar things.
I'm on Mac OSX, if that makes any difference.
The ls command checks the file type of its standard output. If it detects a “tty”, it emits multicolumn output. If it detects any other file type (like a disk file or a pipe), it emits single column output.
Tty is short for teletype. In the old days, you would use an actual teletype to interact with a Unix system. So if standard output was a teletype, ls would produce output optimized for humans. Otherwise, it would produce output optimized for programs.
With the advent of other ways to run an interactive shell, like telnet sessions and window systems, the Unix authors created the pseudo-teletype, or “pty”, a software-only “device” which pretends to be a teletype. One program (like the telnet server, the ssh server, or the terminal window) can use a pty to make another program (the shell) think it is talking to a teletype.
You can use the -C flag to force ls to emit multicolumn output. You can use the -1 (digit one) flag to force single column output.

What is the standard usage argument style?

I'm making some command-line tools for some research I'm doing. I'd like these tools to follow commonly used conventions regarding command line programs in Unix.
Should I use flags or just list parameters?
program one two three
program -a one -b two -c three
Where in the list of commands does the input file normally go, or is it better to < it into the program?
What about the output filename?
Should I specify the file extension for the output format, or have my program automatically put the correct extension on?
When the user enters an invalid command, is there a prototypical "correct usage" message?
Is "--help" or "-h" required?
Also, is there some sort of header file I can include that would help with managing these?
If you're looking for a "standard", then you could do worse than look at GNU's Standards for Command Line Interfaces. Other standards are available.
As far as coding for this goes, take a look at boost::program_options. Not only will this save you rolling a lot of your own code, but it does a good job of formatting the options for presenting to the user (the prototypical "correct usage" message, you asked for).
In answer to your specific questions:
Where in the list of commands does the input file normally go, or is it better to < it into the program?
I would expect these to come at the end of a command line. Like in GNU grep. If you are only processing one file and would like to make stdin available as an input source, that would not surprise most users.
If your command processes lots of files, then it would be unusual to have to specify a switch before the filenames. Think cat.
What about the output filename?
A -o or --output option is fairly common. If your file takes exactly one input and one output, then program inputfile outputfile would not surprise many users. If no output file is specified, perhaps you'll output to stdout; that would not be unusual behaviour and would allow your users to pipe the output through other commands (such as grep, less, etc...), They could also redirect stdout to a file using >.
Should I specify the file extension for the output format, or have my program automatically put the correct extension on?
This is probably a matter for debate. If I specified an output filename, I would expect to find that file created (or replaced, after a prompt) without the program changing the name.
When the user enters an invalid command, is there a prototypical "correct usage" message?
Using GNU grep as an example again:
grep: unrecognized option '--incorrect'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
This wouldn't surprise too many users and points them in the right direction if they've made a typo without swamping them with information.
Is "--help" or "-h" required?
That depends on your customer! I find it frustrating when this option isn't available.
Usually speaking, flags are there for providing options and parameter are for passing information. If you have input,output file as command line argument, use flags like -i -o, so sequence will not matter. -h is required if you want to (and need to) give documentation.

Resources