├── gnu_toolchain ├── libs │ ├── test1.c │ ├── test2.c │ ├── app.c │ └── demo.sh ├── mem_layout │ ├── ml0.c │ ├── ml3.c │ ├── ml4.c │ ├── ml5.c │ ├── ml2.c │ ├── results.txt │ └── ml1.c ├── reciprocal │ ├── reciprocal.hpp │ ├── divbyzero.c │ ├── reciprocal.cpp │ ├── Makefile │ └── main.c ├── factorial │ └── factorial.c └── tiff │ └── tifftest.c ├── memory ├── a ├── dummy_malloc.c ├── malloc_free.c ├── realloc.c ├── sbrk │ ├── get_num.h │ ├── free_and_sbrk.c │ └── get_num.c ├── freeing_after_malloc.c └── mallinfo.c ├── bash ├── print_os.sh ├── hello_linux.sh ├── README_hello_linux.md ├── examples.md └── users.md ├── valgrind ├── uninit.c ├── uninitialised.c ├── uninit1.c ├── block.c ├── mleak.c ├── malloc.c ├── free.c ├── test.c └── memoryleak.c ├── processes ├── system_ls.c ├── ls_root.c ├── fork_1.c ├── atexit_fork.c ├── execl.c ├── ids.c ├── shared_variable.c ├── atexit.c ├── system_signals.c ├── fork_exec.c ├── wait.c └── making_zombie.c ├── c ├── interface.cpp ├── readme.md ├── str │ ├── str_upper.c │ ├── strlen.c │ ├── gets_puts.c │ ├── frequency.c │ ├── string_sort.c │ └── printf.c ├── struct │ ├── car.c │ ├── threebitfield.c │ ├── multiplebitfield.c │ ├── struct_with_flexible_array.c │ └── padding_example.c ├── square.c ├── printable.c ├── ascii.c ├── volatile.c ├── long.c ├── delta_time.c └── makefile ├── gnu_linux_sw ├── print-env.c ├── syscall_error.c ├── client.c ├── better_sleep.c ├── readfile.c ├── getopt.c ├── getopt_long.c └── errors_from_sycalls.c ├── ipc ├── pipe │ ├── popen_wr.c │ ├── pipe_one_process.c │ ├── pipe_with_fork.c │ ├── popen_rd.c │ ├── pipe_rd_wr.c │ ├── dup2.c │ └── pipe.c ├── sem │ ├── sem_init.c │ ├── sem_all_deall.c │ └── sem_pv.c ├── mmap │ ├── copy_on_write_shmat.cpp │ ├── mmap-read.c │ └── mmap-write.c ├── shm │ └── shm.c └── socket │ ├── socket-client.c │ ├── socket-server.c │ └── socket-inet.c ├── signals ├── jumps.c ├── restarts_itself.c ├── ctrl_c_events.c ├── sigalarm.c ├── sigusr1.c └── sigchld.c ├── README.md ├── .gitignore └── modules └── hello-module ├── hello.c └── Makefile /gnu_toolchain/libs/test1.c: -------------------------------------------------------------------------------- 1 | int f () 2 | { 3 | return 3; 4 | } 5 | -------------------------------------------------------------------------------- /gnu_toolchain/libs/test2.c: -------------------------------------------------------------------------------- 1 | int g () 2 | { 3 | return 4; 4 | } 5 | -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/ml0.c: -------------------------------------------------------------------------------- 1 | int main(void) 2 | { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /memory/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICOMP-UNC/so1-ejemplos/HEAD/memory/a -------------------------------------------------------------------------------- /gnu_toolchain/libs/app.c: -------------------------------------------------------------------------------- 1 | int main () 2 | { 3 | return f() + g(); 4 | } 5 | -------------------------------------------------------------------------------- /bash/print_os.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | os_name=$(uname -o) 4 | 5 | echo "Hello $os_name!" 6 | -------------------------------------------------------------------------------- /valgrind/uninit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int x; 6 | printf ("x = %d\n", x); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /processes/system_ls.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main () 4 | { 5 | int return_value; 6 | return_value = system ("ls -l /"); 7 | return return_value; 8 | } 9 | -------------------------------------------------------------------------------- /gnu_toolchain/reciprocal/reciprocal.hpp: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | extern double reciprocal(int i); 6 | 7 | #ifdef __cplusplus 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /processes/ls_root.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main () 4 | { 5 | int return_value; 6 | return_value = system ("ls -l /"); 7 | 8 | return return_value; 9 | } 10 | -------------------------------------------------------------------------------- /valgrind/uninitialised.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( void ) 5 | { 6 | char* arr = malloc(10); 7 | (void) write( 1 /* stdout */, arr, 10 ); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /valgrind/uninit1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | char *p; 7 | 8 | char c = *p; 9 | 10 | printf("\n [%c]\n",c); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /bash/hello_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Stores the operating system's name in the variable `os_name` 4 | os_name=$(uname -s) 5 | 6 | # Outputs "Hello" followed by the operating system's name 7 | echo "Hello $os_name!" 8 | -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/ml3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int global; /* Uninitialized variable stored in bss*/ 4 | 5 | int main(void) 6 | { 7 | static int i; /* Uninitialized static variable stored in bss */ 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /valgrind/block.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void f(void) 4 | { 5 | int* x = malloc(10 * sizeof(int)); 6 | x[10] = 0; 7 | } 8 | 9 | int main(void) 10 | { 11 | f(); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/ml4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int global; /* Uninitialized variable stored in bss*/ 4 | 5 | int main(void) 6 | { 7 | static int i = 100; /* Initialized static variable stored in DS*/ 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /valgrind/mleak.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | char *p = malloc(1); 7 | *p = 'a'; 8 | 9 | char c = *p; 10 | 11 | printf("\n [%c]\n",c); 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /c/interface.cpp: -------------------------------------------------------------------------------- 1 | //name: reciprocal.cpp 2 | 3 | double reciprocal(int i) 4 | { 5 | my_win.my_reciprobal(); 6 | } 7 | 8 | 9 | 10 | 11 | 12 | ARCH=linux 13 | 14 | if ARCH==linux: 15 | linux/src/reciprocal.cpp 16 | else: 17 | win/src/reciprocal.cpp -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/ml5.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int global = 10; /* Initialized global variable stored in DS*/ 4 | 5 | int main(void) 6 | { 7 | static int i = 100; /* Initialized static variable stored in DS*/ 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /valgrind/malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | char *p = malloc(1); 7 | *p = 'a'; 8 | 9 | char c = *(p+1); 10 | 11 | printf("\n [%c]\n",c); 12 | 13 | free(p); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /valgrind/free.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | char *p = malloc(1); 7 | *p = 'a'; 8 | 9 | char c = *p; 10 | 11 | printf("\n [%c]\n",c); 12 | 13 | free(p); 14 | c = *p; 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/ml2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Initialized variable stored in Data Segment (DS) 4 | * 5 | * Note: that setting global to 0 places it in BSS 6 | * `int global = 0;` 7 | * 8 | */ 9 | int global = 1; 10 | // int global = 0; 11 | 12 | int main(void) 13 | { 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /valgrind/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | char *p; 7 | 8 | // Allocation #1 of 19 bytes 9 | p = (char *) malloc(19); 10 | 11 | // Allocation #2 of 12 bytes 12 | p = (char *) malloc(12); 13 | free(p); 14 | 15 | // Allocation #3 of 16 bytes 16 | p = (char *) malloc(16); 17 | 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /gnu_linux_sw/print-env.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Listing 2.3 ( print-env.c) Printing the Execution Environment 3 | */ 4 | 5 | #include 6 | 7 | /* The ENVIRON variable contains the environment. See: man environ*/ 8 | extern char** environ; 9 | 10 | int main () 11 | { 12 | char** var; 13 | 14 | for (var = environ; *var != NULL; ++var) 15 | printf ("%s\n", *var); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /ipc/pipe/popen_wr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main () 5 | { 6 | FILE* stream = popen("sort", "w"); 7 | 8 | fprintf (stream, "This is a test.\n"); 9 | fprintf (stream, "Hello, world.\n"); 10 | fprintf (stream, "My dog has fleas.\n"); 11 | fprintf (stream, "This program is great.\n"); 12 | fprintf (stream, "One fish, two fish.\n"); 13 | 14 | return pclose(stream); 15 | } 16 | -------------------------------------------------------------------------------- /signals/jumps.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | jmp_buf buf; 4 | 5 | //setjmp/longjmp example 6 | int main() 7 | { 8 | if (setjmp(buf) != 0) { 9 | printf(“back in main due to an error\n”); 10 | else 11 | printf(“first time through\n”); 12 | 13 | p1(); /* p1 calls p2, which calls p3 */ 14 | } 15 | 16 | void p3() 17 | { 18 | // 19 | if (error) 20 | longjmp(buf, 1) 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## so1-ejemplos 2 | 3 | Este repositorio reune código utilizado en las demos en clases, ejemplos en las presentaciones y material adicional. 4 | 5 | ## Git 6 | 7 | ### Alias de Git 8 | 9 | ``` 10 | git config --global alias.co checkout 11 | git config --global alias.br branch 12 | git config --global alias.ci commit 13 | git config --global alias.st 'status -uno' 14 | git config --global alias.last 'log -1 HEAD' 15 | ``` 16 | -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/results.txt: -------------------------------------------------------------------------------- 1 | $ size ml{0..5} 2 | 3 | 4 | text data bss dec hex filename 5 | 1418 544 8 1970 7b2 ml0 6 | 1418 544 8 1970 7b2 ml1 7 | 1418 548 4 1970 7b2 ml2 8 | 1418 544 16 1978 7ba ml3 9 | 1418 548 12 1978 7ba ml4 10 | 1418 552 8 1978 7ba ml5 11 | -------------------------------------------------------------------------------- /processes/fork_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | pid_t pid; 9 | 10 | 11 | int x = 1; 12 | 13 | pid = fork(); 14 | 15 | if (pid != 0) { 16 | printf("parent: x = %d\n", --x); 17 | exit(0); 18 | } 19 | else { 20 | printf("child: x = %d\n", ++x); 21 | exit(0); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /c/readme.md: -------------------------------------------------------------------------------- 1 | ## Repaso de C 2 | 3 | En esta sección encontrarás ejemplos de código para repasar conceptos de C que te van a servir a lo largo de la materia. 4 | 5 | ### Para compilar los ejemplos: 6 | ``` 7 | $ make 8 | ``` 9 | ### Para ejecutar un ejemplo: 10 | 1. Ubicarse en la carpeta donde se encuentra el ejecutable 11 | 2. Abrir una terminal y ejecutarlo de la siguiente forma: 12 | ``` 13 | $ ./ 14 | ``` 15 | 16 | -------------------------------------------------------------------------------- /c/str/str_upper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // toupper() 4 | 5 | /* 6 | * C strupr() function converts a string to uppercase letters. 7 | * 8 | * DEPRECATED MS WINDOWS FUNCTION 9 | * 10 | */ 11 | void main() 12 | { 13 | char str[10] = "Hello C."; 14 | for(int i = 0; str[i]; i++){ 15 | str[i] = toupper(str[i]); 16 | } 17 | printf("%s", str); 18 | //printf("%s", strupr(str)); 19 | } 20 | -------------------------------------------------------------------------------- /processes/atexit_fork.c: -------------------------------------------------------------------------------- 1 | #include // exit 2 | #include // printf 3 | #include // fork 4 | 5 | 6 | void cleanup(void) 7 | { 8 | printf("cleaning up\n"); 9 | } 10 | 11 | void main() 12 | { 13 | atexit(cleanup); 14 | 15 | if (fork() == 0) { 16 | printf("hello from child\n"); 17 | } 18 | else { 19 | printf("hello from parent\n"); 20 | } 21 | 22 | exit(EXIT_SUCCESS); 23 | } 24 | -------------------------------------------------------------------------------- /c/struct/car.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // declares the struct type 4 | struct Car { 5 | char *make; 6 | char *model; 7 | int year; 8 | }; 9 | 10 | int main() 11 | { 12 | 13 | // declares and initializes an object of a previously-declared struct type 14 | struct Car c = { 15 | .year=1923, 16 | .make="Nash", 17 | .model="48 Sports Touring Car" 18 | }; 19 | 20 | printf("car: %d %s %s\n", c.year, c.make, c.model); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /c/str/strlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Compute the length of a string manually without using strlen() function. 5 | 6 | Example: 7 | Enter a string: Sistemas Operativos I 8 | Length of string: 21 9 | */ 10 | int main() 11 | { 12 | char s[1000]; //1KB 13 | unsigned i; 14 | 15 | printf("Enter a string: "); 16 | scanf("%s", s); 17 | 18 | for(i = 0; s[i] != '\0'; ++i); 19 | 20 | printf("Length of string: %d\n", i); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /processes/execl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | 11 | if (fork() == 0) { 12 | execl("/usr/bin/touch", "touch", "foo", NULL); 13 | 14 | abort(); 15 | execl("/usr/bin/cp", "cp", "foo", "bar", NULL); 16 | } 17 | 18 | wait(NULL); 19 | 20 | printf("copy completed\n"); 21 | 22 | exit(EXIT_SUCCESS); 23 | } 24 | -------------------------------------------------------------------------------- /gnu_linux_sw/syscall_error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | 12 | int main() { 13 | 14 | int fd = open ("inputfile.txt", O_RDONLY); 15 | if (fd == -1) { 16 | /* The open failed. Print an error message and exit. */ 17 | fprintf (stderr, "error opening file: %s\n", strerror (errno)); 18 | exit (1); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gnu_toolchain/mem_layout/ml1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * Bss (aka: Better save space). 5 | * The bss variables are not copied into the section. 6 | * Instead, memory addresses are reserved. 7 | * 8 | */ 9 | 10 | int global; /* Uninitialized variable stored in bss*/ 11 | // int global1; /* Uninitialized variable stored in bss*/ 12 | //int global2; /* Uninitialized variable stored in bss*/ 13 | //int global3; /* Uninitialized variable stored in bss*/ 14 | 15 | int main(void) 16 | { 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /c/struct/threebitfield.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | bit field 5 | +++++++++ 6 | 7 | Declares a member with explicit , in bits. Adjacent bit field members 8 | may bwidthe packed to share and straddle the individual bytes. 9 | 10 | */ 11 | 12 | struct S { 13 | // three-bit unsigned field, allowed values are 0...7 14 | unsigned int b : 3; 15 | }; 16 | 17 | int main(void) 18 | { 19 | struct S s = {7}; 20 | 21 | // unsigned overflow 22 | ++s.b; 23 | 24 | // output: 0 25 | printf("%d\n", s.b); 26 | } 27 | -------------------------------------------------------------------------------- /gnu_toolchain/reciprocal/divbyzero.c: -------------------------------------------------------------------------------- 1 | // Example program 2 | #include 3 | 4 | int main() 5 | { 6 | /* 7 | * in standard IEEE 754 division by zero is allowed 8 | * output: -nan 9 | */ 10 | //double a = 0.0/0.0; 11 | 12 | /* 13 | * in standard IEEE 754 division by zero is allowed 14 | * output: inf 15 | */ 16 | double a = 3.0/0; 17 | 18 | /* 19 | * Floating point exception (core dumped) 20 | * 21 | */ 22 | // int a = 3/0; 23 | // int a = 0/0; 24 | 25 | printf("%f", a); 26 | } 27 | -------------------------------------------------------------------------------- /ipc/sem/sem_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* We must define union semun ourselves.*/ 6 | union semun { 7 | int val; 8 | struct semid_ds *buf; 9 | unsigned short int *array; 10 | struct seminfo *__buf; 11 | }; 12 | 13 | /* Initialize a binary semaphore with a value of 1.*/ 14 | 15 | int binary_semaphore_initialize (int semid) 16 | { 17 | union semun argument; 18 | unsigned short values[1]; 19 | values[0] = 1; 20 | argument.array = values; 21 | 22 | return semctl (semid, 0, SETALL, argument); 23 | } 24 | -------------------------------------------------------------------------------- /signals/restarts_itself.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | sigjmp_buf buf; 7 | 8 | void handler(int sig) 9 | { 10 | siglongjmp(buf, 1); 11 | } 12 | 13 | // A program that restarts itself when ctrl-c’d 14 | int main() 15 | { 16 | signal(SIGINT, handler); 17 | 18 | if (!sigsetjmp(buf, 1)) 19 | printf("starting\n"); 20 | else 21 | printf("restarting\n"); 22 | 23 | while(1) { 24 | sleep(1); 25 | printf("processing...\n"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /memory/dummy_malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *dummy_malloc(size_t size) 7 | { 8 | void *p; 9 | p = sbrk (0); 10 | /* If sbrk fails , we return NULL */ 11 | if (sbrk(size) == (void*)-1) 12 | return NULL; 13 | 14 | return p; 15 | } 16 | 17 | int 18 | main() 19 | { 20 | printf("Initial\n"); 21 | 22 | void * p = dummy_malloc(100000); 23 | if (p == NULL) { 24 | perror("malloc"); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | printf("After malloc\n"); 29 | } 30 | -------------------------------------------------------------------------------- /signals/ctrl_c_events.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static void handler(int sig) 7 | { 8 | printf("You think hitting ctrl-c will stop the bomb?\n"); 9 | sleep(2); 10 | printf("Well..."); 11 | 12 | fflush(stdout); 13 | sleep(1); 14 | printf("OK\n"); 15 | exit(0); 16 | } 17 | 18 | // A program that reacts to externally generated events (ctrl-c) 19 | int main() 20 | { 21 | /* installs ctl-c handler */ 22 | signal (SIGINT, handler); 23 | 24 | while (1) { 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /c/str/gets_puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | gets() and puts() 5 | +++++++++++++++++ 6 | 7 | Functions gets() and puts() are two string functions 8 | gets() to take string input from the user 9 | puts() to display string output to the user 10 | 11 | */ 12 | 13 | int main() 14 | { 15 | char name[30]; 16 | 17 | printf("Enter name: "); 18 | 19 | // read string from user 20 | fgets(name, sizeof(name), stdin); 21 | //gets(name); 22 | 23 | printf("Name: "); 24 | 25 | // display string 26 | puts(name); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /gnu_linux_sw/client.c: -------------------------------------------------------------------------------- 1 | /*Listing 2.4 (client.c) Part of a Network Client Program*/ 2 | 3 | #include 4 | #include 5 | 6 | int main () 7 | { 8 | char* server_name = getenv ("SERVER_NAME"); 9 | 10 | // char* user = getenv ("USER"); 11 | // path = "/home/" 12 | // strcat(path, user) 13 | 14 | /* The SERVER_NAME environment variable was not set. Use the default. */ 15 | if (server_name == NULL) 16 | server_name = "server.my-company.com"; 17 | 18 | printf ("accessing server %s\n", server_name); 19 | 20 | /* Access the server here... */ 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /c/struct/multiplebitfield.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | bit field 5 | +++++++++ 6 | 7 | Multiple adjacent bit fields are permitted 8 | to be (and usually are) packed together 9 | */ 10 | 11 | struct S { 12 | // will usually occupy 4 bytes: 13 | // 5 bits: value of b1 14 | // 11 bits: unused 15 | // 6 bits: value of b2 16 | // 2 bits: value of b3 17 | // 8 bits: unused 18 | unsigned b1 : 5, : 11, b2 : 6, b3 : 2; 19 | }; 20 | 21 | int main(void) 22 | { 23 | // prints 4 24 | printf("%zu\n",sizeof(struct S)); 25 | } 26 | 27 | 28 | // TODO:: agregar cast de dato a struct -------------------------------------------------------------------------------- /gnu_toolchain/factorial/factorial.c: -------------------------------------------------------------------------------- 1 | # include 2 | 3 | /* 4 | * Factorial of a non-negative integer, is multiplication of all integers 5 | * smaller than or equal to n. 6 | * For example factorial of 6 is 6*5*4*3*2*1 which is 720. 7 | */ 8 | int main() 9 | { 10 | int i, num, j; 11 | printf ("Enter the number: "); 12 | scanf ("%d", &num ); 13 | 14 | for (i=1; i 7 | #include 8 | 9 | int main() 10 | { 11 | float num, root; 12 | printf("Enter a number: "); 13 | 14 | // Reads character input from the user 15 | scanf("%f", &num); 16 | 17 | root = sqrt(num); 18 | printf("Square root of %.2f = %.2f", num, root); 19 | 20 | return 0; 21 | } 22 | 23 | /* 24 | Compile 25 | -------- 26 | gcc square.c -lm -o square 27 | 28 | Output 29 | ------ 30 | Enter a number: 12 31 | Square root of 12.00 = 3.46 32 | 33 | */ 34 | 35 | 36 | -------------------------------------------------------------------------------- /c/printable.c: -------------------------------------------------------------------------------- 1 | /* C program to illustrate isprint() and iscntrl() functions. */ 2 | 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | char ch = 'a'; 9 | // char ch = 0x53; 10 | // char ch = 2; 11 | 12 | if (isprint(ch)) { 13 | printf("%c is printable character\n", ch); 14 | } 15 | else { 16 | printf("%c is not printable character\n", ch); 17 | } 18 | 19 | if (iscntrl(ch)) { 20 | printf("%c is control character\n", ch); 21 | } 22 | else { 23 | printf("%c is not control character\n", ch); 24 | } 25 | 26 | return (0); 27 | } 28 | -------------------------------------------------------------------------------- /gnu_toolchain/reciprocal/reciprocal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "reciprocal.hpp" 3 | 4 | double reciprocal(int i) 5 | { 6 | // It should be non-zero. 7 | assert (i != 0); 8 | 9 | // return 1/i; //Floating point exception (core dumped) 10 | return 1.0/i; 11 | } 12 | 13 | 14 | /* 15 | % ./reciprocal 0 16 | The reciprocal of 0 is inf 17 | 18 | % gcc --version 19 | gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 20 | Copyright (C) 2019 Free Software Foundation, Inc. 21 | This is free software; see the source for copying conditions. There is NO 22 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | */ -------------------------------------------------------------------------------- /processes/ids.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Always use the pid_t typedef, which is defined in . 6 | 7 | getpid 8 | ====== 9 | returns the identifier of the calling process. 10 | pid _t getpid(void); 11 | 12 | - This is often used by routines that generate unique temporary filenames. 13 | 14 | getppid 15 | ====== 16 | returns the identifier of the parent. 17 | pid_t getppid(void); 18 | 19 | */ 20 | int main () 21 | { 22 | printf ("The process ID is %d\n", (int) getpid()); 23 | printf ("The parent process ID is %d\n", (int) getppid()); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /valgrind/memoryleak.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const int ARR_SIZE = 1000; 6 | 7 | int main() { 8 | // create an arrat of ARR_SIZE ints 9 | int *intArray = malloc(sizeof(int) * ARR_SIZE); 10 | 11 | // populate them 12 | for (int i=0; i 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | char *s, buf[1024]; 8 | 9 | int fds[2]; 10 | 11 | s = "hello world\n"; 12 | 13 | pipe(fds); 14 | 15 | // sleep(60); 16 | // check fds in /proc 17 | 18 | // write to pipe's input 19 | write(fds[1], s, strlen(s)); //-> | 20 | 21 | // write to pipe's output 22 | read(fds[0], buf, strlen(s)); // | -> buf 23 | 24 | printf("fds[0] = %d, fds[1] = %d\n", fds[0], fds[1]); 25 | 26 | // write to std out 27 | write(1, buf, strlen(s)); 28 | 29 | return 1; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /c/str/frequency.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | 5 | Example: Find frequency of character in a string 6 | ++++++++++++++++++++++++++++++++++++++++++++++++ 7 | 8 | 9 | */ 10 | 11 | int main() 12 | { 13 | char str[1000], ch; 14 | int i, frequency = 0; 15 | 16 | printf("Enter a string: "); 17 | fgets(str, sizeof(str), stdin); // read string from user 18 | // gets(str); // deprecated 19 | 20 | printf("Enter a character to find the frequency: "); 21 | scanf("%c",&ch); 22 | 23 | for (i = 0; str[i] != '\0'; ++i) { 24 | if (ch == str[i]) ++frequency; 25 | } 26 | 27 | printf("Frequency of %c = %d", ch, frequency); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /signals/sigalarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int beeps = 0; 7 | 8 | /* SIGALRM handler */ 9 | void handler(int sig) 10 | { 11 | printf("BEEP\n"); 12 | fflush(stdout); 13 | 14 | if (++beeps < 5) alarm(1); 15 | else { 16 | printf("BOOM!\n"); 17 | exit(0); 18 | } 19 | } 20 | 21 | int main() 22 | { 23 | signal(SIGALRM, handler); 24 | 25 | /* send SIGALRM in 1 second */ 26 | alarm(5); 27 | 28 | while (1) { 29 | /* handler returns here */ 30 | } 31 | } 32 | 33 | /* 34 | $ a.out 35 | BEEP 36 | BEEP 37 | BEEP 38 | BEEP 39 | BEEP 40 | BOOM! 41 | */ 42 | -------------------------------------------------------------------------------- /memory/malloc_free.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct 4 | { 5 | int field1; 6 | char* field2; 7 | } SomeStruct; 8 | 9 | void do_stuff(SomeStruct * somestruct) 10 | { 11 | // do something with SomeStruct 12 | } 13 | 14 | /* 15 | how a C program might allocate, use, and later free 16 | a structure on the heap 17 | */ 18 | int main() 19 | { 20 | SomeStruct* myObject = (SomeStruct*) malloc (sizeof(SomeStruct)); 21 | 22 | if(myObject != NULL) 23 | { 24 | myObject->field1 = 1234; 25 | myObject->field2 = "Hello World!"; 26 | 27 | do_stuff(myObject); 28 | 29 | free (myObject); 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | .vscode/c_cpp_properties.json 54 | -------------------------------------------------------------------------------- /c/ascii.c: -------------------------------------------------------------------------------- 1 | /* 2 | Print ASCII Value (ascii.c) 3 | +++++++++++++++++++++++++++ 4 | 5 | In C programming, a character variable holds an ASCII value 6 | (an integer number between 0 and 127) rather than character itself. 7 | 8 | Example Output: 9 | --------------- 10 | Enter a character: G 11 | ASCII value of G = 71 12 | */ 13 | 14 | #include 15 | 16 | int main() 17 | { 18 | char c; 19 | printf("Enter a character: "); 20 | 21 | // Reads character input from the user 22 | scanf("%c", &c); 23 | 24 | // %d displays the integer value of a character 25 | // %c displays the actual character 26 | printf("ASCII value of %c = %d\n", c, c); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /processes/shared_variable.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | pid_t pid; 6 | int shared_variable = 0; 7 | 8 | pid = fork(); 9 | 10 | if (pid == 0) { 11 | shared_variable += 5; 12 | printf("Proceso hijo - Valor de la variable compartida: %d\n", shared_variable); 13 | } else if (pid > 0) { 14 | shared_variable -= 3; 15 | printf("Proceso padre - Valor de la variable compartida: %d\n", shared_variable); 16 | } else { 17 | printf("Ha ocurrido un error al crear el proceso hijo.\n"); 18 | } 19 | 20 | printf("Proceso x - Valor de la variable compartida: %d\n", shared_variable); 21 | 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /ipc/sem/sem_all_deall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* We must define union semun ourselves.*/ 6 | union semun { 7 | int val; 8 | struct semid_ds *buf; 9 | unsigned short int *array; 10 | struct seminfo *__buf; 11 | }; 12 | 13 | /* Obtain a binary semaphore’s ID, allocating if necessary.*/ 14 | int binary_semaphore_allocation (key_t key, int sem_flags) 15 | { 16 | return semget (key, 1, sem_flags); 17 | } 18 | 19 | /* Deallocate a binary semaphore. All users must have finished their 20 | use. Returns -1 on failure. */ 21 | int binary_semaphore_deallocate (int semid) 22 | { 23 | union semun ignored_argument; 24 | 25 | return semctl (semid, 1, IPC_RMID, ignored_argument); 26 | } 27 | -------------------------------------------------------------------------------- /processes/atexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void 6 | bye(void) 7 | { 8 | printf("That was all, folks\n"); 9 | } 10 | 11 | int 12 | main(void) 13 | { 14 | long a; 15 | int i; 16 | 17 | /* 18 | POSIX allows an application to test at compile or run time whether certain options are supported, 19 | or what the value is of certain configurable constants or limits. 20 | */ 21 | a = sysconf(_SC_ATEXIT_MAX); 22 | printf("ATEXIT_MAX = %ld\n", a); 23 | 24 | i = atexit(bye); 25 | if (i != 0) { 26 | fprintf(stderr, "cannot set exit function\n"); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | exit(EXIT_SUCCESS); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /ipc/pipe/pipe_with_fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* 7 | * IPC can be used to enforce the order of the execution of processes. 8 | */ 9 | 10 | int main () 11 | { 12 | char *s, buf[1024]; 13 | int fds[2]; 14 | 15 | pipe(fds); 16 | 17 | if (fork() == 0) { 18 | printf("child\n"); 19 | 20 | s = "hello world\n"; 21 | write(fds[1], s, strlen(s)); 22 | 23 | exit(0); 24 | } 25 | 26 | printf("father will block until read\n"); 27 | 28 | read(fds[0], buf, 12); 29 | printf("father continues..\n"); 30 | 31 | // write to std out 32 | write(1, buf, 12); 33 | 34 | return 1; 35 | } 36 | -------------------------------------------------------------------------------- /processes/system_signals.c: -------------------------------------------------------------------------------- 1 | /* 2 | During execution of the command, SIGCHLD will be blocked, and SIGINT 3 | and SIGQUIT will be ignored, in the process that calls system(). 4 | (These signals will be handled according to their defaults inside the 5 | child process that executes command.) 6 | 7 | As mentioned, system() ignores SIGINT and SIGQUIT. This may make pro‐ 8 | grams that call it from a loop uninterruptible, unless they take care 9 | themselves to check the exit status of the child. 10 | 11 | For example: 12 | */ 13 | 14 | int main (argc, argv) 15 | { 16 | while (something) { 17 | int ret = system("foo"); 18 | 19 | if (WIFSIGNALED(ret) && 20 | (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT)) 21 | break; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ipc/pipe/popen_rd.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PATH_MAX 70 4 | 5 | /* Using popen() with ls Utility */ 6 | int main () 7 | { 8 | FILE *fp; 9 | int status; 10 | char path[PATH_MAX]; 11 | 12 | /* Open a read-only pipe stream from command ls*/ 13 | fp = popen("ls *", "r"); 14 | if (fp == NULL) { 15 | /* Handle error */; 16 | } 17 | 18 | printf("CWD Content:\n"); 19 | while (fgets(path, PATH_MAX, fp) != NULL) { 20 | printf("- %s", path); 21 | } 22 | 23 | status = pclose(fp); 24 | if (status == -1) { 25 | /* Error reported by pclose() */ 26 | } 27 | else { 28 | /* Use macros described under wait() to inspect `status' in 29 | order to determine success/failure of command executed by popen() */ 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /signals/sigusr1.c: -------------------------------------------------------------------------------- 1 | // Listing 3.5 (sigusr1.c) Using a Signal Handler 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | sig_atomic_t sigusr1_count = 0; 9 | 10 | void handler (int signal_number) 11 | { 12 | ++sigusr1_count; 13 | } 14 | 15 | 16 | 17 | /* 18 | * example shows: sigaction, SIGUSR1 19 | */ 20 | int main () 21 | { 22 | // signal(SIGUSR1, handler); 23 | 24 | struct sigaction sa; 25 | memset(&sa, 0, sizeof (sa)); 26 | 27 | sa.sa_handler = &handler; 28 | 29 | 30 | sigaction(SIGUSR1, &sa, NULL); 31 | 32 | /* Do some lengthy stuff here. */ 33 | 34 | /* ... */ 35 | 36 | kill(getpid(), SIGUSR1); 37 | 38 | /* ... */ 39 | 40 | kill(getpid(), SIGUSR1); 41 | 42 | printf ("SIGUSR1 was raised %d times\n", sigusr1_count); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /c/volatile.c: -------------------------------------------------------------------------------- 1 | /* 2 | Can a variable be both const and volatile? 3 | ------------------------------------------ 4 | yes, the const means that the variable cannot be assigned a new value. 5 | The value can be changed by other code or pointer. 6 | */ 7 | 8 | #include 9 | 10 | int main(void) 11 | { 12 | const int local = 10; 13 | // const volatile int local = 10; 14 | 15 | int* ptr = (int*)&local; 16 | printf("Initial value of local : %d \n", local); 17 | 18 | *ptr = 100; 19 | printf("Modified value of local: %d \n", local); 20 | 21 | socket.write(local+22); 22 | // socket.write(10+22); 23 | // socket.write(32); 24 | 25 | return 0; 26 | } 27 | 28 | 29 | // void fn() { 30 | 31 | // volatile int counter=0; 32 | 33 | // while(counter < 10) { 34 | // while(TRUE) { 35 | 36 | // //read sensor 37 | // } 38 | // } 39 | -------------------------------------------------------------------------------- /signals/sigchld.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | sig_atomic_t child_exit_status; 7 | 8 | void clean_up_child_process (int signal_number) 9 | { 10 | /* Clean up the child process. */ 11 | int status; 12 | wait (&status); 13 | 14 | /* Store its exit status in a global variable. */ 15 | child_exit_status = status; 16 | } 17 | 18 | // Cleaning Up Children by Handling SIGCHLD 19 | int main () 20 | { 21 | /* Handle SIGCHLD by calling clean_up_child_process. */ 22 | struct sigaction sigchld_action; 23 | memset (&sigchld_action, 0, sizeof (sigchld_action)); 24 | 25 | sigchld_action.sa_handler = &clean_up_child_process; 26 | sigaction (SIGCHLD, &sigchld_action, NULL); 27 | 28 | /* Now do things, including forking a child process. */ 29 | /* ... */ 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /c/struct/struct_with_flexible_array.c: -------------------------------------------------------------------------------- 1 | /* 2 | struct with flexible array member 3 | +++++++++++++++++++++++++++++++++ 4 | 5 | Initialization, sizeof, and the assignment operator 6 | ignore the flexible array member. 7 | 8 | Structures with flexible array members (or unions whose 9 | last member is a structure with flexible array member) 10 | cannot appear as array elements or as members of other structures. 11 | */ 12 | 13 | // s.d is a flexible array member 14 | struct s { 15 | int n; 16 | double d[]; 17 | }; 18 | 19 | int main() 20 | { 21 | // OK: d is as if double d[1], but undefined behaviour (UB) to access 22 | struct s t1 = {0}; 23 | 24 | // error: non-static initialization of a flexible array member 25 | struct s t2 = {0, 1}; 26 | 27 | // error: initialization ignores flexible array 28 | // error: non-static initialization of a flexible array member 29 | struct s t3 = { 1, { 4.2 } }; 30 | } 31 | -------------------------------------------------------------------------------- /c/struct/padding_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Student 5 | { 6 | int id1; 7 | char name; 8 | int id2; 9 | char c; 10 | float percentage; 11 | }; 12 | 13 | int main(void) 14 | { 15 | struct Student student = { 16 | .id1 = 1, 17 | .name = 'A', 18 | .id2 = 2, 19 | .c = 'B', 20 | .percentage = 80.5 21 | }; 22 | printf("Size of members of the struct:\n- id1: %zu bytes\n- name: %zu byte\n- id2: %zu bytes\n- c: %zu byte\n- percentage: %zu bytes\n", sizeof(student.id1), sizeof(student.name), sizeof(student.id2), sizeof(student.c), sizeof(student.percentage)); 23 | printf("Expected size of the struct: %zu bytes\n", sizeof(student.id1)+ sizeof(student.name)+ sizeof(student.id2)+ sizeof(student.c) + sizeof(student.percentage)); 24 | printf("Actual size of the struct: %zu bytes\n", sizeof(student)); 25 | } 26 | -------------------------------------------------------------------------------- /processes/fork_exec.c: -------------------------------------------------------------------------------- 1 | // Using fork and exec Together 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int spawn (char* program, char** arg_list) 8 | { 9 | pid_t child_pid; 10 | 11 | /* Duplicate this process. */ 12 | child_pid = fork (); 13 | 14 | if (child_pid != 0) { 15 | return child_pid; 16 | } 17 | else { 18 | printf ("Child id %d - before execvp\n", getpid()); 19 | 20 | execvp (program, arg_list); 21 | 22 | /* returns only if an error occurs. */ 23 | fprintf (stderr, "an error occurred in execvp\n"); 24 | abort (); 25 | } 26 | } 27 | 28 | 29 | int main() 30 | { 31 | 32 | char *const args[] = {"ls", "-l", "/", NULL}; 33 | 34 | // ok, it does not return 35 | spawn ("ls", (char**) args); 36 | 37 | // fail, it returns 38 | // spawn ("noexistingcmd", (char**) args); 39 | 40 | printf ("Parent process %d - bye \n", getpid()); 41 | 42 | return 0; 43 | } -------------------------------------------------------------------------------- /memory/realloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void foo (int len, int extra) 8 | { 9 | int i, *p; 10 | 11 | /* allocate a block of len ints */ 12 | if ((p = (int *) malloc(len * sizeof(int))) == NULL) { 13 | fprintf(stderr, "malloc failed: %s\n", strerror(errno)); 14 | exit(1); 15 | } 16 | 17 | for (i = 0; i < len; i++) 18 | p[i] = i; 19 | 20 | /* add m ints to end of p block */ 21 | if ((p = (int *) realloc(p, (len+extra) * sizeof(int))) == NULL) { 22 | fprintf(stderr, "realloc failed: %s\n", strerror(errno)); 23 | exit(1); 24 | } 25 | 26 | for (i = len; i < len+extra; i++) 27 | p[i] = i; 28 | 29 | /* print new array */ 30 | for (i = 0; i < len+extra; i++) 31 | printf("%d\n", p[i]); 32 | 33 | free(p); /* return p to available memory pool */ 34 | } 35 | 36 | int main() 37 | { 38 | foo(10, 15); 39 | } 40 | -------------------------------------------------------------------------------- /ipc/sem/sem_pv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Wait on a binary semaphore. 6 | Block until the semaphore value is positive, then 7 | decrement it by 1. */ 8 | int binary_semaphore_wait (int semid) 9 | { 10 | struct sembuf operations[1]; 11 | 12 | /* Use the first (and only) semaphore.*/ 13 | operations[0].sem_num = 0; 14 | 15 | /* Decrement by 1. */ 16 | operations[0].sem_op = -1; 17 | 18 | /* Permit undo’ing. */ 19 | operations[0].sem_flg = SEM_UNDO; 20 | return semop (semid, operations, 1); 21 | } 22 | 23 | /* Post to a binary semaphore: increment its value by 1. 24 | This returns immediately. */ 25 | int binary_semaphore_post (int semid) 26 | { 27 | struct sembuf operations[1]; 28 | 29 | /* Use the first (and only) semaphore.*/ 30 | operations[0].sem_num = 0; 31 | 32 | /* Increment by 1. */ 33 | operations[0].sem_op = 1; 34 | 35 | /* Permit undo’ing. */ 36 | operations[0].sem_flg = SEM_UNDO; 37 | 38 | return semop (semid, operations, 1); 39 | } 40 | -------------------------------------------------------------------------------- /c/long.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | In this program, the sizeof operator is used to find the size of int, long, long long, double and long double variables. 5 | As you can see, the size of long int and long double variables are larger than int and double variables, respectively. 6 | By the way, the sizeof operator returns size_t (unsigned integral type). 7 | The size_t data type is used to represent the size of an object. The format specifier used for size_t is %zu. 8 | 9 | Note: The long keyword cannot be used with float and char types. 10 | */ 11 | int main() { 12 | int a; 13 | long b; // equivalent to long int b; 14 | long long c; // equivalent to long long int c; 15 | double e; 16 | long double f; 17 | 18 | printf("Size of int = %zu bytes \n", sizeof(a)); 19 | printf("Size of long int = %zu bytes\n", sizeof(b)); 20 | printf("Size of long long int = %zu bytes\n", sizeof(c)); 21 | printf("Size of double = %zu bytes\n", sizeof(e)); 22 | printf("Size of long double = %zu bytes\n", sizeof(f)); 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /ipc/pipe/pipe_rd_wr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(void) 8 | { 9 | int fd[2], nbytes; 10 | pid_t childpid; 11 | char string[] = "Hello, world!\n"; 12 | char readbuffer[80]; 13 | 14 | pipe(fd); 15 | 16 | if ((childpid = fork()) == -1) { 17 | perror("fork"); 18 | exit(1); 19 | } 20 | 21 | if (childpid == 0) { 22 | 23 | /* Child process closes up input side of pipe */ 24 | close(fd[0]); 25 | 26 | /* Send "string" through the output side of pipe */ 27 | write(fd[1], string, (strlen(string)+1)); 28 | 29 | exit(0); 30 | } 31 | else { 32 | /* Parent process closes up output side of pipe */ 33 | close(fd[1]); 34 | 35 | /* Read in a string from the pipe */ 36 | nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); 37 | printf("Received string: %s", readbuffer); 38 | } 39 | 40 | return(0); 41 | } 42 | -------------------------------------------------------------------------------- /modules/hello-module/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * Get rid of the WARNING: modpost: missing MODULE_LICENSE() 6 | * by declaring code as GPL. 7 | */ 8 | MODULE_LICENSE("GPL"); 9 | 10 | int hello_init(void) 11 | { 12 | printk(KERN_INFO "Hola Mundo!\n"); 13 | return 0; 14 | } 15 | 16 | void hello_exit(void) 17 | { 18 | printk(KERN_INFO "Adios Mundo Cruel!\n"); 19 | } 20 | 21 | 22 | module_init(hello_init); 23 | module_exit(hello_exit); 24 | 25 | /* 26 | 27 | $ sudo insmode ./hello.ko 28 | 29 | $ cat /proc/modules | grep hello 30 | hello 16384 0 - Live 0x0000000000000000 (OE) 31 | 32 | $ kmod list | grep hello 33 | Module Size Used by 34 | hello 16384 0 35 | 36 | $ cat /var/log/syslog | grep Hola 37 | Nov 5 19:27:41 pablo kernel: [ 7353.271985] Hola Mundo! 38 | 39 | $ sudo rmod ./hello.ko 40 | 41 | $ cat /var/log/syslog | grep Adios 42 | Nov 5 19:51:52 pablo kernel: [ 8804.273746] Adios Mundo Cruel! 43 | 44 | # or ussing dmesg - print or control the kernel ring buffer 45 | $ dmesg -T 46 | */ 47 | -------------------------------------------------------------------------------- /gnu_linux_sw/better_sleep.c: -------------------------------------------------------------------------------- 1 | // Listing 8.8 (better_sleep.c) High-Precision Sleep Function 2 | 3 | /* 4 | show EINTR using 5 | int nanosleep(const struct timespec *req, struct timespec *rem); 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | int better_sleep (double sleep_time) 12 | { 13 | struct timespec tv; 14 | /* Construct the timespec from the number of whole seconds... */ 15 | tv.tv_sec = (time_t) sleep_time; 16 | /* ... and the remainder in nanoseconds. */ 17 | tv.tv_nsec = (long) ((sleep_time - tv.tv_sec) * 1e+9); 18 | 19 | while (1) { 20 | /* Sleep for the time specified in tv. If interrupted by a 21 | signal, place the remaining time left to sleep back into tv. 22 | */ 23 | int rval = nanosleep (&tv, &tv); 24 | 25 | if (rval == 0) 26 | /* Completed the entire sleep time; all done. */ 27 | return 0; 28 | 29 | else if (errno == EINTR) 30 | /* Interrupted by a signal. Try again. */ 31 | continue; 32 | 33 | else 34 | /* Some other error; bail out. */ 35 | return rval; 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /ipc/mmap/copy_on_write_shmat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Creating a copy-on-write mapped data file with the shmat subroutine 3 | */ 4 | 5 | #include 6 | 7 | if( ( fildes = open( filename , 2 ) ) < 0 ) 8 | { 9 | printf( "cannot open file\n" ); 10 | exit(1); 11 | } 12 | 13 | // Map the file to a segment as copy-on-write, with the shmat subroutine: 14 | // The SHM_COPY constant is defined in the /usr/include/sys/shm.h file. 15 | // This constant indicates that the file is a copy-on-write mapped file. 16 | // Include this header file and other shared memory header files in a program with the following directives: 17 | file_ptr = shmat( fildes, 0, SHM_COPY ); 18 | 19 | // Use file_ptr as a pointer to the start of the data file, and access the data as if it were in memory. 20 | while ( file_ptr < eof) 21 | { 22 | // . 23 | // . 24 | // . 25 | // (references to file using file_ptr) 26 | } 27 | 28 | // Use the fsync subroutine to write changes to the copy of the file on disk to save the changes: 29 | fsync( fildes ); 30 | 31 | // Close the file when the program is finished working with it: 32 | close( fildes ); -------------------------------------------------------------------------------- /modules/hello-module/Makefile: -------------------------------------------------------------------------------- 1 | # "kbuild" is the build system used by the Linux kernel. Modules must use 2 | # kbuild to stay compatible with changes in the build infrastructure and 3 | # to pick up the right flags to "gcc." 4 | 5 | # To build external modules, you must have a prebuilt kernel available 6 | # that contains the configuration and header files used in the build. 7 | # Also, the kernel must have been built with modules enabled. If you are 8 | # using a distribution kernel, there will be a package for the kernel you 9 | # are running provided by your distribution. 10 | 11 | # The kbuild system will build .o from .c, 12 | # and, after linking, will result in the kernel module .ko. 13 | obj-m := hello.o 14 | 15 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 16 | PWD := $(shell pwd) 17 | 18 | 19 | # modules 20 | # The default target for external modules. It has the 21 | # same functionality as if no target was specified. See 22 | # description above. 23 | default: 24 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 25 | 26 | # clean 27 | # Remove all generated files in the module directory onl 28 | clean: 29 | $(MAKE) -C $(KERNELDIR) M=$(PWD) clean 30 | -------------------------------------------------------------------------------- /gnu_toolchain/reciprocal/Makefile: -------------------------------------------------------------------------------- 1 | reciprocal: main.o reciprocal.o 2 | g++ $(CFLAGS) -o reciprocal main.o reciprocal.o 3 | 4 | main.o: main.c reciprocal.hpp 5 | gcc $(CFLAGS) -c main.c 6 | 7 | reciprocal.o: reciprocal.cpp reciprocal.hpp 8 | g++ $(CFLAGS) -c reciprocal.cpp 9 | # @g++ $(CFLAGS) -c reciprocal.cpp -> @ will silent the rule. 10 | 11 | clean: 12 | rm -f *.o reciprocal 13 | 14 | # The $(CFLAGS) is a make variable.You can define this variable either 15 | # in the Makefile itself or on the command line: 16 | # 17 | # % make CFLAGS=-O2 18 | # 19 | # Compile with debuging enabled: 20 | # % make CFLAGS=-g 21 | # 22 | # If you now change main.c in some trivial way and type make again, 23 | # you can see that make knew to rebuild main.o and to re-link the program, 24 | # but it didn’t bother to recompile reciprocal.cpp because none of the 25 | # dependencies for reciprocal.o had changed. 26 | # 27 | # 28 | # TAREA PARA EL ALUMNO 29 | # Suppose that your project has one directory called src, for source files, and another called include. 30 | # To indicate that g++ should use the ../include directory: 31 | # % g++ -c -I ../include reciprocal.cpp 32 | # The -I option tell GCC where to search for header files. 33 | 34 | 35 | -------------------------------------------------------------------------------- /ipc/mmap/mmap-read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define FILE_LENGTH 0x100 9 | 10 | // Read an Integer from a Memory-Mapped File, and Double It 11 | int main (int argc, char* const argv[]) 12 | { 13 | int fd; 14 | void* file_memory; 15 | int integer; 16 | 17 | /* Open the file. */ 18 | fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR); 19 | 20 | /* Create the memory mapping. */ 21 | file_memory = mmap (0, FILE_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 22 | close (fd); 23 | 24 | /* Read the integer, print it out, and double it. */ 25 | scanf (file_memory, “%d”, &integer); 26 | printf (“value: %d\n”, integer); 27 | sprintf ((char*) file_memory, “%d\n”, 2 * integer); 28 | 29 | /* Release the memory (unnecessary because the program exits).*/ 30 | munmap (file_memory, FILE_LENGTH); 31 | 32 | return 0; 33 | } 34 | 35 | /* 36 | Here’s an example of running these example programs. It maps the file 37 | /tmp/integer-file . 38 | 39 | % ./mmap-write /tmp/integer-file 40 | % cat /tmp/integer-file 41 | 42 42 | % ./mmap-read /tmp/integer-file 43 | value: 42 44 | % cat /tmp/integer-file 45 | 84 46 | */ 47 | -------------------------------------------------------------------------------- /processes/wait.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int spawn (char* program, char** arg_list) 8 | { 9 | pid_t child_pid; 10 | 11 | /* Duplicate this process. */ 12 | child_pid = fork (); 13 | 14 | if (child_pid != 0) { 15 | return child_pid; 16 | } 17 | else { 18 | execvp (program, arg_list); 19 | 20 | /* returns only if an error occurs. */ 21 | fprintf (stderr, "an error occurred in execvp\n"); 22 | abort (); 23 | } 24 | } 25 | 26 | int main () 27 | { 28 | int child_status; 29 | /* The argument list to pass to the “ls” command. */ 30 | 31 | char* arg_list[] = { 32 | "ls", /* argv[0], the name of the program. */ 33 | "-l", 34 | "/", 35 | NULL /* The argument list must end with a NULL. */ 36 | }; 37 | 38 | /* Spawn a child process running the “ls” command. Ignore the 39 | returned child process ID. */ 40 | spawn("ls", arg_list); 41 | 42 | /* Wait for the child process to complete. */ 43 | wait(&child_status); 44 | 45 | if (WIFEXITED (child_status)) 46 | printf ("the child process exited normally, with exit code %d\n", 47 | WEXITSTATUS (child_status)); 48 | else 49 | printf ("the child process exited abnormally\n"); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /ipc/mmap/mmap-write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define FILE_LENGTH 0x100 10 | 11 | /* Return a uniformly random number in the range [low,high]. 12 | */ 13 | int random_range (unsigned const low, unsigned const high) 14 | { 15 | unsigned const range = high - low + 1; 16 | 17 | return low + (int) (((double) range) * rand () / (RAND_MAX + 1.0)); 18 | } 19 | 20 | int main (int argc, char* const argv[]) 21 | { 22 | int fd; 23 | void* file_memory; 24 | 25 | /* Seed the random number generator.*/ 26 | srand (time (NULL)); 27 | 28 | /* Prepare a file large enough to hold an unsigned integer.*/ 29 | fd = open (argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 30 | lseek (fd, FILE_LENGTH+1, SEEK_SET); 31 | write (fd, "", 1); 32 | lseek (fd, 0, SEEK_SET); 33 | 34 | /* Create the memory mapping. */ 35 | file_memory = mmap (0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0); 36 | close (fd); 37 | 38 | /* Write a random integer to memory-mapped area. */ 39 | sprintf((char*) file_memory, "%d\n", random_range (-100, 100)); 40 | 41 | /* Release the memory (unnecessary because the program exits). */ 42 | munmap (file_memory, FILE_LENGTH); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /c/str/string_sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Sort Strings in Dictionary Order 6 | ++++++++++++++++++++++++++++++++ 7 | 8 | Code a program that sorts N strings (entered by the user) 9 | in lexicographical order (dictionary order). 10 | 11 | Example Output: 12 | -------------- 13 | 14 | Enter 10 words: 15 | C 16 | C++ 17 | Java 18 | PHP 19 | Python 20 | Perl 21 | Ruby 22 | R 23 | JavaScript 24 | PHP 25 | 26 | In lexicographical order: 27 | C 28 | C++ 29 | Java 30 | JavaScript 31 | PHP 32 | PHP 33 | Perl 34 | Python 35 | R 36 | Ruby 37 | 38 | */ 39 | 40 | int main() 41 | { 42 | int i, j; 43 | char str[10][50], temp[50]; 44 | 45 | printf("Enter 10 words:\n"); 46 | 47 | for(i=0; i<10; ++i) { 48 | scanf("%s[^\n]", str[i]); 49 | } 50 | 51 | for (i=0; i<9; ++i) { 52 | for (j=i+1; j<10 ; ++j) { 53 | if (strcmp(str[i], str[j])>0) { 54 | strcpy(temp, str[i]); 55 | strcpy(str[i], str[j]); 56 | strcpy(str[j], temp); 57 | } 58 | } 59 | } 60 | 61 | printf("\nIn lexicographical order: \n"); 62 | for (i=0; i<10; ++i) { 63 | puts(str[i]); // printf("%s\n", str[i]); 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /c/delta_time.c: -------------------------------------------------------------------------------- 1 | /* Program to measure time taken by a function */ 2 | #include 3 | #include 4 | 5 | /*A function that terminates when enter key is pressed*/ 6 | void critical_function() 7 | { 8 | printf("critical_function() starts \n"); 9 | printf("Press enter to stop critical_function \n"); 10 | while (1) { 11 | printf("Press\n"); 12 | if (getchar()) 13 | break; 14 | } 15 | printf("critical_function() ends \n"); 16 | } 17 | 18 | /*The main program calls critical_function() and measures time taken by critical_function()*/ 19 | int main() 20 | { 21 | // Calculate the time taken by critical_function() 22 | clock_t t; 23 | t = clock(); 24 | critical_function(); 25 | clock_t dt = clock() - t; 26 | 27 | /* 28 | * Clock ticks per second 29 | * This macro expands to an expression representing the number of clock ticks per second. 30 | * Clock ticks are units of time of a constant but system-specific length, as those returned by function clock. 31 | * Dividing a count of clock ticks by this expression yields the number of seconds. 32 | */ 33 | double time_taken_sec = ((double)dt)/CLOCKS_PER_SEC; 34 | 35 | printf("CLOCKS_PER_SEC %ld \n", CLOCKS_PER_SEC); 36 | printf("critical_function() took %f seconds to execute \n", time_taken_sec); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /gnu_toolchain/reciprocal/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | warning: implicit declaration of function ‘atoi’ [-Wimplicit-function-declaration] 5 | 9 | i = atoi(argv[1]); 6 | | ^~~~ 7 | */ 8 | #include 9 | 10 | #include "reciprocal.hpp" 11 | 12 | /* 13 | * Compute the reciprocal of an integer 14 | * 15 | * Project with one C++ source file (reciprocal.cpp) 16 | * and one C source file (main.c). 17 | * These two files are supposed to be compiled and then 18 | * linked together to produce a program called reciprocal. 19 | */ 20 | int main (int argc, char **argv) 21 | { 22 | 23 | /* 24 | if (argc < 2) { 25 | fprintf(stderr, "Usage: %s str [base]\n", argv[0]); 26 | exit(EXIT_FAILURE); 27 | } 28 | */ 29 | 30 | int j; 31 | j = atoi(argv[1]); 32 | printf("The reciprocal of %d is %g\n", j, reciprocal(j)); 33 | 34 | return 0; 35 | } 36 | 37 | 38 | /* 39 | Bugs 40 | 41 | 1) no arg1 42 | ---------- 43 | 44 | ./reciprocal 45 | Segmentation fault (core dumped) 46 | 47 | Fix 48 | --- 49 | if (argc < 2) { 50 | fprintf(stderr, "Usage: %s str [base]\n", argv[0]); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | 2) arg1 is 0 55 | ------------ 56 | 57 | ./reciprocal 0 58 | reciprocal: reciprocal.cpp:7: double reciprocal(int): Assertion `i != 0' failed. 59 | Aborted (core dumped) 60 | 61 | */ -------------------------------------------------------------------------------- /c/makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | #CFLAGS = -Wall -pedantic -g -Werror 3 | STRUCT = struct 4 | STR = str 5 | 6 | all: ascii delta_time padding_example printable square car multiplebitfield threebitfield frequency gets_puts str_upper string_sort strlen 7 | 8 | ascii: 9 | $(CC) $@.c -o $@ 10 | 11 | delta_time: 12 | $(CC) $@.c -o $@ 13 | 14 | padding_example: 15 | $(CC) $(STRUCT)/$@.c -o $(STRUCT)/$@ 16 | 17 | printable: 18 | $(CC) $@.c -o $@ 19 | 20 | square: 21 | $(CC) $@.c -lm -o $@ 22 | 23 | car: 24 | $(CC) $(STRUCT)/$@.c -o $(STRUCT)/$@ 25 | 26 | multiplebitfield: 27 | $(CC) $(STRUCT)/$@.c -o $(STRUCT)/$@ 28 | 29 | threebitfield: 30 | $(CC) $(STRUCT)/$@.c -o $(STRUCT)/$@ 31 | 32 | frequency: 33 | $(CC) $(STR)/$@.c -o $(STR)/$@ 34 | 35 | gets_puts: 36 | $(CC) $(STR)/$@.c -o $(STR)/$@ 37 | 38 | #printf: 39 | # $(CC) $(STR)/$@.c -o $(STR)/$@ 40 | 41 | str_upper: 42 | $(CC) $(STR)/$@.c -o $(STR)/$@ 43 | 44 | string_sort: 45 | $(CC) $(STR)/$@.c -o $(STR)/$@ 46 | 47 | strlen: 48 | $(CC) $(STR)/$@.c -o $(STR)/$@ 49 | 50 | #$(STRUCT)_with_flexible_array: 51 | # $(CC) $(STRUCT)/$@.c -o $(STRUCT)/$@ 52 | 53 | #volatile: 54 | # $(CC) $@.c -o $@ 55 | 56 | clean: 57 | rm -rf ascii delta_time padding_example printable square $(STRUCT)/car $(STRUCT)/multiplebitfield $(STRUCT)/threebitfield $(STRUCT)/padding_example $(STR)/frequency $(STR)/gets_puts $(STR)/printf $(STR)/str_upper $(STR)/string_sort $(STR)/strlen 58 | -------------------------------------------------------------------------------- /memory/sbrk/get_num.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************\ 2 | * Copyright (C) Michael Kerrisk, 2020. * 3 | * * 4 | * This program is free software. You may use, modify, and redistribute it * 5 | * under the terms of the GNU Lesser General Public License as published * 6 | * by the Free Software Foundation, either version 3 or (at your option) * 7 | * any later version. This program is distributed without any warranty. * 8 | * See the files COPYING.lgpl-v3 and COPYING.gpl-v3 for details. * 9 | \*************************************************************************/ 10 | 11 | /* get_num.h 12 | 13 | Header file for get_num.c. 14 | */ 15 | #ifndef GET_NUM_H 16 | #define GET_NUM_H 17 | 18 | #define GN_NONNEG 01 /* Value must be >= 0 */ 19 | #define GN_GT_0 02 /* Value must be > 0 */ 20 | 21 | /* By default, integers are decimal */ 22 | #define GN_ANY_BASE 0100 /* Can use any base - like strtol(3) */ 23 | #define GN_BASE_8 0200 /* Value is expressed in octal */ 24 | #define GN_BASE_16 0400 /* Value is expressed in hexadecimal */ 25 | 26 | long getLong(const char *arg, int flags, const char *name); 27 | 28 | int getInt(const char *arg, int flags, const char *name); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /ipc/shm/shm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main () 6 | { 7 | int segment_id; 8 | char* shared_memory; 9 | struct shmid_ds shmbuffer; 10 | int segment_size; 11 | const int shared_segment_size = 0x6400; 12 | 13 | /* Allocate a shared memory segment. */ 14 | segment_id = shmget (IPC_PRIVATE, shared_segment_size, 15 | IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 16 | 17 | /* Attach the shared memory segment. */ 18 | shared_memory = (char*) shmat (segment_id, 0, 0); 19 | printf ("shared memory attached at address %p\n", shared_memory); 20 | 21 | /* Determine the segment’s size. */ 22 | shmctl (segment_id, IPC_STAT, &shmbuffer); 23 | segment_size = shmbuffer.shm_segsz; 24 | printf ("segment size: %d\n", segment_size); 25 | 26 | /* Write a string to the shared memory segment. */ 27 | sprintf (shared_memory, "Hello, world."); 28 | 29 | /* Detach the shared memory segment. */ 30 | shmdt (shared_memory); 31 | 32 | /* Reattach the shared memory segment, at a different address. */ 33 | shared_memory = (char*) shmat (segment_id, (void*) 0x5000000, 0); 34 | printf ("shared memory reattached at address %p\n", shared_memory); 35 | 36 | /* Print out the string from shared memory. */ 37 | printf ("%s\n", shared_memory); 38 | 39 | /* Detach the shared memory segment. */ 40 | shmdt (shared_memory); 41 | 42 | /* Deallocate the shared memory segment.*/ 43 | shmctl (segment_id, IPC_RMID, 0); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /ipc/pipe/dup2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Redirect Output from a Pipe with dup2 7 | int main () 8 | { 9 | int fds[2]; 10 | pid_t pid; 11 | 12 | /* Create a pipe. 13 | File descriptors for the two ends of the pipe are 14 | placed in fds. */ 15 | pipe (fds); 16 | 17 | /* Fork a child process. */ 18 | pid = fork (); 19 | 20 | if (pid == (pid_t) 0) { 21 | 22 | /* This is the child process. Close our copy of the write end of 23 | the file descriptor. */ close (fds[1]); 24 | 25 | /* Connect the read end of the pipe to standard input. */ 26 | dup2 (fds[0], STDIN_FILENO); 27 | 28 | /* Replace the child process with the “sort” program. */ 29 | execlp ("sort", "sort", (char *) NULL); 30 | } 31 | else { 32 | /* This is the parent process. */ 33 | FILE* stream; 34 | 35 | /* Close our copy of the read end of the file descriptor. */ 36 | close (fds[0]); 37 | 38 | /* Convert the write file descriptor to a FILE object, and write 39 | to it. */ 40 | stream = fdopen (fds[1], "w"); 41 | 42 | fprintf (stream, "This is a test.\n"); 43 | fprintf (stream, "Hello, world.\n"); 44 | fprintf (stream, "My dog has fleas.\n"); 45 | fprintf (stream, "This program is great.\n"); 46 | fprintf (stream, "One fish, two fish.\n"); 47 | fflush (stream); 48 | 49 | close (fds[1]); 50 | 51 | /* Wait for the child process to finish. */ 52 | waitpid (pid, NULL, 0); 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /gnu_toolchain/libs/demo.sh: -------------------------------------------------------------------------------- 1 | # create objects 2 | gcc -c test1.c 3 | gcc -c test2.c 4 | gcc -c app.c 5 | 6 | # create lib 7 | ar cr libtest.a test1.o test2.o 8 | 9 | # list files in library 10 | ar -t libtest.a 11 | # test1.o 12 | # test2.o 13 | 14 | # BAD ORDER, link against the lib 15 | gcc -o app -L. -ltest app.o 16 | 17 | # NO location option 18 | gcc -o app app.o -ltest 19 | # /usr/bin/ld: cannot find -ltest 20 | # collect2: error: ld returned 1 exit status 21 | 22 | # link against the lib 23 | gcc -o app app.o -L. -ltest 24 | 25 | # run and check result 26 | ./app 27 | echo $? 28 | 29 | # Inspecting Symbols 30 | # ------------------ 31 | nm app.o 32 | # U f 33 | # U g 34 | # U _GLOBAL_OFFSET_TABLE_ 35 | # 0000000000000000 T main 36 | nm libtest.a 37 | # test1.o: 38 | # 0000000000000000 T f 39 | # test2.o: 40 | # 0000000000000000 T g 41 | 42 | nm app | grep -n -E -w "g|f" 43 | # -n print line numbers 44 | # -E To use a Regular Expression (g or f function) 45 | # -w match entire words only 46 | 47 | # MORE INFO 48 | # --------- 49 | 50 | # About _GLOBAL_OFFSET_TABLE_ 51 | # https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_zSeries/x2251.html 52 | 53 | # About grep 54 | https://phoenixnap.com/kb/grep-command-linux-unix-examples 55 | 56 | # list dynamic dependencies 57 | ldd app 58 | # linux-vdso.so.1 (0x00007ffc261ed000) 59 | # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6a7b2e8000) 60 | # /lib64/ld-linux-x86-64.so.2 (0x00007f6a7b4fa000) 61 | -------------------------------------------------------------------------------- /ipc/socket/socket-client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* Write TEXT to the socket given by file descriptor SOCKET_FD. 8 | */ 9 | void write_text (int socket_fd, const char* text) 10 | { 11 | /* Write the number of bytes in the string, including 12 | NUL-termination. */ 13 | int length = strlen (text) + 1; 14 | write (socket_fd, &length, sizeof (length)); 15 | 16 | /* Write the string. */ 17 | write (socket_fd, text, length); 18 | } 19 | 20 | int main (int argc, char* const argv[]) 21 | { 22 | const char* const socket_name = argv[1]; 23 | const char* const message = argv[2]; 24 | 25 | int socket_fd; 26 | struct sockaddr_un name; 27 | 28 | /* Create the socket. */ 29 | socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); 30 | 31 | /* Store the server’s name in the socket address. */ 32 | name.sun_family = AF_LOCAL; 33 | strcpy (name.sun_path, socket_name); 34 | 35 | /* Connect the socket. */ 36 | connect (socket_fd, &name, SUN_LEN (&name)); 37 | 38 | /* Write the text on the command line to the socket. */ 39 | write_text (socket_fd, message); 40 | close (socket_fd); 41 | 42 | return 0; 43 | } 44 | 45 | /* 46 | To try this example, start the server program in one window. 47 | Specify a path to a socket—for example, /tmp/socket . 48 | 49 | % ./socket-server /tmp/socket 50 | 51 | In another window, run the client a few times, specifying the same socket path plus 52 | messages to send to the client: 53 | 54 | % ./socket-client /tmp/socket “Hello, world.” 55 | % ./socket-client /tmp/socket “This is a test.”5.5 56 | 57 | The server program receives and prints these messages. 58 | 59 | To close the server, send the message “quit” from a client: 60 | 61 | % ./socket-client /tmp/socket “quit” 62 | 63 | The server program terminates. 64 | */ 65 | -------------------------------------------------------------------------------- /c/str/printf.c: -------------------------------------------------------------------------------- 1 | // To print Pi to five decimal places: 2 | 3 | #include 4 | #include 5 | fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0)); 6 | 7 | // To print a date and time in the form "Sunday, July 3, 10:02", where 8 | // weekday and month are pointers to strings: 9 | 10 | #include 11 | fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min); 12 | 13 | // Many countries use the day-month-year order. Hence, an international‐ 14 | // ized version must be able to print the arguments in an order specified 15 | // by the format: 16 | 17 | #include 18 | fprintf(stdout, format, 19 | weekday, month, day, hour, min); 20 | 21 | // where format depends on locale, and may permute the arguments. With 22 | // the value: 23 | 24 | // "%1$s, %3$d. %2$s, %4$d:%5$.2d\n" 25 | 26 | // one might obtain "Sonntag, 3. Juli, 10:02". 27 | 28 | // To allocate a sufficiently large string and print into it (code correct 29 | // for both glibc 2.0 and glibc 2.1): 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | char * 36 | make_message(const char *fmt, ...) 37 | { 38 | int size = 0; 39 | char *p = NULL; 40 | va_list ap; 41 | 42 | /* Determine required size */ 43 | 44 | va_start(ap, fmt); 45 | size = vsnprintf(p, size, fmt, ap); 46 | va_end(ap); 47 | 48 | if (size < 0) 49 | return NULL; 50 | 51 | size++; /* For '\0' */ 52 | p = malloc(size); 53 | if (p == NULL) 54 | return NULL; 55 | 56 | va_start(ap, fmt); 57 | size = vsnprintf(p, size, fmt, ap); 58 | va_end(ap); 59 | 60 | if (size < 0) { 61 | free(p); 62 | return NULL; 63 | } 64 | 65 | return p; 66 | } 67 | 68 | // If truncation occurs in glibc versions prior to 2.0.6, this is treated 69 | // as an error instead of being handled gracefully. 70 | -------------------------------------------------------------------------------- /gnu_linux_sw/readfile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include // For printf(), perror() 7 | 8 | char* read_from_file(const char* filename, size_t length) { 9 | char* buffer; 10 | int fd; 11 | ssize_t bytes_read; 12 | 13 | /* Allocate the buffer. */ 14 | buffer = (char*) malloc(length + 1); // +1 for the null terminator 15 | if (buffer == NULL) { 16 | perror("Failed to allocate buffer"); 17 | return NULL; 18 | } 19 | 20 | /* Open the file. */ 21 | fd = open(filename, O_RDONLY); 22 | if (fd == -1) { 23 | /* open failed. Deallocate buffer before returning. */ 24 | perror("Failed to open file"); 25 | free(buffer); 26 | return NULL; 27 | } 28 | 29 | /* Read the data. */ 30 | bytes_read = read(fd, buffer, length); 31 | if (bytes_read == -1) { 32 | /* read failed. Deallocate buffer and close fd before returning. */ 33 | perror("Failed to read file"); 34 | free(buffer); 35 | close(fd); 36 | return NULL; 37 | } 38 | 39 | /* Ensure null termination for string operations. */ 40 | buffer[bytes_read] = '\0'; 41 | 42 | /* Close the file. */ 43 | close(fd); 44 | 45 | return buffer; 46 | } 47 | 48 | int main(int argc, char* argv[]) { 49 | const char* filename = "/proc/cpuinfo"; // Use a valid file path 50 | size_t length = 150; // Adjust buffer size for demonstration 51 | 52 | /* Read from file */ 53 | char* content = read_from_file(filename, length); 54 | if (content == NULL) { 55 | fprintf(stderr, "Error reading from file\n"); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | /* Print the content */ 60 | printf("File content:\n%s\n", content); 61 | 62 | /* Free the allocated buffer */ 63 | free(content); 64 | 65 | return EXIT_SUCCESS; 66 | } 67 | -------------------------------------------------------------------------------- /processes/making_zombie.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Making a Zombie Process 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int main () 10 | { 11 | pid_t child_pid; 12 | 13 | /* Create a child process. */ 14 | child_pid = fork (); 15 | 16 | if (child_pid > 0) { 17 | /* This is the parent process. Sleep for a minute. */ 18 | sleep (60); 19 | } 20 | 21 | else { 22 | /* This is the child process. Exit immediately. */ 23 | exit (0); 24 | } 25 | 26 | return 0; 27 | } 28 | 29 | 30 | /* 31 | 32 | $ ps -A | grep a.out 33 | 8135 pts/1 00:00:00 a.out 34 | 8136 pts/1 00:00:00 a.out 35 | 36 | # ..process finish.. 37 | 38 | $ ps -A | grep a.out 39 | $ 40 | 41 | */ 42 | 43 | /* 44 | Run it, and while it’s still running, list the processes on the system by invoking the following command in another window: 45 | ps -e -o pid,ppid,stat,cmd 46 | 47 | PROCESS STATE CODES 48 | Z defunct ("zombie") process, terminated but not reaped by its parent 49 | 50 | $ ps -e -o pid,ppid,stat,cmd | grep a.out 51 | 8381 4055 S+ ./a.out 52 | 8382 8381 Z+ [a.out] 53 | 54 | 55 | */ 56 | 57 | /* 58 | You cannot kill a zombie 59 | 60 | $ ps -e -o pid,ppid,stat,cmd | grep a.out 61 | 8422 4055 S+ ./a.out 62 | 8423 8422 Z+ [a.out] 63 | 8428 3996 S+ grep --color=auto a.out 64 | 65 | # try to kill the zombie 66 | $ kill -9 8423 67 | $ ps -e -o pid,ppid,stat,cmd | grep a.out 68 | 8422 4055 S+ ./a.out 69 | 8423 8422 Z+ [a.out] 70 | 8430 3996 S+ grep --color=auto a.out 71 | */ 72 | 73 | /* Kill the parent 74 | 75 | The zombie gets clean by init 76 | 77 | $ ps -e -o pid,ppid,stat,cmd | grep a.out 78 | 8465 4055 S+ ./a.out 79 | 8466 8465 Z+ [a.out] 80 | 8468 3996 S+ grep --color=auto a.out 81 | 82 | $ kill -9 8465 83 | $ ps -e -o pid,ppid,stat,cmd | grep a.out 84 | 8483 3996 S+ grep --color=auto a.out 85 | 86 | */ 87 | -------------------------------------------------------------------------------- /memory/sbrk/free_and_sbrk.c: -------------------------------------------------------------------------------- 1 | /* free_and_sbrk.c 2 | + 3 | + Test if free(3) actually lowers the program break. 4 | + 5 | + Demonstrate what happens to the program break when memory is freed. 6 | + 7 | + 8 | + Usage: free_and_sbrk num-allocs block-size [step [min [max]]] 9 | + 10 | + Try: free_and_sbrk 1000 10240 2 1 1000 11 | + free_and_sbrk 1000 10240 1 1 999 12 | + free_and_sbrk 1000 10240 1 500 1000 13 | + 14 | + (Only the last of these should see the program break lowered.) 15 | +*/ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define MAX_ALLOCS 1000000 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | char *ptr[MAX_ALLOCS]; 28 | int freeStep, freeMin, freeMax, blockSize, numAllocs, j; 29 | 30 | printf("\n"); 31 | 32 | if (argc < 3 || strcmp(argv[1], "--help") == 0) 33 | usageErr("%s num-allocs block-size [step [min [max]]]\n", argv[0]); 34 | 35 | numAllocs = getInt(argv[1], GN_GT_0, "num-allocs"); 36 | if (numAllocs > MAX_ALLOCS) 37 | cmdLineErr("num-allocs > %d\n", MAX_ALLOCS); 38 | 39 | blockSize = getInt(argv[2], GN_GT_0 | GN_ANY_BASE, "block-size"); 40 | 41 | freeStep = (argc > 3) ? getInt(argv[3], GN_GT_0, "step") : 1; 42 | freeMin = (argc > 4) ? getInt(argv[4], GN_GT_0, "min") : 1; 43 | freeMax = (argc > 5) ? getInt(argv[5], GN_GT_0, "max") : numAllocs; 44 | 45 | if (freeMax > numAllocs) 46 | cmdLineErr("free-max > num-allocs\n"); 47 | 48 | printf("Initial program break: %10p\n", sbrk(0)); 49 | 50 | printf("Allocating %d*%d bytes\n", numAllocs, blockSize); 51 | 52 | for (j = 0; j < numAllocs; j++) { 53 | ptr[j] = malloc(blockSize); 54 | if (ptr[j] == NULL) 55 | perror("malloc"); 56 | } 57 | 58 | printf("Program break is now: %10p\n", sbrk(0)); 59 | 60 | printf("Freeing blocks from %d to %d in steps of %d\n", 61 | freeMin, freeMax, freeStep); 62 | for (j = freeMin - 1; j < freeMax; j += freeStep) 63 | free(ptr[j]); 64 | 65 | printf("After free(), program break is: %10p\n", sbrk(0)); 66 | 67 | exit(EXIT_SUCCESS); 68 | } 69 | -------------------------------------------------------------------------------- /ipc/pipe/pipe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Write COUNT copies of MESSAGE to STREAM, pausing for a second 6 | between each. */ 7 | void writer(const char* message, int count, FILE* stream) 8 | { 9 | for (; count > 0; --count) { 10 | 11 | /* Write the message to the stream, and send it off immediately.*/ 12 | fprintf (stream, "%s\n", message); 13 | fflush (stream); 14 | 15 | /* Snooze a while. */ 16 | sleep (1); 17 | } 18 | } 19 | 20 | /* Read random strings from the stream as long as possible.*/ 21 | void reader(FILE* stream) 22 | { 23 | char buffer[1024]; 24 | 25 | /* Read until we hit the end of the stream. fgets reads until 26 | either a newline or the end-of-file. */ 27 | while (!feof (stream) 28 | && !ferror (stream) 29 | && fgets (buffer, sizeof (buffer), stream) != NULL) 30 | fputs (buffer, stdout); 31 | } 32 | 33 | // Listing 5.7 (pipe.c) Using a Pipe to Communicate with a Child Process 34 | int main () 35 | { 36 | int fds[2]; 37 | pid_t pid; 38 | 39 | /* Create a pipe. 40 | File descriptors for the two ends of the pipe are 41 | placed in fds. */ 42 | pipe (fds); 43 | 44 | /* Fork a child process. */ 45 | pid = fork (); 46 | 47 | if (pid == (pid_t) 0) { 48 | FILE* stream; 49 | 50 | /* This is the child process. Close our copy of the write end of 51 | the file descriptor. */ 52 | close (fds[1]); 53 | 54 | /* Convert the read file descriptor to a FILE object, and read 55 | from it. */ 56 | stream = fdopen (fds[0], "r"); 57 | reader (stream); 58 | close (fds[0]); 59 | } 60 | else { 61 | /* This is the parent process. */ 62 | FILE* stream; 63 | 64 | /* Close our copy of the read end of the file descriptor. */ 65 | close (fds[0]); 66 | 67 | /* Convert the write file descriptor to a FILE object, and write 68 | to it. */ 69 | stream = fdopen (fds[1], "w"); 70 | writer ("Hello, world.", 5, stream); 71 | close (fds[1]); 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /gnu_toolchain/tiff/tifftest.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Using libtiff 3 | * Small program that uses libtiff to open a TIFF image file 4 | * 5 | * First install the lib: 6 | * $ sudo apt install libtiff-dev 7 | * 8 | * Then, you can check the manual: 9 | * $ man libtiff 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | int main (int argc, char** argv) 17 | { 18 | TIFF* tiff; 19 | tiff = TIFFOpen (argv[1], "r"); 20 | TIFFClose (tiff); 21 | 22 | return 0; 23 | } 24 | 25 | /* 26 | $ ldd a.out 27 | linux-vdso.so.1 (0x00007ffdee17b000) 28 | libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5 (0x00007fc834b8a000) 29 | libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc834998000) 30 | libwebp.so.6 => /usr/lib/x86_64-linux-gnu/libwebp.so.6 (0x00007fc83472f000) 31 | libzstd.so.1 => /usr/lib/x86_64-linux-gnu/libzstd.so.1 (0x00007fc834686000) 32 | liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007fc83465d000) 33 | libjbig.so.0 => /usr/lib/x86_64-linux-gnu/libjbig.so.0 (0x00007fc83444f000) 34 | libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007fc8343c8000) 35 | libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc8343ac000) 36 | libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc83425d000) 37 | /lib64/ld-linux-x86-64.so.2 (0x00007fc834c2b000) 38 | libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc83423a000) 39 | */ 40 | 41 | // (base) pablo@pablo:~/so1/clases/2_gnu_toolchain/examples/tiff$ gcc tifftest.c 42 | // tifftest.c: In function ‘main’: 43 | // tifftest.c:18:2: error: unknown type name ‘TIFF’ 44 | // 18 | TIFF* tiff; 45 | // | ^~~~ 46 | // tifftest.c:19:9: warning: implicit declaration of function ‘TIFFOpen’ [-Wimplicit-function-declaration] 47 | // 19 | tiff = TIFFOpen (argv[1], "r"); 48 | // | ^~~~~~~~ 49 | // tifftest.c:19:7: warning: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion] 50 | // 19 | tiff = TIFFOpen (argv[1], "r"); 51 | // | ^ 52 | // tifftest.c:20:2: warning: implicit declaration of function ‘TIFFClose’ [-Wimplicit-function-declaration] 53 | // 20 | TIFFClose (tiff); 54 | // | ^~~~~~~~~ 55 | 56 | // link against libtiff.so 57 | // tiff$ gcc tifftest.c -ltiff 58 | -------------------------------------------------------------------------------- /bash/README_hello_linux.md: -------------------------------------------------------------------------------- 1 | ## Bash Script Creation Guide 2 | 3 | Create a simple bash script that outputs a greeting along with the operating system's name. 4 | 5 | ### Steps to Create the Bash Script 6 | 7 | 1. **Open the Terminal:** 8 | - Open your terminal by searching for "Terminal" in your applications menu or by pressing `Ctrl + Alt + T` (Linux) or `Cmd + Space` and typing "Terminal" (macOS). 9 | 10 | 2. **Navigate to the Desired Directory:** 11 | - Use the `cd` command to navigate to the directory where you want to create the script. For example: 12 | ```bash 13 | cd ~/Desktop 14 | ``` 15 | 16 | 3. **Create a New File:** 17 | - Create a new file using the `touch` command or a text editor like `nano`. To create a file named `hello_linux.sh`, run: 18 | ```bash 19 | touch hello_linux.sh 20 | ``` 21 | - Alternatively, open the file directly in a text editor: 22 | ```bash 23 | nano hello_linux.sh 24 | ``` 25 | 26 | 4. **Write the Script:** 27 | - Open the file in a text editor (`nano`, `vim`, etc.) and add the following lines: 28 | ```bash 29 | #!/bin/bash 30 | os_name=$(uname -o) 31 | echo "Hello $os_name!" 32 | ``` 33 | - **Shebang (`#!/bin/bash`)**: The first line of the script that specifies which shell to use for executing the script. 34 | 35 | 36 | 5. **Save and Exit the Editor:** 37 | - In `nano`, press `Ctrl + O` to save the file, then press `Enter` to confirm. After saving, press `Ctrl + X` to exit the editor. 38 | 39 | 6. **Make the Script Executable:** 40 | - Change the file permissions to make the script executable by using the `chmod` command: 41 | ```bash 42 | chmod +x hello_linux.sh 43 | ``` 44 | 45 | 7. **Run the Script:** 46 | - Run the script by typing: 47 | ```bash 48 | ./hello_linux.sh 49 | ``` 50 | 51 | 8. **View the Output:** 52 | - After running the script, you should see an output like: 53 | ``` 54 | Hello GNU/Linux! 55 | ``` 56 | - The output will vary depending on the operating system you are using. 57 | 58 | 59 | ### Conclusion 60 | 61 | By following these steps, you can create, edit, and execute a simple bash script on your system. This exercise helps in understanding basic shell scripting and terminal commands. 62 | -------------------------------------------------------------------------------- /ipc/socket/socket-server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* Read text from the socket and print it out. Continue until the 9 | socket closes. Return nonzero if the client sent a “quit” 10 | message, zero otherwise. */ 11 | int server (int client_socket) 12 | { 13 | while (1) { 14 | int length; 15 | char* text; 16 | 17 | /* First, read the length of the text message from the socket. 18 | read returns zero, the client closed the connection. */ 19 | if (read (client_socket, &length, sizeof (length)) == 0) 20 | return 0; 21 | 22 | /* Allocate a buffer to hold the text. */ 23 | text = (char*) malloc (length); 24 | 25 | /* Read the text itself, and print it. */ 26 | read (client_socket, text, length); 27 | printf (“%s\n”, text); 28 | 29 | /* Free the buffer. */ 30 | free (text); 31 | 32 | /* If the client sent the message “quit,” we’re all done.*/ 33 | if (!strcmp (text, “quit”)) 34 | return 1; 35 | } 36 | } 37 | 38 | int main (int argc, char* const argv[]) 39 | { 40 | const char* const socket_name = argv[1]; 41 | int socket_fd; 42 | struct sockaddr_un name; 43 | int client_sent_quit_message; 44 | 45 | /* Create the socket. */ 46 | socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); 47 | 48 | /* Indicate that this is a server. */ 49 | name.sun_family = AF_LOCAL; 50 | strcpy (name.sun_path, socket_name); 51 | bind (socket_fd, &name, SUN_LEN (&name)); 52 | 53 | /* Listen for connections. */ 54 | listen (socket_fd, 5); 55 | 56 | /* Repeatedly accept connections, spinning off one server() to deal 57 | with each client. Continue until a client sends a “quit” message.*/ 58 | do { 59 | struct sockaddr_un client_name; 60 | socklen_t client_name_len; 61 | int client_socket_fd; 62 | 63 | /* Accept a connection. */ 64 | client_socket_fd = accept (socket_fd, &client_name, &client_name_len); 65 | 66 | /* Handle the connection. */ 67 | client_sent_quit_message = server (client_socket_fd); 68 | 69 | /* Close our end of the connection. */ 70 | close (client_socket_fd); 71 | } 72 | while (!client_sent_quit_message); 73 | 74 | /* Remove the socket file.*/ 75 | close (socket_fd); 76 | unlink (socket_name); 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /ipc/socket/socket-inet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* Print the contents of the home page for the server’s socket. 10 | Return an indication of success. */ 11 | void get_home_page (int socket_fd) 12 | { 13 | char buffer[10000]; 14 | ssize_t number_characters_read; 15 | 16 | /* Send the HTTP GET command for the home page. */ 17 | sprintf (buffer, “GET /\n”); 18 | write (socket_fd, buffer, strlen (buffer)); 19 | 20 | /* Read from the socket. The call to read may not 21 | return all the data at one time, so keep 22 | trying until we run out. */ 23 | while (1) { 24 | number_characters_read = read (socket_fd, buffer, 10000); 25 | if (number_characters_read == 0) 26 | return; 27 | 28 | /* Write the data to standard output. */ 29 | fwrite (buffer, sizeof (char), number_characters_read, stdout); 30 | } 31 | } 32 | /* 33 | This program takes the hostname of the Web server on the command line (not a 34 | URL—that is, without the “http://”). It calls gethostbyname to translate the hostname 35 | into a numerical IP address and then connects a stream (TCP) socket to port 80 on 36 | that host.Web servers speak the Hypertext Transport Protocol (HTTP), so the program 37 | issues the HTTP GET command and the server responds by sending the text of the 38 | home page. 39 | */ 40 | int main (int argc, char* const argv[]) 41 | { 42 | int socket_fd; 43 | struct sockaddr_in name; 44 | struct hostent* hostinfo; 45 | 46 | /* Create the socket. */ 47 | socket_fd = socket (PF_INET, SOCK_STREAM, 0); 48 | 49 | /* Store the server’s name in the socket address. */ 50 | name.sin_family = AF_INET; 51 | 52 | /* Convert from strings to numbers. */ 53 | hostinfo = gethostbyname (argv[1]); 54 | if (hostinfo == NULL) 55 | return 1; 56 | else 57 | name.sin_addr = *((struct in_addr *) hostinfo->h_addr); 58 | 59 | /* Web servers use port 80. */ 60 | name.sin_port = htons (80); 61 | 62 | /* Connect to the Web server */ 63 | if (connect (socket_fd, &name, sizeof (struct sockaddr_in)) == -1) { 64 | perror (“connect”); 65 | return 1; 66 | } 67 | 68 | /* Retrieve the server’s home page. */ 69 | get_home_page (socket_fd); 70 | 71 | return 0; 72 | } 73 | 74 | /* 75 | For example, to retrieve the home page from the Web site 76 | invoke this: 77 | www.codesourcery.com , 78 | % ./socket-inet www.codesourcery.com 79 | */ 80 | -------------------------------------------------------------------------------- /memory/freeing_after_malloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Here is an example of the proper way to free all 3 | the blocks in a chain, and the strings that they point to. 4 | 5 | source: 6 | https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html 7 | source: https://www.gnu.org/software/libc/manual/html_node/Freeing-after-Malloc.html 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* 15 | subroutine that calls malloc and reports an error if the value 16 | is a null pointer, returning only if the value is nonzero. 17 | This function is conventionally called xmalloc. 18 | */ 19 | void * 20 | xmalloc (size_t size) 21 | { 22 | void *addr = malloc (size); 23 | if (addr == 0) { 24 | // fatal ("virtual memory exhausted"); 25 | fprintf(stderr, "malloc failed: %s\n", strerror(errno)); 26 | } 27 | 28 | return addr; 29 | } 30 | 31 | /* 32 | The function savestring will copy a sequence of characters 33 | into a newly allocated null-terminated string 34 | */ 35 | char * 36 | savestring (const char *ptr, size_t len) 37 | { 38 | char *addr = (char *) xmalloc (len + 1); 39 | addr[len] = '\0'; 40 | 41 | return (char *) memcpy (addr, ptr, len); 42 | } 43 | 44 | struct chain 45 | { 46 | struct chain *next; 47 | char *name; 48 | }; 49 | 50 | void 51 | print_chain (struct chain *chain) 52 | { 53 | while (chain != 0) { 54 | struct chain *next = chain->next; 55 | printf("%s\n", chain->name); 56 | chain = chain->next; 57 | } 58 | } 59 | 60 | void 61 | free_chain (struct chain *chain) 62 | { 63 | while (chain != 0) { 64 | struct chain *next = chain->next; 65 | free (chain->name); 66 | free (chain); 67 | chain = next; 68 | } 69 | } 70 | 71 | int 72 | main() 73 | { 74 | /* Normally you would cast the value as a pointer to the kind of object 75 | that you want to store in the block. 76 | */ 77 | struct chain * c = (struct chain *) xmalloc(sizeof(struct chain)); 78 | struct chain * c1 = (struct chain *) xmalloc(sizeof(struct chain)); 79 | 80 | /* initializing the space with zeros */ 81 | memset (c, 0, sizeof (struct chain)); 82 | memset (c1, 0, sizeof (struct chain)); 83 | 84 | /*link nodes*/ 85 | c->next = c1; 86 | 87 | char local_name_1[] = "mynode-1"; 88 | char local_name_2[] = "mynode-2"; 89 | 90 | c->name = savestring(local_name_1, strlen(local_name_1)); 91 | c1->name = savestring(local_name_2, strlen(local_name_2)); 92 | 93 | print_chain(c); 94 | free_chain(c); 95 | 96 | // don't access object after free() 97 | // print_chain(c); 98 | } 99 | -------------------------------------------------------------------------------- /memory/mallinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void 6 | display_mallinfo(void) 7 | { 8 | struct mallinfo mi; 9 | 10 | mi = mallinfo(); 11 | 12 | printf("Total non-mmapped bytes (arena): %d\n", mi.arena); 13 | printf("# of free chunks (ordblks): %d\n", mi.ordblks); 14 | printf("# of free fastbin blocks (smblks): %d\n", mi.smblks); 15 | printf("# of mapped regions (hblks): %d\n", mi.hblks); 16 | printf("Bytes in mapped regions (hblkhd): %d\n", mi.hblkhd); 17 | printf("Max. total allocated space (usmblks): %d\n", mi.usmblks); 18 | printf("Free bytes held in fastbins (fsmblks): %d\n", mi.fsmblks); 19 | printf("Total allocated space (uordblks): %d\n", mi.uordblks); 20 | printf("Total free space (fordblks): %d\n", mi.fordblks); 21 | printf("Topmost releasable block (keepcost): %d\n", mi.keepcost); 22 | } 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | // #define MAX_ALLOCS 2000000 28 | #define MAX_ALLOCS 200000 29 | char *alloc[MAX_ALLOCS]; 30 | int numBlocks, j, freeBegin, freeEnd, freeStep; 31 | size_t blockSize; 32 | 33 | if (argc < 3 || strcmp(argv[1], "--help") == 0) { 34 | fprintf(stderr, "%s num-blocks block-size [free-step " 35 | "[start-free [end-free]]]\n", argv[0]); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | numBlocks = atoi(argv[1]); 40 | blockSize = atoi(argv[2]); 41 | freeStep = (argc > 3) ? atoi(argv[3]) : 1; 42 | freeBegin = (argc > 4) ? atoi(argv[4]) : 0; 43 | freeEnd = (argc > 5) ? atoi(argv[5]) : numBlocks; 44 | 45 | printf("============== Before allocating blocks ==============\n"); 46 | display_mallinfo(); 47 | 48 | for (j = 0; j < numBlocks; j++) { 49 | if (numBlocks >= MAX_ALLOCS) { 50 | fprintf(stderr, "Too many allocations\n"); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | alloc[j] = malloc(blockSize); 55 | if (alloc[j] == NULL) { 56 | perror("malloc"); 57 | exit(EXIT_FAILURE); 58 | } 59 | } 60 | 61 | printf("\n============== After allocating blocks ==============\n"); 62 | display_mallinfo(); 63 | 64 | for (j = freeBegin; j < freeEnd; j += freeStep) 65 | free(alloc[j]); 66 | 67 | printf("\n============== After freeing blocks ==============\n"); 68 | display_mallinfo(); 69 | 70 | exit(EXIT_SUCCESS); 71 | } 72 | 73 | /* 74 | In the following example run of the program, 1000 allocations of 100 75 | bytes are performed, and then every second allocated block is freed: 76 | 77 | $ ./a.out 1000 100 2 78 | 79 | 80 | One alloc of 1Mib. See: hblks 81 | $ ./a.out 1 1000000 2 82 | 83 | */ 84 | -------------------------------------------------------------------------------- /bash/examples.md: -------------------------------------------------------------------------------- 1 | # basic examples 2 | 3 | ```sh 4 | echo $SHELL 5 | cd 6 | pwd 7 | ``` 8 | 9 | # list content 10 | 11 | ```sh 12 | ls 13 | 14 | ## listar directorio 15 | ls -d 16 | 17 | # print the index number of each file (inodo) 18 | # A cada archivo se le asigna un indice unico 19 | ls -i 20 | ``` 21 | 22 | # Create a directory 23 | 24 | ```sh 25 | mkdir 26 | mkdir -p 27 | ``` 28 | 29 | ```sh 30 | touch 31 | ``` 32 | # echo y redireccion 33 | 34 | ```sh 35 | echo "header" > template 36 | cp 37 | mv 38 | ``` 39 | 40 | # see file content 41 | 42 | ```sh 43 | cat 44 | less 45 | more 46 | head 47 | ``` 48 | 49 | # enlace permanente (nivel inodo) 50 | # no soporta directorios y otras limitaciones 51 | ln txt tx1 52 | 53 | # enlace simbolico (referencia a traves del nombre, en vez de hacerlo por el inodo) 54 | # puede ser a directorios 55 | ln -s txt tx2 56 | 57 | # Remove 58 | 59 | ```shell 60 | rm 61 | 62 | # iterativo 63 | rm -i 64 | 65 | # rm iterativo por alias 66 | alias rm = "rm -i" 67 | 68 | # solo borra dirs vacios 69 | rmdir 70 | 71 | rm -rf 72 | ``` 73 | 74 | To delete all files and directories, including hidden ones, 75 | in a specified directory and its subdirectories, you can use the find command. 76 | Here's how to do it: 77 | 78 | ```sh 79 | # -mindepth 1: Ensures that the root directory itself is not included in the results, only its contents. 80 | find /path/to/challenge_directory -mindepth 1 -delete 81 | ``` 82 | 83 | # Pipe 84 | 85 | ```sh 86 | # usuarios usando el sistema en orden alfabetico 87 | who | sort 88 | ``` 89 | 90 | # OR Condition 91 | 92 | ```sh 93 | test -f car.c && echo "is a file" 94 | ``` 95 | 96 | # AND Condition 97 | 98 | ```sh 99 | test -d car.c || echo "not a dir" 100 | ``` 101 | 102 | # intercambiar el nombre de dos archivos 103 | # usando repetidamente el comando mv 104 | 105 | ```sh 106 | mv arch1 aux; mv ach2 arch1; mv aux arch1 107 | ``` 108 | 109 | # imprime dentro de una hora, en orden alfabetico, de entre las primeras 110 | # 100 lineas de arc las lineas que contengan la palabra Warning, 111 | # comprobando antes que arc es accesible. 112 | # El cojunto de comandos se ejecuta en segundo plano 113 | 114 | ```sh 115 | (sleep 3600; test -r arc && head -100 arc | grep Warning | sort ) & 116 | ``` 117 | 118 | # Command output as argument 119 | 120 | ```sh 121 | # remove files filtered by grep 122 | rm `grep -l *` 123 | ``` 124 | 125 | How to reboot or shut down using the command line: 126 | 127 | shutdown 128 | reboot 129 | halt 130 | poweroff 131 | 132 | https://zpenterprises.co/how-to-reboot-or-shut-down-linux-using-the-command-line/ 133 | 134 | -------------------------------------------------------------------------------- /bash/users.md: -------------------------------------------------------------------------------- 1 | # User Management in Linux 2 | 3 | This document provides various ways to list users on a Linux or Unix-like system and find specific user information such as user IDs. 4 | 5 | ## 1. Viewing All Users 6 | 7 | ### Using the `/etc/passwd` File 8 | 9 | The `/etc/passwd` file contains all user account information on the system. To see all users, you can use: 10 | 11 | ```bash 12 | cat /etc/passwd 13 | ``` 14 | 15 | Each line in this file represents a user in the following format: 16 | 17 | ``` 18 | username:x:UID:GID:User Info:Home Directory:Shell 19 | ``` 20 | 21 | more: 22 | 23 | ```bash 24 | man 5 passwd 25 | ``` 26 | 27 | To display only the usernames: 28 | 29 | ```bash 30 | cut -d: -f1 /etc/passwd 31 | ``` 32 | 33 | ### Using the `getent` Command 34 | 35 | The `getent` command queries the system's user database. It can be used to list all users, and it supports network-based databases like LDAP. 36 | 37 | To list all users: 38 | 39 | ```bash 40 | getent passwd 41 | ``` 42 | 43 | To display only the usernames: 44 | 45 | ```bash 46 | getent passwd | cut -d: -f1 47 | ``` 48 | 49 | ### Listing System and Regular Users 50 | 51 | - **List system users (UID < 1000):** 52 | 53 | ```bash 54 | awk -F: '$3 < 1000 {print $1}' /etc/passwd 55 | ``` 56 | 57 | - **List regular users (UID ≥ 1000):** 58 | 59 | ```bash 60 | awk -F: '$3 >= 1000 {print $1}' /etc/passwd 61 | ``` 62 | 63 | ### Using the `compgen` Command 64 | 65 | To quickly list all users: 66 | 67 | ```bash 68 | compgen -u 69 | ``` 70 | 71 | ## 2. Finding User IDs (UID) 72 | 73 | To find the user ID (UID) of the current user: 74 | 75 | ```bash 76 | id -u 77 | ``` 78 | 79 | To find the UID of a specific user: 80 | 81 | ```bash 82 | id -u 83 | ``` 84 | 85 | ### Checking the `/etc/passwd` File 86 | 87 | You can also find the UID of a user by searching for their entry in `/etc/passwd`: 88 | 89 | ```bash 90 | grep /etc/passwd 91 | ``` 92 | 93 | The third field in the result will be the user's UID. 94 | 95 | ## 3. Listing Currently Logged-In Users 96 | 97 | To see the list of users currently logged into the system, use the `who` or `w` commands: 98 | 99 | ```bash 100 | who 101 | ``` 102 | 103 | or 104 | 105 | ```bash 106 | w 107 | ``` 108 | 109 | These commands show the usernames and other details like login time and terminal. 110 | 111 | ## 4. Programmatically Finding User IDs 112 | 113 | If you're writing a C program and want to find the user ID of the current user, you can use the `getuid()` function. Here's a sample C program: 114 | 115 | ```c 116 | #include 117 | #include 118 | 119 | int main() { 120 | uid_t user_id = getuid(); // Get the current user ID 121 | printf("User ID: %d\n", user_id); 122 | return 0; 123 | } 124 | ``` 125 | 126 | ## Conclusion 127 | 128 | These methods help you list and manage users on a Linux or Unix-like system. Whether you're a system administrator or developer, these commands provide an efficient way to interact with user account data. 129 | -------------------------------------------------------------------------------- /gnu_linux_sw/getopt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Example program using getopt() to handle two program options: 3 | * -n: A flag with no associated value. 4 | * -t : Expects an associated value (number of seconds). 5 | * 6 | * Usage: 7 | * ./program [-n] [-t ] [name] 8 | * 9 | * If only -n is provided, the name argument is optional. 10 | */ 11 | 12 | #include // for getopt() 13 | #include // for atoi(), exit() 14 | #include // for printf(), fprintf() 15 | 16 | int main(int argc, char *argv[]) { 17 | int flag_n = 0; // Set when -n is provided 18 | int seconds = 0; // Value provided by -t 19 | int t_option_provided = 0; // Flag to track if -t was given 20 | int opt; // To hold options from getopt() 21 | 22 | // Parse command-line options 23 | while ((opt = getopt(argc, argv, "nt:")) != -1) { 24 | switch (opt) { 25 | case 'n': 26 | flag_n = 1; // Set flag when -n is provided 27 | break; 28 | case 't': 29 | seconds = atoi(optarg); // Convert the argument to an integer 30 | if (seconds <= 0) { // Check for valid input 31 | fprintf(stderr, "Invalid value for -t: %s\n", optarg); 32 | exit(EXIT_FAILURE); 33 | } 34 | t_option_provided = 1; 35 | break; 36 | default: // '?' case for unknown options 37 | fprintf(stderr, "Usage: %s [-n] [-t ] [name]\n", argv[0]); 38 | exit(EXIT_FAILURE); 39 | } 40 | } 41 | 42 | // Display parsed options and their values 43 | printf("Flag -n: %d\n", flag_n); 44 | printf("Option -t: %d (provided: %d)\n", seconds, t_option_provided); 45 | printf("optind (index of first non-option argument): %d\n", optind); 46 | 47 | // If the -n option is not provided, ensure at least one non-option argument (name) is required 48 | if (optind >= argc && !flag_n) { 49 | fprintf(stderr, "Expected a name argument after options\n"); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | // Display the non-option argument (name) if provided 54 | if (optind < argc) { 55 | printf("Name argument: %s\n", argv[optind]); 56 | } else if (flag_n) { 57 | printf("No name provided, but -n option was given.\n"); 58 | } 59 | 60 | // Other code logic can be added here 61 | 62 | // Exit successfully 63 | return EXIT_SUCCESS; 64 | } 65 | 66 | 67 | /* 68 | 69 | ```bash 70 | ./program -n -t 5 myname 71 | ``` 72 | 73 | argv[0] = "./program" 74 | argv[1] = "-n" 75 | argv[2] = "-t" 76 | argv[3] = "5" 77 | argv[4] = "myname" 78 | 79 | ### optind 80 | 81 | optind is used to indicate the index in argv[] where the 82 | first non-option argument is located after option processing. 83 | 84 | ### How `optind` Works: 85 | 86 | - **Initially**: `optind` is set to 1, as the first element (`argv[0]`) is the program name. 87 | - **During Parsing**: Each time `getopt()` processes an option (e.g., `-n` or `-t`), it increments `optind`. 88 | - **After Parsing**: When `getopt()` finishes processing all options, 89 | `optind` will point to the first argument that is **not** an option (i.e., not starting with `-`). 90 | 91 | */ -------------------------------------------------------------------------------- /gnu_linux_sw/getopt_long.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Listing 2.2 (getopt_long.c) Using getopt_long 3 | * --------------------------------------------- 4 | * 5 | * Listing shows an example of how you might use getopt_long to process your arguments. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /* The name of this program.*/ 13 | const char* program_name; 14 | /* Prints usage information for this program to STREAM (typically 15 | stdout or stderr), and exit the program with EXIT_CODE. Does not 16 | return. */ 17 | void print_usage (FILE* stream, int exit_code) 18 | { 19 | fprintf (stream, "Usage: %s options [ inputfile ... ]\n", program_name); 20 | fprintf (stream, 21 | " -h --help Display this usage information.\n" 22 | " -o --output filename Write output to file.\n" 23 | " -v --verbose Print verbose messages.\n"); 24 | 25 | exit (exit_code); 26 | } 27 | 28 | /* Main program entry point. ARGC contains number of argument list 29 | elements; ARGV is an array of pointers to them. */ 30 | int main (int argc, char* argv[]) 31 | { 32 | int next_option; 33 | 34 | /* A string listing valid short options letters.*/ 35 | const char* const short_options = "ho:v"; 36 | 37 | /* An array describing valid long options. */ 38 | const struct option long_options[] = { 39 | { "help", 0, NULL, 'h' }, 40 | { "output", 1, NULL, 'o' }, 41 | { "verbose", 0, NULL, 'v' }, 42 | { NULL, 0, NULL, 0} /* Required at end of array.*/ 43 | }; 44 | 45 | /* The name of the file to receive program output, or NULL for 46 | standard output. */ 47 | const char* output_filename = NULL; 48 | 49 | /* Whether to display verbose messages. */ 50 | int verbose = 0; 51 | 52 | /* Remember the name of the program, to incorporate in messages. 53 | The name is stored in argv[0]. */ 54 | program_name = argv[0]; 55 | 56 | do { 57 | next_option = getopt_long (argc, argv, short_options, long_options, NULL); 58 | 59 | // printf ("next_option: %c optind: %d\n", next_option, optind); 60 | switch (next_option) { 61 | /* -h or --help */ 62 | case 'h': 63 | /* User has requested usage information. Print it to standard 64 | output, and exit with exit code zero (normal termination). */ 65 | print_usage (stdout, 0); 66 | /* try echo $?*/ 67 | 68 | /* -o or --output */ 69 | case 'o': 70 | /* This option takes an argument, the name of the output file.*/ 71 | output_filename = optarg; 72 | break; 73 | /* -v or --verbose */ 74 | case 'v': 75 | verbose = 1; 76 | break; 77 | /* The user specified an invalid option. */ 78 | case '?': 79 | /* Print usage information to standard error, and exit with exit 80 | code one (indicating abnormal termination). */ 81 | print_usage (stderr, 1); 82 | /* try echo $?*/ 83 | /* Done with options.*/ 84 | case -1: 85 | break; 86 | /* Something else: unexpected.*/ 87 | default: 88 | abort (); 89 | } 90 | } 91 | while (next_option != -1); 92 | 93 | /* Done with options. OPTIND points to first nonoption argument. 94 | For demonstration purposes, print them if the verbose option was 95 | specified. */ 96 | if (verbose) { 97 | int i; 98 | for (i = 0; i < argc; i++) 99 | printf ("Argument: %s %d\n", argv[i], optind); 100 | } 101 | 102 | /* The main program goes here. 103 | */ 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /memory/sbrk/get_num.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************\ 2 | * Copyright (C) Michael Kerrisk, 2020. * 3 | * * 4 | * This program is free software. You may use, modify, and redistribute it * 5 | * under the terms of the GNU Lesser General Public License as published * 6 | * by the Free Software Foundation, either version 3 or (at your option) * 7 | * any later version. This program is distributed without any warranty. * 8 | * See the files COPYING.lgpl-v3 and COPYING.gpl-v3 for details. * 9 | \*************************************************************************/ 10 | 11 | /* get_num.c 12 | 13 | Functions to process numeric command-line arguments. 14 | */ 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "get_num.h" 21 | 22 | /* Print a diagnostic message that contains a function name ('fname'), 23 | the value of a command-line argument ('arg'), the name of that 24 | command-line argument ('name'), and a diagnostic error message ('msg'). */ 25 | 26 | static void 27 | gnFail(const char *fname, const char *msg, const char *arg, const char *name) 28 | { 29 | fprintf(stderr, "%s error", fname); 30 | if (name != NULL) 31 | fprintf(stderr, " (in %s)", name); 32 | fprintf(stderr, ": %s\n", msg); 33 | if (arg != NULL && *arg != '\0') 34 | fprintf(stderr, " offending text: %s\n", arg); 35 | 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | /* Convert a numeric command-line argument ('arg') into a long integer, 40 | returned as the function result. 'flags' is a bit mask of flags controlling 41 | how the conversion is done and what diagnostic checks are performed on the 42 | numeric result; see get_num.h for details. 43 | 44 | 'fname' is the name of our caller, and 'name' is the name associated with 45 | the command-line argument 'arg'. 'fname' and 'name' are used to print a 46 | diagnostic message in case an error is detected when processing 'arg'. */ 47 | 48 | static long 49 | getNum(const char *fname, const char *arg, int flags, const char *name) 50 | { 51 | long res; 52 | char *endptr; 53 | int base; 54 | 55 | if (arg == NULL || *arg == '\0') 56 | gnFail(fname, "null or empty string", arg, name); 57 | 58 | base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 : 59 | (flags & GN_BASE_16) ? 16 : 10; 60 | 61 | errno = 0; 62 | res = strtol(arg, &endptr, base); 63 | if (errno != 0) 64 | gnFail(fname, "strtol() failed", arg, name); 65 | 66 | if (*endptr != '\0') 67 | gnFail(fname, "nonnumeric characters", arg, name); 68 | 69 | if ((flags & GN_NONNEG) && res < 0) 70 | gnFail(fname, "negative value not allowed", arg, name); 71 | 72 | if ((flags & GN_GT_0) && res <= 0) 73 | gnFail(fname, "value must be > 0", arg, name); 74 | 75 | return res; 76 | } 77 | 78 | /* Convert a numeric command-line argument string to a long integer. See the 79 | comments for getNum() for a description of the arguments to this function. */ 80 | 81 | long 82 | getLong(const char *arg, int flags, const char *name) 83 | { 84 | return getNum("getLong", arg, flags, name); 85 | } 86 | 87 | /* Convert a numeric command-line argument string to an integer. See the 88 | comments for getNum() for a description of the arguments to this function. */ 89 | 90 | int 91 | getInt(const char *arg, int flags, const char *name) 92 | { 93 | long res; 94 | 95 | res = getNum("getInt", arg, flags, name); 96 | 97 | if (res > INT_MAX || res < INT_MIN) 98 | gnFail("getInt", "integer out of range", arg, name); 99 | 100 | return (int) res; 101 | } 102 | -------------------------------------------------------------------------------- /gnu_linux_sw/errors_from_sycalls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include // For chown 5 | #include // For strerror 6 | #include 7 | #include 8 | 9 | /* 10 | Explanation of Error Codes: 11 | 12 | EPERM: Permission denied (insufficient privileges to change ownership). 13 | EROFS: The file is on a read-only file system. 14 | ENAMETOOLONG: The file path exceeds the system's limit for path lengths. 15 | ENOENT: The file or a component of the path does not exist. 16 | ENOTDIR: A component of the path was expected to be a directory but wasn't. 17 | EACCES: Permission denied for a component of the path (e.g., directory traversal). 18 | */ 19 | 20 | // The program accepts two arguments: the file path and the user ID. 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | if (argc < 3) { 25 | fprintf(stderr, "Usage: %s \n", argv[0]); 26 | return 1; 27 | } 28 | 29 | const char *path = argv[1]; 30 | uid_t user_id = atoi(argv[2]); 31 | int rval; 32 | 33 | // Attempt to change ownership, keeping group ID unchanged with -1. 34 | rval = chown(path, user_id, -1); 35 | 36 | if (rval != 0) { 37 | // Save errno because it’s clobbered by the next system call. 38 | int error_code = errno; 39 | 40 | // The operation didn’t succeed; chown should return -1 on error. 41 | assert(rval == -1); 42 | 43 | // Check the value of errno, and take appropriate action. 44 | switch (error_code) { 45 | case EPERM: 46 | /* Permission denied. 47 | * The user doesn’t have permission to change ownership of the file. 48 | * This can occur if the user is not the superuser or does not have the required privileges. 49 | */ 50 | 51 | case EROFS: 52 | /* Read-only file system. 53 | * The file resides on a read-only file system, and you cannot modify its ownership. 54 | */ 55 | 56 | case ENAMETOOLONG: 57 | /* Filename too long. 58 | * The path specified exceeds the allowed maximum length for file paths. 59 | */ 60 | 61 | case ENOENT: 62 | /* File or directory does not exist. 63 | * The file at the specified path does not exist, or a component in the path was not found. 64 | */ 65 | 66 | case ENOTDIR: 67 | /* Not a directory. 68 | * A component of the path provided is not a directory, but it was expected to be one. 69 | */ 70 | 71 | case EACCES: 72 | /* Permission denied. 73 | * A component of the path cannot be accessed because of insufficient permissions, 74 | * such as lacking read or search permission on a parent directory. 75 | */ 76 | 77 | // Something’s wrong with the file. Print an error message. 78 | fprintf(stderr, "error changing ownership of %s: %s\n", path, strerror(error_code)); 79 | break; 80 | 81 | case EFAULT: 82 | /* Invalid address. 83 | * The path points to an invalid memory address, which likely indicates a bug. 84 | */ 85 | abort(); 86 | 87 | case ENOMEM: 88 | /* Out of memory. 89 | * The system has run out of kernel memory to complete the operation. 90 | */ 91 | fprintf(stderr, "%s\n", strerror(error_code)); 92 | exit(1); 93 | 94 | default: 95 | /* Unexpected error. 96 | * This handles any other errors that are not explicitly covered by the previous cases. 97 | */ 98 | abort(); 99 | } 100 | } 101 | else { 102 | printf("Ownership of file '%s' successfully changed to user ID %d\n", path, user_id); 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | 109 | /* 110 | 111 | # README 112 | 113 | 114 | To get the user id: 115 | 116 | ``` 117 | id -u 118 | id -u 119 | ``` 120 | 121 | To run the example: 122 | 123 | 124 | ``` 125 | gcc -o chown_example errors_from_sycalls.c 126 | ./chown_example /path/to/file 127 | ``` 128 | 129 | */ --------------------------------------------------------------------------------