Cross Platform Ch Shell Programming
- Ch Shell (ch) is a C compatible and genuine C shell
- Ch Shell versus C Shell, Bash and Korn Shell
- Keyboard shortcuts in Ch shell
- Ch Extensions to C for Shell Programming and Scripting
- Ch Shell difference between Windows and Unix
- More examples
Ch Shell (ch) is a C language shell and genuine C shell, an alternative to MS-DOS in Windows
Shell programming with scripts is effective
to automate repetitive tasks such as system administration,
regression test, and rapid prototyping.
The language syntax of
conventional Windows MS-DOS and Unix shells such as Bourne shell,
C shell, and Korn shell are awkward.
Similar to symbolic mnemonic forms of lower level assembly languages,
special meanings for clusters of metacharacters
in MS-DOS/Unix shells are difficult to remember.
Therefore, large shell scripts written in these MS-DOS/Unix shell programming languages
are hard to read and difficult to change and maintain. In addition, the power
for these MS-DOS/Unix shell programming languages is limited.
Like millions of hard-to-program VCRs blinking
in American living rooms,
only a fraction of the capabilities of these shell programming languages
are used by the majority of MS-DOS/Unix users.
Most users treat these MS-DOS/Unix shells as command interpreters;
their day-to-day programming tasks are handled
in C or other conventional programming languages.
"I'm starting to use Ch for scripting and to learn C. I often
have to write little scripts and learn more and more of Bash, GNU tools,
and Linux to get done what I wasn't. I then thought I wish there was a
shell
in C, not like the other shells that are strangely called C shells, csh or
tcsh, which are not like C.
Even though learning C is much harder than
Bash or some other scripting language, I realized learning C would have
a lot of advantages. A lot, if not most, of open source and other software
is written in C and understanding C would unlock all that. Also if I
was careful I could write stuff cross platform that would work on
Linux and Windows.
Now whenever I have to script something I try to do it
in C and/or Ch. Ch is a great product.
I can do my scripting and learn C at the same time."
-- James Richards
"I appreciate ch and SoftIntegration. I have used ch as a unix
shell in the past. Right now I use it in the Linux classes that I
teach as an alternative to the standard shells.
I also use it for myself to brush up on my C/C++ basics
or to knock off a quick prototype for my personal use.
Keep up the great work, guys. I believe that this is a fine
product."
--Robert Ritter, Technical Instructor, Centriq Training
Read More Testimonials
|
|
|
|
|
|
Ch is an interpretive implementation of C as Unix/MS-DOS shell.
ch can also be used as a login shell the same as Unix shells.
Ch bridges
the gap between the C language and Unix/MS-DOS shell.
Unix shell commands,
such as vi, ls, mv, grep, find, awk, and sed can run in Ch in
both Windows and Unix, they are integrated into Ch script command.
It is designed for both interactive command interpretation and
shell programming. Ch is a true VHLL for programming while it retains the
shell features such as command-line editing, tab completion, history, aliases, piping,
wildcarding, iteration etc.
When Ch is used in a single command mode,
most features of Ch are the same as conventional Unix shells
such as Bourne shell, C shell, and Korn shell, and MS-DOS shell in Windows.
However, since Ch is a superset of C,
shell scripts written in C and extended Ch shell programming features
are much more powerful, efficient and easy to maintain.
Getting Help
man unix_command |
Read the manual on a unix_command. i.e: 'man ls' to see the manual on "ls"
|
man C_function_name |
Read the manual on C_function_name. i.e: 'man strcpy' to see the manual on
C function 'strcpy' |
Home directory and wildcards
~ |
Your home directory |
~username |
Home directory of username |
~/subdirectory |
The subdirectory directory in your home directory
|
cd - |
it goes back to your previous directory from your current working directory.i.e: if you are in c:/windows, go to C:/Program Files/Microsoft, type 'cd -' to go back to c:/windows.
|
cd -- |
it switches you to the previous previous directory. i.e, if you are in
/usr, go to /usr/local, then go to /usr/local/bin, type 'cd --' to go back to
/usr.
|
cd ~ or cd |
It goes to your home directory from your current working directory
|
* |
Any number of characters. i.e: 'ls *.ch' will list all files ending in .ch
|
? |
Any single character |
History to show the previous commands executed
!! |
Re-execute the last command (or use the arrow shortcut described below)
|
!number |
Execute a command by number |
!string |
Execute the last command beginning with string |
^old^new |
Execute the last command, substituting old with new
|
ctrl-p
|
Scroll backwards through previous commands
|
Pipes and output redirect
command > filename |
Redirect command's standard output to overwrite file 'filename'.
|
command >> filename |
Redirect command's standard output to append to the file 'filename'
|
ch -r command >filename (in both Windows and Unix)
command >filename 2>&1 (in Unix)
command 1>filename 2>&1 (in Windows)
|
Redirect command's standard output (stdout) and standard error (stderr)
to the file 'filename'
|
command < filename |
Redirect command's standard input to read from the file 'filename'
|
command1 | command2 |
Redirect command1's standard output to command2's standard input
|
command & |
Run command in background
|
Ch Shell versus C Shell, Bash and Korn Shell
In terms of shell programming,
Ch will be as
close to C shell as possible, but no closer.
Ch shell is a genuine 'C' shell and portable in Windows
and Unix while C Shell (csh) has nothing like more like C comparing with other
languages such as php etc except its name.
The semantics of history and alias features
in Ch are similar to C-shell.
But the syntax is different from C-shell because
Ch is a superset of C.
The following table highlights the syntax differences
between Ch shell and C shell, but with the same semantics.
C Shell | Ch Shell |
$#argv | _argc |
$argv[*] | strjoin(" ", _argv[1], _argv[2], ..., _argv[_argc]) |
$argv | strjoin(" ", _argv[1], _argv[2], ..., _argv[_argc]) |
$* | strjoin(" ", _argv[1], _argv[2], ..., _argv[_argc]) |
$argv[1-n] | strjoin(" ", _argv[1], _argv[2], ..., _argv[n]) |
$0 | _argv[0] |
$argv[n] | _argv[n] |
$1 $2 ... $9 | _argv[1] _argv[2] ... _argv[9] |
$argv[$#argv] | _argv[_argc] |
set prompt = "ch> " | _prompt = "ch> " |
set path = (/usr/bin /bin) | _path = "/usr/bin /bin" |
umask 022 | umask(022) |
setenv PATH "/usr/bin /bin" | putenv("PATH=/usr/bin /bin") |
echo $PATH | printf("%s\n", getenv("PATH")) |
echo $PATH | echo $(getenv("PATH")) |
echo $PATH | echo $PATH |
echo ${PATH} | echo ${PATH} |
echo $path | printf("%s\n", _path) |
echo $path | echo $_path |
unsetenv PATH | remenv("PATH") |
printenv PATH | getenv("PATH") |
unset path | remvar _path |
unset path | #pragma remvar(_path) |
unset i | remvar i |
unset i | #pragma remvar(i) |
set i =90 | int i = 90 |
set i =91 | i = 91 |
set hostnam =`hostname` | string_t hostnam =`hostname` |
set host =`hostname` | _host =`hostname` |
alias rm "rm -i" | alias("rm", "rm -i") |
alias rm | alias rm |
alias rm | alias("rm") |
alias | alias |
alias | alias() |
unalias rm | unalias rm |
unalias rm | alias("rm", NULL) |
alias f "find . -name \!:1 -print" | alias("f", "find . -name _argv[1] -print") |
alias e "echo \!* \!$ \!#" | alias("e", "echo _argv[*] _argv[$] _argv[#]") |
eval ls | streval("`ls`") |
eval ls | system("ls") |
eval setenv NAME VALUE | streval("putenv(\"NAME=VALUE\")") |
/usr/bin/ls * | /usr/bin/ls * |
./cmd -option | ./cmd -option |
status | _status |
ls ~ * | ls ~ * |
ls > output | ls > output |
ls | tar -cf tarfile | ls | tar -cf tarfile |
ls $PATH | ls $(getenv("PATH")) |
ls $PATH | ls $PATH |
ls $path | ls $_path |
history = 100 | _histsize = 100 |
history | history |
$cmd | $cmd |
!l | !l |
!l -agl | !l -agl |
!3 | 13 |
!-1 | !-1 |
!! | !! |
vi `grep -l "str1 str2" *.c` | vi `grep -l "str1 str2" *.c` |
/* use $ inside ` ` */
set filename="test.txt"
set tmpFilename=$filename
echo `wc -w $tmpFilename` |
string_t filename = "test.txt";
string_t tmpFilename = filename;
echo `wc -w $tmpFilename`; |
.cshrc .login .logout | .chrc .chlogin .chlogout (in Unix),_chrc (in Windows) |
.cshrc .login .logout | .chsrc .chslogin .chslogout (in Unix), _chsrc (in Windows) |
Bash and Korn Shell | Ch Shell |
eval $(date "+month='%B' mon='%m' year='%Y'")
echo $month $mon $year
|
string_t month, mon, year;
streval(`date '+month="%B", mon="%m", year="%Y"'`);
echo $month $mon $year
|
ls /non_exist_directory >junk 2>&1
|
ls /non_exist_directory >junk 2>&1
|
export PS1="\u@\H \W \A >"
|
_prompt=stradd(_user, "@", _host, " ", _cwdn, " ",`date +%k:%M`, " >")
|
Prompt Description
|
bash Prompt
|
ch Prompt
|
Current Working directory
|
\w
|
_cwd
|
the basename of the current working directory
|
\W
|
_cwdn
|
User name
|
\u
|
_user
|
Full hostname
|
\H
|
_host
|
Hostname up to the first '.'
|
\h
|
`hostname -s`
|
The current history number
|
\!
|
_histnum
|
Time of day in 24-hour hh:mm
|
\A
|
`date +%k:%M`
|
Keyboard shortcuts in Ch shell
Copy and Paste (Two ways to do it):
- Using Console GUI: if you want to copy and paste from GUI,
you can run "console" from ch shell. it allows you to do copy and paste by
clicking the button from GUI.
-
shortcut using mouse (this solution works in console GUI above and Ch shell):
To Highlight the text you wish to copy: Click down once, with your cursor on one side of the text you want to copy, with your left mouse button. Hold the mouse button down. Then drag your mouse pointer over the text until all of the text you wish to copy is colored differently than the rest of the text on the page. Now let go of the mouse button. If you have highlighted correctly, the text should stay colored differently.
To Copy: Right click the mouse.
To Paste:
Place your cursor where you want to paste, right click again to paste.
|
TAB: Autocomplete the filename, command or directory name from the cursor position.
Trick to handle a space in the filename or directory when having multiple options, add an escape '\' before the space ' ', then type 'TAB'. i.e:
C:/> cd c:/do[TAB]
Documents/ Documents and Settings/
C:/> cd c:/Documents\ [TAB]
C:/> cd "c:/Documents and Settings"/
Advantage in Ch shell running "cd [tab]" in ch shell will display a list of
directories to select from, while other shells such as bash (version 4.1.2) will display a list of
files (which are not necessary) and directories.
|
Ctrl+a: (home) moves the cursor to the line start (equivalent to the key Home).
|
Ctrl+e : (end) moves the cursor to the line end (equivalent to the key End).
|
Ctrl+p: (previous) recalls the prior command (equivalent to the key Up).
|
Ctrl+n: (next) recalls the next command (equivalent to the key Down)
|
Ctrl+u : clears the line content before the cursor and copies it into the clipboard.
|
Ctrl+k : clears the line content after the cursor and copies it into the clipboard.
|
Ctrl+w : clears the word before the cursor and copies it into the clipboard.
|
Ctrl+y : (yank) adds the clipboard content from the cursor position.
|
Ctrl+d : sends an EOF marker, which closes the current shell (equivalent to the command exit) if there is no text on the current line.
|
Ctrl+c : sends the signal SIGINT to the current task, which aborts and closes it.
|
Ctrl+z (available in unix only): sends the signal SIGTSTP to the current task, which suspends it. To execute it in background one can enter bg. To bring it back from background, the foreground command fg ('process name or id') can be issued.
|
Ch Extensions to C for Shell Programming and Scripting
"I am using Ch shell programming capabilities to automate the
download and extraction of data from archive (*.ar) files using the
Unix ar command for an automation system running under Win2000.
I use ar within a Ch built-in 'for each' loop to extract all files (*.ar)
within a given directory. It works beautifully.
I am very impressed with the capabilities of the Ch language,
and plan to make more use of it in future in developing automation
scripts."
-- Jeremy Walsh, National Institute of Water and Atmospheric
Research, New Zealand
"I just stumbled on your product while looking for something else on the Internet. I had never heard of Ch prior to that, but so far I'm very impressed with everything it is capable of. I've been a C programmer for a long time and do mostly systems programming in an IT environment. I really like the Ch shell and the ability to run C code as a script. I can see a lot of uses for this in a systems programming environment. Just surprised I've never heard of it before now. Looks like you focus on larger companies and education. I haven't been in college in a long time and I've spent most of my career in small companies, but I do see its usefulness. I will definitely be exploring this further."
-- Robert Berry
"We use Ch for the classes 'Introduction to Computer Concepts' and 'General Applications Programming' to introduce the concept of interpreted/scripting languages and do a brief overview of shell commands. These are classes for non-computer science majors. Ch is ideal for our purposes; the conventional way (remoting to Linux servers) seems to be less effective for non computer science major students. Ch works great! Thank you very much."
--Yuliya Kopylova, University of South Carolina
"As a C debugger and learning tool -- being able to execute C snippets as scripts is a much better debugging method than breakpoints (at least for what I do). Plus if I run across a function I'm not familiar with I can just try it without the whole write/compile/link/run tedium. I especially love that I have access to the C interpreter, the WSH, and the Win32API. This way I can use regular C, VBScript, JScript, or MFC C++ seamlessly as the situation requires.
In summary: cool shell, very stable and reliable so far. Glad to see C holding the line against the barbaric Basic and Java incursions."
-- Weldon Goree, Sr. Network Administratorar
Read More Testimonials
|
|
|
|
|
|
Ch extends C with following features, which make it
especially suitable for shell programming and cross platform scripting.
-
Ch can be used in either command shell or program
mode interpretively.
Ch language environment can be used as a command shell.
In command shell,
history substitution, event designator, quick substitution, command
substitution, aliases, and file or directory
name completion using a tab key
are available in Ch.
An example of Ch shell in action is given as follows:
> hello.c
Hello, world!
(execute the famous hello.c program without compilation)
> int i, *p;
> p = &i;
> *p = 90;
> printf("i = %d\n", i);
i = 90
>if (i == 90) printf("good\n"); else printf("bad\n");
good
> int **p2
> p2 = &p
> printf("**p2 = %d\n", **p2)
**p2 = 90
> ls * > junkfile
(all file names go to junkfile)
> i**p
8100
> array int a[2][3]
> a = (array int [2][3])5
> a
5 5 5
5 5 5
> 2*transpose(a)
10 10
10 10
10 10
> which ls
ls is aliased to ls -F // if ls is an alias set in ~/[_]chrc
>
> int i;
> for (i=0; i<6;i++) printf("%d\n",i);
0
1
2
3
4
5
>
-
A quick calculator
#return to get the calculation result from ch shell
> 5*9-4+334-(5*9)*2
285
>
-
POSIX
Ch supports POSIX for across platform directory and file processing.
Sample code can be found here.
-
String data type
C is a small language; it has no string data type.
Pointers to char are handled as strings in C.
Ch provides an alternative string data type for pointers.
It eliminates potential bugs before they happen.
The string data type can also be used with existing C functions
and C data type of 'pointers to char'.
For shell programming,
a string data type
is added to C in Ch.
It is seamlessly merged
with pointer to char.
All functions defined in the standard C library header string.h
are valid for both pointers to char and strings.
String is a first-class object in Ch.
For example, the following code fragment
string_t s, a[3];
s = "great string"
s = stradd("greater ", s)
strcpy(a[0], s);
printf("a[0] = %s\n", a[0]);
will display
greater great string.
-
Foreach-loop is added for shell iteration.
The code below will create three directories
dir1, dir2
and
dir3
in the current directory.
string_t token, str="dir1 dir2 dir3";
foreach(token; str) {
mkdir $token;
}
-
Here document and Verbatim output.
The Here document and verbatim output features can be achieved using
the code block feature of function fprintf.
The Ch function sendApplet() below generates a C program.
void sendApplet(char *x, char *y, char *expr) {
fprintf(stdout, "#include\n");
fprintf(stdout, "int main() {\n");
fprintf(stdout, " double x = %s;\n", x);
fprintf(stdout, " double y = %s;\n", y);
fprintf(stdout, " printf(\"x = %%f, \", x);\n");
fprintf(stdout, " printf(\"y = %%f \\n\", y);\n");
fprintf(stdout, " printf(\"%s = %%f\\n\", %s);\n", expr, expr);
fprintf(stdout, "}\n");
}
The above function sendApplet() can be rewritten in Ch as follows.
If you want to redirect to a file instead of 'stdout',
you can simple open a file and replace 'stdout' below with your file handler.
void sendApplet(char *x, char *y, char *expr) {
fprintf stdout << ENDFILE
#include
int main() {
double x = $x;
double y = $y;
printf("x = %f", x);
printf("y = %f\n", y);
printf("$expr = %f\n", $expr);
}
ENDFILE
}
-
The controlling variable of the switch and case
statement can be a string in addition to integral type.
#!/bin/ch
char *ch="SoftIntegration Ch";
float version=2;
string_t hostname=`hostname`;
switch (hostname) {
case "mymachine":
printf("Hello world\n");
break;
case "testmachine":
fprintf stdout << ENDPRINT
Welcome to use $ch version $version
SoftIntegration, Inc.
ENDPRINT
echo Ch is cool! I can now use a C program to backup files
dump 0ubdsf 80 50000 50000 /dev/nrst0 /dev/sd0a
break;
default:
break;
}
If you want to prevent the variable or expression substitution for '$',
you can precede the '$' with '\'. '$' is
passed unchanged if followed by a blank, tab, or end-of-line.
-
Variable substitution and command substitution with combination of shell commands and C code
Shell commands such as sed, awk, wc, grep, etc. can be combined
with C code to run in Ch with variable substitution and command substitution.
Executable programs can also be used directly in a Ch script.
Below is an example:
#!/bin/ch
string_t result1;
char result2[50];
grep "test" myfile.txt;
if ( _status == 0 )
{
printf(" 'test' is found in myfile.txt\n");
}
else
{
printf("Cannot find 'test' in myfile.txt\n");
}
result1=`wc -l /etc/passwd`;
echo $result1;
strcpy(result2, `wc -l /etc/passwd`);
printf("%s\n", result2);
The output for result1 and result2 are the same in the above program.
-
Safe Ch is designed for the growing need of internet computing.
In addition to restrictions imposed by conventional restricted shell,
many other features are disabled in safe Ch
for across-network internet computing.
A system administrator may grant limited access to
users using safe Ch.
-
System variables
_argc and _argv
for command line argument interface.
System variables
_argc and _argv
are equivalent to arguments
argc and argv in startup C function
int main(int argc, char *argv[]);
Assume program
cpfile.ch
contains the following statements.
#!/bin/ch
cp /dir/source/$(_argv[1]) /dir/dest/
Program
cpfile.ch
can be used to copy any file located
at
directory
/dir/source
to directory
/dir/dest.
For example, the following commands
> cpfile file1
> cpfile file2
will copy files
file1 and
file2
from
directory
/dir/source
to directory
/dir/dest.
-
FAQ
Ch Shell difference between Windows and Unix
Ch shell runs slightly different in Windows and Unix.
- command substitution
In windows ch shell, the following command substitution is supported.
> `date`
> char *a=`date`;
> echo $a
Wed Nov 26 21:12:23 Pacific Standard Time 2011
However, Ch shell in Windows doesn't support the following command substituion.
> echo `date`
In Unix Ch shell, they are all supported.
- background process
In windows, Ch shell supports background process ( & ) for win32 GUI
applications, not the unix utilities. For example: "ls & " doens't work. however, "notepad &" works fine. In Unix, there is no such a problem
in Ch shell.
- stdout and stderr redirect
> ch -r command >filename (in both Windows and Unix)
> command >filename 2>&1 (in Unix)
> command 1>filename 2>&1 (in Windows)
- path
In Unix, ch shell works the same as bash or csh.
The working directory in Ch shell in windows differs from cygwin and msdos shell.
|
Ch shell |
cygwin or unix shell in windows |
MSDOS shell |
working directory |
c:/Users/username |
/c/Users/username |
c:\Users\username |
More examples
-
Example 1
The following Ch shell script can be
used to backup file systems.
#include<stdio.h>
int main () {
printf("Hello, world!\n");
echo Ch is cool! I can now use a C program to backup files
dump 0ubdsf 80 50000 50000 /dev/nrst0 /dev/sd0a
}
-
Example 2 with Read eval print loop (REPL) features.
double x;
x = 2.5;
x = streval("2*x")
printf("x = %.2lf\n", x);
The output is 5.00.
-
Example 3
The example below will print out all sub-directories and files
in the current directory, as well as the full command path
for command
gzip.
#!/bin/ch
#include <stdio.h>
char *s;
int i=0;
foreach (s;`ls`) {
i++;
echo $s;
}
printf("the total number of directory and files are %d\n",i);
s =`which gzip`;
echo $s;
-
Example 4
Below is another sample shell script.
#!/bin/ch
int main() {
char *s = "pointer to char";
int i;
float f, *p;
f = 6;
p= &f;
printf("s = %s\n", s);
printf("*p = %f\n", f);
/* output from the following statement is "6 6 pointer to char o" */
echo $f $(*p) $s $(*(s+1));
pwd
ls > junk
}
-
Example 5
The following shell commands in Bourne Shell sh
#!/bin/sh
command argument << EOF
input from the console command line
abcd
EOF
can be handled in Ch as follows:
#!/bin/ch
#include
FILE *fp;
string_t command_args="input from the console command line\nabcd";
fp = popen("command", "w");
fwrite(command_args, strlen(command_args), sizeof(char), fp);
pclose(fp);
-
Example 6
List all commands available anywhere in your path in Unix.
#!/bin/ch
#include
string_t dir, file; /* define string type */
foreach (dir; `echo $PATH | tr ":" " "`) {
foreach (file; `ls $dir`) {
if (access (dir/file, X_OK) ==0 ) {
echo $dir/$file;
}
}
}
-
Example 7
Find and compile all .c files into .o
in the current directory when the .o is old or absent.
#!/bin/ch
#include
struct stat cstat, ostat;
string_t c, o;
foreach (c; `find . -name "*.c"`) {
o=`echo $c | sed 's/.c$/.o/'`;
stat(o, &ostat);
stat(c, &cstat);
if (ostat.st_mtime > cstat.st_mtime) {
echo "compiling $c to $o";
gcc -c -o "$o" "$c";
}
}
-
Example 8
Uses awk in Ch shell.
cat file_name | awk "{print \$1}"
awk "{print \$1}" < file_name
Note: This article is also translated to Serbo-Croatian
language, Greek and German.
|