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

✅ Done (2026-04-25)

Man pages

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

✅ Done (2026-04-25)

Debugging tools

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

✅ Done (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

✅ Done (2026-04-26)

Types and variables

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

✅ Done (2026-04-26)

File I/O (stdio)

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

✅ Done (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>.

✅ Done (2026-04-26)

Loops

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

✅ Done (2026-04-26)

Error checking

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

✅ Done (2026-04-26)

printf formatting

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

✅ Done (2026-04-26)

Hex reader

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

✅ Done (2026-04-26)

Syscall tracing (strace)

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

✅ Done (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.

✅ Done (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.

✅ Done (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.

❌ Not started

open / read / close

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

❌ Not started

Buffers

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

❌ Not started

EOF at syscall level

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

❌ Not started

ssize_t

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

❌ Not started

Standard input

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

❌ Not started

Ctrl+D

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

❌ Not started

Phase 3: Headers & the Preprocessor

Topic Description Status

#include

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

❌ Not started

#define

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

❌ Not started

Header discovery

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

❌ Not started

Phase 4: Memory & Pointers

Topic Description Status

Pointers

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

❌ Not started

Arrays and buffers

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

❌ Not started

malloc / free

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

❌ Not started

Strings

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

❌ Not started

Phase 5: Networking (Work Application)

Topic Description Status

Sockets

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

❌ Not started

TCP client

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

❌ Not started

Structs

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

❌ Not started

select / poll / epoll

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

❌ Not started

Phase 6: Build Systems & Real Projects

Topic Description Status

Makefiles

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

❌ Not started

Multi-file projects

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

❌ Not started

Libraries

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

❌ Not started

Reading source

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

❌ Not started

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.

❌ Not started

Bit masks

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

❌ Not started

Byte order

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

❌ Not started

Packed structs

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

❌ Not started

Hex arithmetic

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

❌ Not started

volatile

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

❌ Not started

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.

❌ Not started

Ethernet frame

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

❌ Not started

ARP

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

❌ Not started

IP header

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

❌ Not started

TCP/UDP headers

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

❌ Not started

ICMP

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

❌ Not started

Pcap parsing

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

❌ Not started

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.

❌ Not started

802.1X / EAP

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

❌ Not started

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.

❌ Not started

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.

❌ Not started

ioctl

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

❌ Not started

/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.

❌ Not started

Signal handling

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

❌ Not started

Process management

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

❌ Not started

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.

❌ Not started

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.

❌ Not started

ftrace from C

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

❌ Not started

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.

❌ Not started

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.

❌ Not started

Format string attacks

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

❌ Not started

Integer overflows

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

❌ Not started

ASLR and PIE

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

❌ Not started

seccomp

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

❌ Not started

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.

❌ Not started

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.

❌ Not started

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.

❌ Not started

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.

❌ Not started

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.

❌ Not started

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.

❌ Not started

SPI / I2C

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

❌ Not started

Interrupts

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

❌ Not started

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.

❌ Not started

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.

❌ Not started

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.