C Programming

C Programming

Attribute Value

Goal

Read and write systems-level C — file I/O, syscalls, memory, networking

Interest Link

Programming > C

Status

Phase 1 — stdio + syscall tracing (fopen, fgetc, EOF, strace, ftrace)

Rationale

Required for work. Understanding syscalls, kernel interfaces, and library functions. Man pages sections 2 (syscalls) and 3 (library) become primary documentation. Bridges gap between bash/Python scripting and systems programming.

Approach

Man pages as curriculum. Write small programs, compile with gcc, verify with xxd, strace, ltrace. No IDE — terminal + nvim only.

Primary Resources

Man pages (sections 2, 3), "You Suck at Programming" channel, K&R (The C Programming Language)

Documentation

education/programming/c/ in domus-captures

Curriculum

Phase 0: Environment & Compilation

Topic Description Status

Compiler setup

gcc, cc, compilation flags (-o, -Wall, -g), linking

■■■■■■■■■■ 10/10 (2026-04-25)

Man pages

man 3 printf vs man 1 printf — sections 2 (syscalls) and 3 (libc). Reading SYNOPSIS, RETURN VALUES, ERRORS.

■■■■■■■■■■ 10/10 (2026-04-25)

Debugging tools

xxd (hex dump), strace (syscall trace), ltrace (library trace), gdb basics

■■■■■■■■■■ 10/10 (2026-04-25)

Phase 1: stdio — The Abstraction Layer

Based on "What is Actually EOF?" transcript. The f functions: fopen, fgetc, fclose, fprintf.

Topic Description Status

Hello World

#include <stdio.h>, main(), return 0, compile and run

■■■■■■■■■■ 10/10 (2026-04-26)

Types and variables

int, char, int c (why int not char for fgetc), pointers (FILE *fp)

■■■■■■■■■■ 10/10 (2026-04-26)

File I/O (stdio)

fopen() / fgetc() / fclose() — open, read one byte, close. man 3 fopen.

■■■■■■■■■■ 10/10 (2026-04-26)

EOF

EOF is not a character — it’s the return value of fgetc() when nothing is left. Value: -1. Defined in <stdio.h>.

■■■■■■■■■■ 10/10 (2026-04-26)

Loops

while(true) with break, then idiomatic whilec = fgetc(fp != EOF). <stdbool.h> for true.

■■■■■■■■■■ 10/10 (2026-04-26)

Error checking

fopen() returns NULL on failure. Check before using. return 1 for error exit. perror().

■■■■■■■■■■ 10/10 (2026-04-26)

printf formatting

%c (char), %d (int), %02x (hex), %s (string), %zd (ssize_t), \n (newline)

■■■■■■■■■■ 10/10 (2026-04-26)

Hex reader

Built simplified xxd%02x output, 16-byte rows, byte counting

■■■■■■■■■■ 10/10 (2026-04-26)

Syscall tracing (strace)

strace -e openat,write,close — see fopen→openat, fprintf→write, fclose→close. Libc translates.

■■■■■■■■■■ 10/10 (2026-04-27)

Kernel tracing (ftrace)

function_graph tracer on do_sys_openat2 — 40+ kernel functions per fopen. AppArmor common_perm() visible. Steven Rostedt’s infrastructure.

■■■■■■■■■■ 10/10 (2026-04-27)

Infrastructure tracing

strace on curl (ISE API call) — DNS to BIND (10.50.1.90:53), TCP to ISE (9060), TLS cert loading from ~/.secrets/. Everything is syscalls.

■■■■■■■■■■ 10/10 (2026-04-27)

Phase 2: Syscalls — The Raw Interface

One layer below stdio. open(), read(), close() — no buffering, no EOF constant.

Topic Description Status

File descriptors

int fd = open() returns a number, not a struct. 0=stdin, 1=stdout, 2=stderr. man 2 open.

□□□□□□□□□□ 0/10

open / read / close

open() with O_RDONLY flags, read() into a buffer, close(fd). Headers: <fcntl.h>, <unistd.h>.

□□□□□□□□□□ 0/10

Buffers

char buf[1] — read into a buffer of size N. read() returns bytes read, 0 = done, -1 = error.

□□□□□□□□□□ 0/10

EOF at syscall level

No EOF constant. read() returns 0 — "successfully read zero bytes." You interpret that as done.

□□□□□□□□□□ 0/10

ssize_t

Signed size type. read() returns ssize_t — positive (bytes read), 0 (EOF), -1 (error).

□□□□□□□□□□ 0/10

Standard input

File descriptor 0. No need to open() — it’s already open. read(0, buf, 1). This is how cat works.

□□□□□□□□□□ 0/10

Ctrl+D

Terminal flushes empty buffer → program reads 0 bytes → interprets as EOF. Ctrl+D doesn’t "send EOF."

□□□□□□□□□□ 0/10

Phase 3: Headers & the Preprocessor

Topic Description Status

#include

<stdio.h> (system), "myfile.h" (local). What headers provide — function declarations, constants, types.

□□□□□□□□□□ 0/10

#define

EOF is #define EOF (-1). Symbolic constants. Macros.

□□□□□□□□□□ 0/10

Header discovery

man 3 fopen → SYNOPSIS tells you which header to include. Compiler errors guide you.

□□□□□□□□□□ 0/10

Phase 4: Memory & Pointers

Topic Description Status

Pointers

FILE fp — pointer to a struct. dereference. & address-of. NULL check.

□□□□□□□□□□ 0/10

Arrays and buffers

char buf[1024] — stack-allocated buffer. Array decay to pointer.

□□□□□□□□□□ 0/10

malloc / free

Heap allocation. When stack isn’t enough. Memory leaks.

□□□□□□□□□□ 0/10

Strings

Null-terminated char arrays. strlen(), strcpy(), strncpy(). Buffer overflows.

□□□□□□□□□□ 0/10

Phase 5: Networking (Work Application)

Topic Description Status

Sockets

socket(), bind(), listen(), accept(), connect(). man 2 socket.

□□□□□□□□□□ 0/10

TCP client

Connect to a server, send/receive data. RADIUS, syslog, REST — all TCP underneath.

□□□□□□□□□□ 0/10

Structs

struct sockaddr_in — IP address structures. Byte order (htons, ntohs).

□□□□□□□□□□ 0/10

select / poll / epoll

Multiplexing I/O — handling multiple connections. How nginx/ISE work internally.

□□□□□□□□□□ 0/10

Phase 6: Build Systems & Real Projects

Topic Description Status

Makefiles

gcc flags, targets, dependencies. make as build tool (you already know this from Antora).

□□□□□□□□□□ 0/10

Multi-file projects

.h header files, .c implementation files, extern, static functions.

□□□□□□□□□□ 0/10

Libraries

Static (.a) vs shared (.so). ldd, ldconfig. How libcurl, libssl work.

□□□□□□□□□□ 0/10

Reading source

Read coreutils source (cat.c, wc.c). /usr/share/doc/, kernel headers.

□□□□□□□□□□ 0/10

Phase 7: Bitwise Operations & Data Representation

The language of hardware, protocols, and kernel registers.

Topic Description Status

Bitwise operators

& (AND), | (OR), ^ (XOR), ~ (NOT), << (left shift), >> (right shift). Setting, clearing, toggling bits.

□□□□□□□□□□ 0/10

Bit masks

Extract fields from packed values. VLAN ID from 802.1Q tag (vlan_id = tag & 0x0FFF). Subnet mask as bitmask.

□□□□□□□□□□ 0/10

Byte order

Big-endian (network) vs little-endian (x86). htons(), ntohs(), htonl(), ntohl(). Why RADIUS packets look backwards in memory.

□□□□□□□□□□ 0/10

Packed structs

attributepacked — no padding. Required for protocol headers. sizeof surprises without it.

□□□□□□□□□□ 0/10

Hex arithmetic

Add, subtract, AND/OR in hex. Subnet calculations in C. 0xFFFFFF00 = /24 mask.

□□□□□□□□□□ 0/10

volatile

Tells compiler "this value changes outside my code." Required for hardware registers, memory-mapped I/O, signal handlers.

□□□□□□□□□□ 0/10

Phase 8: Raw Networking — Protocol Construction

Build the protocols you operate. Same packets your switches and ISE process.

Topic Description Status

Raw sockets

socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) — send and receive raw Ethernet frames. Requires CAP_NET_RAW. man 7 packet.

□□□□□□□□□□ 0/10

Ethernet frame

Build an Ethernet header in C: struct ethhdr — dst MAC, src MAC, EtherType. Parse frames from the wire.

□□□□□□□□□□ 0/10

ARP

Craft ARP requests/replies. Understand how switches learn MAC addresses. Build your own arping.

□□□□□□□□□□ 0/10

IP header

Parse and construct IPv4 headers — version, IHL, TTL, protocol, checksum. struct iphdr. Validate checksum in C.

□□□□□□□□□□ 0/10

TCP/UDP headers

Parse transport headers. Understand port numbers as 2-byte fields. TCP flags as bitmask (SYN = 0x02, ACK = 0x10).

□□□□□□□□□□ 0/10

ICMP

Build a ping program in raw C. ICMP echo request/reply. Checksum calculation. This is what ping does internally.

□□□□□□□□□□ 0/10

Pcap parsing

Read .pcap files in C — parse the global header, packet headers, then Ethernet→IP→TCP. Build a simplified tcpdump.

□□□□□□□□□□ 0/10

802.1Q VLAN tagging

Parse and insert VLAN tags in Ethernet frames. 4-byte tag: TPID (0x8100) + PCP + DEI + VID. Extract VLAN ID with bitmask.

□□□□□□□□□□ 0/10

802.1X / EAP

Parse EAP frames — EAPoL header, EAP packet structure. Understand what ISE receives when your workstation authenticates.

□□□□□□□□□□ 0/10

Phase 9: Kernel Interfaces & Systems Programming

Talk to the kernel directly. Understand the systems you trace with ftrace.

Topic Description Status

Netlink sockets

socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) — query and modify the kernel routing table, ARP/neighbor table, interfaces from C. How ip route and ip neigh work. man 7 netlink.

□□□□□□□□□□ 0/10

MAC table (FDB)

Read the kernel’s forwarding database via netlink. RTM_GETNEIGH — same data as bridge fdb show. Build your own show mac address-table.

□□□□□□□□□□ 0/10

ioctl

ioctl() — the swiss army knife syscall. Get/set interface flags, MTU, hardware address. man 2 ioctl, man 7 netdevice.

□□□□□□□□□□ 0/10

/proc and /sys

Read kernel state from C: /proc/net/arp (ARP table), /proc/net/tcp (TCP connections), /sys/class/net/ (interface details). Parse structured text in C.

□□□□□□□□□□ 0/10

Signal handling

signal(), sigaction() — handle SIGINT, SIGTERM, SIGHUP gracefully. How daemons stay alive. man 7 signal.

□□□□□□□□□□ 0/10

Process management

fork(), exec(), wait(), pipe() — how shells work. Build a simplified sh. man 2 fork.

□□□□□□□□□□ 0/10

mmap

Memory-mapped files and shared memory. mmap() maps a file directly into memory — no read/write syscalls. How databases and log files work at scale. man 2 mmap.

□□□□□□□□□□ 0/10

epoll (event-driven I/O)

epoll_create, epoll_ctl, epoll_wait — handle thousands of connections. How nginx, HAProxy, and ISE’s RADIUS listener work. man 7 epoll.

□□□□□□□□□□ 0/10

ftrace from C

Read and write /sys/kernel/tracing/ from a C program. Programmatic control of Rostedt’s infrastructure. Trace your own functions.

□□□□□□□□□□ 0/10

eBPF (intro)

Write C programs that run inside the kernel. Packet filtering, tracing, security enforcement at wire speed. The future of AppArmor, firewalling, and observability.

□□□□□□□□□□ 0/10

Phase 10: Security in C

Write secure code. Break insecure code. Understand what AppArmor protects against.

Topic Description Status

Buffer overflows

Stack smashing, gets() vs fgets(), stack canaries, ASLR. Write a vulnerable program, then exploit it. Understand what -fstack-protector does.

□□□□□□□□□□ 0/10

Format string attacks

printf(user_input) vs printf("%s", user_input). Read arbitrary memory. Understand why gcc -Wall warns about this.

□□□□□□□□□□ 0/10

Integer overflows

Signed/unsigned confusion. size_t vs ssize_t. What happens when int wraps. How this causes real CVEs.

□□□□□□□□□□ 0/10

ASLR and PIE

Address Space Layout Randomization. Position-Independent Executables. cat /proc/self/maps. Why addresses change every run.

□□□□□□□□□□ 0/10

seccomp

Restrict which syscalls a process can make. Write a seccomp filter in C. This is how Docker and Chrome sandbox processes. Complements AppArmor.

□□□□□□□□□□ 0/10

Capabilities

CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_PTRACE — fine-grained root. man 7 capabilities. Why raw sockets need CAP_NET_RAW not full root.

□□□□□□□□□□ 0/10

TLS in C

OpenSSL’s C API — SSL_CTX_new(), SSL_connect(), SSL_read(), SSL_write(). Build a TLS client that connects to ISE. Same handshake your ers() function does.

□□□□□□□□□□ 0/10

RADIUS packet

Build a RADIUS Access-Request in C — shared secret, authenticator, AVPs. Send to ISE, parse Access-Accept. Understand every field in your MnT auth history.

□□□□□□□□□□ 0/10

Phase 11: Embedded & Hardware (Optional Track)

Requires a microcontroller board. Different toolchain, no OS, no libc.

Topic Description Status

Cross-compilation

arm-none-eabi-gcc — compile for ARM on your x86 workstation. Linker scripts, startup code. Different world from gcc -o hello.

□□□□□□□□□□ 0/10

GPIO

Blink an LED. Read a button. Direct register manipulation — volatile uint32_t *GPIO_PORT = (uint32_t *)0x40020000. No fopen, no kernel — you ARE the kernel.

□□□□□□□□□□ 0/10

UART / Serial

Send bytes between board and workstation. minicom on your end, register writes on the board. This is how serial consoles on switches work.

□□□□□□□□□□ 0/10

SPI / I2C

Talk to sensors — temperature, accelerometer, OLED display. Master/slave protocols. Clock + data lines.

□□□□□□□□□□ 0/10

Interrupts

Hardware events trigger your C function — no polling. Timer interrupts, GPIO edge detection. How network cards signal "packet arrived."

□□□□□□□□□□ 0/10

RTOS

FreeRTOS task scheduling — multiple "threads" on a microcontroller with no MMU. Priority-based preemption. How IoT devices (your Philips FSE, TCP clocks) run firmware.

□□□□□□□□□□ 0/10

Bare-metal TCP/IP

lwIP or similar — TCP/IP stack without Linux. Understand every layer because you built it. This is how medical devices and industrial controllers network.

□□□□□□□□□□ 0/10

Table 1. Recommended starter hardware
Board Why Cost

Raspberry Pi Pico

RP2040, great docs, C SDK, no Linux — true bare metal

~$4

STM32 Nucleo-F446RE

ARM Cortex-M4, industry standard, excellent HAL docs

~$15

ESP32-DevKitC

WiFi + Bluetooth, FreeRTOS built-in, IoT focus

~$10

Resources

Video

  • "What is Actually EOF?" — You Suck at Programming (Dave)

    • Three abstraction layers: stdio → syscalls → bash heredocs

    • Transcript: education/programming/c/eof-transcript.adoc

    • Key insight: EOF is not a character, not a signal — it’s "read returned zero bytes"

Books

  • The C Programming Language (Kernighan & Ritchie, 2nd Ed.) — the original, still the best

  • C Programming: A Modern Approach (K.N. King, 2nd Ed.) — more accessible, covers C99

  • Expert C Programming: Deep C Secrets (van der Linden) — advanced, demystifies the weird parts

  • Unix Network Programming (W. Richard Stevens) — the bible for socket programming (Phase 5, 8)

  • Linux System Programming (Robert Love) — syscalls, file I/O, process management (Phase 2, 9)

  • Understanding the Linux Kernel (Bovet & Cesati) — kernel internals (Phase 9, 10)

  • Making Embedded Systems (Elecia White) — practical embedded C (Phase 11)

Man Pages (Primary Curriculum)

  • man 3 intro — introduction to library functions

  • man 2 intro — introduction to system calls

  • man 3 stdio — standard I/O overview

  • man 3 fopen, man 3 fgetc, man 3 fclose — Phase 1 functions

  • man 2 open, man 2 read, man 2 close, man 2 write — Phase 2 syscalls

  • man 7 signal — signal handling concepts

  • man 7 packet — raw packet sockets (Phase 8)

  • man 7 netlink — kernel netlink interface (Phase 9)

  • man 7 netdevice — network device ioctl (Phase 9)

  • man 7 epoll — event-driven I/O (Phase 9)

  • man 7 capabilities — Linux capabilities (Phase 10)

Online

Key People

Dennis Ritchie

Created C and co-created Unix. K&R is his book.

Brian Kernighan

Co-authored K&R. Coined "Hello, World."

Steven Rostedt

Author of ftrace. Your kernel tracing infrastructure.

Robert Love

Linux kernel developer, wrote the systems programming book.

W. Richard Stevens

Wrote the networking bibles. Died in 1999. His books are still the standard.

Linus Torvalds

Created Linux. Writes C daily. His code review emails are curriculum.