Application accepts command line argument of the form : *argument but not of the form argument* or *argument* - c

For example if my program name is test.c
Then for the following run command the argc = 2 instead of 4.
$test abc pqr* *xyz*

Try to run:
$ echo abc pqr* *xyz*
and you will understand why you don't get the argc value you were expecting

It is probably because your shell / cmd.exe (no specifics are given!) use the * as file glob. If there are no files found that match the glob, the result will be empty.
Try calling you program like this:
test abc 'pqr*' 'xyz'
refer to http://en.wikipedia.org/wiki/Glob_%28programming%29 for details about globbing, and your shell's manual for details about escaping globs.

Related

Dash and C: eval "$(<cmdfile)" and system("eval \"\$(<cmdfile)\"") giving different results

I would like to use the system() function in C to evaluate an expression within a file cmdfile but I'm not getting the same results as when I do so on the command line directly. The content of cmdfile is the following:
$ cat cmdfile
echo hello
and when I evaluate its content on the command line directly, it works:
$ eval "$(<cmdfile)"
hello
To do the same in C, I'm using system(). This is my code:
$ cat systest.c
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char* cmd = argv[1];
printf("%s\n", cmd);
system(cmd);
return 0;
}
The trouble is that I don't see any output when using the above code:
$ ./systest "eval \"\$(<cmdfile)\""
eval "$(<cmdfile)"
There should be hello printed right after the printf output but it doesn't work. Still, I know that system() is definitely doing something, because if I give it a non-existing filename, dash complains:
$ ./systest "eval \"\$(<cmdfileFF)\""
eval "$(<cmdfileFF)"
sh: 1: cannot open cmdfileFF: No such file
and if I just evaluate echo hello without involving cmdfile, it works too:
$ ./systest "eval \"echo hello\""
eval "echo hello"
hello
I'd like to know what is causing this difference in behaviour. Is there any other way of executing the content of cmdfile in dash? I'm restricted to only using the built-in commands of dash on the command line, so options such as ./systest "eval \"\$(cat cmdfile)\"" are not possible. Further, the expansion of "$(<cmdfile)" should only happen within system(), not before (thus ./systest "eval \"$(<cmdfile)\"" won't work.
I tested this with dash 0.5.10.2-6 and dash 0.5.8-2.1ubuntu2.
Thank you for any insight!
Edit
Thanks to Jonathan Leffler's comment, I now realise that dash doesn't understand the $(<file) syntax. So what would be a dash-compatible equivalent?
Wrap-up
So my confusion was due to the fact that system(...) always uses /bin/sh, but when testing my expressions on the command line, I was accidentally invoking bash instead of dash. Hence the results were different.
$(< …) substitution isn’t POSIX-sh-compatible, but your sh is restricted to about that. A general alternative is to replace < cmdfile with cat cmdfile:
./systest "eval \"\$(cat cmdfile)\""
but I think dot-sourcing is equivalent in this case:
./systest '. ./cmdfile'
The proper fix is to put a shebang line in the script and mark it as executable.
#!/bin/sh
echo "hello"
The shebang needs to be the absolutely first line of the file (its first two bytes should be # and !). The quoting around the argument to echo is not strictly necessary here, but good practice. (See also When to wrap quotes around a shell variable?)
Changing the permissions only needs to be done once, when you have just created the file:
chmod +x ./cmdfile
Now, you can simply use
system("./cmdfile")

shell script "Thread: command not found"

So I am trying to write my first shell script that can automatically run some C codes for me. I read some materials online and here is my short shell script:
#!/bin/sh
# script for grading assignment 3
echo -n "Enter the student's index >"
read index
echo "You entered: $index"
#### Functions
function question_one
{
gcc -pthread -o $index.1 $index.1.c
taskset -c 1 ./$index.1 5 5
}
#### Main
$(question_one)
As you can see, the shell script is quite simple and what it does is also quite easy to understand. First compile a C source file named like 1.1.c, 2.1.c or 3.1.c and then run the output file with just one single CPU.
When I run this script, looks like it can successfully compile the file but unable to run the output file correctly. The error message is "assignment_three_grading: line 18: Thread: command not found". However, if I type in the commands manually by myself, everything is fine.
$(question_one)
Change this to simply:
question_one
To invoke a function you just name it as if it were a regular command. Using $(...) captures its output and tries to execute that output as another command name: definitely not what you want here.

perl command not found

I have a c code and I want take my code a perl command as argument like this:
./code ‫'‪'perl -e 'print "A"x202;'"cat file‬‬
"cat file": command not found
I have cat command in my machine.
could you possibly tell me what the problem is?
thank you in advance
I'm not exactly sure how you want to use the cat command in your case, however, as #ikegami said, you are nesting quotes. In your perl part, use q{} or qq[] to get single or double quotes, and circumvent actually typing them out -- what you use as a delimiter is free with q and qq
use double quotes for your perl script if you can, so what you get is
./code 'perl -e " use q<> or qq++ here "'
It could be that your path is not correctly set inside your code.
I would advice to pass the full cat command path.
You can get the full path of the cat command by typing:
which cat
In my machine the cat command is located in /bin directory, therefore I would give:
./code ‫'‪'perl -e 'print "A"x202;'"/bin/cat file‬‬

How to get input file name from Unix terminal in C?

My program gets executed like:
$./sort 1 < test.txt
sort is the program name
1 is the argument (argv[1])
and test.txt is the file I am inputting from
Is it possible to extract the name file from this? if so how?
The problem is I already wrote my whole program as if I could extract the name from the input line, so I need to be able to pass it into arguments.
Any help is appreciated,
Thanks!
You can't. The shell opens (open(2)) that file and sets up the redirect (most likely using dup2).
The only possible way would be for the shell to explicitly export the information in an environment variable that you could read via getenv.
But it doesn't always make sense. For example, what file name would you expect from
$ echo "This is the end" | ./sort 1
Though this can't be done portably, it's possible on Linux by calling readlink on /proc/self/fd/0 (or /proc/some_pid/fd/0).
eg, running:
echo $(readlink /proc/self/fd/0 < /dev/null)
outputs:
/dev/null
No you can't: the shell sends the content of test.txt to the standard input of your program.
Look at this:
sort << _EOF
3
1
2
_EOF
The < > | operators are processed by the shell, they alter standard input,output,error of the programs in the cmd line.
If you happen to run Solaris, you could parse pfiles output to get the file associated, if any, with stdin.
$ /usr/bin/sleep 3600 < /tmp/foo &
[1] 8430
$ pfiles 8430
8430: /usr/bin/sleep 3600
Current rlimit: 65536 file descriptors
0: S_IFREG mode:0600 dev:299,2 ino:36867886 uid:12345 gid:67890 size=123
O_RDONLY|O_LARGEFILE
/tmp/foo
1: S_IFCHR mode:0600 dev:295,0 ino:12569206 uid:12345 gid:67890 rdev:24,2
...
On most Unix platforms, you will also get the same information from lsof -p if this freeware is installed.

Shell script to test command line program

I have a program written in C that operates similar to the below output.
WELCOME TO PROGRAM.
Hit 1 to do task 1.
Hit 2 to do task 2.
Hit q to quit.
What i need is a bash shell script that start the program, then enters 1, 2 and q into the program so i can test all the functionality in one command.
I would assume it to look similar to the following
#!/bin/bash
./start kernel
1
2
q
You can use a "here document" . The syntax looks like this:
./start kernel <<EOF
1
2
q
EOF
"EOF" can be whatever unique word you want, as long as it isn't something you'll actually need in the input.
Typically you use expect for testing these types of applications.
You can save your input in a text file - input.txt and execute your program this way: ./program < input.txt
I do this:
#! /bin/bash
printf "1\n2\nq\n" | ./start kernel
You can think of shell scripts as what they are... just each line being executed in an (albeit new) shell.
A simple way to do this sort of input is, assuming [your program] accepts stdin, is:
#!/bin/bash
echo "1" | [your program] > [logfile1]
echo "2" | [your program] > [logfile2]
echo "q" | [your program] > [logfileq]

Resources