I work on vsc with remote-ssh. On local side the code works fine, but in ssh I can only compile the code (gcc program.c -o program -std=c11) but when I run it with .\program
I get the error message: bash: .program: command not found
What could be the reason and how can I fix it?
Use ./program. In Bash, and Unix systems generally, the character to separate file system components is the forward slash, “/”. The backward slash, “\” is used to “escape” characters normal purposes and treat the character literally. So \p says to treat “p” as an ordinary “p”, which it already is. So .\program is equivalent to .program, which requests the shell to execute a file named .program. Since there is no such file, it gives you an error message.
Related
I created a simple bash script called "myscript.h" I gave it a .h extensions for reasons that I won't disclose here. This bash script lives in "/var/ftp/something with spaces".
From the terminal, I can type in "/var/ftp/something with spaces/myscript.h" and the script works perfectly.
However, from within my C program, I type in
system("/var/ftp/something with spaces/myscript.h")
and it complains that "/var/ftp/something" is not found. I've changed my system call to the following with forward slashes:
system("/var/ftp/something\ with\ spaces/myscript.h")
However, it still complains that "/var/ftp/something" is not found. Assuming I can't change the directory names, how can I get around this?
Thanks!
To run a single script, you might avoid the system(3) library function (and use lower level system calls like fork(2), execve(2), waitpid(2)... which are used by the implementation of system(3)), or you could quote the script name when passing it to system(3).
For more details, read Advanced Linux Programming.
On Linux, system(3) is documented to fork a /bin/sh -c process. See sh(1p). And that POSIX shell has some quoting rules. You might use double-quotes and backslashes appropriately. So you would construct (and perhaps check) the string passed to system(3) (perhaps using asprintf(3) or snprintf(3) with care). Be aware that the C compiler also has (different) quoting conventions for string literals.
In general, you should avoid code injection (imagine a naughty user giving some a; rm -rf $HOME &; input as a "directory" name; you don't want to run system(3) on the weird "/var/ftp/a; rm -rf $HOME &;/myscript.h" string)
In your particular case, I recommend using fork(2), execve(2) (perhaps thru some carefully choosen exec(3) function), waitpid(2)... appropriately. This has the slight advantage to avoid depending on and running /bin/sh so could be slightly faster (by a millisecond).
Understand more the role of an Unix shell; for example, read about the various shell expansions in bash (they are similar to those mandated by POSIX sh) and be aware of globbing. See glob(7)
Note that you're adding quotes when running from the shell. You need to do the same here. Add quotes to the path name you're sending to system:
system("\"/var/ftp/something with spaces/myscript.h\"")
This should work with gcc version 5.4.0
system("\'\'/var/ftp/something\\ with\\ spaces/myscript.h\'\'");
Just put the filename inside single quotes
system("rm '/var/ftp/something with spaces/myscript.h'")
I have written a c program. I want to pipe the program and I want to make it look meaningful. So instead of writing ./a.out each time, I want to name it changetext. To achieve that, I compiled my program following way: gcc -o changetext myprog.c. To the best of my knowledge, this should replace the use of ./a.out and changetext should do that instead. But I'm getting command not found. I am new to c and unix environment. Any suggestion appreciated.
As I said in a comment, you can either put a dot slash (./) in front of the executable to run it
./changetext
Or you put in in a directory that is referenced in the PATH environment variable. A nice explanation of this safety feature can be found here (thanks to rubenvb):
http://www.linfo.org/dot_slash.html
It says that this is more or less to distinguish built-in commands from user-written commands with the same name. I am not convinced though. The shell could simply prefer built-in names to user-supplied ones, and look in the current directory as well as in the PATH.
But this is the *nix way.
In order to compile and run a program such as your changetext with just the command chanhetext, you must put the binary in a directory listed in your PATH environment variable. It is recommended that you put programs that you made for your own use in the ~/bin/ directory. The command you would use to accomplish this would be the following, assuming ~/bin/ already exists:
gcc -o ~/bin/changetext myprog.c
If it does not exist, you can simply create it, then log out and back in.
If you are tired of doing the ./ before the program name you can always make an alias such as
alias a='./a.out' or alias changetext='./changetext'
this just basically look for everytime you type changetext or a and then replaces it to have the ./ infront of it
As a beginner, I am trying to write a simple c program to learn and execute the "write" function.
I am trying to execute a simple c program simple_write.c
#include <unistd.h>
#include <stdlib.h>
int main()
{
if ((write(1, “Here is some data\n”, 18)) != 18)
write(2, “A write error has occurred on file descriptor 1\n”,46);
exit(0);
}
I also execute chmod +x simple_write.c
But when i execute ./simple_write.c, it gives me syntax error near unexpected token '('
Couldn't figure out why this happens ??
P.S: The expected output is:-
$ ./simple_write
Here is some data
$
You did
$ chmod +x simple_write.c
$ ./simple_write.c
when you should have done
$ cc simple_write.c -o simple_write
$ chmod +x simple_write # On second thought, you probably don’t need this.
$ ./simple_write
In words: compile the program to create an executable simple_write
(without .c) file, and then run that.
What you did was attempt to execute your C source code file
as a shell script.
Notes:
The simple_write file will be a binary file.
Do not look at it with tools meant for text files
(e.g., cat, less, or text editors such as gedit).
cc is the historical name for the C compiler.
If you get cc: not found (or something equivalent),
try the command again with gcc (GNU C compiler).
If that doesn’t work,
If you’re on a shared system (e.g., school or library),
ask a system administrator how to compile a C program.
If you’re on your personal computer (i.e., you’re the administrator),
you will need to install the compiler yourself (or get a friend to do it).
There’s lots of guidance written about this; just search for it.
When you get to writing more complicated programs,
you are going to want to use
make simple_write
which has the advantages of
being able to orchestrate a multi-step build,
which is typical for complex programs, and
it knows the standard ways of compiling programs on that system
(for example, it will probably “know” whether to use cc or gcc).
And, in fact, you should be able to use the above command now.
This may (or may not) simplify your life.
P.S. Now that this question is on Stack Overflow,
I’m allowed to talk about the programming aspect of it.
It looks to me like it should compile, but
The first write line has more parentheses than it needs.
if (write(1, "Here is some data\n", 18) != 18)
should work.
In the second write line,
I count the string as being 48 characters long, not 46.
By the way, do you know how to make the first write fail,
so the second one will execute? Try
./simple_write >&-
You cannot execute C source code in Linux (or other systems) directly.
C is a language that requires compilation to binary format.
You need to install C compiler (the actual procedure differs depending on your system), compile your program and only then you can execute it.
Currently it was interpreted by shell. The first two lines starting with # were ignored as comments. The third line caused a syntax error.
Ok,
I got what i was doing wrong.
These are the steps that I took to get my problem corrected:-
$ gedit simple_write.c
Write the code into this file and save it (with .c extension).
$ make simple_write
$ ./simple_write
And I got the desired output.
Thanks!!
Should a daemon on an embedded device using Busybox be written in C or as a script?
All the examples I have seen use #! /bin/ash at the top of the file and that is for scripting? But in the device I'm writing to has only complied C files (I think) and symbolic links in /usr/bin.
Every way I try to compile a C file with #include </bin/ash> (e.g. gcc -Wall -o daemon_busybox daemon_busybox.c) I get error after error report in /bin/ash:
/bin/ash:174:1: error: stray ‘\213’ in program
/bin/ash:174:1: error: stray ‘\10’ in program
/bin/ash:174:1: error: stray ‘\273’ in program
/bin/ash:174:1: error: stray ‘\204’ in program
/bin/ash:174:1: error: stray ‘\342’ in program
Note I have set this: /bin/ash -> busybox
Any ideas which way I should go?
Update:
I've been given the task trying to see if a daemon can be run on a small device that runs Linux (2.6.35-at-alpha4) and Java (SE Embedded Runtime Environment) with very limited memory (i.e. a 10 second wait to get java -version to report back).
Two weeks ago I didn't know much about daemons — only knew the word. So, this is all new to me.
On my development machine I have built two different daemon files, one in C and one as a script. Both run very nicely on my Linux machine.
But because of the very small size of the target device there is only busybox (no /lib/lsb/init-functions). So I'm trying to build a 3rd daemon file. I believe it should be written in C for this device, but all examples for busybox point to scripting.
Once your question is edited so that the file name you're trying to #include is visible, the problem becomes self-evident:
#include </bin/ash>
This tries to make the C compiler include the binary of busybox (via the symlink /bin/ash) into the code to be compiled. The average binary is not a valid C source file; this is doomed to failure.
Perhaps you simply need to drop that line — the C compiler stands a better chance of working if it is given header files and source files to compile. Maybe there's more work needed; we don't have enough information to help there.
Many daemons are written as C programs, but a carefully written shell script could be used instead.
Personally, I would like to do this as a script (I've never liked C). But on the device everything in the /usr/sbin folder looks like a C file. So, the conservative coder in me says C is the way to go. I know: ask the guys developed the device — but they're long gone. Right now my daemon is just a test (i.e. printf("Hello World\n"); ). I'm trying to get printf passed to Busybox. But so far I cannot get this file to compile. I just need a simple daemon in C to start.
OK; your C code for that should be just:
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
Save it in hw_daemon.c. Compile it using:
gcc -o hw_daemon hw_daemon.c
If that won't compile, then you've not got a workable C development environment for the target machine. If that will compile, you should be able to run it with:
./hw_daemon
and you should see the infamous 'Hello World' message appear.
If that does not work, then you can go with the script version instead, in a file hw_script.sh:
#!/bin/ash
printf "Hello World\n"
You should be able to run that with:
Predicted output — not output observed on a machine.
$ ash hw_script.sh
Hello World
$ chmod +x hw_script.sh
$ ./hw_script.sh
Hello World
$
If neither of those works at all, then you've got major problems on the system (maybe Busybox doesn't provide a printf command workalike, for example, and you need to use echo "Hello World" instead of the printf).
I'm on a Mac and in terminal I'm compiling my program
gcc -Wall -g -o example example.c
it compiles (there are no errors), but when I try to provide command line arguments
example 5 hello how are you
terminal responds with "-bash: example: command not found"
how am supposed to provide the arguments I want to provide after compiling?
Run it like this with path:
./example 5 hello how are you
Unless the directory where the example binary is part of the PATH variable, what you have won't work even if the binary you are running is in the current directory.
It is not a compilation issue, but an issue with your shell. The current directory is not in your PATH (look with echo $PATH and use which to find out how the shell uses it for some particular program, e.g. which gcc).
I suggest testing your program with an explicit file path for the program like
./example 5 hello how are you
You could perhaps edit your ~/.bashrc to add . at the end of your PATH. There are pro and conses (in particular some possible security issues if your current directory happens to be sometimes a "malicious" one like perhaps /tmp might be : bad guys might put there a gcc which is a symlink to /bin/rm so you need to add . at the end of your PATH if you do).
Don't forget to learn how to use a debugger (like gdb). This skill is essential when coding in C (or in C++). Perhaps consider also upgrading your gcc (Apple don"t like much its current GPLv3 license so don't distribute the recent one; try just gcc -v and notice that the latest released GCC is today 4.8.1).
./example 5 Hello how are you is the syntax you're looking for.
This article lends a good explanation as to why this is important.
Basically, when you hit Enter, the shell checks to see if the first set of characters is an absolute path. If it's not, it checks the PATH variable to find executables with the name of the command you are trying to run. If it's found, it will be run, but otherwise it will crash and burn and you will become very sad.