Posts

Showing posts with the label c

POSIX Capabilities Part 3 - CAP_SYS_BOOT - Allow Non-root user to reboot

Image
Linux provide 'reboot' api to allow user to perform a reboot from Linux Code. #include <unistd.h> #include <sys/reboot.h> int reboot(int cmd); reboot(RB_AUTOBOOT); will print the message "Restarting system." and reboot will be performed. If a non-root user tries to perform this, it will fail with permission denied error. Now, if we run cap_sys_boot_test, the system will reboot when run with non-root user.

POSIX Capabilities Part2 - CAP_DAC_OVERRIDE - Bypass permission check

Image
CAP_DAC_OVERRIDE: Allows a non-root user full file system access. Bypasses file read, write and execute permission check. DAC stands for "discretionary access control" Let's see an example using this capability. You can see from the above screenshot, after giving 'CAP_DAC_OVERRIDE' capability, i am able to open '/etc/shadow' which only root user can access.

Implement Copy, move and delete a file in Linux- rename, unlink

Image
Hi Guys, In this post, we will see how to use Linux API's to perform copy, move and delete file operations There is no direct Linux System Call for copy operation, we need to manually open one file in read mode, and other in create mode, and then start writing one by one For move operation, the Linux System call is rename  #include <stdio.h>  int rename(const char *oldpath, const char *newpath); For delete operation, the Linux System call is unlink #include <unistd.h> int unlink(const char *pathname); Sample Code to use all the API's Output:

Serial Port Programming Part 10 - Reading/Writing Status of Control Lines: DTR/RTS/CTS/DSR

Image
If the user is interested in finding out the status of Control Lines:DTR/DSR/RTS/CTS. He can use 'TIOCMGET' control code in the ioctl call. 'TIOCMSET' control code in  ioctl allows you to set/clear DTR and RTS lines as they are output. Example Code: Output:

Serial Port Programming Part 9 - Hardware Flow Control - RTS,CTS

Image
What is Flow Control? Technically, flow control is a mechanism in which receiver can control the transmission speed. This is done in case of superfast sender and slow receiver. If we don't have flow control, in this case, the receive buffer in the receiver will be overwritten with the new data. Hardware Flow Control in RS-232: RS-232 provides two control lines for hardware flow control: RTS (Request to Send) CTS (Clear to Send) RTS/CTS is handshaking method which uses one wire in each direction to allow each device to indicate to the other whether or not it is ready to receive data at a given moment of time. The RTS pin of one device will be connected to CTS pin of the other device. RTS pin is output and CTS pin is input. In case of connecting DTE to DTE(null modem cabling), we connect RTS of one device to CTS of other device. In case of connecting DTE to DCE (straight through cabling), we connect RTS to RTS and CTS to CTS. A device which...

stdout vs stderr

Image
When a process is created in Linux, three file handles are already open for use: 1. stdin (Standard input) with file descriptor value '0' 2. stdout (Standard output) with file descriptor value '1' 3. stderr (Standard Error) with file descriptor value '2' read(0, buf, sizeof(buf)) will read from the standard input which is the keyboard and store it in 'buf'. Note: We need to null terminate the buffer manually. write(1, "hello", sizeof("hello")) will write to the standard output which is the console write(2, "hello", sizeof("hello")) will write to the standard error which is also console So, why we have two (stdout and stderr), as they are performing the same operation. No there are some differences: stdout vs stderr: stdout is fully buffered and stderr is not buffered . This means when we write to stdout, it goes to a buffer and when we command it to display on the console, it displays it. For e...

My notes on FILES in C

Reading File Line by line: FILE *fp  = fopen("filename", "r"); char buf[512]; while(fgets(buf, 512, fp)!=NULL) {     puts(buf); } fclose(fp); Reading File Character by Character: FILE *fp  = fopen("filename", "r"); int ch; while((ch = fgetc(fp))!=EOF) {     putchar(ch); } fclose(fp); Random Access : ftell(fp) returns the offset of the File The  rewind() function sets the file position indicator for the stream pointed to by stream to the beginning of the file.               (void) fseek(stream, 0L, SEEK_SET)

Runtime loading of dynamic libraries in Linux

Image
In Linux, libraries which are linked during linking stage of the program, gets loaded during the startup of the program, unless a copy is already present in memory. Another approach provided by Linux operating system is to load/unload the libraries at run time whenever it is needed. API's are provided by Linux for Loading the Library -- dlopen() Looking up for symbols -- dlsym() Handling Errors -- dlerror() Unloading the Library -- dlclose() Header File : #include <dlfcn.h> Note: While building the program, you need to link 'ldl' library: -ldl Flow: 1. Process begins with a call to dlopen API, providing the path of the shared library and the mode. Main two values for this mode are RTLD_NOW, RTLD_LAZY. This informs the dynamic linker when to perform relocations. RTLD_NOW will make all the necessary relocations at the dlopen call time, whereas RTLD_LAZY will perform relocations only when they're needed. dlopen function returns a handle which is...

Avoid gcc deleting intermediate files while compiling C Code

Image
We know our C Code goes through four stages: Preprocessing, compiling, assembling and linking gcc creates many intermediate files for each stage. By default gcc deletes these intermediate files. You can instruct gcc to avoid deleting intermediate files passing '--save-temps' option to it. Observe from the above screenshot, the intermediate files after Preprocessing (*.i) Compiling (*.s) assembling (*.o) Are placed in the same directory

TIVA Launchpad TM4C123 Part 2 - Push Button

SW1 Push button is connected to PF0 Pin, SW2 Push button is connected to PF4 Pin. Notice that there is no pull up resistor connected to SW1 or SW2. To use SW1 and SW2 we need to enable the internal pull-up resistor for PF0 and PF4 pins. Steps for Switching Green LED on SW1 push and RED Led on SW2 Push 1. Enable the clock to PORTF 2. Set the Direction Register PF4, PF0 as input and PF1, PF3 as output 3. Select the Digital I/O feature of PORTF 4. Enable the pull-up resistor option in PUR register for PF0 and PF4 pins 5. Read GPIODATA value and set the LED depending on which button is pressed 6. Repeat Step 5 For SW2, extra steps need to be taken as PF0 pin to which SW2 is shared with NMI. To prevental accidental write to configuration registers and thus NMI, the configuration register bits for PF0 are normally locked. It may be unlocked by writing a passcode value of 0x4C4F434B to the LOCK register followed by setting bit 0 of the commit register. main.c Now press SW1 ...

TIVA Launchpad TM4C123 Part 1 - Blinking RGB LED

Image
Before we start writing programs, we need to install the following softwares. 1. Download and install the latest version of Code Composer Studio (CCS): http://processors.wiki.ti.com/index.php/Download_CCS 2. Download and install the full version of TivaWare from below link. The file name to download is SW-TM4C-x.x.exe http://www.ti.com/tool/sw-tm4c 3. Download and install the latest LM Flash Programmer http://www.ti.com/tool/lmflashprogrammer 4. Download the TM4C123GHGPM Microcontroller datasheet and User Guide http://www.ti.com/lit/ds/symlink/tm4c123gh6pm.pdf http://www.ti.com/lit/ug/spmu296/spmu296.pdf 5. Run the Code Composer Studio 6. File -> New -> CCS Project 7. Select 'TIVA TM4C123GH6PM' from the drop down list, enter the Project Name: 'LED_BLINK' and click on 'Finish' 8. On the board, PF1 is connected to RED LED, PF2 is connected to BLUE LED and PF3 is connected to GREEN LED. GPIO Registers in TM4C123: Dat...

My notes on Sorting in C

Bubble Sort: Simplest sorting algorithm Repeatedly comparing pair of  adjacent element and swapping if they are not in order Not suited for large datasets, as its worst-case complexity is O(n2) where n is the number of elements because the entire array needs to be iterated for every element. E.g. 15, 32, 26, 34, 11 First Pass: ( 15 , 32 , 26, 34, 11) -> ( 15 ,  32 , 26, 34, 11)  No swapping as the elements are in order (15,  32 , 26 , 34, 11) -> (15,  26 , 32 , 34, 11) Swapped as 32 > 26 (15, 26,  32 , 34 , 11)  -> (15, 26,  32 , 34 , 11) No Swapping as the elements are in order (15, 26, 32,  34 , 11 ) -> (15, 26, 32,  11 , 34 ) Swapped as 34 > 11 Second Pass: ( 15 ,  26 , 32, 11, 34) -> ( 15 ,  26 , 32, 11, 34) No swapping as the elements are in order (15,  26 ,  32 , 11, 34) -> (15,  26 ...

My notes on dynamic memory allocation in C

Dynamic Memory Allocation: Process in which the size of the data structure can be changed at run time. 4 Library functions: malloc calloc realloc free Header File: <stdlib.h> malloc : stands for memory allocation. Reserves a block of memory of the specified number of bytes. It returns a pointer of type void which can be casted into any type. ptr = (cast-type*) malloc(byte-size); If space is insufficient, allocation fails and returns a NULL pointer. calloc: stands for contiguous allocation. malloc allocates a single block of memory,  whereas calloc allocates multiple blocks of memory and initializes them to zero. ptr = (cast-type*)calloc(n, element-size); free: free the memory allocated using malloc and calloc. free(ptr); realloc: Change the size of previously existing memory using realloc function ptr = realloc(ptr, x); Here ptr is reallocated with new size 'x' malloc vs calloc: 1. Initialization: malloc does not init...

Serial Port Programming Part 5 - tcflush - TCIFLUSH,TCOFLUSH example

Image
tcflush flushes/discards data which is written but not transmitted and/or  data which is received but not read by user The exact operation depends on the 'queue_selector' argument . #include <termios.h> int tcflush(int fildes, int queue_selector); Possible values of queue_selector are: TCIFLUSH - Flushes/Discards received data, but not read TCOFLUSH - Flushes/Discards written data, but not transmitted TCIOFLUSH - Flushes/Discards both Let's write a sample code to check what happens when we 1. Loop until there are bytes in input buffer using 'FIONREAD' ioctl  2. Call tcflush with queue selector 'TCIFLUSH' 3. Check how many bytes are present in input buffer with 'FIONREAD' ioctl Need two USB to serial/serial devices connected (TX-RX/RX-TX) Code: Output: Same behavior will happen when we call write on the serial port with large number of bytes, and in the next statement call tcflush wit...

Serial Port Programming Part 4 - tcdrain - example, internal implementation

Image
The tcdrain will block the process until all the data which is present in the Linux TTY buffer is written to the hardware. tcdrain is a C Library function which translates it to ioctl with command argument set to 'TCSBRK' Let's see how tcdrain is internally implemented in kernel: 'tty_ioctl' function present in drivers/tty/tty_io.c handles all the ioctl calls from Serial Port You can see from the above screenshot, it calls tty_wait_until_sent function, it is defined in drivers/tty/tty_ioctl.c file tty_wait_until_sent uses wait_event_interruptible_timeout until the tty_chars_in_buffer function returns 0. tty_chars_in_buffer returns the number of bytes present in the device private output queue. This is implemented by the particular serial port device driver. If we use 'pl2303' device, then it will be in the pl2303 usb serial port driver. Let's write a C Code to understand better. Connect two serial port devices TX and RX. Below code...

My notes on Integer promotion, arithmetic conversions in C

Integer Promotions: Integer types smaller than int are promoted when an operation is performed on them. If all the values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise it is converted to an unsigned int. E.g.: char c1, c2; c1 = c1 + c2; c1 and c2 gets promoted to integer , sum is calculated and then truncated to fit into char type. signed char cresult, c1, c2, c3; c1 = 100; c2 = 3; c3 = 4; cresult = c1 * c2/c3; Assuming that signed char is represented as 8-bit value, Integer promotion happens c1, c2 and c3 are promoted to int. Finally the result is truncated to char which is 75. char a = 30, b = 20, c = 10;  char d = (a * b) / c; a, b and c are promoted to integer, operation is performed on them and finally the result is truncated to char which is 60, no data is lost in this case The logic behind integer promotion is to avoid accidental overflows during arithmetic operations. Mixed Mode A...

Inline Functions vs Macros

Macro invocations do not perform type checking, or even check that arguments are wellformed, whereas function calls usually do. In C, a macro cannot use the return keyword with the same meaning as a function would do (it would make the function that asked the expansion terminate, rather than the macro). In other words, you cannot make the macro return something which is not the result of the last expression invoked inside it. Since C macros use mere textual substitution, this may result in unintended side-effects and inefficiency due to re-evaluation of arguments and order of operations. Compiler errors within macros are often difficult to understand, because they refer to the expanded code, rather than the code the programmer typed Many constructs are awkward or impossible to express using macros, or use a significantly different syntax. Inline functions use the same syntax as ordinary functions, and can be inlined and un-inlined at will with ease. Debugging information for inl...

My notes on Function Pointers in C

Function code is stored in the memory, start of the function code or address of a function is a "function pointer" 1. Function Pointers point to the code, not data 2. Function pointer is different from normal pointer, Function name can be used to get the function address Syntax: return_type (*pointer_name)(argument_list) Note: Remember always the declaration name is preceded by * and enclosed in parenthesis (), If we remove the bracket the meaning changes. E.g. void display(int a) {            printf("value of a is %d\n", a); } int main() {      void (*func)(int) = display;       func(10);       return 0; } 3. Like normal pointers, we can have arrays of function pointers. void add(int a, int b) {        printf("a+b:%d\n", a+b); } void subtract(int a, int b) {        printf("a-b:%d\n", a-b); } void mul(int a, int b) {      ...

My notes on two dimensional arrays in C

2D Array: Array of Arrays. 2D Array is also known as matrix in C Two ways to initialize 2D Array: 1. int arr[2][3] = { 10, 11, 12, 13, 14, 15}; 2. int arr[2][3] = {{10, 11, 12}, {13, 14, 15}}; Second method is more readable. In 2D Array, it is compulsory to specify the second dimension while declaring the array. int arr[2][3] = { 10, 11, 12, 13, 14, 15}; //Valid Declaration int arr[][3] = { 10, 11, 12, 13, 14, 15}; //Valid Declaration int arr[2][] = { 10, 11, 12, 13, 14, 15}; //Invalid Declaration int arr[][] = { 10, 11, 12, 13, 14, 15}; //Invalid Declaration How are 2-D Arrays stored in C? As computer memory is linear and there are no rows and columns. 2-D Arrays are stored in row-major order. This means the first row is stored first, then second row and so on. Pointers and 2-D Arrays: A pointer that points to the 0th element of the array and a pointer that points to the whole array are totally different. int *ptr; //Pointer to int int (*ptr1)[...

Serial Port Programming Part 3 - Finding out the number of bytes available in serial read buffer

Consider the scenario in which I want to wait until 'n' number of bytes received on serial port before calling read, as read system call will remove the contents of the serial input buffer. Such situation can be in case where your packet length is 50 bytes and you want to wait until all the 50 bytes are received. The FIONREAD ioctl returns the number of bytes present in the serial input buffer. ioctl(fd, FIONREAD, &bytes); Let's write a sample code to wait until 50 bytes are present in the serial input buffer and then perform read. Two USB to serial devices should be connected (TX->RX, RX->TX) to run the program. Code: Run the noncanonical_write we wrote in previous post multiple times.While loop will exit when more than 50 bytes are present in the serial input buffer