Skip to main content
WorkProjects

POSIX Print Spooler

Job scheduler with signal handling

stable
View raw

A POSIX-compliant print spooler written in C99 against raw system calls — fork, execvp, pipe, dup2, waitpid, sigaction, Unix domain sockets. Multi-process job pipelines, a signal-driven scheduler, and a runtime conversion graph that chains file-type converters into printer endpoints. Zero system() calls.

What it is

A driver CLI, a scheduler, and per-job pipelines that chain converters into printer endpoints over Unix domain sockets. Jobs traverse JOB_CREATED -> JOB_RUNNING -> {PAUSED, FINISHED, ABORTED, DELETED}; printers traverse DISABLED -> IDLE -> BUSY. The scheduler matches jobs to eligible printers by declared file type and resolves multi-stage conversions via shortest-path search over a directed graph. Built for Stony Brook CSE 320 (Systems Programming, Spring 2025); the presi.h contract is instructor-fixed, all src/ logic is original.

By the numbers

MetricValue
Source lines1,684 C across 5 files
Headers9 in include/
Test files3 (Criterion framework)
Capacity32 printers, 64 concurrent jobs
system() calls0
Compiler flags-Wall -Werror

Architecture

 driver (CLI)
     |
     v
 command_handler  -- parses type / printer / conversion / print / pause / resume / cancel / disable / enable
     |
     v
 job_manager      -- job table, state machine, pipeline fork/exec, pgid tracking
     |                ^
     |                | SIGCHLD, SIGSTOP/SIGCONT, SIGTERM
     v                |
 printer_manager  -- printer table, Unix domain socket connect, file-type match
     |
     v
 printer processes (util/printer)    converter processes (util/convert)
  • src/cli.c (279 lines) — readline-style command loop.
  • src/command_handler.c (533 lines) — lexing, dispatch, argument validation.
  • src/job_manager.c (579 lines) — job lifecycle, fork pipeline, SIGCHLD reaper.
  • src/printer_manager.c (207 lines) — printer registry, socket wiring.
  • src/main.c (86 lines) — getopt entry, sf_init/sf_fini bookends.

Key features

  • Process pipelines — each job spawns a master that forks a chain of converters via fork() + pipe() + dup2() + execvp(). The final stage writes to a printer fd returned by presi_connect_to_printer(). Pipeline members share a process group so signals hit every stage atomically.
  • Signal handlingSIGCHLD reaps dying pipeline children and updates job state without blocking the CLI; SIGSTOP/SIGCONT pause and resume jobs by targeting the whole process group; SIGTERM drives graceful shutdown. All handlers are async-signal-safe; sigprocmask() protects shared state across the main loop and the handler.
  • IPC — Unix domain sockets connect the spooler to printer daemons; pipes carry converted bytes between pipeline stages. No shared memory, no threads.
  • Conversion graphconversions.c exposes a directed graph of conversion <from> <to> <cmd> edges. The scheduler runs shortest-path search to synthesize a multi-stage pipeline when no direct converter exists.
  • Job controlpause, resume, cancel, disable target live jobs or printers; state transitions fire sf_* event hooks for deterministic grading and replay.

What makes it stand out

  • Raw POSIX, zero shell. No system(), no wrappers — every process is fork + execvp, every byte moves through explicit pipes or sockets.
  • Graph-resolved pipelines. Indirect conversions synthesize at runtime via shortest-path search over the converter graph.
  • Clean under Valgrind. --leak-check=full --track-fds=yes runs zero leaks, zero leaked descriptors across the Criterion suite.

Stack

LayerTechnology
LanguageC99 (_POSIX_SOURCE, _DEFAULT_SOURCE)
Process / IPCfork, execvp, waitpid, pipe, dup2, setpgid, Unix domain sockets
Signalssigaction, sigprocmask, kill
ToolchainGCC -Wall -Werror, Criterion, Valgrind