I have to do a little project for my school and I would like to have some help for a little problem.
For this project I have to recreate a command interpreter like bash/shell without advanced option like redirection or pipe for now.
I finished it and i decided to do a little more. I created a prompt like this :
"my_login" ~/home/"my_login"/rendu/PSU_2014_minishell1 $
But when i do "cd" my prompt needs to change , problem is I can't refresh it because i took the environment variable PWD.
And to complicate a little more the work, i can't use every systems call I should use only:
opendir
readdir
closedir
malloc
free
exit
chdir
fork
stat
lstat
fstat
open
close
read
write
execve
access
wait
waitpid
wait3
wait4
signal
kill
I have an idea but I don't know how to do it. I thought I can execute the binairy "/bin/pwd" to have my location , but I don't how how to get this information after execute it, have you any idea?
Thanks !
And sorry for my bad english, I am French.
Related
I've got a cmd line app in C under Linux that has to run another process, the problem is that the child process prints a lot in a comand line and the whole app gets messy.
Is it possible to disallow child process to print anything in cmd line from parent process? It would be very helpful to for example being able to define a command that allows or disallows printing by a child process.
There's the time-honoured tradition of just redirecting the output to the bit bucket(a), along the lines of:
system("runChild >/dev/null 2>&1");
Or, if you're doing it via fork/exec, simply redirect the file handles using dup2 between the fork and exec.
It won't stop a determined child from outputting to your standard output but it will have to be very tricky to do that.
(a) I'm not usually a big fan of that, just in case something goes wrong. I'd prefer to redirect it to a real file which can be examined later if need be (and deleted eventually if not).
Read Advanced Linux Programming then syscalls(2).
On recent Linux, every executable is in ELF format (except init or systemd; play with pstree(1) or proc(5)) is running in a process started by fork(2) (or clone(2)...) and execve(2).
You might use cleverly dup2(2) with open(2) to redirect STDOUT_FILENO to /dev/null (see null(4), stdout(3), fileno(3))
I've got a cmd line app in C under Linux that has to run another process, the problem is that the child process prints a lot in a comand line
I would instead provide a way to selectively redirect the child process' output. You could use program arguments or environment variables (see getenv(3) and/or environ(7)) to provide such an option to your user.
An example of such a command program starting and redirecting subprocesses and redirecting them is your GCC compiler (see gcc(1); it runs cc1 and as(1) and ld(1)...). Consider downloading and studying its source code.
Study also -for inspiration- the source code of some shell (e.g. sash), or write your own one.
Good morning;
Right now, I'm writing a program which makes a Montecarlo simulation of a physical process and then pipes the data generated to gnuplot to plot a graphical representation. The simulation and plotting work just fine; but I'm interested in printing an error message which informs the user that gnuplot is not installed. In order to manage this, I've tried the following code:
#include <stdio.h>
#include <stdlib.h>
FILE *pipe_gnuplot;
int main()
{
pipe_gnuplot = _popen("gnuplot -persist", "w");
if (pipe_gnuplot==NULL)
{
printf("ERROR. INSTALL gnuplot FIRST!\n");
exit (1);
}
return 0;
}
But, instead of printing my error message, "gnuplot is not recognized as an internal or external command, operable program or batch file" appears (the program runs on Windows). I don't understand what I'm doing wrong. According to _popen documentation, NULL should be returned if the pipe opening fails. Can you help me managing this issue? Thanks in advance and sorry if the question is very basic.
Error handling of popen (or _popen) is difficult.
popen creates a pipe and a process. If this fails, you will get a NULL result, but this occurs only in rare cases. (no more system resources to create a pipe or process or wrong second argument)
popen passes your command line to a shell (UNIX) or to the command processor (Windows). I'm not sure if you would get a NULL result if the system cannot execute the shell or command processor respectively.
The command line will be parsed by the shell or command processor and errors are handled as if you entered the command manually, e.g. resulting in an error message and/or a non-zero exit code.
A successful popen means nothing more than that the system could successfully start the shell or command processor. There is no direct way to check for errors executing the command or to get the exit code of the command.
Generally I would avoid using popen if possible.
If you want to program specifically for Windows, check if you can get better error handling from Windows API functions like CreateProcess.
Otherwise you could wrap your command in a script that checks the result and prints specific messages you can read and parse to distinguish between success and error. (I don't recommend this approach.)
Just to piggy-back on #Bodo's answer, on a POSIX-compatible system you can use wait() to wait for a single child process to return, and obtain its exit status (which would typically be 127 if the command was not found).
Since you are on Windows you have _cwait(), but this does not appear to be compatible with how _popen is implemented, as it requires a handle to the child process, which _popen does not return or give any obvious access to.
Therefore, it seems the best thing to do is to essentially manually re-implemented popen() by creating a pipe manually and spawning the process with one of the spawn[lv][p][e] functions. In fact the docs for _pipe() give an example of how one might do this (although in your case you want to redirect the child process's stdin to the write end of your pipe).
I have not tried writing an example though.
I'm trying to write a shell that will eventually take advantage of concurrency. Right now I've got a working shell parser but I'm having trouble figuring out how to execute commands. I've looked a bit at exec (execvp etc.) and it looks promising but I have some questions.
Can exec handle file input/output redirection? Can I set up pipes using exec?
I'm also wondering about subshells. What should subshells return; the exit status of its last statement? Can subshells be a part of a pipe?
These might seem like really dumb questions but please bear with my inexperience.
Can exec handle file input/output redirection?
No, you do that with open() and dup() or dup2() (and close()).
Can I set up pipes using exec?
No, you do that with pipe(), dup() or dup2() and lots of close() calls.
I'm also wondering about subshells. What should subshells return, the exit status of its last statement?
That's the normal convention, yes.
Can subshells be a part of a pipe?
Yes. In a normal shell, you can write something like:
(cd /some/where; find . -name '*.png') | sed 's/xyz/prq/' > mapped.namelist
If you want to get scared, you could investigate posix_spawn() and its support functions. Search for 'spawn' at the POSIX 2008 site, and be prepared to be scared. I think it is actually easier to do the mapping work ad hoc than to codify it using posix_spawn() and its supporters.
The standard technique for a shell is to use fork-exec. In this model, to execute an application the shell uses fork to create a new process that is a copy of itself, and then uses one of the exec variants to replace its own code, data, etc. with the information specified by an executable file on disk.
The nice thing about this model is that the shell can do a little extra work with file descriptors (which are not thrown away by exec) before it changes out its address space. So to implement redirection, it changes out the file descriptors 0, 1, and 2 (stdin, stdout, and stderr, respectively) to point to another open file, instead of console I/O. You use dup2 to change out the meaning of one of these file descriptors, and then exec to start the new process.
I have C program ( program.c ) that calls a shell script ( command.sh ).
command.sh returns an output (a password), i need to get this output in my program.c.
using system(command); , i can't get hold of the output.
is there any other way in C to solve my problem?
Not in pure C. You want POSIX. Specifically popen function.
The specification has a nice example, that you can just copy 1:1
http://pubs.opengroup.org/onlinepubs/009604499/functions/popen.html
Sounds like you're afraid to use libraries. Please try and use libraries, they're just as much part of Unix as shell tools.
In pure C (well ... ignoring the contents of the system() call) you can redirect the shell script output to a file, then read that file.
system("whatever > file");
handle = fopen("file", "r");
/* if ok use handle */
fclose(handle);
You can use popen() as suggested above, but note that in this case you have no control over the process you created (e.g. you will not be able to kill it), you also will not know its exit status.
I suggest using classical pipe/fork/exec combination. Then you will know the pid of your child process, so you will be able so send signals, also with pipe() you are able to redirect process standard output, so you can easily read it in your parent process. As example you can see my accepted answer to popen() alternative.
You should open a pipe using popen but this sounds tedious. A C program calling a shell script for a password.
Ive got my program in C, 6 source files, and the aim is to copy those files to any other Linux OS computer, and (probably compile, im newbie, so not sure what is needed here) run this program in background. Something like:
user#laptop:~$ program
Program is running in a background. In order to stop Program, type
XXX.
Any tips on this?
Thanks in advance!
Put a daemon(0,0); call in your C program.
stopping it is a bit trickier, I suppose there is only one copy of the program running. Put the program's PID in a file, write another utility (XXX) which reads the PID from the file and kills it.
Important: daemon forks, get the PID of the program after calling daemon.
But maybe you are too newby and just want to execute your program with program& and later kill it.
I completely missunderstood the question. You need shell scripting for this.
For file copying you can use scp. Execute command on the other host with ssh. It should be something like (not tested):
pid=`ssh user#host "make >/dev/null 2>&1; nohup ./program; echo $!`
later you can stop it with
ssh user#host "kill $pid"
First, you should fork().
In parent, you should just exit, in child process - you should handle SIGHUP signal.
In such way - you have daemon.