# sysv-wrapper Makefile. # # Build: make # Install: make install DESTDIR= (defaults to /) # Clean: make clean # # Installs the wrapper at /sbin/sysv-wrapper and symlinks the legacy # tool names to it. /sbin/init is NOT symlinked here — that path is # the zyginit daemon binary. If you want sysv-wrapper to handle # `init ` too, move zyginit aside (e.g. to /sbin/zyginit) and # symlink /sbin/init -> sysv-wrapper instead. CC ?= gcc CFLAGS ?= -O2 -Wall DESTDIR ?= SBIN = $(DESTDIR)/sbin WRAPPER = $(SBIN)/sysv-wrapper all: sysv-wrapper sysv-wrapper: wrapper.c version.h $(CC) $(CFLAGS) -o $@ wrapper.c install: sysv-wrapper install -d $(SBIN) install -m 0755 sysv-wrapper $(WRAPPER) ln -sf sysv-wrapper $(SBIN)/halt ln -sf sysv-wrapper $(SBIN)/reboot ln -sf sysv-wrapper $(SBIN)/poweroff ln -sf sysv-wrapper $(SBIN)/telinit clean: rm -f sysv-wrapper .PHONY: all install clean ELF>@@8@8@ @@@pp-- -==-==PPP ppp$$###StdPPP Ptd!!!44QtdRtd-==88GNUGNU-ATb䎸n /lib64/ld-linux-x86-64.so.2emi <b; [ R.4C"freestrdup__xpg_basename__libc_start_mainexeclstderrfprintf__cxa_finalizestrerrorfwritestrcmp__errno_locationlibc.so.6GLIBC_2.34GLIBC_2.2.5_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTablezui = =X@X@???? ??@@@@ @(@ 0@ 8@ @@ H@HH/HtH5/%/@%/h%/h%/h%/h%/h%/h%/h%/hp%/h`%/h P%/fAVSPHHH5H11H.L008H5HLHI1H[A^4@1I^HHPTE11H=S.f.H=.H.H9tH6.Ht H=.H5.H)HH?HHHtH.HtfD=u.u+UH=-Ht H=V.dM.]wUAWAVATSIH>[HIH'HÃ|UMfH5LtA<$-u7A|$Vu/A|$u'H=H1H1L_H5HtH5jHu~EH,H8IH51tH,HH=oINЃCH HcHH=DH5 HuH= gH5 Hu*H= CqH= 5cH= 'UH5 HuH=y 4H+H8H5j HH+H8IH5 1`[A\A^A_]HHiEEEout of memory --version%s %s 0.1.2telinithaltrebootpoweroffsysv-wrapper: unknown invocation '%s' usage: %s singlemultireload%s: unknown runlevel '%s' /sbin/zygctl%s: cannot exec %s: %s sysv-wrapper;4(hHP8zRx &D$4FJ w?;*3$"\@8tABB B(A0(B BBA$\BAA PABGNU`~FDO{"type":"deb","os":"ubuntu","name":"glibc","version":"2.42-0ubuntu3.1","architecture":"amd64"} z  ==op ? ooxooPo=6FVfvX@GCC: (Ubuntu 15.2.0-4ubuntu4) 15.2.0Ubuntu clang version 21.1.2 (2ubuntu6) # \(3p5H^`@j= =(#=!? *G r P@c`@j pP@} X@ h@v@&`@0`@ 9Las" Scrt1.o__abi_tagwrapper.crun_zygctlcrtstuff.cderegister_tm_clones__do_global_dtors_auxcompleted.0__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entry__FRAME_END___DYNAMIC__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE_free@GLIBC_2.2.5__libc_start_main@GLIBC_2.34__errno_location@GLIBC_2.2.5_ITM_deregisterTMCloneTable_edata_fini__data_startstrcmp@GLIBC_2.2.5fprintf@GLIBC_2.2.5__gmon_start____dso_handle_IO_stdin_used__xpg_basename@GLIBC_2.2.5_end__bss_startmainfwrite@GLIBC_2.2.5__TMC_END___ITM_registerTMCloneTablestrdup@GLIBC_2.2.5strerror@GLIBC_2.2.5execl@GLIBC_2.2.5__cxa_finalize@GLIBC_2.2.5_initstderr@GLIBC_2.2.5.symtab.strtab.shstrtab.note.gnu.property.note.gnu.build-id.interp.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.note.ABI-tag.note.package.init_array.fini_array.dynamic.got.plt.data.bss.commentPP .pp$AIo$S [ppcoPP"poxx0B  @    !!40"0"## (#(#p=-=-=-?/0 ?/hP@P0`@`00`0L0h 57(/****************************************************************************** __ ____ __ / / ___ ____ _/ __/_____________ _/ /__ / / / _ \/ __ `/ /_/ ___/ ___/ __ `/ / _ \ / /___/ __/ /_/ / __(__ ) /__/ /_/ / / __/ /_____/\___/\__,_/_/ /____/\___/\__,_/_/\___/ (C)opyright 2025-2026, Leafscale, LLC - https://www.leafscale.com Project: zyginit Filename: version.h Authors: Chris Tusa License: Description: Generated version constant. Do not edit by hand — regenerated by scripts/bump-version.sh. ******************************************************************************/ #ifndef ZYGINIT_VERSION_H #define ZYGINIT_VERSION_H #define ZYGINIT_VERSION "0.2.7" #endif /* * sysv-wrapper — translate traditional sysv-init commands to zygctl calls. * * Installed as multiple symlinks pointing at the same binary; we dispatch * on argv[0] (basename) so each link behaves like the legacy tool. * * /sbin/init map runlevel char to a zygctl verb * /sbin/telinit same; telinit is the historical client name * /sbin/halt zygctl halt * /sbin/reboot zygctl reboot * /sbin/poweroff zygctl poweroff * * The wrapper itself does not connect to zyginit's socket — it just exec's * /sbin/zygctl with the right verb. zygctl handles the socket protocol. * * Note: when /sbin/init is run by the kernel as PID 1, it is the zyginit * daemon binary, NOT this wrapper. This wrapper lives at a different path * (or replaces /sbin/init only on systems where zyginit is at /sbin/zyginit). * On the current Hammerhead deploy /sbin/init IS zyginit; the wrapper * is therefore meant for /sbin/halt, /sbin/reboot, /sbin/poweroff, * /sbin/telinit. If you DO want /sbin/init to be this wrapper, install * zyginit at /sbin/zyginit and point the kernel boot path there. */ #include #include #include #include #include #include #include "version.h" #define ZYGCTL "/sbin/zygctl" static int run_zygctl(const char *verb) { execl(ZYGCTL, "zygctl", verb, (char *)NULL); /* execl returns only on failure */ (void) fprintf(stderr, "%s: cannot exec %s: %s\n", "sysv-wrapper", ZYGCTL, strerror(errno)); return (1); } static int init_dispatch(int argc, char **argv) { if (argc < 2) { (void) fprintf(stderr, "usage: %s \n", argv[0]); return (1); } switch (argv[1][0]) { case '0': return (run_zygctl("halt")); case '5': return (run_zygctl("poweroff")); case '6': return (run_zygctl("reboot")); case '1': case 's': case 'S': return (run_zygctl("single")); case '2': case '3': case '4': return (run_zygctl("multi")); case 'q': case 'Q': return (run_zygctl("reload")); default: (void) fprintf(stderr, "%s: unknown runlevel '%s'\n", argv[0], argv[1]); return (1); } } int main(int argc, char **argv) { const char *me; char *argv0_copy; /* basename(3) on illumos modifies its argument, so duplicate first */ argv0_copy = strdup(argv[0]); if (argv0_copy == NULL) { (void) fprintf(stderr, "out of memory\n"); return (1); } me = basename(argv0_copy); if (argc >= 2 && (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)) { (void) printf("%s %s\n", me, ZYGINIT_VERSION); free(argv0_copy); return (0); } if (strcmp(me, "init") == 0 || strcmp(me, "telinit") == 0) return (init_dispatch(argc, argv)); if (strcmp(me, "halt") == 0) return (run_zygctl("halt")); if (strcmp(me, "reboot") == 0) return (run_zygctl("reboot")); if (strcmp(me, "poweroff") == 0) return (run_zygctl("poweroff")); (void) fprintf(stderr, "sysv-wrapper: unknown invocation '%s'\n", me); return (1); }