├── .gitattributes ├── 9781484263204.jpg ├── Chapter_02 ├── thread_argument.c ├── thread_creation.c ├── thread_equal.c ├── thread_multiple_arguments.c └── thread_termination.c ├── Chapter_04 ├── ChangeDirectory.c ├── CurrentWorkingDirectory.c ├── DirectoryContentReader.c ├── DirectoryCreation.c ├── HardLink.c ├── Read and Write Permissions.c ├── RemoveDirectory.c ├── Softlink.c ├── Unlink.c ├── WriteFile.c ├── chmod.c ├── closeFile.c ├── closingDirectory.c ├── fileCreation.c ├── fileRename.c ├── openFile.c └── readFile.c ├── Chapter_05 ├── Command Line Arguments.c ├── Environment List.c ├── Environment Variable Creation.c ├── Environment Variable Deletion.c ├── Get Environment.c ├── Orphan Process.c ├── Process Creation.c ├── Signal Generation and Handling.c ├── Simple Process Creation.c ├── Wait System Call.c ├── Zombie Process.c ├── _Exit.c ├── abort.c ├── alarm.c ├── appendPermission.c ├── execl.c ├── execle.c ├── execlp.c ├── execv.c ├── execve.c ├── execvp.c ├── exit.c ├── helloworld.c ├── kill.c ├── pause.c ├── raise.c ├── sleep.c ├── vfork.c └── waitpid.c ├── Chapter_06 ├── FIFO_CLIENT_ONE_WAY.c ├── FIFO_SERVER_ONE_WAY.c ├── MessageQueue_Receiver.c ├── MessageQueue_Sender.c ├── RaceCondition.c ├── pipes.c ├── pipes_with_processes.c └── semaphore.c ├── Chapter_07 ├── Shared Memory Reader.c └── Shared Memory Writer.c ├── Chapter_08 ├── TCP Client.c ├── TCP Server.c ├── UDP Client.c └── UDP Server.c ├── Contributing.md ├── LICENSE.txt ├── README.md └── errata.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /9781484263204.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/practical-system-programming-c/eea20830926e4e9742e9bc61cf978a5287fd84eb/9781484263204.jpg -------------------------------------------------------------------------------- /Chapter_02/thread_argument.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void *sayGreetings(void *input) { 5 | printf("Hello %s\n", (char *)input); 6 | pthread_exit(NULL); 7 | } 8 | 9 | int main() { 10 | 11 | char name[50]; 12 | printf("Enter your name: \n"); 13 | fgets(name,50, stdin); 14 | 15 | pthread_t thread; 16 | pthread_create(&thread, NULL, sayGreetings, name); 17 | pthread_join(thread, NULL); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /Chapter_02/thread_creation.c: -------------------------------------------------------------------------------- 1 | #include // Standard I/O Routines Library 2 | #include // Unix Standard Library 3 | #include // POSIX Thread Creation Library 4 | 5 | void *customThreadFunction(){ 6 | 7 | for(int i = 0; i < 15; i++){ 8 | printf("I am a Custom Thread Function Created By Programmer.\n"); 9 | sleep(1); 10 | } 11 | 12 | return NULL; 13 | } 14 | 15 | int main(){ 16 | 17 | pthread_t thread; // Thread Descriptor 18 | int status; // Status Variable to store the Status of the thread. 19 | 20 | status = pthread_create(&thread, NULL, customThreadFunction, NULL); 21 | 22 | /* status = 0 ==> If thread is created Sucessfully. 23 | status = 1 ==> If thread is unable to create. */ 24 | 25 | if(!status){ 26 | printf("Custom Created Successfully.\n"); 27 | }else{ 28 | printf("Unable to create the Custom Thread.\n"); 29 | return 0; 30 | } 31 | 32 | // Main Function For loop 33 | for(int i = 0; i < 15; i++){ 34 | printf("I am the process thread created by compiler By default.\n"); 35 | sleep(1); 36 | } 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /Chapter_02/thread_equal.c: -------------------------------------------------------------------------------- 1 | #include // Standard I/O Routines Library 2 | #include // Unix Standard Library 3 | #include // POSIX Thread Creation Library 4 | 5 | void *customThreadFunction(){ 6 | printf("This is my custom thread\n"); 7 | return NULL; 8 | } 9 | 10 | int main(){ 11 | 12 | pthread_t thread1, thread2; 13 | pthread_create(&thread1, NULL, customThreadFunction, NULL); 14 | pthread_create(&thread2, NULL, customThreadFunction, NULL); 15 | 16 | if(pthread_equal(thread1, thread2)){ 17 | printf("Two threads are Equal..!\n"); 18 | }else{ 19 | printf("Two threads are not equal\n"); 20 | } 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter_02/thread_multiple_arguments.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Data Collector. 6 | struct arguments { 7 | char* name; 8 | int age; 9 | char *bloodGroup; 10 | }; 11 | 12 | // Thread Function 13 | void *sayGreetings(void *data) { 14 | printf("Name: %s", ((struct arguments*)data)->name); 15 | printf("Age: %d\n", ((struct arguments*)data)->age); 16 | printf("Blood Group: %s\n", ((struct arguments*)data)->bloodGroup); 17 | return NULL; 18 | } 19 | 20 | int main() { 21 | 22 | struct arguments *person = (struct arguments *)malloc(sizeof(struct arguments)); 23 | printf("This is a Simple Data Collection Application\n"); 24 | char bloodGroup[5], name[50]; 25 | int age; 26 | printf("Enter the name of the person: "); 27 | fgets(name, 50, stdin); 28 | printf("Enter the age of the person: "); 29 | scanf("%d",&age); 30 | printf("Enter the person's Blood Group: "); 31 | scanf("%s", bloodGroup); 32 | 33 | person->name = name; 34 | person->age = age; 35 | person->bloodGroup = bloodGroup; 36 | 37 | pthread_t thread; 38 | pthread_create(&thread, NULL, sayGreetings, (void *)person); 39 | pthread_join(thread, NULL); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /Chapter_02/thread_termination.c: -------------------------------------------------------------------------------- 1 | #include // Standard I/O Routines Library 2 | #include // Unix Standard Library 3 | #include // POSIX Thread Creation Library 4 | 5 | void *customThreadFunction(){ 6 | 7 | for(int i = 0; i < 5; i++){ 8 | printf("I am a Custom Thread Function Created By Programmer.\n"); 9 | sleep(1); 10 | if(i == 3){ 11 | printf("My JOB is Done. I am now being terminated by programmer.\n"); 12 | pthread_exit(NULL); 13 | } 14 | } 15 | 16 | return NULL; 17 | } 18 | 19 | int main(){ 20 | 21 | pthread_t thread; // Thread Descriptor 22 | pthread_create(&thread, NULL, customThreadFunction, NULL); 23 | 24 | for(int i = 0; i < 5; i++){ 25 | printf("I am the process thread created by compiler By default.\n"); 26 | sleep(1); 27 | } 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Chapter_04/ChangeDirectory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | char DIR[75]; 7 | 8 | printf("Working Directory Before Operation: %s\n", getcwd(DIR, 75)); 9 | 10 | int status = chdir(".."); 11 | 12 | if(status == 0){ 13 | printf("Directory Changed Sucessfully.!\n"); 14 | }else{ 15 | printf("Unable to change the Directory.\n"); 16 | } 17 | 18 | printf("Working Directory After Operation: %s\n", getcwd(DIR, 75)); 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Chapter_04/CurrentWorkingDirectory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | char WORKING_DIR[75]; 7 | 8 | printf("Current Working Directory is: %s\n", getcwd(WORKING_DIR, 75)); 9 | 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter_04/DirectoryContentReader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | // Directory Entry 7 | struct dirent *DIR_ENTRY; 8 | 9 | // opendir() returns a pointer of DIR type. 10 | DIR *DIR_READER = opendir("."); 11 | 12 | if (DIR_READER == NULL) { 13 | printf("Could not open current directory" ); 14 | exit(0); 15 | } 16 | 17 | while ((DIR_ENTRY = readdir(DIR_READER)) != NULL) 18 | printf("%s\n", DIR_ENTRY->d_name); 19 | 20 | closedir(DIR_READER); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /Chapter_04/DirectoryCreation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main(){ 7 | 8 | int isCreated; 9 | char *DIR_NAME; 10 | printf("Enter the Directory name you want to create: "); 11 | scanf("%[^\n]%*c", DIR_NAME); 12 | // You can Set your own permissions based on your Requirements. 13 | isCreated = mkdir(DIR_NAME, 0777); 14 | 15 | if(isCreated == 0){ // The value is 0 for Successful 16 | printf("Directory is Created Succesfully\n"); 17 | }else{ // Value is -1 if it is unsuccessful. 18 | printf("Unable to Create Directory\n"); 19 | } 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter_04/HardLink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main(){ 6 | 7 | int link_status; 8 | 9 | char filepath[50], linkname[50]; 10 | printf("Enter the filename: "); 11 | scanf("%[^\n]%*c", filepath); 12 | printf("Enter the linkname: "); 13 | scanf("%[^\n]%*c", linkname); 14 | 15 | link_status = link(filepath, linkname); 16 | // Hardlink will be Created. 17 | // 0 ---> Successful || -1 ---> Failure. 18 | 19 | if(link_status == 0){ 20 | printf("HardLink is Created Succesfully.!"); 21 | }else{ 22 | printf("Unable to Create the Hard Link."); 23 | } 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Chapter_04/Read and Write Permissions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | char filepath[100]; 7 | // Taking the Input from the user 8 | printf("Enter the filename with path: "); 9 | scanf("%[^\n]%*c", filepath); 10 | 11 | int read_status, file_status, write_status; 12 | 13 | file_status = access(filepath, F_OK); 14 | if(file_status == -1){ 15 | printf("%s File does not exist in the specified location.\n", filepath); 16 | _exit(0); 17 | } 18 | 19 | read_status = access(filepath, R_OK); 20 | write_status = access(filepath, W_OK); 21 | // Checks for the both Read and Write Access 22 | if(read_status == 0 && write_status == 0){ 23 | printf("%s File has both read and write permissions\n", filepath); 24 | }else if(read_status == 0 && write_status == -1){ 25 | // If file has only read access then 26 | printf("%s File has only read permissions\n", filepath); 27 | }else if(read_status == -1 && write_status == 0){ 28 | // If file has only write access then 29 | printf("%s File has only write permissions\n", filepath); 30 | }else{ 31 | // If file does not have both read and write access then 32 | printf("%s File has no read and write permissions", filepath); 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Chapter_04/RemoveDirectory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int rmdir(char *dirname); 6 | 7 | int main(){ 8 | 9 | int isRemoved; 10 | char *DIR_NAME; 11 | printf("Enter the Directory name you want to create: "); 12 | scanf("%[^\n]%*c", DIR_NAME); 13 | isRemoved = rmdir(DIR_NAME); 14 | 15 | if(isRemoved == 0){ // The value is 0 for Successful 16 | printf("Directory is Deleted Succesfully\n"); 17 | }else{ // Value is -1 if it is unsuccessful. 18 | printf("Unable to Delete Directory\n"); 19 | } 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter_04/Softlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | int link_status; 7 | char filepath[50], linkname[50]; 8 | // Taking User Input for file path 9 | printf("Enter the filepath: "); 10 | scanf("%[^\n]%*c", filepath); 11 | printf("Enter the linkname: "); 12 | scanf("%[^\n]%*c", linkname); 13 | 14 | link_status = symlink(filepath,linkname); 15 | // 0 ---> On Success || -1 ---> If Any Error Occurs 16 | if(link_status == 0){ 17 | printf("Softlink is Created Succesfully.!"); 18 | }else{ 19 | printf("Unable to Create the Link."); 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /Chapter_04/Unlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | int unlink_status; 7 | char linkname[100]; 8 | // Taking the Link name as Input from the user to unlink 9 | printf("Enter the link name to unlink:"); 10 | scanf("%[^\n]%*c", linkname); 11 | 12 | unlink_status = unlink(linkname); 13 | // 0 --->On Success || -1 ---> Failure. 14 | if(unlink_status == 0){ 15 | printf("File is unlinked Successfully.!"); 16 | }else{ 17 | printf("Unable to unlink the file."); 18 | } 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Chapter_04/WriteFile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | 9 | char *filename; 10 | printf("Enter the filename to open:"); 11 | scanf("%[^\n]%*c", filename); 12 | int file_descriptor = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0777); 13 | if (file_descriptor == -1) { 14 | perror("File not Found.!"); 15 | exit(1); 16 | } 17 | char *content; 18 | 19 | printf("Enter the content to write on a given file: "); 20 | scanf("%[^\n]%*c", content); 21 | 22 | int size = write(file_descriptor, content, strlen(content)); 23 | 24 | printf("%d %lu %d", file_descriptor, strlen(content), size); 25 | 26 | close(file_descriptor); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Chapter_04/chmod.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int chmod(char *path, mode_t mode); 6 | 7 | int main(){ 8 | 9 | int permission_status, new_permission_value; 10 | char filepath[100]; 11 | 12 | // Taking the Input from the user 13 | printf("Enter the filename with path: "); 14 | scanf("%[^\n]%*c", filepath); 15 | printf("Enter the new permission set: "); 16 | // Permission Set value starts with 0. 17 | // Eg: if i want to set 444 to a particular file then i need to give like 0444. 18 | scanf("%d", &new_permission_value); 19 | 20 | // Setting the Permissions 21 | permission_status = chmod(filepath, new_permission_value); 22 | // 0 ---> On Success || -1 ---> On Failure. 23 | if (permission_status == 0){ 24 | printf("New permissions are Setted Successfully.!"); 25 | }else{ 26 | printf("Permissions Changed Sucessfully"); 27 | } 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Chapter_04/closeFile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int close(int file_descriptor); 5 | 6 | int main(){ 7 | 8 | int file_descriptor; 9 | char *filename; 10 | 11 | printf("Enter the filename: "); 12 | scanf("%s", filename); 13 | // Setting Permission to Read Write for the file. 14 | file_descriptor = open(filename, O_RDWR, 0); 15 | 16 | if(file_descriptor == 3){ 17 | printf("File Opened Successfully!\n"); 18 | }else{ 19 | printf("Unable to Open the File.\n"); 20 | } 21 | 22 | int close_status = close(file_descriptor); 23 | 24 | if(close_status == 0){ 25 | printf("File Descriptor is closed Succesfully\n"); 26 | }else{ 27 | printf("File Descriptor is not closed\n"); 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /Chapter_04/closingDirectory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | // Directory Entry 7 | struct dirent *DIR_ENTRY; 8 | 9 | // opendir() returns a pointer of DIR type. 10 | DIR *DIR_READER = opendir("."); 11 | 12 | if (DIR_READER == NULL) { 13 | printf("Could not open current directory" ); 14 | exit(0); 15 | } 16 | 17 | int status = closedir(DIR_READER); 18 | if(status == 0){ 19 | printf("Directory Closed Successfully.!"); 20 | }else{ 21 | printf("Unable to close the Directory."); 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Chapter_04/fileCreation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | int file_descriptor; 7 | char *filename; 8 | 9 | printf("Enter the filename: "); 10 | scanf("%s", filename); 11 | // Setting Permission to Read Write for the file. 12 | file_descriptor = creat(filename, O_RDWR | O_CREAT); 13 | 14 | if(file_descriptor == 3){ 15 | printf("File Created Successfully!"); 16 | }else{ 17 | printf("Unable to Create the File."); 18 | } 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Chapter_04/fileRename.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | char trim(char *filename, const char *sep); 6 | 7 | int main(){ 8 | 9 | char old_filename[50], new_filename[50]; 10 | printf("Enter the old filename: "); 11 | scanf("%[^\n]%*c", old_filename); 12 | printf("Enter the new filename you want to put: "); 13 | scanf("%[^\n]%*c",new_filename); 14 | 15 | 16 | int status = rename(old_filename, new_filename); 17 | 18 | if(status == 0){ 19 | printf("Filename Changed Sucessfully."); 20 | }else{ 21 | printf("Unable to change the filename."); 22 | } 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter_04/openFile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | int file_descriptor; 7 | char *filename; 8 | 9 | printf("Enter the filename: "); 10 | scanf("%s", filename); 11 | // Setting Permission to Read Only for the file. 12 | file_descriptor = open(filename, O_RDONLY); 13 | 14 | if(file_descriptor == 3){ 15 | printf("%s Opened Successfully!",filename); 16 | }else{ 17 | printf("Unable to Open %s",filename); 18 | } 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Chapter_04/readFile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | 8 | int file_descriptor, size; 9 | char *filename; 10 | char *content = (char *) calloc(100, sizeof(char)); 11 | 12 | printf("Enter the filename to read:"); 13 | scanf("%[^\n]%*c",filename); 14 | 15 | file_descriptor = open(filename, O_RDONLY); 16 | // Program will exit if the given file not found. 17 | if (file_descriptor == -1) { 18 | perror("File Not found."); 19 | exit(1); 20 | } 21 | // Helps us to read the Content from a given file descriptor. 22 | size = read(file_descriptor, content, 100); 23 | 24 | printf("Number of bytes returned are: %d\n", size); 25 | content[size] = '\0'; 26 | printf("File Content: %s\n", content); 27 | 28 | // Closes the file descriptor. 29 | close(file_descriptor); 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Chapter_05/Command Line Arguments.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char * argv[]){ 4 | 5 | printf("Number of Arguments Passed: %d\n", argc); 6 | // This loop prints the all the command line values that are passed through the program 7 | for(int i=0;i 2 | 3 | int main(){ 4 | 5 | extern char **environ; 6 | 7 | char **environment_list = environ; 8 | 9 | /* This code Helps us to prints the all the 10 | Environments available in the operating system. 11 | */ 12 | while(*environment_list != NULL){ 13 | printf("%s\n", *environment_list); 14 | environment_list++; 15 | } 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Chapter_05/Environment Variable Creation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | char variable_name[15]; 7 | char variable_value[255]; 8 | int overwrittenValue; 9 | printf("Enter your Variable name:"); 10 | scanf("%s", variable_name); 11 | printf("Enter the Variable Value: "); 12 | scanf("%s", variable_value); 13 | 14 | // 1 ---> Represents the Overridden of Value. 15 | // 0 ---> Doesn't override the value 16 | printf("Enter the Overridden Value: "); 17 | scanf("%d", &overwrittenValue); 18 | 19 | // Returns 0 --> On Success || -1 on failure 20 | int status = setenv(variable_name, variable_value, overwrittenValue); 21 | 22 | if(status == 0){ 23 | printf("Environment variable Created Successfully.!\n"); 24 | }else if(status == -1){ 25 | printf("Environment variable Created Successfully.!\n"); 26 | } 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Chapter_05/Environment Variable Deletion.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | char *variable_name; 7 | printf("Enter the variable to Delete:"); 8 | scanf("%s",variable_name); 9 | // Returns 0 --> On Success || -1 on failure 10 | int status = unsetenv(variable_name); 11 | 12 | if(status == 0){ 13 | printf("Environment Variable is Deleted Successfully.!\n"); 14 | }else{ 15 | printf("Unable to Delete the Environment variable.\n"); 16 | } 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /Chapter_05/Get Environment.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | 6 | char *environment_name; 7 | printf("Enter the Environment name: "); 8 | scanf("%s", environment_name); 9 | 10 | printf("Environment Value: %s\n", getenv(environment_name)); 11 | 12 | return 0; 13 | 14 | } -------------------------------------------------------------------------------- /Chapter_05/Orphan Process.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | 8 | pid_t child_pid = fork(); 9 | 10 | // Parent process 11 | if (child_pid > 0){ 12 | printf("In Parent Process.!\n"); 13 | 14 | }else{ 15 | printf("In Child process.!\n"); 16 | // Making the Child Process to Sleep for some time. 17 | sleep(10); 18 | printf("After Sleep Time"); 19 | } 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter_05/Process Creation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | 7 | int pid, my_pid, my_parent_pid; 8 | pid = getpid(); 9 | printf("Before fork: Process id is %d\n", pid); 10 | 11 | pid = fork(); 12 | 13 | if (pid < 0) { 14 | perror("Unable to create the process.\n"); 15 | exit(1); 16 | } 17 | 18 | // Child process 19 | if (pid == 0) { 20 | printf("This is child process\n"); 21 | my_pid = getpid(); 22 | my_parent_pid = getppid(); 23 | printf("Process id is %d and PPID is %d\n", my_pid, my_parent_pid); 24 | } else { // Parent process 25 | sleep(1); 26 | printf("This is parent process\n"); 27 | my_pid = getpid(); 28 | my_parent_pid = getppid(); 29 | printf("Process id is %d and PPID is %d\n", my_pid, my_parent_pid); 30 | printf("Newly created process id or child pid is %d\n", pid); 31 | } 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Chapter_05/Signal Generation and Handling.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void CUSTOM_HANDLER(int); 7 | 8 | int main () { 9 | 10 | // SIGINT is used to intimate when any interrupt occurs to the program. 11 | signal(SIGINT, CUSTOM_HANDLER); 12 | 13 | while(1) { 14 | printf("Hello World...!\n"); 15 | sleep(1); 16 | } 17 | 18 | return 0; 19 | } 20 | 21 | // This function will call when any signal interrupt occurs. 22 | void CUSTOM_HANDLER(int signum) { 23 | printf("\nCaught signal %d, coming out from Program\n", signum); 24 | exit(1); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Chapter_05/Simple Process Creation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | int pid = fork(); 7 | 8 | if(pid > 0){ 9 | printf("Parent Process is created\n"); 10 | }else if(pid == 0){ 11 | printf("Child Process is created\n"); 12 | } 13 | 14 | return 0; 15 | } -------------------------------------------------------------------------------- /Chapter_05/Wait System Call.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | 7 | int status = fork(); 8 | 9 | if (status == 0) { 10 | printf("Hello from child\n"); 11 | printf("Child work is Completed and terminating.!\n"); 12 | }else if(status > 0){ 13 | printf("Hello from parent\n"); 14 | wait(NULL); 15 | printf("Parent has terminated\n"); 16 | } 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /Chapter_05/Zombie Process.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | 8 | pid_t child_pid = fork(); 9 | 10 | // Parent process 11 | if (child_pid > 0){ 12 | printf("In Parent Process.!\n"); 13 | // Making the Parent Process to Sleep for some time. 14 | sleep(10); 15 | }else{ 16 | printf("In Child process.!\n"); 17 | exit(0); 18 | } 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter_05/_Exit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(){ 6 | 7 | printf("Current Running Process ID: %d\n", getpid()); 8 | _Exit(0); 9 | printf("Nothing will execute\n"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /Chapter_05/abort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(){ 7 | 8 | int status = fork(); 9 | 10 | if(status == 0){ 11 | printf("Child Process ID: %d\n", getpid()); 12 | }else if(status > 0){ 13 | printf("Parent Process ID: %d\n", getpid()); 14 | } 15 | 16 | abort(); 17 | printf("Due to abnormal termination this line will not execute.\n"); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Chapter_05/alarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void raisedAlarm(int sig); 7 | 8 | int main(){ 9 | 10 | alarm(5); 11 | 12 | signal(SIGALRM, raisedAlarm); 13 | 14 | while(1){ 15 | printf("Hello World...!\n"); 16 | sleep(1); 17 | } 18 | 19 | return 0; 20 | } 21 | 22 | void raisedAlarm(int sig){ 23 | printf("The Alarm has Raised.\n"); 24 | exit(0); 25 | } -------------------------------------------------------------------------------- /Chapter_05/appendPermission.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | 9 | char filename[255]; 10 | printf("Enter the filename to open:"); 11 | scanf("%[^\n]%*c", filename); 12 | int file_descriptor = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0777); 13 | if (file_descriptor == -1) { 14 | perror("File not Found.!"); 15 | exit(1); 16 | } 17 | char content[1024]; 18 | 19 | printf("Enter the content to write on a given file: "); 20 | scanf("%[^\n]%*c", content); 21 | 22 | int size = write(file_descriptor, content, strlen(content)); 23 | 24 | printf("%d %lu %d\n", file_descriptor, strlen(content), size); 25 | 26 | close(file_descriptor); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Chapter_05/execl.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | char *binary_path = "/bin/ls"; 6 | char *arg1 = "-l"; 7 | char *arg2 = "-a"; 8 | char *arg3 = "."; 9 | 10 | // System call to perform the ls -la operation in the CWD (Current Working Directory) 11 | execl(binary_path, binary_path, arg1, arg2, arg3, NULL); 12 | 13 | return 0; 14 | } 15 | 16 | int execle(const char *path, const char *arg, ..., NULL, char * const envp[] ) 17 | -------------------------------------------------------------------------------- /Chapter_05/execle.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | char *binary_path = "/bin/zsh"; 6 | char *arg1 = "-c"; 7 | char *arg2 = "echo \"Visit $HOSTNAME:$PORT from your browser.\""; 8 | char *const envp[] = {"HOSTNAME=www.netflix.com", "PORT=80", NULL}; 9 | 10 | // execle() System call can able to access 11 | // the envp environment variables. 12 | 13 | execle(binary_path, binary_path, arg1, arg2, NULL, envp); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Chapter_05/execlp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | char *binary_executable = "ls"; 6 | char *arg1 = "-lq"; 7 | char *arg2 = "."; 8 | 9 | // System call to perform the ls -la operation in the 10 | // CWD (Current Working Directory) 11 | execlp(binary_executable, binary_executable, arg1, arg2, NULL); 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter_05/execv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | //A null terminated array of character pointers 7 | char *args[]={"./hello",NULL}; 8 | execv(args[0],args); 9 | 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter_05/execve.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | char *binary_path = "/bin/bash"; 6 | // Argument Array 7 | char *const args[] = {binary_path, "-c", "echo \"Visit $HOSTNAME:$PORT from your browser.\"", NULL}; 8 | // Environment Variable Array 9 | char *const env[] = {"HOSTNAME=www.netflix.com", "PORT=80", NULL}; 10 | 11 | execve(binary_path, args, env); 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter_05/execvp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | //A null terminated array of character pointers 7 | char *program_name = "ls"; 8 | char *args[]={program_name,"-la", ".", NULL}; 9 | execvp(program_name,args); 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Chapter_05/exit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(){ 6 | 7 | int pid = fork(); 8 | 9 | if(pid == 0){ 10 | // Prints the Child Process ID. 11 | printf("Child Process ID: %d\n", getpid()); 12 | exit(0); 13 | }else{ 14 | // Prints the Parent Process ID. 15 | printf("Parent Process Id: %d\n", getppid()); 16 | exit(0); 17 | } 18 | 19 | printf("Processes are exited and this line will not print\n"); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter_05/helloworld.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | printf("Hello World...!\n"); 5 | 6 | return 0; 7 | } -------------------------------------------------------------------------------- /Chapter_05/kill.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(){ 6 | 7 | int pid = fork(); 8 | 9 | if(pid == 0){ 10 | printf("Child PID: %d\n",getpid()); 11 | }else{ 12 | printf("Parent PID: %d\n", getppid()); 13 | } 14 | sleep(3); 15 | kill(getpid(), SIGQUIT); 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /Chapter_05/pause.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void catchSignal(int); 7 | 8 | int main(void){ 9 | 10 | alarm(10); 11 | 12 | signal(SIGALRM, catchSignal); 13 | 14 | if(alarm(7) > 0){ 15 | printf("An alarm has been set already.\n"); 16 | } 17 | 18 | pause(); 19 | 20 | printf("We will not see this text.\n"); 21 | 22 | return 1; 23 | } 24 | 25 | void catchSignal(int signo){ 26 | printf("Caught the signal with number: %d\n", signo); 27 | exit(0); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Chapter_05/raise.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void SIGNAL_HANDLER(int); 6 | 7 | int main () { 8 | 9 | signal(SIGINT, SIGNAL_HANDLER); 10 | 11 | 12 | printf("Raising a new signal\n"); 13 | 14 | int status = raise(SIGINT); 15 | 16 | if(status != 0){ 17 | printf("Something went wrong Unable to raise the new signal\n"); 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | void SIGNAL_HANDLER(int signal) { 24 | printf("signal caught and handled gracefully\n"); 25 | } -------------------------------------------------------------------------------- /Chapter_05/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(){ 6 | 7 | for(int i=0; i<5; i++){ 8 | printf("Hello World.\n"); 9 | sleep(1); 10 | } 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter_05/vfork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(){ 6 | 7 | pid_t status; 8 | status = vfork(); 9 | printf("Process is Executing: %d\n", getpid()); 10 | if(status == 0){ 11 | printf("Process is executing: %d\n", getpid()); 12 | exit(0); 13 | } 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Chapter_05/waitpid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(){ 6 | 7 | int pid; 8 | int status; 9 | 10 | pid = fork(); 11 | 12 | // Terminates the Child process. 13 | if(!pid){ 14 | printf("My PID: %d\n",getpid()); 15 | _exit(0); 16 | } 17 | 18 | waitpid(pid,&status,WUNTRACED); 19 | 20 | if(WIFEXITED(status)) { 21 | printf("Exit Normally\n"); 22 | printf("Exit status: %d\n",WEXITSTATUS(status)); 23 | _exit(0); 24 | }else { 25 | printf("Exit NOT Normal\n"); 26 | _exit(1); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Chapter_06/FIFO_CLIENT_ONE_WAY.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define FIFO_FILE "MYFIFO" 9 | 10 | int main() { 11 | int fd; 12 | int end_process; 13 | int stringlen; 14 | char readbuf[80]; 15 | char end_str[5]; 16 | printf("FIFO_CLIENT: Send messages, infinitely, to end enter \"quit\"\n"); 17 | fd = open(FIFO_FILE, O_CREAT|O_WRONLY); 18 | strcpy(end_str, "quit"); 19 | 20 | while (1) { 21 | printf("Enter Message: "); 22 | fgets(readbuf, sizeof(readbuf), stdin); 23 | stringlen = strlen(readbuf); 24 | readbuf[stringlen - 1] = '\0'; 25 | end_process = strcmp(readbuf, end_str); 26 | 27 | if (end_process != 0) { 28 | write(fd, readbuf, strlen(readbuf)); 29 | printf("Sent Message: \"%s\" and Message length is %d\n", readbuf, (int)strlen(readbuf)); 30 | } else { 31 | write(fd, readbuf, strlen(readbuf)); 32 | printf("Sent Message: \"%s\" and Message length is %d\n", readbuf, (int)strlen(readbuf)); 33 | close(fd); 34 | break; 35 | } 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Chapter_06/FIFO_SERVER_ONE_WAY.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | #define FIFO_FILE "MYFIFO" 10 | 11 | int main() { 12 | int fd; 13 | char readbuf[80]; 14 | char end[10]; 15 | int to_end; 16 | int read_bytes; 17 | 18 | // Create the FIFO if it does not exist 19 | mknod(FIFO_FILE, S_IFIFO|0640, 0); 20 | strcpy(end, "quit"); 21 | 22 | while(1) { 23 | fd = open(FIFO_FILE, O_RDONLY); 24 | read_bytes = read(fd, readbuf, sizeof(readbuf)); 25 | readbuf[read_bytes] = '\0'; 26 | printf("Received Message: \"%s\" and Message length is %d\n", readbuf, (int)strlen(readbuf)); 27 | to_end = strcmp(readbuf, end); 28 | if (to_end == 0) { 29 | close(fd); 30 | break; 31 | } 32 | } 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Chapter_06/MessageQueue_Receiver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define PERMISSIONS 0644 10 | 11 | struct messageBuffer { 12 | long mtype; 13 | char data[1024]; 14 | }; 15 | 16 | int main() { 17 | struct messageBuffer buf; 18 | int msqid; 19 | int toend; 20 | key_t key; 21 | 22 | if ((key = ftok("messagequeue.txt", 'B')) == -1) { 23 | 24 | perror("ftok"); 25 | exit(1); 26 | } 27 | 28 | if ((msqid = msgget(key, PERMISSIONS)) == -1) { 29 | 30 | // connect to the queue 31 | printf("Unable to Create the Message Queue.\n"); 32 | perror("msgget"); 33 | exit(1); 34 | } 35 | printf("Message Queue: ready to receive messages.\n"); 36 | 37 | for(;;) { /* normally receiving never ends but just to make conclusion this program ends wuth string of end */ 38 | if (msgrcv(msqid, &buf, sizeof(buf.data), 0, 0) == -1) { 39 | perror("msgrcv"); 40 | exit(1); 41 | } 42 | printf("received: \"%s\"\n", buf.data); 43 | toend = strcmp(buf.data,"end"); 44 | if (toend == 0) 45 | break; 46 | } 47 | printf("message queue: done receiving messages.\n"); 48 | system("rm messagequeue.txt"); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /Chapter_06/MessageQueue_Sender.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Permissions for the Message Queue. 11 | #define PERMISSIONS 0644 12 | 13 | struct messageBuffer { 14 | long messageType; 15 | char data[1024]; 16 | }; 17 | 18 | int main() { 19 | struct messageBuffer buf; 20 | int msqid; 21 | int len; 22 | key_t key; 23 | system("touch messagequeue.txt"); 24 | 25 | if ((key = ftok("messagequeue.txt", 'B')) == -1) { 26 | perror("ftok"); 27 | exit(1); 28 | } 29 | 30 | if ((msqid = msgget(key, PERMISSIONS | IPC_CREAT)) == -1) { 31 | perror("msgget"); 32 | exit(1); 33 | } 34 | printf("Message Queue is ready to send messages.\n"); 35 | printf("Enter lines of text, ^D to quit:\n"); 36 | buf.messageType = 1; /* we don't really care in this case */ 37 | 38 | while(fgets(buf.data, sizeof buf.data, stdin) != NULL) { 39 | len = strlen(buf.data); 40 | // Removing the newline at end if it exists 41 | if (buf.data[len-1] == '\n') buf.data[len-1] = '\0'; 42 | if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */ 43 | perror("msgsnd"); 44 | } 45 | strcpy(buf.data, "end"); 46 | len = strlen(buf.data); 47 | if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */ 48 | perror("msgsnd"); 49 | 50 | if (msgctl(msqid, IPC_RMID, NULL) == -1) { 51 | perror("msgctl"); 52 | exit(1); 53 | } 54 | printf("Message Queue is done with sending messages.\n"); 55 | return 0; 56 | } 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Chapter_06/RaceCondition.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Global Data variables. 7 | int a = 5, b = 7; 8 | 9 | // Function that access the global data. 10 | void* add_two_numbers(void* arg){ 11 | a = a + 3; 12 | b = b - 1; 13 | printf("a value is: %d and ", a); 14 | printf("b value is: %d\n", b); 15 | sleep(1); 16 | exit(0); 17 | } 18 | 19 | int main(){ 20 | 21 | // Creating the thread instances. 22 | pthread_t t1, t2, t3; 23 | 24 | pthread_create(&t1, NULL, add_two_numbers, NULL); 25 | pthread_create(&t2, NULL, add_two_numbers, NULL); 26 | pthread_create(&t3, NULL, add_two_numbers, NULL); 27 | 28 | pthread_join(t1, NULL); 29 | pthread_join(t2, NULL); 30 | pthread_join(t3, NULL); 31 | 32 | //Destroying the threads. 33 | pthread_exit(t1); 34 | pthread_exit(t2); 35 | pthread_exit(t3); 36 | return 0; 37 | } -------------------------------------------------------------------------------- /Chapter_06/pipes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define BUFFER_SIZE 1024 6 | 7 | // Global Variables 8 | int pipefds[2]; 9 | int status; 10 | char writemessage[BUFFER_SIZE]; 11 | char readmessage[BUFFER_SIZE]; 12 | 13 | // pipeOperation() to perform read and write Operations. 14 | void pipeOperation(){ 15 | printf("Writing to pipe - Message is %s", writemessage); 16 | write(pipefds[1], writemessage, sizeof(writemessage)); 17 | read(pipefds[0], readmessage, sizeof(readmessage)); 18 | printf("Reading from pipe – Message is %s", readmessage); 19 | } 20 | int main() { 21 | 22 | status = pipe(pipefds); 23 | if (status == -1) { 24 | printf("Unable to create pipe\n"); 25 | return 1; 26 | } 27 | 28 | printf("Enter the message to write into Pipe\n"); 29 | printf("To exit type \"quit\" \n"); 30 | 31 | fgets(writemessage, BUFSIZ, stdin); 32 | 33 | while (strcmp(writemessage, "quit\n") != 0) { 34 | pipeOperation(); 35 | fgets(writemessage, BUFSIZ, stdin); 36 | } 37 | 38 | close(pipefds[0]); 39 | close(pipefds[1]); 40 | return 0; 41 | } 42 | 43 | int semctl(int semid, int semnum, int cmd, …) 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Chapter_06/pipes_with_processes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUFFER_SIZE 1024 7 | 8 | // Global Variables 9 | int pipefds[2]; 10 | int status, pid; 11 | char writemessage[BUFFER_SIZE]; 12 | char readmessage[BUFFER_SIZE]; 13 | 14 | void pipeOperation(){ 15 | pid = fork(); 16 | // Child Process to Read the Data. 17 | if(pid == 0){ 18 | read(pipefds[0], readmessage, sizeof(readmessage)); 19 | printf("Child Process: Reading from pipe – Message is %s", readmessage); 20 | }else{ // Parent Process to write the data. 21 | printf("Parent Process: Writing to pipe - Message is %s", writemessage); 22 | write(pipefds[1], writemessage, sizeof(writemessage)); 23 | } 24 | 25 | } 26 | 27 | int main() { 28 | 29 | status = pipe(pipefds); 30 | if (status == -1) { 31 | printf("Unable to create pipe\n"); 32 | return 1; 33 | } 34 | 35 | printf("Enter the message to write into Pipe\n"); 36 | printf("To exit type \"quit\" \n"); 37 | 38 | fgets(writemessage, BUFSIZ, stdin); 39 | 40 | while (strcmp(writemessage, "quit\n") != 0) { 41 | pipeOperation(); 42 | fgets(writemessage, BUFSIZ, stdin); 43 | kill(pid, SIGKILL); // Killling 44 | } 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /Chapter_06/semaphore.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | sem_t mutex; 8 | 9 | int a = 5, b = 7; 10 | // Function to access the global data 11 | void* add_two_numbers(void* arg){ 12 | sem_wait(&mutex); 13 | a = a + 3; 14 | b = b - 1; 15 | printf("a value is: %d and ", a); 16 | printf("b value is: %d\n", b); 17 | sleep(1); 18 | sem_post(&mutex); 19 | } 20 | 21 | int main(){ 22 | sem_init(&mutex, 0, 1); 23 | pthread_t t1, t2, t3; 24 | pthread_create(&t1, NULL, add_two_numbers, NULL); 25 | sleep(1); 26 | pthread_create(&t2, NULL, add_two_numbers, NULL); 27 | sleep(1); 28 | pthread_create(&t3, NULL, add_two_numbers, NULL); 29 | sleep(1); 30 | 31 | pthread_join(t1, NULL); 32 | pthread_join(t2, NULL); 33 | pthread_join(t3, NULL); 34 | sem_destroy(&mutex); 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /Chapter_07/Shared Memory Reader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | 7 | // ftok to generate unique key 8 | key_t key = ftok("memory",67); 9 | 10 | // shmget returns an identifier in shmid 11 | int shmid = shmget(key, 1024,0666|IPC_CREAT); 12 | 13 | if(shmid == -1){ 14 | printf("Unable to Connect with the shared memory segment.\n"); 15 | } 16 | // shmat to attach to shared memory 17 | char *str = (char*) shmat(shmid,(void*)0,0); 18 | 19 | printf("Data read from memory: %s\n",str); 20 | 21 | //detach from shared memory 22 | shmdt(str); 23 | 24 | // destroy the shared memory 25 | shmctl(shmid,IPC_RMID,NULL); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /Chapter_07/Shared Memory Writer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | // ftok to generate unique key 8 | key_t key = ftok("memory",67); 9 | 10 | // shmget returns an identifier in shmid 11 | int shmid = shmget(key, 1024,0666|IPC_CREAT); 12 | 13 | if(shmid == -1){ 14 | printf("Unable to create the Shared Memory Segment.\n"); 15 | } 16 | 17 | // shmat to attach to shared memory 18 | char *str = (char*) shmat(shmid,(void*)0,0); 19 | 20 | printf("Enter Data to write into the Shared Memory Segment: "); 21 | scanf("%[^\n]s", str); 22 | 23 | printf("Data written in memory: %s\n",str); 24 | 25 | //detach from shared memory 26 | shmdt(str); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Chapter_08/TCP Client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define MESSAGE_LENGTH 1024 // Maximum number of data that can transfer 10 | #define PORT 8888 // port number to connect 11 | #define SA struct sockaddr // Creating Macro for the socketaddr as SA 12 | 13 | // Global Data 14 | int socket_file_descriptor, connection; 15 | struct sockaddr_in serveraddress, client; 16 | char message[MESSAGE_LENGTH]; 17 | 18 | int main(){ 19 | 20 | // Socket Creation 21 | socket_file_descriptor = socket(AF_INET, SOCK_STREAM, 0); 22 | if(socket_file_descriptor == -1){ 23 | printf("Creation of Socket failed.!\n"); 24 | exit(1); 25 | } 26 | 27 | // Erases the memory 28 | bzero(&serveraddress, sizeof(serveraddress)); 29 | 30 | // Setting the Server Properties 31 | serveraddress.sin_addr.s_addr = inet_addr("127.0.0.1"); 32 | // Setting the port numeber 33 | serveraddress.sin_port = htons(PORT); 34 | // Protocol family 35 | serveraddress.sin_family = AF_INET; 36 | 37 | // Establishing the Connection with server 38 | connection = connect(socket_file_descriptor, (SA*)&serveraddress, sizeof(serveraddress)); 39 | 40 | if(connection == -1){ 41 | printf("Connection with the server failed.!\n"); 42 | exit(1); 43 | } 44 | 45 | // Interacting with the server 46 | 47 | while(1){ 48 | 49 | bzero(message, sizeof(message)); 50 | 51 | printf("Enter the message you want to send to the server: "); 52 | scanf("%[^\n]%*c", message); 53 | 54 | if ((strncmp(message, "end", 3)) == 0) { 55 | write(socket_file_descriptor, message, sizeof(message)); 56 | printf("Client Exit.\n"); 57 | break; 58 | } 59 | 60 | // Sending the data to the server by storing the number of bytes transferred in bytes variable 61 | ssize_t bytes = write(socket_file_descriptor, message, sizeof(message)); 62 | 63 | // If the number of bytes is >= 0 then the data is sent successfully 64 | if(bytes >= 0){ 65 | printf("Data send to the server succesfully.!\n"); 66 | } 67 | 68 | bzero(message, sizeof(message)); 69 | 70 | // Reading the response from the server. 71 | read(socket_file_descriptor, message, sizeof(message)); 72 | 73 | printf("Data received from server: %s\n", message); 74 | 75 | } 76 | // Closing the Socket Connection 77 | close(socket_file_descriptor); 78 | 79 | return 0; 80 | } -------------------------------------------------------------------------------- /Chapter_08/TCP Server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define MESSAGE_LENGTH 1024 // Maximum number of data that can transfer 11 | #define PORT 8888 // port number to connect 12 | #define SA struct sockaddr // Creating Macro for the socketaddr as SA 13 | 14 | struct sockaddr_in serveraddress, client; 15 | socklen_t length; 16 | int sockert_file_descriptor, connection, bind_status, connection_status; 17 | char message[MESSAGE_LENGTH]; 18 | 19 | int main(){ 20 | 21 | // Creating the Socket 22 | sockert_file_descriptor = socket(AF_INET, SOCK_STREAM, 0); 23 | 24 | if(sockert_file_descriptor == -1){ 25 | printf("Scoket creation failed.!\n"); 26 | exit(1); 27 | } 28 | 29 | // Erases the memory 30 | bzero(&serveraddress, sizeof(serveraddress)); 31 | 32 | // Server Properties 33 | serveraddress.sin_addr.s_addr = htonl(INADDR_ANY); 34 | // Setting the port number 35 | serveraddress.sin_port = htons(PORT); 36 | // Protocol family 37 | serveraddress.sin_family = AF_INET; 38 | 39 | // Binding the newly created socket with the given Ip Address 40 | bind_status = bind(sockert_file_descriptor, (SA*)&serveraddress, sizeof(serveraddress)); 41 | 42 | if(bind_status == -1){ 43 | printf("Socket binding failed.!\n"); 44 | exit(1); 45 | } 46 | 47 | // Server is listening for new creation 48 | connection_status = listen(sockert_file_descriptor, 5); 49 | 50 | if(connection_status == -1){ 51 | printf("Socket is unable to listen for new connections.!\n"); 52 | exit(1); 53 | }else{ 54 | printf("Server is listening for new connection: \n"); 55 | } 56 | 57 | length = sizeof(client); 58 | 59 | connection = accept(sockert_file_descriptor, (SA*)&client, &length); 60 | 61 | if(connection == -1){ 62 | printf("Server is unable to accept the data from client.!\n"); 63 | exit(1); 64 | } 65 | 66 | // Communication Establishment 67 | while(1){ 68 | 69 | bzero(message, MESSAGE_LENGTH); 70 | 71 | read(connection, message, sizeof(message)); 72 | 73 | if (strncmp("end", message, 3) == 0) { 74 | printf("Client Exited.\n"); 75 | printf("Server is Exiting..!\n"); 76 | break; 77 | } 78 | 79 | printf("Data received from client: %s\n", message); 80 | bzero(message, MESSAGE_LENGTH); 81 | 82 | printf("Enter the message you want to send to the client: "); 83 | scanf("%[^\n]%*c", message); 84 | 85 | // Sending the data to the server by storing the number of bytes transferred in bytes variable 86 | ssize_t bytes = write(connection, message, sizeof(message)); 87 | 88 | // If the number of bytes is >= 0 then the data is sent successfully 89 | if(bytes >= 0){ 90 | printf("Data successfully sent to the client.!\n"); 91 | } 92 | 93 | } 94 | // Closing the Socket Connection 95 | close(sockert_file_descriptor); 96 | 97 | return 0; 98 | } -------------------------------------------------------------------------------- /Chapter_08/UDP Client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define MAX 1024 // Maximum number of data that can transfer 10 | #define PORT 8080 // port number to connect 11 | #define SA struct sockaddr // Creating Macro for the socketaddr as SA 12 | 13 | // Driver code 14 | int main() { 15 | 16 | char buffer[100]; 17 | char *message = "Greetings from Client"; 18 | int sockfd, n; 19 | struct sockaddr_in servaddr; 20 | 21 | // clear servaddr 22 | bzero(&servaddr, sizeof(servaddr)); 23 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 24 | servaddr.sin_port = htons(PORT); 25 | servaddr.sin_family = AF_INET; 26 | 27 | // create datagram socket 28 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 29 | 30 | // connect to server 31 | if(connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) { 32 | printf("\n Something went wrong Connection Failed \n"); 33 | _exit(0); 34 | } 35 | 36 | // request to send datagram 37 | // no need to specify server address in sendto 38 | // connect stores the peers IP and port 39 | sendto(sockfd, message, MAX, 0, (SA*)NULL, sizeof(servaddr)); 40 | 41 | // waiting for response 42 | recvfrom(sockfd, buffer, sizeof(buffer), 0, (SA*)NULL, NULL); 43 | puts(buffer); 44 | 45 | // close the descriptor 46 | close(sockfd); 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Chapter_08/UDP Server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define MAX 1024 // Maximum number of data that can transfer 10 | #define PORT 8080 // port number to connect 11 | #define SA struct sockaddr // Creating Macro for the socketaddr as SA 12 | 13 | // Driver code 14 | int main() { 15 | 16 | char buffer[100]; 17 | char *message = "Greetings from Server"; 18 | int sockfd; 19 | socklen_t len; 20 | struct sockaddr_in servaddr, cli; 21 | bzero(&servaddr, sizeof(servaddr)); 22 | 23 | // Create a UDP Socket 24 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 25 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 26 | servaddr.sin_port = htons(PORT); 27 | servaddr.sin_family = AF_INET; 28 | 29 | // bind server address to socket descriptor 30 | bind(sockfd, (SA*)&servaddr, sizeof(servaddr)); 31 | 32 | //receive the datagram 33 | len = sizeof(cli); 34 | int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (SA*)&cli,&len); 35 | //receive message from server 36 | buffer[n] = '\0'; 37 | puts(buffer); 38 | 39 | // send the response 40 | sendto(sockfd, message, MAX, 0, (SA*)&cli, sizeof(cli)); 41 | 42 | close(sockfd); 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Freeware License, some rights reserved 2 | 3 | Copyright (c) 2020 Sri Manikanta Palakollu 4 | 5 | Permission is hereby granted, free of charge, to anyone obtaining a copy 6 | of this software and associated documentation files (the "Software"), 7 | to work with the Software within the limits of freeware distribution and fair use. 8 | This includes the rights to use, copy, and modify the Software for personal use. 9 | Users are also allowed and encouraged to submit corrections and modifications 10 | to the Software for the benefit of other users. 11 | 12 | It is not allowed to reuse, modify, or redistribute the Software for 13 | commercial use in any way, or for a user’s educational materials such as books 14 | or blog articles without prior permission from the copyright holder. 15 | 16 | The above copyright notice and this permission notice need to be included 17 | in all copies or substantial portions of the software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Practical System Programming with C*](https://www.apress.com/9781484263204) by Sri Manikanta Palakollu (Apress, 2020). 4 | 5 | [comment]: #cover 6 | ![Cover image](9781484263204.jpg) 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *Practical System Programming with C* 2 | 3 | On **page xx** [Summary of error]: 4 | 5 | Details of error here. Highlight key pieces in **bold**. 6 | 7 | *** 8 | 9 | On **page xx** [Summary of error]: 10 | 11 | Details of error here. Highlight key pieces in **bold**. 12 | 13 | *** --------------------------------------------------------------------------------