I get a wierd Linux system message "Transport Endpoint is not connected" in response to a write call immediately after a successful open call. All this happens immediately after a Slackware Linux 2.6.33.4 reboot.
I'm writing a forms-handler in C and it runs under lighttpd and fastcgi (and before some smart alec pipes up and asks 'why am I not using his/her favourite language, it's because I like C --- OK? OK!).
I've got the major facilities of the application running - it displays index.htm (which is a form) and when the form is 'Submit'ted, finds the program I've written which correctly processes the contents returned and displays the next form. It's got complex enough that now I need to print some debugging statements somewhere, to give me some feedback from program additions. Thus arises the problem.
Research indicates that this message usually means that the endpoint of the file path is not or has become not mounted but /tmp/debug.log (which is the file I'm trying to create/append-to lives on the root partition. But then why is the open() successful but the write() is not?
The program fragment below is the bit which is giving trouble. The printf() statements send output to the web interface (for those unfamiliar with libfcgi) to give me some idea what's happening.
I can't get my (properly indented) code through this forum's demented code filter and I can't attach it in a zip file, so you'll just have to take my word that the syntax is correct.
Any clues?
This line
if(fd = open(DEBUG_FILE_NAME, (O_CREAT | O_APPEND | O_RDWR), (S_IWUSR | S_IRGRP | S_IROTH | S_IRUSR)) < 0)
results in fd being set to the result of open(DEBUG_FILE_NAME, (O_CREAT | O_APPEND | O_RDWR), (S_IWUSR | S_IRGRP | S_IROTH | S_IRUSR)) < 0 which most likely is 0.
So the write(fd, ... tries to write to stdin, which is weird, so you get a weird error ... ;-)
To fix this fix the parenthesis.
You could do this for example in save manner by using Yoda-Conditions:
if (0 > (fd = open(DEBUG_FILE_NAME, (O_CREAT | O_APPEND | O_RDWR), (S_IWUSR | S_IRGRP | S_IROTH | S_IRUSR))))
("save" in terms that everything important is at the left in one place: if (0 > (fd = open(...)
I have a small snippet
fd = open("data", O_RDONLY | O_CREAT, 0666) is giving me the permission wrongly.
When I did the ls -l data I got this
-rw------- 1 mayukhsarkar staff 0 Aug 17 11:44 data
can some tell what's wrong?
Note: In koding.com I am getting permission like this
-rw-r--r-- 1 mayukh mayukh 0 Aug 17 06:11 data
SOLVED: umask(000) before the open syscall did the trick
You're passing the mode incorrectly. It needs to be passed as a third argument:
open("data", O_RDONLY | O_CREAT, 0666);
Note that creating a file with O_RDONLY doesn't make a lot of sense, as you won't be able to write to it after creating it...
I'm trying to open and create a POSIX message queue with one user (named "usuario-prueba") in order to send a message to the queue, and just open and receive the message with another user (named "usuario-prueba2"). Both users belong to the same group, however it seems impossible to open the queue with the second user (I get "permission denied" message).
Here're some outputs:
usuario-prueba#myhost:~$ id
uid=1001(usuario-prueba) gid=1002(usuario-prueba) grupos=1002(usuario-prueba),1001(pruebas-mqueue)
usuario-prueba2#myhost:~$ id
uid=1002(usuario-prueba2) gid=1003(usuario-prueba2) grupos=1003(usuario-prueba2),1001(pruebas-mqueue)
As you can see both users belong to the same group (pruebas-mqueue) as I told before.
I'm creating and opening the queue with:
flags = O_RDWR | O_CREAT
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
What is wrong?
I know execvp can be used to execute simple commands as follows:
char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);
I want to know what goes on in here when I run execvp. In man page it says execvp replaces the image of the process image with the new one. However here I am running a command not an executable.
To be specific, say there is a command that specifically requires an input e.g. cat. If I have a text file text.txt which contains the file name expected for cat and I redirect stdin to the file stream of the file, would the output of execle("cat","cat",NULL) or execvp("cat", arg) (obviously where arg stores "cat" and NULL) result in the output in the console as the cat /filename would? My intuition is I have to read the file and may be parse it to store the arguments in the arg. However I want to make sure.
Thanks in advance!
Here's what happens in an execvp call:
Your libc implementation searches in PATH, if applicable, for the file that is to be executed. Most, if not all, commands in UNIX-like systems are executables. What will happen if it is not? Try it. Have a look at how glibc does it.
Typically, if the executable is found, a call to execve will be made. Parts of execve may be implemented in libc or it may be a system call (like in Linux).
Linux prepares a program by allocating memory for it, opening it, scheduling it for execution, initialises memory structures, sets up its arguments and environment from the supplied arguments to the execvp call, finds a handler appropriate for loading the binary, and sets the current task (the execvp caller) as not executing. You can find its implementation here.
All steps above conform to the requirements set by POSIX which are described in the relevant manual pages.
Regarding your questions:
In man page it says execvp replaces the image of the process image
with the new one. However here I am running a command not an
executable.
Long-long time ago shell was very limited and almost all UNIX commands was standalone executables. Now, mostly for speed purposes some subset of UNIX commands is implemented inside shell itself, those commands are called builtins. You can check whatever command is implemented in your shell as built-in or not via type command:
λ ~/ type echo
echo is a shell builtin
(Full list of builtins with descriptions can be found in man pages to your shell e.g. man bash-builtins or man builtin.)
But still most of the commands still have their executable-counterpart:
λ ~/ whereis echo
/bin/echo
So in your specific case when you are running:
char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);
You are actually replacing address space of current process with address space of (most likely) /bin/ls.
My intuition is I have to read the file and may be parse it to store
the arguments in the arg.
Indeed you you have. But you also may use some in-kernel functions for that aka "shebang":
Instead of putting file name in separate file add so-called shebang as the first line of the file you want to cat:
#!/bin/cat
And add chmod +x to it. Then you can run it as executable (via any of exec functions or shell):
λ ~/tmp/ printf '#!/bin/cat\nTEST\n' > cat_me
λ ~/tmp/ chmod +x cat_me
λ ~/tmp/ ./cat_me
#!/bin/cat
TEST
Of cause it's has a drawback of printing shebang itself with file but still it's fun to do it in-kernel =)
BTW. Problem that you described if so common that there is a special executable called xargs which (in very simplified explanation) executes given program on list of arguments passed via stdin. For more information consult with man xargs.
For easy memorization of exec-family I often use following table:
Figure 8.14. Differences among the six exec functions
+----------+----------+----------+----------+--------+---------+--------+
| Function | pathname | filename | agr list | argv[] | environ | envp[] |
+----------+----------+----------+----------+--------+---------+--------+
| execl | * | | * | | * | |
+----------+----------+----------+----------+--------+---------+--------+
| execlp | | * | * | | * | |
+----------+----------+----------+----------+--------+---------+--------+
| execle | * | | * | | | * |
+----------+----------+----------+----------+--------+---------+--------+
| execv | * | | | * | * | |
+----------+----------+----------+----------+--------+---------+--------+
| execvp | | * | | * | * | |
+----------+----------+----------+----------+--------+---------+--------+
| execve | * | | | * | | * |
+----------+----------+----------+----------+--------+---------+--------+
| letter | | p | l | v | | e |
+----------+----------+----------+----------+--------+---------+--------+
So in your case execvp takes filename, argv(v) and environ(e).
Then it's tries to "guess" pathname (aka full path) by appending filename (in your case cat) to each path component in PATH until it find path with executable filename.
Much more information about whats going on under the exec's hood (including inheritance stuff) can be found in Advanced Programming in the UNIX Environment (2nd Edition) by W. Richard Stevens and Stephen A. Rago aka APUE2.
If you are interested in UNIX internals you should probably read it.
"ls" isn't just a command, it's actually a program (most commands are). When you run execvp like that, it will nuke your entire program, its memory, its stack, its heap, etc... conceptually "clear it out" and give it to "ls" so it can use it for its own stack, heap, etc.
In short, execvp will destroy your program, and replace it with another program, in this case "ls".
My intuition is I have to read the file and may be parse it to store the arguments in the arg. However I want to make sure.
Your intuition is largely correct. The cat utility that you're using as an example has two separate code paths:
If there are filenames specified as arguments, it will open and read each one in turn.
If there are no filenames specified, it will read from standard input.
This behavior is specifically implemented in the cat utility -- it is not implemented at any lower level. In particular, it is definitely not part of the exec system call. The exec system calls do not "look at" arguments at all; they just pass them straight on to the new process in argv, and that process gets to handle them however it sees fit.
I am testing the mkdir function to create a new directory:
folder = mkdir("./linux", 511);
or
folder = mkdir("./linux", 0777);
or
folder = mkdir("./linux", S_IRWXU | S_IRWXG | S_IRWXO);
As you can see, I try to authorize the full permission to the directory but here's what comes up with ls -l | grep linux:
drwxr-xr-x 2 manuzhang manuzhang 4096 2012-01-04 06:53 linux
why can't I authorize write permission for group and others?
Updates:
weird thing, as you guys told me I tried umask. It works with either umask(S_IWGRP) or umask(S_IWOTH) but fails with umask(S_IWGRP | S_IWOTH), any ideas?
From man 2 mkdir:
The argument mode specifies the permissions to use. It is modified by the process's umask in the usual way: the permissions of the created directory are (mode & ~umask & 0777).
I suggest you look at your umask - it is probably set to 0022. Try a chmod post-mkdir.
Permissions set by system calls like mkdir and open are always masked against the current process's umask. You can change the current umask using the umask() function; make sure to set it back when you're done.
Check the umask function: man 2 umask