- fork()
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
int main(void) {
pid_t pid;
switch (pid = fork()) {
case -1:
/* Error */
fprintf(stderr, "Failed to call fork(): %s\n", strerror(errno));
return (1);
case 0:
/* Child process */
printf("I am a child process, ppid = %d, pid = %d\n",
getppid(), getpid());
break;
default:
/* Parent process */
printf("I am a parent process, ppid = %d, pid = %d\n",
getppid(), getpid());
/*
* Parent process should call either wait(NULL) or wait(pid, NULL, 0)
* to wait for the child process to exit
*/
if (wait(NULL) < 0) {
fprintf(stderr, "Failed to call wait(): %s\n", strerror(errno));
return (1);
}
break;
}
return (0);
}
- Argument list
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
printf("argc = %d\n", argc);
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
}
- Exec
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
/*
* This may not work for all programs
*/
void do_execve(void) {
execve("./display", NULL, NULL);
}
/*
* The guarantee way to work for all programs
*/
void do_execve2(void) {
char *argv[] = {
"display",
NULL
};
execve("./display", argv, NULL);
}
/*
* Do /bin/ls
*/
void do_execve3(void) {
char *argv[] = {
"ls",
NULL
};
if (execve("/bin/ls", argv, NULL) < 0) {
fprintf(stderr, "Failed to call execve(): %s\n", strerror(errno));
}
}
/*
* Do /bin/ls -l -a
*/
void do_execve4(void) {
char *argv[] = {
"ls",
"-l",
"-a",
NULL
};
if (execve("/bin/ls", argv, NULL) < 0) {
fprintf(stderr, "Failed to call execve(): %s\n", strerror(errno));
}
}
/*
* One of my favor command :)
*/
void do_execve5(void) {
char *argv[] = {
"cat",
"/etc/passwd",
NULL
};
if (execve("/bin/cat", argv, NULL) < 0) {
fprintf(stderr, "Failed to call execve(): %s\n", strerror(errno));
}
}
/*
* Similar to do_execve3() but use ls instead of /bin/ls, which it won't work.
* Expect error.
*/
void do_execve6(void) {
char *argv[] = {
"ls",
NULL
};
if (execve("ls", argv) < 0) {
fprintf(stderr, "Failed to call execve(): %s\n", strerror(errno));
}
}
/*
* Fix do_execve6() by calling execvp(), which will follow PATH and look for
* the program
*/
void do_execvp(void) {
char *argv[] = {
"ls",
NULL
};
if (execvp("ls", argv) < 0) {
fprintf(stderr, "Failed to call execvp(): %s\n", strerror(errno));
}
}
int main(void) {
pid_t pid;
switch (pid = fork()) {
case -1:
/* Error */
fprintf(stderr, "Failed to call fork(): %s\n", strerror(errno));
return (1);
case 0:
/* Child process */
do_execve();
/* Should not reach here */
break;
default:
/* Parent process */
/*
* Parent process should call either wait(NULL) or wait(pid, NULL, 0)
* to wait for the child process to exit
*/
if (wait(NULL) < 0) {
fprintf(stderr, "Failed to call wait(): %s\n", strerror(errno));
return (1);
}
break;
}
return (0);
}
- pipe() & fork()
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
int fds[2]; /* fds[0] is for reading, fds[1] is for writing */
/* Get a pipe */
if (pipe(fds) < 0) {
fprintf(stderr, "Failed to call pipe(): %s\n", strerror(errno));
return (1);
}
switch (fork()) {
case -1:
/* Error */
fprintf(stderr, "Failed to call fork(): %s\n", strerror(errno));
return (1);
case 0: {
/* Child process */
char buf[128];
int n;
/* Close fds[1] */
close(fds[1]);
/* Read from fds[0] */
n = read(fds[0], buf, sizeof(buf));
printf("Parent said: \"%.*s\"\n", n, buf);
break;
}
default: {
/* Parent process */
char msg[] = "Go back to your room and think about what you've done!";
/* Close fds[0] */
close(fds[0]);
/* Write to from fds[1] */
write(fds[1], msg, sizeof(msg));
wait(NULL);
}
}
return (0);
}
- dup() & dup2()
#include <stdio.h>
#include <unistd.h>
int main(void) {
/* Close stdout */
close(1);
/*
* Dup stderr to stdout.
* ie. everything goes to stdout will now go to stderr
*/
dup2(2, 1);
/* Output something to stdout */
printf("This goes to stderr, not stdout!\n");
return (0);
}
- toupper() & tolower()
#include <stdio.h>
#include <string.h>
int main(void) {
int i;
char *hello = "Hello World!";
for (i = 0; i < strlen(hello); i++) {
printf("%c", toupper(hello[i]));
}
printf("\n");
return (0);
}
- NOTE: The pipe arrangement in your lab2 is opposite to example in "Pipe & Fork". So, don't just cut and paste.
- It is always a good practice to check the return values of system/function calls and document your code.