Difference between revisions of "Exec system call"

From Teknologisk videncenter
Jump to: navigation, search
m (Simple use)
m
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
The '''exec()''' family executes a file as a new process. See [[fork system call]] for "cloning" a process.
 
The '''exec()''' family executes a file as a new process. See [[fork system call]] for "cloning" a process.
  
The
+
*The '''exec()''' family replaces the current process image with a new process image.
 +
*Never returns to caller - unless an error occur.
 +
 
 
=Simple use=
 
=Simple use=
 
The '''execlp()''' is one of the function call in the exec family. See manpage
 
The '''execlp()''' is one of the function call in the exec family. See manpage
Line 16: Line 18:
 
int main()
 
int main()
 
{
 
{
         execlp("ls", "ls", "-l", "/etc", NULL);
+
         execlp("ls", "ls", "-l", "/etc", NULL); // See security note below!!!
         return 1;
+
         return 1; // This line only runs if execlp() fails
 
}
 
}
 
</source>
 
</source>
 +
==Security==
 +
As '''execlp()''' searches through $PATH to find the executable file - it is possible to put an executable with the same name earlier in $PATH and run a bogus and evil program. Use '''execl("/usr/bin/ls", "ls", "-l", "/etc", NULL);''' instead.
 +
 +
Best practice is not to use the '''p''' exec types as it  uses $PATH to find the executable '''execlp()''', '''execvp()''' or '''execvpe()'''
  
 +
=Parent and child with different code=
 +
{{:fork system call#Parent and child with different code}}
 
[[Category:Linux]][[Category:C]]
 
[[Category:Linux]][[Category:C]]

Latest revision as of 11:10, 19 December 2022

The exec() family executes a file as a new process. See fork system call for "cloning" a process.

  • The exec() family replaces the current process image with a new process image.
  • Never returns to caller - unless an error occur.

Simple use

The execlp() is one of the function call in the exec family. See manpage

The five arguments in the execlp() below is:

  1. ls - the executable file must be in $PATH
  2. ls - argv[0] as seen from the executable file
  3. -l - argv[1] as seen from the executable file
  4. /etc - argv[2] as seen from the executable file
  5. NULL - argv[3] as seen from the executable file - end of argument list
#include <stdio.h>
#include <unistd.h>
int main()
{
        execlp("ls", "ls", "-l", "/etc", NULL); // See security note below!!!
        return 1; // This line only runs if execlp() fails
}

Security

As execlp() searches through $PATH to find the executable file - it is possible to put an executable with the same name earlier in $PATH and run a bogus and evil program. Use execl("/usr/bin/ls", "ls", "-l", "/etc", NULL); instead.

Best practice is not to use the p exec types as it uses $PATH to find the executable execlp(), execvp() or execvpe()

Parent and child with different code

If we want a parent and a child to execute different code and share a resource, for example a server that send information to a client.

Three files:

  1. my_system.c - forks and starts the server code as parent and the client code as child.
  2. server.c"' - contains the server code
  3. client.c - contains the client code

Typical output when starting my_system

Note:

  • Server executable running with the parent PID
  • Client executable running with the child PID
Starting server as parent - my PID is 2644553
Starting client as child  - my PID is 2644554
Server started my PID is 2644553
Client started my PID is 2644554
Client received: hello: 1
Client received: hello: 2
Client received: hello: 3
Client received: hello: 4
Client received: hello: 5
Server signing out
Client signing out

my_system.c

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sys/types.h>
 4 
 5 int main()
 6 {
 7         int arr[2];
 8         char argv[50];
 9         pipe(arr);
10         if(fork())
11         {
12                 printf("Starting server as parent - my PID is %d\n", getpid());
13                 fflush(stdout);
14                 close(arr[0]);
15                 sprintf(argv,"%d",arr[1]);
16                 execlp("./server","server",argv,NULL);
17         }
18         else
19         {
20                 printf("Starting client as child  - my PID is %d\n", getpid());
21                 fflush(stdout);
22                 close(arr[1]);
23                 sprintf(argv,"%d",arr[0]);
24                 execlp("./client","client",argv,NULL);
25         }
26         return 1;
27 }

server.c

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <unistd.h>
 4 #include <stdlib.h>
 5 #include <string.h>
 6 
 7 int main(int argc,char *argv[])
 8 {
 9         char buf[40]="hello";
10         int fd,i;
11 
12         fd = atoi(argv[1]);
13         printf("Server started my PID is %d\n", getpid());
14         for (i=1; i <= 5; i++) {
15                 sprintf(buf,"hello: %d",i);
16                 write(fd,buf,strlen(buf)+1);
17                 sleep(1);
18         }
19         buf[0] == 0;
20         close(fd);
21         puts("Server signing out");
22 
23         return 0;
24 }

client.c

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sys/types.h>
 4 #include <stdlib.h>
 5 
 6 int main(int argc,char *argv[])
 7 {
 8         char buf[11];
 9         int fd;
10 
11         printf("Client started my PID is %d\n", getpid());
12         fd = atoi(argv[1]);
13         while(read(fd,buf,10) > 0)
14         {
15                 printf("Client received: %s\n",buf);
16         }
17         close(fd);
18         printf("Client signing out\n");
19         return 0;
20 }