From eedc8a504aaedc9e771cf4212fb3a51d3bd8ee70 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Thu, 30 Oct 2025 13:45:34 -0700 Subject: [PATCH 01/49] Uses endian independent structure layouts to access returned ethernet packet length field --- src/ether_nethub.c | 4 +--- src/ether_sunos.c | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ether_nethub.c b/src/ether_nethub.c index e9803e26..d7d0f471 100644 --- a/src/ether_nethub.c +++ b/src/ether_nethub.c @@ -297,12 +297,10 @@ static int recvPacket(void) { #if defined(BYTESWAP) log_debug((" recvPacket() :: byte-swapping %d bytes at %p\n", bLen, (void *)ether_buf)); dblwordsSwap(ether_buf, bLen); - IOPage->dlethernet[2] = bLen; #else log_debug((" recvPacket() :: %d bytes at %p\n", bLen, (void *)ether_buf)); - IOPage->dlethernet[3] = bLen; #endif - + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = blen; ether_bsize = 0; diff --git a/src/ether_sunos.c b/src/ether_sunos.c index ba75cf14..73799fc7 100644 --- a/src/ether_sunos.c +++ b/src/ether_sunos.c @@ -477,7 +477,7 @@ int *ether_debug(void) { estat[0] = 0; if (ether_fd < 0) return (NIL); printf("fd %d bsize %d buf %p icb %X in %d out %d\n ", ether_fd, ether_bsize, (void *)ether_buf, - IOPage->dlethernet[3], ether_in, ether_out); + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB, ether_in, ether_out); #endif /* MAIKO_ENABLE_ETHERNET */ return (estat); @@ -542,7 +542,7 @@ LispPTR check_ether(void) { memcpy(ðer_buf[0], &nit_buf[nitpos], fromlen); ether_bsize = 0; /* deactivate receiver */ ether_in++; - IOPage->dlethernet[3] = fromlen; + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = fromlen; DBPRINT( ("Found packet len %d, at pos %d in buflen %d.\n", fromlen, nitpos, nitlen)); nitpos += fromlen; @@ -586,7 +586,7 @@ LispPTR check_ether(void) { memcpy(ðer_buf[0], nit_buf, data.len); ether_bsize = 0; ether_in++; - IOPage->dlethernet[3] = data.len; + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = data.len; ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->ETHERInterrupt = 1; ETHEREventCount++; Irq_Stk_Check = Irq_Stk_End = 0; @@ -649,7 +649,7 @@ LispPTR get_packet(void) { memcpy(ðer_buf[0], &nit_buf[nitpos], fromlen); ether_bsize = 0; /* deactivate receiver */ ether_in++; - IOPage->dlethernet[3] = fromlen; + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = fromlen; DBPRINT(("Found packet len %d, at pos %d in buflen %d.\n", fromlen, nitpos, nitlen)); nitpos += fromlen; return (ATOM_T); @@ -683,7 +683,7 @@ LispPTR get_packet(void) { memcpy(ðer_buf[0], nit_buf, data.len); ether_bsize = 0; ether_in++; - IOPage->dlethernet[3] = data.len; + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = data.len; return (ATOM_T); } } else if (errno != EWOULDBLOCK) From cdaa7b6889f55877fbec8667b68e9e6e014f4853 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 7 Dec 2025 18:39:59 -0800 Subject: [PATCH 02/49] Cleans up the interrupt state structure to match Lisp naming Adds names for individual interrupt-in-progress bits in the struct interrupt_state to match the structure defined in Lisp. Adjusts the base datatype to DLword to make clear the size and alignment of interrupt bits in the structure. --- inc/lispemul.h | 58 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/inc/lispemul.h b/inc/lispemul.h index cbf05598..95a7b1f6 100644 --- a/inc/lispemul.h +++ b/inc/lispemul.h @@ -65,21 +65,28 @@ typedef struct closure_type { #endif /* BIGVM */ typedef struct interrupt_state { /* Interrupt-request mask to communicate with INTERRUPTED */ - unsigned LogFileIO : 1; /* console msg arrived to print */ - unsigned ETHERInterrupt : 1; /* 10MB activity happened */ - unsigned IOInterrupt : 1; /* I/O happened (not used yet) */ - unsigned gcdisabled : 1; - unsigned vmemfull : 1; - unsigned stackoverflow : 1; - unsigned storagefull : 1; - unsigned waitinginterrupt : 1; - unsigned nil : 8; /* mask of ints being processed */ + DLword LogFileIO : 1; /* console msg arrived to print */ + DLword ETHERInterrupt : 1; /* 10MB activity happened */ + DLword IOInterrupt : 1; /* I/O happened (not used yet) */ + DLword gcdisabled : 1; + DLword vmemfull : 1; + DLword stackoverflow : 1; + DLword storagefull : 1; + DLword waitinginterrupt : 1; + DLword P_LogFileIO : 1; /* interrupts awaiting processing, cleared by Lisp */ + DLword P_ETHERInterrupt : 1; + DLword P_IOInterrupt : 1; + DLword P_gcdisabled : 1; + DLword P_vmemfull : 1; + DLword P_stackoverflow : 1; + DLword P_storagefull : 1; + DLword P_waitinginterrupt : 1; DLword intcharcode; } INTSTAT; typedef struct interrupt_state_2 { /* alternate view of the interrupt state */ - unsigned pendingmask : 8; - unsigned handledmask : 8; + DLword pendingmask : 8; + DLword handledmask : 8; DLword nil; } INTSTAT2; @@ -204,21 +211,28 @@ typedef struct closure_type { typedef struct interrupt_state { /* Interrupt-request mask to communicate with INTERRUPTED */ DLword intcharcode; - unsigned nil : 8; - unsigned waitinginterrupt : 1; - unsigned storagefull : 1; - unsigned stackoverflow : 1; - unsigned vmemfull : 1; - unsigned gcdisabled : 1; - unsigned IOInterrupt : 1; /* I/O happened (not used yet) */ - unsigned ETHERInterrupt : 1; /* 10MB activity happened */ - unsigned LogFileIO : 1; /* console msg arrived to print */ + DLword P_waitinginterrupt : 1; /* interrupts awaiting processing, cleared by Lisp */ + DLword P_storagefull : 1; + DLword P_stackoverflow : 1; + DLword P_vmemfull : 1; + DLword P_gcdisabled : 1; + DLword P_IOInterrupt : 1; + DLword P_ETHERInterrupt : 1; + DLword P_LogFileIO : 1; + DLword waitinginterrupt : 1; + DLword storagefull : 1; + DLword stackoverflow : 1; + DLword vmemfull : 1; + DLword gcdisabled : 1; + DLword IOInterrupt : 1; /* I/O happened (not used yet) */ + DLword ETHERInterrupt : 1; /* 10MB activity happened */ + DLword LogFileIO : 1; /* console msg arrived to print */ } INTSTAT; typedef struct interrupt_state_2 { /* alternate view of the interrupt state */ DLword nil; - unsigned handledmask : 8; - unsigned pendingmask : 8; + DLword handledmask : 8; + DLword pendingmask : 8; } INTSTAT2; struct state { From a074c4a3c01368d2a112beba2d11f1f17730f20b Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 7 Dec 2025 21:11:39 -0800 Subject: [PATCH 03/49] Adds required include of for strncpy in non-BYTESWAP compilations. --- inc/locfile.h | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/locfile.h b/inc/locfile.h index 59de1d69..2e19cf73 100644 --- a/inc/locfile.h +++ b/inc/locfile.h @@ -11,6 +11,7 @@ #include #include /* for NAME_MAX */ #include /* for MAXNAMLEN */ +#include /* for strncpy in non-BYTESWAP case */ #include "lispemul.h" /* for DLword */ #include "commondefs.h" /* for error */ From 5432d7381934efa249ea78fb5867c522854d08b6 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Thu, 11 Dec 2025 09:18:40 -0800 Subject: [PATCH 04/49] Adds generation of SIGIO on X11 connection if O_ASYNC defined --- src/xinit.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/xinit.c b/src/xinit.c index 8ad1db78..a0b2772d 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -17,6 +17,8 @@ #include // for false, bool, true #include // for NULL #include // for exit +#include // for fcntl, O_ASYNC, ... +#include // for getpid #include "adr68k.h" // for NativeAligned4FromLAddr #include "dbprint.h" // for TPRINT #include "devif.h" // for (anonymous), MRegion, DspInterface, OUTER_S... @@ -248,6 +250,7 @@ DspInterface X_init(DspInterface dsp, LispPTR lispbitmap, unsigned width_hint, u unsigned depth_hint) { Screen *Xscreen; + int xfd; dsp->identifier = Display_Name; /* This is a hack. The display name */ /* has to dealt with in a more */ @@ -360,5 +363,12 @@ DspInterface X_init(DspInterface dsp, LispPTR lispbitmap, unsigned width_hint, u break; } XInitImage(&dsp->ScreenBitmap); + +#if defined(O_ASYNC) + xfd = ConnectionNumber(dsp->display_id); + if (fcntl(xfd, F_SETOWN, getpid()) == -1) perror("X_init: fcntl F_SETOWN error"); + if (fcntl(xfd, F_SETFL, fcntl(xfd, F_GETFL, 0) | O_ASYNC) == -1) perror("X_init: fcntl F_SETFL O_ASYNC error"); +#endif + return (dsp); } From 6c8096262134034e18498ca1503b6852a54c400f Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 28 Apr 2026 18:46:22 -0700 Subject: [PATCH 05/49] Replaces display subsystem specific procedures with process_Display_events() Cleans up include of xwinmandefs.h and sdldefs.h to depend on which display subsystem is being compiled in to create ldex and ldesdl. Replaces process_SDLevents and process_Xevents with process_Display_events to avoid conditional compilation around which process_..._events to call. Updates commentary in various places to be clearer. Unrelated change included in xc.c: Cleans up usage of booleans extended_frame and need_irq to use TRUE/FALSE since they are declared integer not LispPTR and therefore should not be using T/NIL. Changes to be committed: modified: inc/sdldefs.h modified: inc/xwinmandefs.h modified: src/sdl.c modified: src/xc.c modified: src/xwinman.c --- inc/sdldefs.h | 3 +- inc/xwinmandefs.h | 2 +- src/sdl.c | 2 +- src/xc.c | 83 +++++++++++++++++++---------------------------- src/xwinman.c | 4 +-- 5 files changed, 39 insertions(+), 55 deletions(-) diff --git a/inc/sdldefs.h b/inc/sdldefs.h index e1a0c185..65705f8a 100644 --- a/inc/sdldefs.h +++ b/inc/sdldefs.h @@ -1,11 +1,10 @@ #ifndef SDLDEFS_H #define SDLDEFS_H 1 - void sdl_notify_damage(int x, int y, int w, int h); void sdl_setCursor(int hot_x, int hot_y); void sdl_bitblt_to_screen(int x, int y, int w, int h); void sdl_set_invert(int flag); void sdl_setMousePosition(int x, int y); -void process_SDLevents(); +void process_Display_events(void *dsp); int init_SDL(char *windowtitle, int w, int h, int s); #endif diff --git a/inc/xwinmandefs.h b/inc/xwinmandefs.h index e1f58f25..28e060a8 100644 --- a/inc/xwinmandefs.h +++ b/inc/xwinmandefs.h @@ -7,5 +7,5 @@ void Set_BitGravity(XButtonEvent *event, DspInterface dsp, Window window, int gr void enable_Xkeyboard(DspInterface dsp); void disable_Xkeyboard(DspInterface dsp); void beep_Xkeyboard(DspInterface dsp); -void process_Xevents(DspInterface dsp); +void process_Display_events(DspInterface dsp); #endif diff --git a/src/sdl.c b/src/sdl.c index 7ef98b4a..572f29a7 100644 --- a/src/sdl.c +++ b/src/sdl.c @@ -1393,7 +1393,7 @@ void sdl_update_display() { } #endif int process_events_time = 0; -void process_SDLevents() { +void process_Display_events(void *dsp) { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { diff --git a/src/xc.c b/src/xc.c index bfb1b925..fdd0a777 100644 --- a/src/xc.c +++ b/src/xc.c @@ -98,24 +98,21 @@ #include "ubf3defs.h" #include "unwinddefs.h" #include "vars3defs.h" -#ifdef XWINDOW +#if defined(XWINDOW) #include "xwinmandefs.h" +#elif defined(SDL) +#include "sdldefs.h" #endif #include "z2defs.h" #ifdef DOS -#include "devif.h" extern KbdInterface currentkbd; extern DspInterface currentdsp; extern MouseInterface currentmouse; -#elif defined(XWINDOW) +#else extern DspInterface currentdsp; #endif /* DOS */ -#ifdef SDL -extern void process_SDLevents(); -#endif - typedef struct conspage ConsPage; typedef ByteCode *InstPtr; @@ -154,6 +151,8 @@ LispPTR tscache asm("bx"); /* used by SIGIO signal handler to indicate I/O may be possible */ extern volatile sig_atomic_t IO_Signalled; +/* used by SIGVTALRM signal handler to indicate timer expired */ +extern volatile sig_atomic_t timer_Signalled; #ifdef PCTRACE /* For keeping a trace table (ring buffer) of 100 last PCs */ @@ -164,7 +163,7 @@ int pccounter = 0; /* ring-buffer counter */ #endif /* PCTRACE */ extern int extended_frame; -int extended_frame; /*indicates if soft stack overflow */ +int extended_frame; /* TRUE/FALSE indicates if soft stack overflow */ static const int n_mask_array[16] = { 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, @@ -175,9 +174,9 @@ extern int TIMER_INTERVAL; #if defined(MAIKO_EMULATE_TIMER_INTERRUPTS) || defined(MAIKO_EMULATE_ASYNC_INTERRUPTS) -# if !defined(MAIKO_TIMER_ASYNC_EMULATION_INSNS_COUNTDOWN) -# define MAIKO_TIMER_ASYNC_EMULATION_INSNS_COUNTDOWN 20000 -# endif +#if !defined(MAIKO_TIMER_ASYNC_EMULATION_INSNS_COUNTDOWN) +#define MAIKO_TIMER_ASYNC_EMULATION_INSNS_COUNTDOWN 20000 +#endif int insnsCountdownForTimerAsyncEmulation = MAIKO_TIMER_ASYNC_EMULATION_INSNS_COUNTDOWN; static int pseudoTimerAsyncCountdown = MAIKO_TIMER_ASYNC_EMULATION_INSNS_COUNTDOWN; @@ -285,15 +284,12 @@ op_ufn : { #if defined(MAIKO_EMULATE_TIMER_INTERRUPTS) || defined(MAIKO_EMULATE_ASYNC_INTERRUPTS) if (--pseudoTimerAsyncCountdown <= 0) { - Irq_Stk_Check = 0; - Irq_Stk_End = 0; -#if defined(MAIKO_EMULATE_ASYNC_INTERRUPTS) - IO_Signalled = TRUE; -#endif + /* Request interrupt handling */ + Irq_Stk_End = Irq_Stk_Check = 0; #ifdef MAIKO_OS_EMSCRIPTEN - emscripten_sleep(1); + emscripten_sleep(1); #endif - pseudoTimerAsyncCountdown = insnsCountdownForTimerAsyncEmulation; + pseudoTimerAsyncCountdown = insnsCountdownForTimerAsyncEmulation; } #endif @@ -1101,7 +1097,6 @@ op_ufn : { int need_irq; static int period_cnt = 60; extern int KBDEventFlg; - extern int ETHEREventCount; extern LispPTR *KEYBUFFERING68k; extern LispPTR *PENDINGINTERRUPT68k; extern LispPTR ATOM_STARTED; @@ -1115,15 +1110,15 @@ op_ufn : { odd bugs, ... */ /**** Changed back to > 31 July 97 ****/ re_check_stack: - need_irq = 0; + need_irq = FALSE; if (((UNSIGNED)(CSTKPTR + 1) > Irq_Stk_Check) && (Irq_Stk_End > 0) && (Irq_Stk_Check > 0)) { HARD_PUSH(TOPOFSTACK); EXT; - extended_frame = NIL; + extended_frame = FALSE; if (do_stackoverflow(NIL)) { stackoverflow_help: period_cnt = 60; - need_irq = T; + need_irq = TRUE; error("Stack Overflow, MUST HARDRESET!"); RET; TOPOFSTACK = NIL_PTR; @@ -1131,28 +1126,28 @@ op_ufn : { RET; POP; } - Irq_Stk_Check = (UNSIGNED)EndSTKP - STK_MIN(FuncObj); need_irq = (Irq_Stk_End == 0) || extended_frame; - *PENDINGINTERRUPT68k |= extended_frame; + Irq_Stk_Check = (UNSIGNED)EndSTKP - STK_MIN(FuncObj); Irq_Stk_End = (UNSIGNED)EndSTKP; + *PENDINGINTERRUPT68k |= extended_frame ? ATOM_T : 0; } - /* This is a good time to process keyboard/mouse and ethernet I/O - * X events are not managed in the async/SIGIO code while - * raw ethernet, serial port, and socket connections are. - * If the system is configured with SIGIO handling we have a hint - * that allows us to cheaply skip if there's nothing to do + /* clear the flags set by the OS interrupt handlers that would + * allow us to distinguish between them. */ -#ifdef XWINDOW - process_Xevents(currentdsp); -#endif -#ifdef SDL - process_SDLevents(); + timer_Signalled = IO_Signalled = FALSE; + /* this is a reasonable time to handle X/SDL display and + * other I/O events. These routines will set Irq_Stk_Check and + * Irq_Stk_End to zero and set interrupt state flags for the + * interrupts to be generated + */ + process_Display_events(currentdsp); +#ifndef INIT + process_io_events(); #endif - if (IO_Signalled) { - IO_Signalled = FALSE; - process_io_events(); - } + /* Irq_Stk_End and Irq_Stk_Check can also have been set to 0 by + * the VTALRM or SIGIO handlers (see timer.c) + */ if ((Irq_Stk_End <= 0) || (Irq_Stk_Check <= 0) || need_irq) { if (StackOffsetFromNative(CSTKPTR) > InterfacePage->stackbase) { @@ -1240,22 +1235,12 @@ op_ufn : { *PENDINGINTERRUPT68k = NIL; cause_interruptcall(INTERRUPTFRAME_index); } - } else if (ETHEREventCount > 0) { - INTSTAT *intstate = ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word)); - if (!(intstate->ETHERInterrupt) && !(((INTSTAT2 *)intstate)->handledmask & 0x40)) { - intstate->ETHERInterrupt = 1; - ((INTSTAT2 *)intstate)->handledmask |= ((INTSTAT2 *)intstate)->pendingmask; - cause_interruptcall(INTERRUPTFRAME_index); - ETHEREventCount--; - } else - *PENDINGINTERRUPT68k = ATOM_T; } RET; CLR_IRQ; } /* Interrupts not Disabled */ else { - /* Clear out IRQ (loses pending interrupt request - if interrupts are disabled) */ + /* Clear out IRQ (loses pending request if interrupts are disabled) */ CLR_IRQ; goto re_check_stack; } diff --git a/src/xwinman.c b/src/xwinman.c index 5f5c0f9d..df3f2a5e 100644 --- a/src/xwinman.c +++ b/src/xwinman.c @@ -172,7 +172,7 @@ void beep_Xkeyboard(DspInterface dsp) /************************************************************************/ /* */ -/* p r o c e s s _ X e v e n t s */ +/* p r o c e s s _ D i s p l a y _ e v e n t s */ /* */ /* Take X key/mouse events and turn them into Lisp events */ /* */ @@ -180,7 +180,7 @@ void beep_Xkeyboard(DspInterface dsp) extern int Current_Hot_X, Current_Hot_Y; /* Cursor hotspot */ -void process_Xevents(DspInterface dsp) +void process_Display_events(DspInterface dsp) { XEvent report; From 116aba297c2f8ce8268ef3cf87d1200480aa385c Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Wed, 29 Apr 2026 17:28:12 -0700 Subject: [PATCH 06/49] Adds new ethernet implementation ether_pcap.c, enabled in subsequent commits. --- bin/makefile-tail | 8 + src/ether_pcap.c | 417 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 425 insertions(+) create mode 100644 src/ether_pcap.c diff --git a/bin/makefile-tail b/bin/makefile-tail index 80bc2586..ef8081ec 100644 --- a/bin/makefile-tail +++ b/bin/makefile-tail @@ -118,6 +118,7 @@ DEVICES = $(OBJECTDIR)dspsubrs.o \ $(OBJECTDIR)ether_common.o \ $(OBJECTDIR)ether_sunos.o \ $(OBJECTDIR)ether_nethub.o \ + $(OBJECTDIR)ether_pcap.o \ $(OBJECTDIR)tty.o \ $(OBJECTDIR)initkbd.o @@ -495,6 +496,13 @@ $(OBJECTDIR)ether_nethub.o: $(SRCDIR)ether_nethub.c $(REQUIRED-INCS) \ $(INCDIR)dbprint.h $(INCDIR)etherdefs.h $(CC) $(RFLAGS) $(SRCDIR)ether_nethub.c -o $(OBJECTDIR)ether_nethub.o +$(OBJECTDIR)ether_pcap.o: $(SRCDIR)ether_pcap.c $(REQUIRED-INCS) \ + $(INCDIR)commondefs.h $(INCDIR)lispemul.h \ + $(INCDIR)lispmap.h $(INCDIR)emlglob.h $(INCDIR)lsptypes.h $(INCDIR)lspglob.h \ + $(INCDIR)ifpage.h $(INCDIR)iopage.h $(INCDIR)miscstat.h $(INCDIR)adr68k.h \ + $(INCDIR)dbprint.h $(INCDIR)etherdefs.h + $(CC) $(RFLAGS) $(SRCDIR)ether_pcap.c -o $(OBJECTDIR)ether_pcap.o + $(OBJECTDIR)findkey.o: $(SRCDIR)findkey.c $(REQUIRED-INCS) \ $(INCDIR)lispemul.h $(INCDIR)lispmap.h \ $(INCDIR)emlglob.h $(INCDIR)stack.h $(INCDIR)lspglob.h $(INCDIR)ifpage.h \ diff --git a/src/ether_pcap.c b/src/ether_pcap.c new file mode 100644 index 00000000..b534d98e --- /dev/null +++ b/src/ether_pcap.c @@ -0,0 +1,417 @@ +/* $Id: ether.c,v 1.4 2001/12/24 01:09:02 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */ + +/************************************************************************/ +/* */ +/* (C) Copyright 1989-1996 inclusive Venue. All Rights Reserved. */ +/* Manufactured in the United States of America. */ +/* */ +/************************************************************************/ + +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) + +#include "version.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef MAIKO_OS_SOLARIS +#include +#else +#include +#endif +#include +#ifdef MAIKO_OS_LINUX +#include +#else +#include +#endif +#include +#include +#include + +#include +#include +#include + +#include "commondefs.h" +#include "byteswapdefs.h" +#include "lispemul.h" +#include "lispmap.h" +#include "lisp2cdefs.h" +#include "emlglob.h" +#include "lsptypes.h" +#include "lspglob.h" +#include "adr68k.h" +#include "dbprint.h" +#include "etherdefs.h" +#include "ifpage.h" +#include "iopage.h" + +extern int ether_enabled; /* 0/1 should ethernet be turned on */ +extern int ether_fd; /* file descriptor for ether socket */ +extern u_char ether_host[6]; /* 48 bit address of this node */ +extern char ether_ifname[32]; /* name of ethernet interface */ +extern u_char broadcast[6]; +extern int ether_bsize; /* if nonzero then a receive is pending */ +extern u_char *ether_buf; /* address of receive buffer */ + +extern LispPTR *PENDINGINTERRUPT68k; +extern fd_set LispReadFds; + +#ifndef ETHERTYPE_PUP +#define ETHERTYPE_PUP 0x0200 +#endif +#ifndef ETHERTYPE_XNS +#define ETHERTYPE_XNS 0x0600 +#endif +#ifndef ETHERTYPE_3TO10 +#define ETHERTYPE_3TO10 0x0201 +#endif +#ifndef AF_PACKET +#define AF_PACKET (AF_MAX+1) +#endif + +static pcap_t *pcap_handle; + +/* PCAP packet filter for + * "(not arp and not ip) and (ether broadcast or ether dst 11:22:33:44:55:66)" + * into which we will insert our MAC address in place of 11:22:... + * Generate with tcpdump -dd '(...)' + * Could be compiled from the string by pcap_compile(), but then we wouldn't know the + * offset to substitute our ethernet address - if we used pcap_compile() we might want + * to just put our ethernet address into the text before compiling. + * + * Idea: let's not put the interface in promiscuous mode - then we don't have to test + * for broadcast and our mac address and this simplifies the setup by quite a bit. + * We'll still need to get the mac address for use in the interface page. + */ + +static struct bpf_insn bpf_insns_none[] = { + { 0x6, 0, 0, 0x00000000 } +}; + +static struct bpf_program filter_match_xns; + +static struct bpf_program filter_match_none = { + sizeof(bpf_insns_none) / sizeof(struct bpf_insn), + bpf_insns_none +}; + +static int ether_in = 0; /* number of packets received */ +static int ether_out = 0; /* number of packets sent */ + +/********************************************************************** + * recvPacket() + * retrieves an ether packet from the network and deposits it + * in the expected byte order in ether_buf, and sets ether_bsize + * to 0. + * Returns: 0 if no packet was read, + * length in bytes of the packet if one was read. + * + **********************************************************************/ +static int recvPacket() { + int pcap_rval = 0; + bpf_u_int32 hlen; + const uint16_t *packet = NULL; + struct pcap_pkthdr *header = NULL; + + switch (pcap_next_ex(pcap_handle, &header, (void *)&packet)) { + case 0: + return (0); + case PCAP_ERROR: + pcap_perror(pcap_handle, "recvPacket"); + return (0); + } + hlen = header->len; + if (hlen > ether_bsize || hlen == 0) return (0); + +#ifdef BYTESWAP + for (int i = 0; i < (hlen + 1) / 2; i++) { + GETBASEWORD((DLword *)ether_buf, i) = ntohs(packet[i]); + } +#else + memcpy(ether_buf, packet, hlen); +#endif + + ether_bsize = 0; + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = hlen; + return (hlen); +} + +/************************************************************************/ +/* */ +/* e t h e r _ s u s p e n d */ +/* */ +/* Suspend receiving packets. */ +/* */ +/************************************************************************/ + +LispPTR ether_suspend(LispPTR args[]) +{ + if (ether_fd == -1) return (NIL); + + /* The trick here is to install a packet filter */ + /* that rejects all packets, I think... */ + + pcap_setfilter(pcap_handle, &filter_match_none); + return (ATOM_T); +} /* ether_suspend */ + +/************************************************************************/ +/* */ +/* e t h e r _ r e s u m e */ +/* */ +/* resume receiving packets */ +/* */ +/************************************************************************/ + +LispPTR ether_resume(LispPTR args[]) +{ + if (ether_fd == -1) return (NIL); + + /* Install a packet filter that accepts all packets we want */ + pcap_setfilter(pcap_handle, &filter_match_xns); + return (ATOM_T); +} /* ether_resume */ + +/************************************************************************/ +/* */ +/* e t h e r _ c t r l r */ +/* */ +/* return T if ether controller is available 175/72/0 */ +/* */ +/************************************************************************/ + +LispPTR ether_ctrlr(LispPTR args[]) +{ + if (ether_fd < 0) return (NIL); + return (ATOM_T); +} + +/********************************************************************** + * ether_reset(args) 175/73/0 + * reset ether controller and disable receipt of packets + **********************************************************************/ +LispPTR ether_reset(LispPTR args[]) +{ + if (ether_fd < 0) { return (NIL); } + ether_bsize = 0; /* deactivate receiver */ + return (ATOM_T); +} /* ether_reset */ + +/************************************************************************/ +/* */ +/* e t h e r _ g e t (175/74/2) */ +/* */ +/* Set up the Ethernet driver to receive a packet. The driver */ +/* first tries to read any pending packet from the net, and if */ +/* there is one, ether_get returns T. If there is no pending */ +/* packet, the failing read sets us up to get an interrupt when */ +/* a packet DOES arrive, and ether_get returns NIL. */ +/* */ +/* args[0] Length of the buffer we're passed */ +/* args[1] LISP address of a packet buffer */ +/* */ +/* sets ether_buf to the buffer address, for check_ether's use */ +/* sets ether_bsize to the buffer size. ether_bsize>0 means */ +/* it's OK to read packets from the network on interrupt. */ +/* */ +/************************************************************************/ +LispPTR ether_get(LispPTR args[]) +{ + LispPTR result = NIL; + LispPTR MaxByteCount; + int length; + + DBPRINT(("Ether Get. ")); + if (ether_fd < 0) return (NIL); + MaxByteCount = BYTESPER_DLWORD * LispIntToCInt(args[0]); /* words to bytes */ + if (MaxByteCount == 0) return (NIL); + ether_buf = (u_char *)NativeAligned2FromLAddr(args[1]); + ether_bsize = MaxByteCount; /* do this LAST; it enables reads */ + length = recvPacket(); + if (length == 0) return (NIL); + return (T); +} /* ether_get */ + +/********************************************************************** + * ether_send(args) 175/75/2 max_words,buffer_addr + * send a packet + **********************************************************************/ +LispPTR ether_send(LispPTR args[]) +{ + DLword wordCount; + DLword *bufferAddr; /* buffer address pointer(in native address) */ +#ifdef BYTESWAP + DLword networkOrderBuffer[750]; +#endif + if (ether_fd < 0) return (NIL); + wordCount = LispIntToCInt(args[0]); + bufferAddr = NativeAligned2FromLAddr(args[1]); +#ifdef BYTESWAP + for (int i = 0; i < wordCount; i++) { + networkOrderBuffer[i] = htons(GETBASEWORD(bufferAddr, i)); + } + bufferAddr = networkOrderBuffer; +#endif + pcap_inject(pcap_handle, bufferAddr, 2 * wordCount); + ether_out++; + return (ATOM_T); +} /* ether_send */ + +/********************************************************************** + * ether_setfilter(args) 175/75/1 filterbits + * check whether a packet has come. if does, notify iocb + **********************************************************************/ + +LispPTR ether_setfilter(LispPTR args[]) +{ return (NIL); } +/* ether_setfilter */ + +/********************************************************************** + * ether_debug() + * returns the ethernet statistics. + **********************************************************************/ + +int estat[3]; + +int *ether_debug() { + estat[0] = 0; + if (ether_fd < 0) return (NIL); + printf("fd %d bsize %d buf %p icb %X in %d out %d\n ", ether_fd, ether_bsize, (void *)ether_buf, + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB, ether_in, ether_out); + return (estat); +} /* end ether_debug */ + +/********************************************************************** + * check_ether() + * checks for an incoming packet + **********************************************************************/ + +LispPTR check_ether() { +/* + * If the receiver is active then check if any packets are available + * from the ethernet, with the side-effect of reading a packet + * and setting the length in the ethernet ICB. + * Returns T if a packet was read, otherwise NIL. + */ + + if (ether_fd < 0 || ether_bsize == 0) return (NIL); + + return (0 == recvPacket()) ? NIL : ATOM_T; +} /* end check_ether */ + +/************************************************************************/ +/* i n i t _ e t h e r */ +/* */ +/* open pcap handle, called from main before starting BCE. */ +/* */ +/************************************************************************/ +void init_ether() { + /* Uses the following pcap library routines - + * pcap_create => gets a pcap_t handle + * pcap_findalldevs => list of network devices to capture on + * pcap_freealldevs => free the list of network devices from pcap_findalldevs + * pcap_set_snaplen => set the snapshot length for a not-yet-activated pcap_t handle + * pcap_set_buffer_size => set buffer size for a not-yet-activated pcap_t handle + * pcap_get_selectable_fd => fd to use in select/poll + * pcap_setnonblock => put pcap_t into non-blocking mode + * pcap_compile => compile filter + * pcap_setfilter => set filter on a pcap_t handle + * pcap_inject/pcap_sendpacket => transmit a packet + */ + + int pcap_rval = 0; + // char *etherdev = getenv("LDEETHERDEV"); /* name of interface we want */ + char devname[32] = {0}; + char errbuf[PCAP_ERRBUF_SIZE] = {0}; + char filter_exp[256]; + + /* ethernet may already be initialized - don't do it again */ + if (ether_fd >= 0 || ether_enabled == 0) return; + + /* select an ethernet interface if one was not provided */ + if (strlen(ether_ifname) == 0) { + pcap_if_t *alldevs = NULL; + pcap_if_t *dev = NULL; + pcap_rval = pcap_findalldevs(&alldevs, errbuf); + for (pcap_if_t *d = alldevs; d; d = d->next) { + if ((d->flags & PCAP_IF_UP) && (d->flags & PCAP_IF_RUNNING) && !(d->flags & PCAP_IF_LOOPBACK)) { + dev = d; + break; + } + } + /* did we find one */ + if (dev) { + strlcpy(ether_ifname, dev->name, sizeof(ether_ifname)); + for (pcap_addr_t *a = dev->addresses; a; a = a->next) { +#if defined(MAIKO_OS_SOLARIS) + /* Solaris defines both AF_LINK and AF_PACKET but neither give us + * the desired result + */ +#elif defined(AF_LINK) + /* this is BSD-like, macOS? */ + if (a->addr->sa_family == AF_LINK) { + memcpy(ether_host, LLADDR(((struct sockaddr_dl *)(a->addr))), sizeof(ether_host)); + break; + } +#elif defined(AF_PACKET) + /* this is Linux-like */ + if (a->addr->sa_family == AF_PACKET) { + memcpy(ether_host, ((struct sockaddr_ll *)(a->addr))->sll_addr, sizeof(ether_host)); + break; + } +#else +#warning Neither AF_LINK nor AF_PACKET address families defined +#endif + } + } + pcap_freealldevs(alldevs); + } + pcap_handle = pcap_create(ether_ifname, errbuf); + if (strlen(errbuf) > 0) { + fprintf(stderr, "%s\n", errbuf); + return; + } + /* set up properties on the pcap_handle and then activate it */ + pcap_rval = pcap_set_immediate_mode(pcap_handle, 1); + pcap_rval = pcap_set_buffer_size(pcap_handle, 65536); + pcap_rval = pcap_set_snaplen(pcap_handle, 1518); + pcap_rval = pcap_setfilter(pcap_handle, &filter_match_none); + pcap_rval = pcap_activate(pcap_handle); + if (pcap_rval != 0) { + pcap_perror(pcap_handle, "pcap_activate: "); + } + if (pcap_rval < 0) { + pcap_close(pcap_handle); + return; + } + snprintf(filter_exp, sizeof(filter_exp), "ether proto 0x600 and (ether multicast or ether dst %02x:%02x:%02x:%02x:%02x:%02x)", + ether_host[0], ether_host[1], ether_host[2], ether_host[3], ether_host[4], ether_host[5]); + pcap_rval = pcap_compile(pcap_handle, &filter_match_xns, filter_exp, 0, PCAP_NETMASK_UNKNOWN); + if (pcap_rval == -1) { + fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle)); + pcap_close(pcap_handle); + return; + } + pcap_rval = pcap_setfilter(pcap_handle, &filter_match_xns); + + pcap_rval = pcap_setnonblock(pcap_handle, 1, errbuf); + ether_fd = pcap_get_selectable_fd(pcap_handle); + FD_SET(ether_fd, &LispReadFds); + + printf("Ethernet starts on interface %s at %02x:%02x:%02x:%02x:%02x:%02x\n", + ether_ifname, ether_host[0], ether_host[1], ether_host[2], + ether_host[3],ether_host[4],ether_host[5]); + DBPRINT(("init_ether: **** Ethernet starts ****\n")); +} +#endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) */ From c10b512a23ed72d49bfa7ce6bfd33f60290ac2a6 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Fri, 1 May 2026 12:17:46 -0700 Subject: [PATCH 07/49] Further clean up of boolean extended_frame in llstk.c (see xc.c in 6c8096262134034e18498ca1503b6852a54c400f) Cleans up usage of booleans extended_frame and need_irq to use TRUE/FALSE since they are declared integer not LispPTR and therefore should not be using T/NIL. --- src/llstk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llstk.c b/src/llstk.c index 89f79d73..31af4f9f 100644 --- a/src/llstk.c +++ b/src/llstk.c @@ -57,7 +57,7 @@ static DLword *extendstack(void) { if (easp < LOLOC(*LastStackAddr_word)) { if ((easp > LOLOC(*GuardStackAddr_word)) && ((*STACKOVERFLOW_word) == NIL)) { - extended_frame = 1; + extended_frame = TRUE; ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->stackoverflow = 1; *STACKOVERFLOW_word = *PENDINGINTERRUPT_word = ATOM_T; } From 3cdbaf8ea508d42ba0b3d08e77529541ffc9ef27 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Wed, 27 May 2026 18:49:20 -0700 Subject: [PATCH 08/49] Minor updates to timer and I/O signalling Update description of interrupt routines to include int_io_service() Upgrade to POSIX SA_SIGINFO style signature for int_io_service() --- src/timer.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/timer.c b/src/timer.c index fed42f74..e9e8a033 100644 --- a/src/timer.c +++ b/src/timer.c @@ -97,6 +97,9 @@ unsigned int TIMEOUT_TIME = 10; /* For file system timeout, seconds, default 10 extern volatile sig_atomic_t IO_Signalled; volatile sig_atomic_t IO_Signalled = FALSE; +extern volatile sig_atomic_t timer_Signalled; +volatile sig_atomic_t timer_Signalled = FALSE; + static int gettime(int casep); @@ -409,9 +412,10 @@ void update_timer(void) { int_init() should be called before first entering dispatch loop. int_timer_init() is called by int_init() and arms the timer interrupt. int_io_init() is called by int_init() and arms the I/O interrupt. + int_io_service() handles the I/O interrupt set up by int_io_init + and sets IO_Signalled for instruction dispatch loop. int_timer_service() catches the timer signal and sets - Irq_Stk_Check & Irq_Stk_End to 0 - so the rest of the system will see it and respond. + and sets timer_Signalled for instruction dispatch loop. int_block() and int_unblock() block timer interrupts and release them. int_io_open(fd) should be called whenever a file that should interrupt us is opened; it enables the interrupt on that fd. @@ -419,9 +423,10 @@ void update_timer(void) { us is closed; it disables the interrupt on that fd. */ -/* TIMER_INTERVAL usec ~ 20 per second. This should live in some - machine-configuration - file somewhere - it can be changed as the -t parameter to lisp*/ +/* TIMER_INTERVAL usec between ticks - typically ~ 10ms, 100 Hz + This should live in some machine-configuration file somewhere + Value can be changed as the -t parameter to lisp +*/ extern int TIMER_INTERVAL; int TIMER_INTERVAL = 10000; @@ -438,9 +443,8 @@ static void int_timer_service(int sig) { /* this may have to do more in the future, like check for nested interrupts, etc... */ - - Irq_Stk_Check = 0; - Irq_Stk_End = 0; + timer_Signalled = TRUE; + Irq_Stk_End = Irq_Stk_Check = 0; } /************************************************************************/ @@ -543,11 +547,10 @@ void int_io_close(int fd) /* */ /************************************************************************/ -static void int_io_service(int sig) +static void int_io_service(int sig, siginfo_t *siginfo, void *v) { - Irq_Stk_Check = 0; - Irq_Stk_End = 0; IO_Signalled = TRUE; + Irq_Stk_End = Irq_Stk_Check = 0; } /************************************************************************/ @@ -564,9 +567,9 @@ static void int_io_service(int sig) static void int_io_init(void) { #if !defined(DOS) || !defined(MAIKO_OS_HAIKU) struct sigaction io_action; - io_action.sa_handler = int_io_service; + io_action.sa_sigaction = int_io_service; sigemptyset(&io_action.sa_mask); - io_action.sa_flags = 0; + io_action.sa_flags = SA_SIGINFO; #ifndef MAIKO_OS_HAIKU if (sigaction(SIGIO, &io_action, NULL) == -1) { From 156208e017a0e53a8db5275559c4cf7bc028a1e8 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Thu, 28 May 2026 17:21:18 -0700 Subject: [PATCH 09/49] Cleanup in ldeether remove unnecessary include malloc.h ldeether should be a dummy program if neither USE_DLPI nor USE_NIT are defined adjust conditional compilation around device opening so that it does not confuse formatters --- src/ldeether.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ldeether.c b/src/ldeether.c index 998d0a8a..c2daceaf 100644 --- a/src/ldeether.c +++ b/src/ldeether.c @@ -10,7 +10,7 @@ #include "version.h" -#ifndef MAIKO_ENABLE_ETHERNET +#if !defined( MAIKO_ENABLE_ETHERNET) || ! (defined(USE_DLPI) || defined(USE_NIT)) /* No ethernet, so have a dummy here. */ unsigned char ether_host[6] = {0, 0, 0, 0, 0, 0}; /* 48 bit address */ int main(int argc, char *argv[]) { return (0); } @@ -36,7 +36,8 @@ char *devices[] = {"emd0", "emd1", "emd2", "emd3", "emd4", 0}; char *devices[] = {"le0", "le1", "le2", "le3", "le4", "ie0", "ie1", "ie2", "ie3", "ie4", "qe0", "qe1", "qe2", "qe3", "qe4", "qe5", "qe6", "qe7", - "fddi0", "fddi1", "fddi2", "fddi3", "fddi4", "bf0", "bf1", 0}; + "fddi0", "fddi1", "fddi2", "fddi3", "fddi4", "bf0", "bf1", "net0", "net1", + 0}; #endif #endif /* USE_DLPI */ @@ -64,7 +65,6 @@ char *devices[] = {"le0", "le1", "le2", "le3", "le4", "ie0", "ie1", "i #include #include -#include #include int ether_fd = -1; /* file descriptor for ether socket */ @@ -107,7 +107,7 @@ int main(int argc, char *argv[]) { ether_intf_type = dlpi_devtype(ether_fd); printf("opened ldeether fd %d.\n", ether_fd); /* first and foremost, get the packet filter module attached - (used for ether_suspend and ether_resume) */ + (used for ether_suspend and ether_resume) */ if (ioctl(ether_fd, I_PUSH, "pfmod") < 0) { perror("IOCTL push of pf lost"); @@ -129,29 +129,29 @@ int main(int argc, char *argv[]) { #elif defined(USE_NIT) #ifndef OS4 - if ((ether_fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW)) >= 0) { + ether_fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); #else /* OS4 */ - if ((ether_fd = open("/dev/nit", O_RDWR)) >= 0) { + ether_fd = open("/dev/nit", O_RDWR); #endif /* OS4 */ - - /* it's open, now query it and find out its name and address */ - /* JRB - must document that LDE uses the first net board as found - by SIOCGIFCONF (see if(4)). Maybe we need an option to specify - which net board (suspect more than one net board on an LDE machine - will be rare, but...). - */ - struct ifconf if_data; - struct ifreq ifbuf[20]; + if (ether_fd >= 0) { + /* it's open, now query it and find out its name and address */ + /* JRB - must document that LDE uses the first net board as found + by SIOCGIFCONF (see if(4)). Maybe we need an option to specify + which net board (suspect more than one net board on an LDE machine + will be rare, abut...). + */ + struct ifconf if_data; + struct ifreq ifbuf[20]; #ifdef OS4 - /* first and foremost, get the packet filter module attached - (used for ether_suspend and ether_resume) */ + /* first and foremost, get the packet filter module attached + (used for ether_suspend and ether_resume) */ - if (ioctl(ether_fd, I_PUSH, "pf") < 0) { - perror("IOCTL push of pf lost"); - close(ether_fd); - goto I_Give_Up; - } + if (ioctl(ether_fd, I_PUSH, "pf") < 0) { + perror("IOCTL push of pf lost"); + close(ether_fd); + goto I_Give_Up; + } #endif /* OS4 */ if_data.ifc_len = sizeof(ifbuf); From 7661a9799c201dbdbaba4ddf76d7a0b544fbd30b Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 31 May 2026 19:20:35 -0700 Subject: [PATCH 10/49] Adds raw XNS ethernet packet access via the PCAP library, along with a number of cleanups which are explained with the individual files modified below: * modified: CMakeLists.txt Adds the new ether_pcap.c file Adds PCAP as an option for the network implementation to use Adjusts the use of MAIKO_ENABLE_ETHERNET so that it is present for all network implementations, and USE_xxx is present for an implementation xxx. Adjust targets to only create ldeether if using SUN_DLPI or SUN_NIT for network * modified: bin/compile-flags Updates noes on MAIKO_ENABLE_ETHERNET usage * modified: bin/linux-x.mk * modified: bin/makefile-darwin.386-x * modified: bin/makefile-darwin.aarch64-x * modified: bin/makefile-darwin.ppc-x * modified: bin/makefile-darwin.x86_64-x * modified: bin/makefile-emscripten.wasm-wasm * modified: bin/makefile-emscripten.wasm_nl-wasm_nl * modified: bin/makefile-freebsd.386-x * modified: bin/makefile-freebsd.aarch64-x * modified: bin/makefile-freebsd.x86_64-x * modified: bin/makefile-init-darwin.386 * modified: bin/makefile-init-darwin.aarch64 * modified: bin/makefile-init-darwin.x86_64 * modified: bin/makefile-init-freebsd.386 * modified: bin/makefile-init-freebsd.aarch64 * modified: bin/makefile-init-freebsd.x86_64 * modified: bin/makefile-init-openbsd.x86_64 * modified: bin/makefile-init-sunos5.sparc * modified: bin/makefile-openbsd.x86_64-x * modified: bin/makefile-sunos5.386-x * modified: bin/makefile-sunos5.i386-x * modified: bin/makefile-sunos5.sparc-x * modified: bin/makefile-sunos5.x86_64-x Moves dspif.o from XFILES to DEVICES since it will be used by SDL as well as X11 * modified: bin/makefile-header * modified: bin/makefile-tail Adds infrastructure to allow selecting network implementation by calling "makeright ..." with additional NETWORK=xxx Moves dspif.o from XFILES to DEVICES since it will be used by SDL as well as X11 * modified: inc/etherdefs.h Moves ether_addr_equal to common code and so into etherdefs.h modified: src/ether_common.c Moves ether_addr_equal to common code Removes ether event counting Adds global for storing ethernet interface name (when necessary) Cleans up use of MAIKO_ENABLE_ETHERNET and USE_xxx defines Adds init_ether() stub for case of no ethernet compiled in, to avoid having conditional compilation in main code. Adds ether_enabled flag to indicate whether it should be enable * modified: src/ether_nethub.c Cleans up use of MAIKO_ENABLE_ETHERNET and USE_xxx defines Fix typo for blen vs. bLen Adds init_ether() so that initialization call is shared between implementations * modified: src/ether_sunos.c Cleans up use of MAIKO_ENABLE_ETHERNET and USE_xxx defines Fix typo in BYTESPER_DLWORD Adjusts return value from get_packet to indicate whether a packet was available (ATOM_T vs NIL) * modified: src/initsout.c Cleans up use of MAIKO_ENABLE_ETHERNET and USE_xxx defines * modified: src/keyevent.c Cleans up use of MAIKO_ENABLE_ETHERNET and USE_xxx defines Changes interrupt handling as not all network implementations have a file descriptor that works with select() calls. Use implementation's check_ether() instead. * modified: src/main.c Cleans up use of MAIKO_ENABLE_ETHERNET and USE_xxx defines Adds processing of -E address%interfacename option for PCAP network implementation Improves error reporting for -E option parsing failures Handles setting of async mode for X display connection to avoid premature interrupts * modified: src/xc.c Updates comments (only) in periodic interrupt handling interval calculation * modified: src/xinit.c Handles setting of async mode for X display connection to avoid premature interrupts - Can't fcntl() to turn on ASYNC mode until SIGIO handler is installed. See main.c. * modified: src/xrdopt.c Adds processing of -E address%interfacename option for PCAP network implementation as X resource ldex.EtherNet --- CMakeLists.txt | 29 +++++---- bin/compile-flags | 23 +++---- bin/linux-x.mk | 1 - bin/makefile-darwin.386-x | 1 - bin/makefile-darwin.aarch64-x | 1 - bin/makefile-darwin.ppc-x | 1 - bin/makefile-darwin.x86_64-x | 1 - bin/makefile-emscripten.wasm-wasm | 2 +- bin/makefile-emscripten.wasm_nl-wasm_nl | 2 +- bin/makefile-freebsd.386-x | 1 - bin/makefile-freebsd.aarch64-x | 1 - bin/makefile-freebsd.x86_64-x | 1 - bin/makefile-header | 13 ++++ bin/makefile-init-darwin.386 | 1 - bin/makefile-init-darwin.aarch64 | 1 - bin/makefile-init-darwin.x86_64 | 3 +- bin/makefile-init-freebsd.386 | 1 - bin/makefile-init-freebsd.aarch64 | 1 - bin/makefile-init-freebsd.x86_64 | 1 - bin/makefile-init-openbsd.x86_64 | 1 - bin/makefile-init-sunos5.sparc | 1 - bin/makefile-openbsd.x86_64-x | 1 - bin/makefile-sunos5.386-x | 1 - bin/makefile-sunos5.i386-x | 1 - bin/makefile-sunos5.sparc-x | 3 +- bin/makefile-sunos5.x86_64-x | 1 - bin/makefile-tail | 7 ++- inc/etherdefs.h | 2 +- src/ether_common.c | 34 ++++++++--- src/ether_nethub.c | 13 +++- src/ether_sunos.c | 75 +++-------------------- src/initsout.c | 6 +- src/keyevent.c | 81 ++++++++++++++----------- src/main.c | 58 ++++++++++++------ src/xc.c | 6 +- src/xinit.c | 6 -- src/xrdopt.c | 34 +++++++++-- 37 files changed, 221 insertions(+), 195 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f01aa16..d13ab177 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,24 +127,27 @@ ENDIF() # the following 2 lines should produce a dropdown-box in the cmake-gui # but this will happen only after running the command line version of cmake, # possibly after "clearing the cache" (i.e. starting with a fresh build directory) -SET(MAIKO_NETWORK_TYPE NONE CACHE STRING "Type of networking to use: one of: NONE, SUN_DLPI, SUN_NIT, NETHUB") -SET_PROPERTY(CACHE MAIKO_NETWORK_TYPE PROPERTY STRINGS NONE SUN_DLPI SUN_NIT NETHUB) +SET(MAIKO_NETWORK_TYPE NONE CACHE STRING "Type of network implementation to use: one of: NONE, PCAP, SUN_DLPI, SUN_NIT, NETHUB") +SET_PROPERTY(CACHE MAIKO_NETWORK_TYPE PROPERTY STRINGS NONE PCAP SUN_DLPI SUN_NIT NETHUB) # configure networking implementation to use IF(MAIKO_NETWORK_TYPE STREQUAL "NETHUB") - LIST(APPEND MAIKO_DEFINITIONS "-DMAIKO_ENABLE_NETHUB") - MESSAGE("-- Configured for NETHUB network support") + LIST(APPEND MAIKO_DEFINITIONS "-DMAIKO_ENABLE_ETHERNET -DUSE_NETHUB") + MESSAGE("-- Configured for NETHUB network implementation") ELSEIF(MAIKO_NETWORK_TYPE STREQUAL "SUN_DLPI") LIST(APPEND MAIKO_DEFINITIONS "-DMAIKO_ENABLE_ETHERNET -DUSE_DLPI") - MESSAGE("-- Configured for (SunOS) DLPI networking") + MESSAGE("-- Configured for (SunOS) DLPI network implementation") ELSEIF(MAIKO_NETWORK_TYPE STREQUAL "SUN_NIT") LIST(APPEND MAIKO_DEFINITIONS "-DMAIKO_ENABLE_ETHERNET -DUSE_NIT") - MESSAGE("-- Configured for (SunOS) NIT networking") + MESSAGE("-- Configured for (SunOS) NIT network implementation") +ELSEIF(MAIKO_NETWORK_TYPE STREQUAL "PCAP") + LIST(APPEND MAIKO_DEFINITIONS "-DMAIKO_ENABLE_ETHERNET -DUSE_PCAP") + LIST(APPEND MAIKO_LIBRARIES "pcap") + MESSAGE("-- Configured for PCAP network implementation") ELSEIF(NOT MAIKO_NETWORK_TYPE STREQUAL "NONE") - MESSAGE(WARNING "Invalid option given for MAIKO_NETWORK_TYPE, must be one of:\nNONE, SUN_DLPI, SUN_NIT, NETHUB") + MESSAGE(WARNING "Invalid option given for MAIKO_NETWORK_TYPE, must be one of:\nNONE, PCAP, SUN_DLPI, SUN_NIT, NETHUB") ENDIF() - IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") LIST(APPEND MAIKO_DEFINITIONS "-DOS5" @@ -220,6 +223,7 @@ SET(MAIKO_SRCS src/ether_common.c src/ether_sunos.c src/ether_nethub.c + src/ether_pcap.c src/findkey.c src/foreign.c src/fp.c @@ -469,9 +473,12 @@ IF(MAIKO_DISPLAY_SDL) TARGET_COMPILE_DEFINITIONS(lde PRIVATE ${MAIKO_DISPLAY_SDL_DEFINITIONS}) ENDIF() -ADD_EXECUTABLE(ldeether src/ldeether.c src/dlpi.c) -TARGET_COMPILE_DEFINITIONS(ldeether PRIVATE ${MAIKO_DEFINITIONS}) -TARGET_INCLUDE_DIRECTORIES(ldeether PRIVATE inc) +IF(MAIKO_NETWORK_TYPE STREQUAL "SUN_DLPI" OR MAIKO_NETWORK_TYPE STREQUAL "SUN_NIT") + MESSAGE("-- Adding ldeether") + ADD_EXECUTABLE(ldeether src/ldeether.c src/dlpi.c) + TARGET_COMPILE_DEFINITIONS(ldeether PRIVATE ${MAIKO_DEFINITIONS}) + TARGET_INCLUDE_DIRECTORIES(ldeether PRIVATE inc) +ENDIF() IF(MAIKO_DISPLAY_X11) ADD_EXECUTABLE(ldex diff --git a/bin/compile-flags b/bin/compile-flags index eeac4ab2..ee3a867d 100755 --- a/bin/compile-flags +++ b/bin/compile-flags @@ -124,19 +124,20 @@ BIGATOMS True if this emulator will support 3-byte symbols, instead of NEWBITBLT True if we want to use assembler BITBLT code, rather than have code created inline by macro calls. -USE_DLPI True if the ethernet API is via the SysV Data Link Provider - Interface. Solaris uses DLPI. - -USE_NIT True if the ethernet API is via the Network Interface Tap. - SunOS uses NIT. - +MAIKO_ENABLE_ETHERNET enables support for networking, the flavor of networking + is chosen with a USE_xxx flag as follows + USE_NETHUB - Dodo Nethub networking for Dodo XNS services, see + documentation: Using-Dodo-networking-with-Maiko.md + USE_PCAP - raw ethernet access for XNS and PUP networking using + the libpcap library + USE_DLPI - raw ethernet access for XNS networking using the + data link provider interface (Solaris only) + USE_NIT - raw ethernet access for XNS networking using the + /dev/nit interface (SunOS/Solaris 1 only) + PKTFILTER True if the ethernet packets are to be filtered before being passed to the Lisp ethernet handler. Available on Sun systems - for both the NIT and DLPI cases. - -MAIKO_ENABLE_NETHUB enables the support for Dodo Nethub networking for Dodo - XNS services, see documentation: using-dodo-networking-with-maiko.md - (implicitely disables USE_DLPI and USE_NIT) + for both the USE_NIT and USE_DLPI cases. MAIKO_EMULATE_TIMER_INTERRUPTS enables emulation of recurring timer interrupts for platforms where SIGVTALRM/ITIMER_VIRTUAL or SIGALRM/ITIMER_REAL diff --git a/bin/linux-x.mk b/bin/linux-x.mk index 730eea1a..34b52cbe 100644 --- a/bin/linux-x.mk +++ b/bin/linux-x.mk @@ -2,7 +2,6 @@ XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-darwin.386-x b/bin/makefile-darwin.386-x index 8b6f4870..91622868 100644 --- a/bin/makefile-darwin.386-x +++ b/bin/makefile-darwin.386-x @@ -4,7 +4,6 @@ CC = clang -m32 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-darwin.aarch64-x b/bin/makefile-darwin.aarch64-x index 37da65ef..2f322c3a 100644 --- a/bin/makefile-darwin.aarch64-x +++ b/bin/makefile-darwin.aarch64-x @@ -4,7 +4,6 @@ CC = clang -target aarch64-apple-darwin $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-darwin.ppc-x b/bin/makefile-darwin.ppc-x index 89140761..0a1d4fe4 100644 --- a/bin/makefile-darwin.ppc-x +++ b/bin/makefile-darwin.ppc-x @@ -4,7 +4,6 @@ CC = cc $(GCC_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-darwin.x86_64-x b/bin/makefile-darwin.x86_64-x index 35a6be8a..f789b1fb 100644 --- a/bin/makefile-darwin.x86_64-x +++ b/bin/makefile-darwin.x86_64-x @@ -4,7 +4,6 @@ CC = clang -target x86_64-apple-darwin $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-emscripten.wasm-wasm b/bin/makefile-emscripten.wasm-wasm index 37f213a3..67780b17 100644 --- a/bin/makefile-emscripten.wasm-wasm +++ b/bin/makefile-emscripten.wasm-wasm @@ -14,7 +14,7 @@ XFLAGS = -DSDL=2 -sUSE_SDL=2 # OPTFLAGS is normally -O2. OPTFLAGS = -O2 -DFLAGS = $(XFLAGS) -DRELEASE=$(RELEASE) -DMAIKO_ENABLE_NETHUB +DFLAGS = $(XFLAGS) -DRELEASE=$(RELEASE) -DMAIKO_ENABLE_ETHERNET -DUSE_NETHUB MEDLEY?=../../medley SYSOUT?=$(MEDLEY)/loadups/full.sysout diff --git a/bin/makefile-emscripten.wasm_nl-wasm_nl b/bin/makefile-emscripten.wasm_nl-wasm_nl index 3ec7af1e..cca40ed2 100644 --- a/bin/makefile-emscripten.wasm_nl-wasm_nl +++ b/bin/makefile-emscripten.wasm_nl-wasm_nl @@ -14,7 +14,7 @@ XFLAGS = -DSDL=2 -sUSE_SDL=2 # OPTFLAGS is normally -O2. OPTFLAGS = -O2 -DFLAGS = $(XFLAGS) -DRELEASE=$(RELEASE) -DMAIKO_ENABLE_NETHUB +DFLAGS = $(XFLAGS) -DRELEASE=$(RELEASE) -DMAIKO_ENABLE_ETHERNET -DUSE_NETHUB MEDLEY?=../../medley SYSOUT?=$(MEDLEY)/loadups/full.sysout diff --git a/bin/makefile-freebsd.386-x b/bin/makefile-freebsd.386-x index bb42820c..712ea982 100644 --- a/bin/makefile-freebsd.386-x +++ b/bin/makefile-freebsd.386-x @@ -4,7 +4,6 @@ CC = clang -m32 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-freebsd.aarch64-x b/bin/makefile-freebsd.aarch64-x index 699bd2ae..843950c9 100644 --- a/bin/makefile-freebsd.aarch64-x +++ b/bin/makefile-freebsd.aarch64-x @@ -4,7 +4,6 @@ CC = clang -m64 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-freebsd.x86_64-x b/bin/makefile-freebsd.x86_64-x index 1c17157b..94bd66fc 100644 --- a/bin/makefile-freebsd.x86_64-x +++ b/bin/makefile-freebsd.x86_64-x @@ -4,7 +4,6 @@ CC = clang -m64 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-header b/bin/makefile-header index 705a7b5a..24aa1dc5 100755 --- a/bin/makefile-header +++ b/bin/makefile-header @@ -16,6 +16,19 @@ CLANG_CFLAGS = -std=gnu99 -fno-strict-aliasing GCC_CFLAGS = -std=gnu99 -fno-strict-aliasing DEVSTUDIO_CFLAGS = -std=gnu99 -fno-strict-aliasing +# Network implementations +NETWORK = NONE # NONE, PCAP, SUN_DLPI, SUN_NIT, NETHUB +NETWORK_CC_NONE = +NETWORK_CC_PCAP = -DMAIKO_ENABLE_ETHERNET -DUSE_PCAP +NETWORK_CC_NETHUB = -DMAIKO_ENABLE_ETHERNET -DUSE_NETHUB +NETWORK_CC_SUN_DLPI = -DMAIKO_ENABLE_ETHERNET -DUSE_DLPI +NETWORK_CC_SUN_NIT = -DMAIKO_ENABLE_ETHERNET -DUSE_NIT +NETWORK_LIB_NONE = +NETWORK_LIB_PCAP = -lpcap +NETWORK_LIB_NETHUB = +NETWORK_LIB_SUN_DLPI = +NETWORK_LIB_SUN_NIT = + DLPIFILES = # for files needed by X windows version diff --git a/bin/makefile-init-darwin.386 b/bin/makefile-init-darwin.386 index 862ab126..fe32ada6 100644 --- a/bin/makefile-init-darwin.386 +++ b/bin/makefile-init-darwin.386 @@ -4,7 +4,6 @@ CC = clang -m32 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-init-darwin.aarch64 b/bin/makefile-init-darwin.aarch64 index feee4583..d1248839 100644 --- a/bin/makefile-init-darwin.aarch64 +++ b/bin/makefile-init-darwin.aarch64 @@ -4,7 +4,6 @@ CC = clang -target aarch64-apple-darwin $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-init-darwin.x86_64 b/bin/makefile-init-darwin.x86_64 index fa669bc1..a6022f98 100644 --- a/bin/makefile-init-darwin.x86_64 +++ b/bin/makefile-init-darwin.x86_64 @@ -4,7 +4,6 @@ CC = clang -m64 -target x86_64-apple-darwin $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ @@ -16,7 +15,7 @@ XFILES = $(OBJECTDIR)xmkicon.o \ XFLAGS = -I/opt/X11/include -DXWINDOW # OPTFLAGS is normally -O2. -OPTFLAGS = -O0 -g +OPTFLAGS = -O3 -g DEBUGFLAGS = # -DDEBUG -DOPTRACE DFLAGS = $(DEBUGFLAGS) $(XFLAGS) -DRELEASE=$(RELEASE) -DNOVERSION -DINIT diff --git a/bin/makefile-init-freebsd.386 b/bin/makefile-init-freebsd.386 index a216d97d..7579ca9a 100644 --- a/bin/makefile-init-freebsd.386 +++ b/bin/makefile-init-freebsd.386 @@ -4,7 +4,6 @@ CC = clang -m32 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-init-freebsd.aarch64 b/bin/makefile-init-freebsd.aarch64 index 0069df90..98b4d895 100644 --- a/bin/makefile-init-freebsd.aarch64 +++ b/bin/makefile-init-freebsd.aarch64 @@ -4,7 +4,6 @@ CC = clang -m64 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-init-freebsd.x86_64 b/bin/makefile-init-freebsd.x86_64 index e303dcfc..145eac8a 100644 --- a/bin/makefile-init-freebsd.x86_64 +++ b/bin/makefile-init-freebsd.x86_64 @@ -4,7 +4,6 @@ CC = clang -m64 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-init-openbsd.x86_64 b/bin/makefile-init-openbsd.x86_64 index facc9a01..3ccd3d05 100644 --- a/bin/makefile-init-openbsd.x86_64 +++ b/bin/makefile-init-openbsd.x86_64 @@ -4,7 +4,6 @@ CC = clang -m64 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-init-sunos5.sparc b/bin/makefile-init-sunos5.sparc index 60ac765b..84367a2d 100644 --- a/bin/makefile-init-sunos5.sparc +++ b/bin/makefile-init-sunos5.sparc @@ -22,7 +22,6 @@ CC = cc -m32 $(DEVSTUDIO_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-openbsd.x86_64-x b/bin/makefile-openbsd.x86_64-x index 9624f317..fd0a68cc 100644 --- a/bin/makefile-openbsd.x86_64-x +++ b/bin/makefile-openbsd.x86_64-x @@ -4,7 +4,6 @@ CC = clang -m64 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-sunos5.386-x b/bin/makefile-sunos5.386-x index 108712d8..ec781cb5 100644 --- a/bin/makefile-sunos5.386-x +++ b/bin/makefile-sunos5.386-x @@ -14,7 +14,6 @@ CC = clang -m32 $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-sunos5.i386-x b/bin/makefile-sunos5.i386-x index 40005ea6..5ce714a8 100644 --- a/bin/makefile-sunos5.i386-x +++ b/bin/makefile-sunos5.i386-x @@ -14,7 +14,6 @@ CC = gcc XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-sunos5.sparc-x b/bin/makefile-sunos5.sparc-x index ed266c45..67ab8f76 100644 --- a/bin/makefile-sunos5.sparc-x +++ b/bin/makefile-sunos5.sparc-x @@ -21,7 +21,6 @@ CC = cc -m32 $(DEVSTUDIO_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ @@ -40,7 +39,7 @@ OPTFLAGS = -O2 -g3 DEBUGFLAGS = # -DSTACKCHECK -DFNSTKCHECK -MACHINEFLAGS = -DOS5 -DUSE_DLPI +MACHINEFLAGS = -DOS5 -DMAIKO_ENABLE_ETHERNET -DUSE_DLPI DFLAGS = $(XFLAGS) \ $(DEBUGFLAGS) \ diff --git a/bin/makefile-sunos5.x86_64-x b/bin/makefile-sunos5.x86_64-x index 5cc9cc45..d574a704 100644 --- a/bin/makefile-sunos5.x86_64-x +++ b/bin/makefile-sunos5.x86_64-x @@ -14,7 +14,6 @@ CC = clang $(CLANG_CFLAGS) XFILES = $(OBJECTDIR)xmkicon.o \ $(OBJECTDIR)xbbt.o \ - $(OBJECTDIR)dspif.o \ $(OBJECTDIR)xinit.o \ $(OBJECTDIR)xscroll.o \ $(OBJECTDIR)xcursor.o \ diff --git a/bin/makefile-tail b/bin/makefile-tail index ef8081ec..62754d35 100644 --- a/bin/makefile-tail +++ b/bin/makefile-tail @@ -35,7 +35,7 @@ REQUIRED-INCS = $(INCDIR)version.h $(INCDIR)maiko/platform.h -CFLAGS = $(OPTFLAGS) $(DFLAGS) +CFLAGS = $(OPTFLAGS) $(DFLAGS) $(NETWORK_CC_$(NETWORK)) RFLAGS = -c $(CFLAGS) -I$(INCDIR) -I$(INCLUDEDIR) OFILES = $(OBJECTDIR)arithops.o \ @@ -83,7 +83,7 @@ OFILES = $(OBJECTDIR)arithops.o \ $(OBJECTDIR)unixcomm.o \ $(OBJECTDIR)uraid.o \ $(OBJECTDIR)rpc.o \ - $(OBJECTDIR)ufn.o \ + $(OBJECTDIR)ufn.o \ $(OBJECTDIR)z2.o \ $(OBJECTDIR)eqf.o \ $(OBJECTDIR)fp.o \ @@ -109,6 +109,7 @@ GCFILES = $(OBJECTDIR)gcscan.o \ $(OBJECTDIR)gcoflow.o DEVICES = $(OBJECTDIR)dspsubrs.o \ + $(OBJECTDIR)dspif.o \ $(OBJECTDIR)initdsp.o \ $(OBJECTDIR)dsk.o \ $(OBJECTDIR)ufs.o \ @@ -149,7 +150,7 @@ $(OSARCHDIR)lde: $(OBJECTDIR)ldeboot.o $(OBJECTDIR)unixfork.o $(CC) $(OBJECTDIR)ldeboot.o $(OBJECTDIR)unixfork.o $(LDELDFLAGS) -o $(OSARCHDIR)lde $(OSARCHDIR)$(LDENAME): $(LIBFILES) $(EXTFILES) $(OBJECTDIR)vdate.o - $(CC) $(LIBFILES) $(EXTFILES) $(OBJECTDIR)vdate.o $(LDFLAGS) -o $(OSARCHDIR)$(LDENAME) + $(CC) $(LIBFILES) $(EXTFILES) $(OBJECTDIR)vdate.o $(LDFLAGS) $(NETWORK_LIB_$(NETWORK)) -o $(OSARCHDIR)$(LDENAME) @ echo "" @ echo "Executable is now named '$(OSARCHDIR)$(LDENAME)'" diff --git a/inc/etherdefs.h b/inc/etherdefs.h index 013984df..971c0157 100644 --- a/inc/etherdefs.h +++ b/inc/etherdefs.h @@ -14,7 +14,7 @@ LispPTR check_ether(void); void init_ifpage_ether(void); void init_ether(void); LispPTR check_sum(LispPTR *args); - +int ether_addr_equal(const uint8_t addr1[6], const uint8_t addr2[6]); void setNethubHost(char* host); void setNethubPort(int port); void setNethubMac(int m0, int m1, int m2, int m3, int m4, int m5); diff --git a/src/ether_common.c b/src/ether_common.c index 1a80e49a..ae943814 100644 --- a/src/ether_common.c +++ b/src/ether_common.c @@ -10,6 +10,7 @@ #include "version.h" #include +#include #include #include "lsptypes.h" @@ -21,24 +22,22 @@ * global variables exported to ether_*.c and possibly others */ +extern int ether_enabled; extern int ether_fd; extern u_char ether_host[6]; +extern u_char ether_ifname[32]; extern const u_char broadcast[6]; extern int ether_bsize; extern u_char *ether_buf; -extern int ETHEREventCount; +int ether_enabled = 0; /* ethernet disabled unless we ask for it */ int ether_fd = -1; /* file descriptor for ether socket */ - u_char ether_host[6] = {0, 0, 0, 0, 0, 0}; /* 48 bit address of this node */ +u_char ether_ifname[32] = {0}; /* interface name (pcap, perhaps others) */ const u_char broadcast[6] = {255, 255, 255, 255, 255, 255}; - int ether_bsize = 0; /* if nonzero then a receive is pending */ u_char *ether_buf = NULL; /* address of receive buffer */ -int ETHEREventCount = 0; - - /* * public procedures */ @@ -104,14 +103,35 @@ LispPTR check_sum(LispPTR *args) } /*check_sum */ +/********************************************************************** + * ether_addr_equal(add1, add2) + * checks ethernet addresses equality + **********************************************************************/ + +int ether_addr_equal(const uint8_t addr1[6], const uint8_t addr2[6]) +{ + return (0 == memcmp(addr1, addr2, 6)); +} + /* * dummy implementation of SUBRs if none of the networking options is compiled in */ -#if !defined(MAIKO_ENABLE_ETHERNET) && !defined(MAIKO_ENABLE_NETHUB) +#if !defined(MAIKO_ENABLE_ETHERNET) + +/************************************************************************/ +/* */ +/* i n i t _ e t h e r */ +/* */ +/* Initialize ethernet implementation specific code */ +/* */ +/************************************************************************/ +void init_ether(void) { + return; +} /************************************************************************/ /* */ diff --git a/src/ether_nethub.c b/src/ether_nethub.c index d7d0f471..8314dd51 100644 --- a/src/ether_nethub.c +++ b/src/ether_nethub.c @@ -7,7 +7,7 @@ /* */ /*******************************************************************************/ -#if defined(MAIKO_ENABLE_NETHUB) && !defined(MAIKO_ENABLE_ETHERNET) +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_NETHUB) #include "version.h" @@ -43,6 +43,7 @@ ** --- ether implementation common data ------------------------------------------- */ +extern int ether_enabled; /* 0/1 should ethernet be turned on */ extern int ether_fd; /* file descriptor for ether socket */ extern u_char ether_host[6]; /* 48 bit address of this node */ extern const u_char broadcast[6]; @@ -131,6 +132,12 @@ static void dblwordsSwap(u_char* basePtr, int forBytes) { ** --- connect, disconnect and transmit packets ----------------------------------- */ +void init_ether(void) { + /* because the rest of the system expects it to be called init_ether() */ + if (ether_enabled == 0) return; + connectToHub(); +} + void connectToHub(void) { if (nethubHost == NULL) { return; @@ -300,7 +307,7 @@ static int recvPacket(void) { #else log_debug((" recvPacket() :: %d bytes at %p\n", bLen, (void *)ether_buf)); #endif - ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = blen; + ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = bLen; ether_bsize = 0; @@ -571,5 +578,5 @@ LispPTR check_ether(void) return (ATOM_T); } -#endif /* MAIKO_ENABLE_NETHUB */ +#endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(USE_NETHUB) */ diff --git a/src/ether_sunos.c b/src/ether_sunos.c index 73799fc7..d27d4c3a 100644 --- a/src/ether_sunos.c +++ b/src/ether_sunos.c @@ -7,10 +7,9 @@ /* */ /************************************************************************/ -#if defined(MAIKO_ENABLE_ETHERNET) && !defined(MAIKO_ENABLE_NETHUB) - #include "version.h" +#if defined(MAIKO_ENABLE_ETHERNET) && defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) #if defined(USE_DLPI) #define PKTFILTER 1 #define NIOCSFLAGS SBIOCSFLAGS @@ -30,7 +29,6 @@ #include #include #include -#ifdef MAIKO_ENABLE_ETHERNET #include #include #include @@ -62,7 +60,6 @@ #endif #include #endif /* DOS */ -#endif /* MAIKO_ENABLE_ETHERNET */ #include "commondefs.h" #include "lispemul.h" @@ -79,6 +76,7 @@ #define NIOCSETF PFIOCSETF #endif +extern int ether_enabled; /* 0/1 should ethernet be turned on */ extern int ether_fd; /* file descriptor for ether socket */ static int ether_intf_type = 0; extern u_char ether_host[6]; /* 48 bit address of this node */ @@ -89,8 +87,6 @@ static u_char nit_buf[3000]; /* the current chunk read from NIT (one packet) * extern LispPTR *PENDINGINTERRUPT68k; extern fd_set LispReadFds; -extern int ETHEREventCount; - #define PacketTypeIP 0x0800 #define PacketTypeARP 0x0806 #define PacketTypeRARP 0x8035 @@ -98,7 +94,6 @@ extern int ETHEREventCount; #define PacketTypePUP 0x0200 #define PacketType3TO10 0x0201 -#ifdef MAIKO_ENABLE_ETHERNET #ifdef PKTFILTER /* the receiving packetfilter structure */ /* if this is changed, be sure to get the references to it in init_ether @@ -213,8 +208,6 @@ int ether_out = 0; /* number of packets sent */ static struct nit_ioc nioc; #endif /* PKTFILTER */ -#endif /* MAIKO_ENABLE_ETHERNET */ - /************************************************************************/ /* */ /* e t h e r _ s u s p e n d */ @@ -226,7 +219,6 @@ static struct nit_ioc nioc; LispPTR ether_suspend(LispPTR args[]) { -#ifdef MAIKO_ENABLE_ETHERNET #ifdef PKTFILTER static struct packetfilt pf = {0, 1, {ENF_PUSHZERO}}; struct strioctl si; @@ -262,8 +254,6 @@ LispPTR ether_suspend(LispPTR args[]) } #endif /* USE_DLPI */ #endif /* PKTFILTER */ -#endif /* MAIKO_ENABLE_ETHERNET */ - return (ATOM_T); } /* ether_suspend */ @@ -277,7 +267,6 @@ LispPTR ether_suspend(LispPTR args[]) LispPTR ether_resume(LispPTR args[]) { -#ifdef MAIKO_ENABLE_ETHERNET struct strioctl si; if (ether_fd == -1) return (NIL); #ifndef PKTFILTER @@ -308,9 +297,6 @@ LispPTR ether_resume(LispPTR args[]) } #endif /* USE_DLPI */ #endif /* PKTFILTER */ - -#endif /* MAIKO_ENABLE_ETHERNET */ - return (ATOM_T); } /* ether_resume */ @@ -362,11 +348,10 @@ LispPTR ether_reset(LispPTR args[]) LispPTR ether_get(LispPTR args[]) { LispPTR result = NIL; -#ifdef MAIKO_ENABLE_ETHERNET LispPTR MaxByteCount; sigset_t signals; - MaxByteCount = BYTERSPER_DLWORD * (0xFFFF & args[0]); /* words to bytes */ + MaxByteCount = BYTESPER_DLWORD * (0xFFFF & args[0]); /* words to bytes */ DBPRINT(("Ether Get. ")); @@ -385,9 +370,6 @@ LispPTR ether_get(LispPTR args[]) /* enable interrupts */ sigprocmask(SIG_UNBLOCK, &signals, NULL); - -#endif /* MAIKO_ENABLE_ETHERNET */ - return (result); } /* ether_get */ @@ -399,7 +381,6 @@ LispPTR ether_get(LispPTR args[]) LispPTR ether_send(LispPTR args[]) { -#ifdef MAIKO_ENABLE_ETHERNET /* * Send a packet. */ @@ -452,8 +433,6 @@ LispPTR ether_send(LispPTR args[]) } #endif /* PKTFILTER */ } -#endif /* MAIKO_ENABLE_ETHERNET */ - return (ATOM_T); } /* ether_send */ @@ -473,30 +452,23 @@ LispPTR ether_setfilter(LispPTR args[]) int estat[3]; int *ether_debug(void) { -#ifdef MAIKO_ENABLE_ETHERNET estat[0] = 0; if (ether_fd < 0) return (NIL); printf("fd %d bsize %d buf %p icb %X in %d out %d\n ", ether_fd, ether_bsize, (void *)ether_buf, ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB, ether_in, ether_out); -#endif /* MAIKO_ENABLE_ETHERNET */ - return (estat); } /* end ether_debug */ -#ifdef MAIKO_ENABLE_ETHERNET static struct timeval EtherTimeout = {0, 0}; -#endif /* MAIKO_ENABLE_ETHERNET */ /********************************************************************** * check_ether() * checks an incoming packet **********************************************************************/ -#ifdef MAIKO_ENABLE_ETHERNET #ifndef PKTFILTER static int nitpos = 0, nitlen = 0; /* for NIT read buffer in OS3 */ #endif -#endif LispPTR check_ether(void) { /* @@ -505,7 +477,6 @@ LispPTR check_ether(void) { * and signal the icb and return T. */ -#ifdef MAIKO_ENABLE_ETHERNET #ifndef PKTFILTER fd_set rfds; int result, fromlen; @@ -520,12 +491,13 @@ LispPTR check_ether(void) { struct strbuf ctl, data; char ctlbuf[2000]; #endif /* PKTFILTER */ + if (ether_fd < 0) return (NIL); FD_SET(ether_fd, &rfds); #ifndef PKTFILTER i = 2; if (/* select(32, &rfds, NULL, NULL, &EtherTimeout) >= 0 ) */ (1)) { - if ((ether_fd >= 0) && (ether_bsize > 0)) { + if (ether_bsize > 0) { while ((select(32, &rfds, NULL, NULL, &EtherTimeout) >= 0) && (i-- > 0)) { if (nitpos >= nitlen) { /* Used up last NIT buffer full; read another. */ nitlen = read(ether_fd, nit_buf, sizeof(nit_buf)); @@ -547,10 +519,8 @@ LispPTR check_ether(void) { ("Found packet len %d, at pos %d in buflen %d.\n", fromlen, nitpos, nitlen)); nitpos += fromlen; ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->ETHERInterrupt = 1; - ETHEREventCount++; Irq_Stk_Check = Irq_Stk_End = 0; *PENDINGINTERRUPT68k = ATOM_T; - /* return(NIL); */ return (ATOM_T); } nitpos += fromlen; @@ -569,7 +539,7 @@ LispPTR check_ether(void) { } #else /* PKTFILTER */ - if (ether_fd >= 0 && ether_bsize > 0 + if (ether_bsize > 0 /* && select(32, &rfds, NULL, NULL, &EtherTimeout) >= 0 * -- [on '90/02/14: getsignsldata() check this] */ && (FD_ISSET(ether_fd, &rfds))) { @@ -588,19 +558,15 @@ LispPTR check_ether(void) { ether_in++; ((DLETHERCSB *)IOPage->dlethernet)->DLFIRSTICB = data.len; ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->ETHERInterrupt = 1; - ETHEREventCount++; Irq_Stk_Check = Irq_Stk_End = 0; *PENDINGINTERRUPT68k = ATOM_T; - return (NIL); /* return(ATOM_T); */ + return(ATOM_T); } } else if (errno != EWOULDBLOCK) { perror("Check_ether read error:\n"); } } #endif /* PKTFILTER */ - -#endif /* MAIKO_ENABLE_ETHERNET */ - return (NIL); } /* end check_ether */ @@ -614,7 +580,6 @@ LispPTR check_ether(void) { /************************************************************************/ LispPTR get_packet(void) { -#ifdef MAIKO_ENABLE_ETHERNET #ifndef PKTFILTER fd_set rfds; int result, fromlen; @@ -689,27 +654,9 @@ LispPTR get_packet(void) { } else if (errno != EWOULDBLOCK) perror("Check_ether read error:\n"); #endif /* PKTFILTER */ - -#endif /* MAIKO_ENABLE_ETHERNET */ - return (NIL); } /* end get_packet */ -#ifdef MAIKO_ENABLE_ETHERNET -/********************************************************************** - * ether_addr_equal(add1, add2) - * checks ethernet addresses equality - * Also believed obsolete - **********************************************************************/ - -static int ether_addr_equal(u_char add1[], u_char add2[]) -{ - int i; - for (i = 0; i < 6; i++) - if (add1[i] != add2[i]) return (0); - return (1); -} - /********************************************************************** * check_filter(buffer) * see if this packet passes the current filter setting @@ -748,7 +695,6 @@ static void init_uid(void) { #if defined(USE_NIT) struct sockaddr_nit snit; #endif /* USE_NIT */ -#endif /* MAIKO_ENABLE_ETHERNET */ /************************************************************************/ /* i n i t _ e t h e r */ @@ -757,8 +703,6 @@ struct sockaddr_nit snit; /* */ /************************************************************************/ void init_ether(void) { -#ifdef MAIKO_ENABLE_ETHERNET - /* JRB - This code will have to be a bit different for SUN 4.0; the probable differences are in commented-out code below (not ifdefed because they're untested...) @@ -770,6 +714,7 @@ void init_ether(void) { ((INTSTAT2 *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->handledmask = 0; */ + if (ether_enabled == 0) return; if (ether_fd < 0) { /* it's not open yet, try and open it; if it's already open here, it was opened by ldeether and @@ -1062,7 +1007,5 @@ void init_ether(void) { DBPRINT(("init_ether: **** Ethernet starts ****\n")); } -#endif /* MAIKO_ENABLE_ETHERNET */ } - -#endif /* defined(MAIKO_ENABLE_ETHERNET) */ +#endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) */ diff --git a/src/initsout.c b/src/initsout.c index f0f63965..623c9ad9 100644 --- a/src/initsout.c +++ b/src/initsout.c @@ -46,7 +46,7 @@ #include "mkcelldefs.h" // for N_OP_createcell #include "testtooldefs.h" // for MakeAtom68k, MAKEATOM -#if defined(MAIKO_ENABLE_ETHERNET) || defined(MAIKO_ENABLE_NETHUB) +#if defined(MAIKO_ENABLE_ETHERNET) #include "etherdefs.h" #endif @@ -117,9 +117,9 @@ void init_ifpage(unsigned sysout_size) { Initialize IFPAGE */ InterfacePage->machinetype = MACHINETYPE_MAIKO; -#if defined(MAIKO_ENABLE_ETHERNET) || defined(MAIKO_ENABLE_NETHUB) +#if defined(MAIKO_ENABLE_ETHERNET) init_ifpage_ether(); /* store ethernet ID in IF page */ -#endif /* MAIKO_ENABLE_ETHERNET or MAIKO_ENABLE_NETHUB */ +#endif /* MAIKO_ENABLE_ETHERNET */ /*InterfacePage->dl24bitaddressable = (sysout_size == 32? 0xffff : 0);*/ InterfacePage->dl24bitaddressable = (sysout_size == 8 ? 0 : 0xffff); new_lastvmem = (sysout_size * PAGES_IN_MBYTE) - 1; diff --git a/src/keyevent.c b/src/keyevent.c index f2b380bd..4c5870c5 100644 --- a/src/keyevent.c +++ b/src/keyevent.c @@ -60,9 +60,9 @@ void Mouse_hndlr(void); /* Fields mouse events from driver */ #include "xwinmandefs.h" #endif -#if defined(MAIKO_ENABLE_ETHERNET) || defined(MAIKO_ENABLE_NETHUB) +#if defined(MAIKO_ENABLE_ETHERNET) #include "etherdefs.h" -#endif /* MAIKO_ENABLE_ETHERNET or MAIKO_ENABLE_NETHUB */ +#endif /* MAIKO_ENABLE_ETHERNET */ #include "dbprint.h" #if (defined(DOS) || defined(XWINDOW)) @@ -121,9 +121,9 @@ extern volatile sig_atomic_t XNeedSignal; extern int LogFileFd; -#if defined(MAIKO_ENABLE_ETHERNET) || defined(MAIKO_ENABLE_NETHUB) +#if defined(MAIKO_ENABLE_ETHERNET) extern int ether_fd; -#endif /* MAIKO_ENABLE_ETHERNET or MAIKO_ENABLE_NETHUB */ +#endif /* MAIKO_ENABLE_ETHERNET */ extern DLword *DisplayRegion68k; @@ -231,52 +231,61 @@ void process_io_events(void) fd_set rfds; u_int iflags; int i; - - memcpy(&rfds, &LispReadFds, sizeof(rfds)); - - if (select(32, &rfds, NULL, NULL, &SelectTimeout) > 0) { + INTSTAT *interrupt_state = ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word)); #ifdef MAIKO_ENABLE_ETHERNET - if (ether_fd >= 0 && FD_ISSET(ether_fd, &rfds)) { /* Raw ethernet (NIT) I/O happened, so handle it. */ - DBPRINT(("Handling enet interrupt.\n\n")); - check_ether(); + /* Unfortunately, not all methods of accessing the ethernet will result in an + * fd on which select() will produce a useful result, so we rely on the ethernet + * implementation-specific check_ether() routine to return NIL(0) or T(non-zero) + * depending on whether a packet has been read - in which case an Ethernet + * interrupt will be signalled up to the Lisp code, and the packet will be + * picked up. + * If there is currently an Ethernet interrupt in progress we won't check, + * and check_ether() should return NIL immediately if the Ethernet is + * not active (ether_fd < 0). + */ + if (0 == interrupt_state->P_ETHERInterrupt) { + if (check_ether()) { + /* the in-process bit gets set when xc.c passes it to Lisp */ + interrupt_state->ETHERInterrupt = 1; + Irq_Stk_Check = Irq_Stk_End = 0; + *PENDINGINTERRUPT68k = ATOM_T; } + } #endif /* MAIKO_ENABLE_ETHERNET */ -#ifdef MAIKO_ENABLE_NETHUB - check_ether(); -#endif /* MAIKO_ENABLE_NETHUB */ + memcpy(&rfds, &LispReadFds, sizeof(rfds)); + if (select(FD_SETSIZE, &rfds, NULL, NULL, &SelectTimeout) <= 0) return; #ifdef RS232 - if (RS232C_Fd >= 0 && (FD_ISSET(RS232C_Fd, &rfds) || (RS232C_remain_data && rs232c_lisp_is_ready()))) - rs232c_read(); + if (RS232C_Fd >= 0 && (FD_ISSET(RS232C_Fd, &rfds) || (RS232C_remain_data && rs232c_lisp_is_ready()))) + rs232c_read(); #endif /* RS232 */ #if defined(MAIKO_HANDLE_CONSOLE_MESSAGES) && defined(LOGINT) - if (LogFileFd >= 0 && FD_ISSET(LogFileFd, &rfds)) { /* There's info in the log file. Tell Lisp to print it. */ - flush_pty(); /* move the msg(s) to the log file */ + if (LogFileFd >= 0 && FD_ISSET(LogFileFd, &rfds)) { /* There's info in the log file. Tell Lisp to print it. */ + flush_pty(); /* move the msg(s) to the log file */ - ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->LogFileIO = 1; + ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->LogFileIO = 1; - *PENDINGINTERRUPT68k = ATOM_T; - Irq_Stk_End = Irq_Stk_Check = 0; - } + *PENDINGINTERRUPT68k = ATOM_T; + Irq_Stk_End = Irq_Stk_Check = 0; + } #endif - iflags = 0; - for (i = 0; i < 32; i++) - if (FD_ISSET(i, &rfds) & FD_ISSET(i, &LispIOFds)) iflags |= 1 << i; - if (iflags) { /* There's activity on a Lisp-opened FD. Tell Lisp. */ - u_int *flags; - flags = (u_int *)NativeAligned4FromLAddr(*IOINTERRUPTFLAGS_word); - *flags = iflags; - - ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->IOInterrupt = 1; - - *PENDINGINTERRUPT68k = ATOM_T; - Irq_Stk_End = Irq_Stk_Check = 0; - } + iflags = 0; + for (i = 0; i < 32; i++) + if (FD_ISSET(i, &rfds) & FD_ISSET(i, &LispIOFds)) iflags |= 1 << i; + if (iflags) { /* There's activity on a Lisp-opened FD. Tell Lisp. */ + u_int *flags; + flags = (u_int *)NativeAligned4FromLAddr(*IOINTERRUPTFLAGS_word); + *flags = iflags; + + ((INTSTAT *)NativeAligned4FromLAddr(*INTERRUPTSTATE_word))->IOInterrupt = 1; + + *PENDINGINTERRUPT68k = ATOM_T; + Irq_Stk_End = Irq_Stk_Check = 0; } -/* #endif */ + /* #endif */ #endif /* DOS */ } /* end process_io_events */ diff --git a/src/main.c b/src/main.c index 590424a9..307de3e5 100644 --- a/src/main.c +++ b/src/main.c @@ -208,12 +208,14 @@ LispPTR *LastStackAddr_word; LispPTR *NeedHardreturnCleanup_word; /*** Ethernet stuff (JRB) **/ -#ifdef MAIKO_ENABLE_ETHERNET +extern int ether_enabled; extern int ether_fd; extern u_char ether_host[6]; -#endif /* MAIKO_ENABLE_ETHERNET */ +extern char ether_ifname[32]; +#ifdef USE_NIT extern struct sockaddr_nit snit; +#endif #ifdef INIT int for_makeinit = 1; @@ -303,7 +305,7 @@ const char *helpstring = -help Print this message\n"; #endif /* DOS */ -#if defined(MAIKO_ENABLE_NETHUB) +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_NETHUB) const char *nethubHelpstring = "\ -nh-host dodo-host Hostname for Dodo Nethub (no networking if missing)\n\ @@ -519,18 +521,19 @@ int main(int argc, char *argv[]) } #endif /* SDL */ /* Can only do this under SUNOs, for now */ +#if defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) else if (!strcmp(argv[i], "-E")) { /**** ethernet info ****/ -#ifdef MAIKO_ENABLE_ETHERNET int b0, b1, b2, b3, b4, b5; #if defined(USE_DLPI) if (argc > ++i && sscanf(argv[i], "%d:%x:%x:%x:%x:%x:%x", ðer_fd, &b0, &b1, &b2, &b3, &b4, &b5) == 7) -#else +#elif defined(USE_NIT) if (argc > ++i && sscanf(argv[i], "%d:%x:%x:%x:%x:%x:%x:%s", ðer_fd, &b0, &b1, &b2, &b3, &b4, &b5, snit.snit_ifname) == 8) #endif /* USE_DLPI */ { + ether_enabled = 1; ether_host[0] = b0; ether_host[1] = b1; ether_host[2] = b2; @@ -538,17 +541,17 @@ int main(int argc, char *argv[]) ether_host[4] = b4; ether_host[5] = b5; } else { - (void)fprintf(stderr, "Missing or bogus -E argument\n"); + (void)fprintf(stderr, "Missing or bogus -E argument (dlpi/nit)\n"); ether_fd = -1; exit(1); } -#endif /* MAIKO_ENABLE_ETHERNET */ - } +#endif /* MAIKO_OS_SOLARIS && (defined(USE_DLPI) || defined(USE_NIT)) */ -#ifdef MAIKO_ENABLE_NETHUB +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_NETHUB) else if (!strcmp(argv[i], "-nh-host")) { if (argc > ++i) { + ether_enabled = 1; setNethubHost(argv[i]); } else { (void)fprintf(stderr, "Missing argument after -nh-host\n"); @@ -599,7 +602,29 @@ int main(int argc, char *argv[]) exit(1); } } -#endif /* MAIKO_ENABLE_NETHUB */ +#endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(USE_NETHUB) */ +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) + else if (!strcmp(argv[i], "-E")) { + ether_enabled = 1; + if (argc > ++i) { + int fields; + int b[6]; + char ifname[32] = {0}; + fields = sscanf(argv[i], "%x:%x:%x:%x:%x:%x%%%31s", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], ifname); + if (fields == 6 || fields == 7) { + for (int x = 0; x < 6; x++) ether_host[x] = b[x] & 0xFF; + if (fields == 7) + strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); + } else { + (void)fprintf(stderr, "Invalid argument for -E (pcap)\n"); + exit(1); + } + } else { + (void)fprintf(stderr, "Missing argument after -E\n"); + exit(1); + } + } +#endif #if defined(MAIKO_EMULATE_TIMER_INTERRUPTS) || defined(MAIKO_EMULATE_ASYNC_INTERRUPTS) else if (!strcmp(argv[i], "-intr-emu-insns")) { @@ -693,13 +718,9 @@ int main(int argc, char *argv[]) FD_ZERO(&LispReadFds); -#ifdef MAIKO_ENABLE_ETHERNET - init_ether(); /* modified by kiuchi Nov. 4 */ -#endif /* MAIKO_ENABLE_ETHERNET */ - -#ifdef MAIKO_ENABLE_NETHUB - connectToHub(); -#endif + /* This must be called before init_ifpage() which will call init_ifpage_ether() */ + /* a dummy stub is compiled in if no ethernet implementation was selected. */ + if (ether_enabled) init_ether(); #ifdef DOS init_host_filesystem(); @@ -810,6 +831,9 @@ void start_lisp(void) { /* entering the bytecode dispatch loop; interrupts get */ /* unblocked here */ int_init(); +#if defined(XWINDOW) + int_io_open(ConnectionNumber(currentdsp->display_id)); +#endif #ifdef DOS _dpmi_lockregion((void *)&dispatch, 32768); #endif /* DOS */ diff --git a/src/xc.c b/src/xc.c index fdd0a777..4237451a 100644 --- a/src/xc.c +++ b/src/xc.c @@ -1167,12 +1167,14 @@ op_ufn : { else period_cnt = (*PERIODIC_INTERRUPT_FREQUENCY68k & 0xffff) * (1000000 / 60) / TIMER_INTERVAL; - /* number of 1/60 second periods between interrupts. + /* number of 1/60 second periods between interrupts (really??) TIMER_INTERVAL is the number of microseconds between timer interrupts. The calculation here avoids some overflow errors although there is some roundoff if the interrupt frequency number is too low, - it will bottom out and just set period_cnt to 0 */ + it will bottom out and just set period_cnt to 0 + Rewrite as ((*PIF & 0xffff) * 1000000UL) / (60 * TIMER_INTERVAL) + */ } } diff --git a/src/xinit.c b/src/xinit.c index a0b2772d..07a1f718 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -364,11 +364,5 @@ DspInterface X_init(DspInterface dsp, LispPTR lispbitmap, unsigned width_hint, u } XInitImage(&dsp->ScreenBitmap); -#if defined(O_ASYNC) - xfd = ConnectionNumber(dsp->display_id); - if (fcntl(xfd, F_SETOWN, getpid()) == -1) perror("X_init: fcntl F_SETOWN error"); - if (fcntl(xfd, F_SETFL, fcntl(xfd, F_GETFL, 0) | O_ASYNC) == -1) perror("X_init: fcntl F_SETFL O_ASYNC error"); -#endif - return (dsp); } diff --git a/src/xrdopt.c b/src/xrdopt.c index 43e3de3a..a47f0a3c 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -100,8 +100,10 @@ extern int for_makeinit, please_fork, noscroll; /*** Ethernet stuff (JRB) **/ #ifdef MAIKO_ENABLE_ETHERNET +extern int ether_enabled; extern int ether_fd; extern u_char ether_host[6]; +extern char ether_ifname[32]; #if defined(USE_NIT) extern struct sockaddr_nit snit; #endif /* USE_NIT */ @@ -135,7 +137,7 @@ void print_Xusage(const char *prog) (void)fprintf(stderr, " -iconbitmap | -ibm -bitmap for the medley icon\n"); (void)fprintf(stderr, " -xsync -turn XSynchronize on. (default is off)\n\n"); -#if defined(MAIKO_ENABLE_NETHUB) +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_NETHUB) (void)fprintf(stderr,"\ -nh-host dodo-host Hostname for Dodo Nethub (no networking if missing)\n\ -nh-port port-number Port for Dodo Nethub (optional, default: 3333)\n\ @@ -324,7 +326,8 @@ void read_Xoption(int *argc, char *argv[]) if (XrmGetResource(rDB, "ldex.Init", "Ldex.Init", str_type, &value) == True) { for_makeinit = 1; } if (XrmGetResource(rDB, "ldex.xsync", "Ldex.xsync", str_type, &value) == True) { xsync = True; } -#ifdef MAIKO_ENABLE_ETHERNET + +#if defined(MAIKO_ENABLE_ETHERNET) && defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) if (XrmGetResource(rDB, "ldex.EtherNet", "Ldex.EtherNet", str_type, &value) == True) { int b0, b1, b2, b3, b4, b5; (void)strncpy(tmp, value.addr, value.size); @@ -333,7 +336,7 @@ void read_Xoption(int *argc, char *argv[]) #elif defined(USE_NIT) if (sscanf(tmp, "%d:%x:%x:%x:%x:%x:%x:%s", ðer_fd, &b0, &b1, &b2, &b3, &b4, &b5, snit.snit_ifname) == 8) -#endif /* USE_NIT */ +#endif { ether_host[0] = b0; ether_host[1] = b1; @@ -347,5 +350,28 @@ void read_Xoption(int *argc, char *argv[]) exit(1); } } -#endif /* MAIKO_ENABLE_ETHERNET */ +#endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) */ + +#if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) + if (XrmGetResource(rDB, "ldex.EtherNet", "Ldex.EtherNet", str_type, &value) == True) { + int b0, b1, b2, b3, b4, b5, fields; + char ifname[32]; + (void)strncpy(tmp, value.addr, value.size); + fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%s", &b0, &b1, &b2, &b3, &b4, &b5, ifname); + if (fields == 6 || fields == 7) { + ether_enabled = 1; + ether_host[0] = b0; + ether_host[1] = b1; + ether_host[2] = b2; + ether_host[3] = b3; + ether_host[4] = b4; + ether_host[5] = b5; + if (fields == 7) + strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); + } else { + (void)fprintf(stderr, "Invalid argument for -E (pcap)\n"); + exit(1); + } + } +#endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) */ } /* end readXoption */ From 967a227e4da741e19f34f0ff20da7562a3583396 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 12:27:37 -0700 Subject: [PATCH 11/49] Response to Gemini review - truncate overly large ether packets --- src/ether_pcap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index b534d98e..08a70e5d 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -247,17 +247,22 @@ LispPTR ether_get(LispPTR args[]) * ether_send(args) 175/75/2 max_words,buffer_addr * send a packet **********************************************************************/ + +/* normally an XNS packet would be no bigger than 576 bytes */ +#define MAXETHERPACKETWORDS 300 + LispPTR ether_send(LispPTR args[]) { DLword wordCount; DLword *bufferAddr; /* buffer address pointer(in native address) */ #ifdef BYTESWAP - DLword networkOrderBuffer[750]; + DLword networkOrderBuffer[MAXETHERPACKETWORDS]; #endif if (ether_fd < 0) return (NIL); wordCount = LispIntToCInt(args[0]); bufferAddr = NativeAligned2FromLAddr(args[1]); #ifdef BYTESWAP + if (wordCount > MAXETHERPACKETWORDS) wordCount = MAXETHERPACKETWORDS; for (int i = 0; i < wordCount; i++) { networkOrderBuffer[i] = htons(GETBASEWORD(bufferAddr, i)); } From fc4e89fecbd091a29d7a4d76ffa7fdd205f91a6f Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 13:06:20 -0700 Subject: [PATCH 12/49] Avoid buffer overflow parsing ldex.EtherNet interface name for pcap mode --- src/xrdopt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index a47f0a3c..07af1556 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -357,7 +357,7 @@ void read_Xoption(int *argc, char *argv[]) int b0, b1, b2, b3, b4, b5, fields; char ifname[32]; (void)strncpy(tmp, value.addr, value.size); - fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%s", &b0, &b1, &b2, &b3, &b4, &b5, ifname); + fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%31s", &b0, &b1, &b2, &b3, &b4, &b5, ifname); if (fields == 6 || fields == 7) { ether_enabled = 1; ether_host[0] = b0; From ea468cd48b98b6d237eb458b20c5612c2b33472f Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 13:25:29 -0700 Subject: [PATCH 13/49] Addresses "major" complaints from Gemini review * pcap_next_ex() does not guarantee even byte alignment on returned packets * pcap_next_ex() does not guarantee even byte length of packet * handle errors from pcap_findalldevs() * avoid NULL pointer dereference if device has no associated address * handle potential errors from pcap_setfilter, pcap_setnonblock, pcap_get_selectable_fd --- src/ether_pcap.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 08a70e5d..4d70befd 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -121,13 +121,14 @@ static int ether_out = 0; /* number of packets sent */ static int recvPacket() { int pcap_rval = 0; bpf_u_int32 hlen; - const uint16_t *packet = NULL; + const uint8_t *packet = NULL; struct pcap_pkthdr *header = NULL; switch (pcap_next_ex(pcap_handle, &header, (void *)&packet)) { case 0: return (0); case PCAP_ERROR: + case PCAP_ERROR_BREAK: pcap_perror(pcap_handle, "recvPacket"); return (0); } @@ -135,8 +136,11 @@ static int recvPacket() { if (hlen > ether_bsize || hlen == 0) return (0); #ifdef BYTESWAP - for (int i = 0; i < (hlen + 1) / 2; i++) { - GETBASEWORD((DLword *)ether_buf, i) = ntohs(packet[i]); + for (int i = 0; i < hlen / 2; i++) { + GETBASEWORD((DLword *)ether_buf, i) = packet[2 * i] << 8 | packet[2 * i + 1]; + } + if (hlen % 2) { /* pick up last byte if length was odd (it shouldn't be!) */ + GETBASEWORD((DLword *)ether_buf, hlen / 2) = packet[hlen - 1] << 8; } #else memcpy(ether_buf, packet, hlen); @@ -349,6 +353,10 @@ void init_ether() { pcap_if_t *alldevs = NULL; pcap_if_t *dev = NULL; pcap_rval = pcap_findalldevs(&alldevs, errbuf); + if (pcap_rval == PCAP_ERROR) { + fprintf(stderr, "%s\n", errbuf); + return; + } for (pcap_if_t *d = alldevs; d; d = d->next) { if ((d->flags & PCAP_IF_UP) && (d->flags & PCAP_IF_RUNNING) && !(d->flags & PCAP_IF_LOOPBACK)) { dev = d; @@ -365,13 +373,13 @@ void init_ether() { */ #elif defined(AF_LINK) /* this is BSD-like, macOS? */ - if (a->addr->sa_family == AF_LINK) { + if (a->addr && a->addr->sa_family == AF_LINK) { memcpy(ether_host, LLADDR(((struct sockaddr_dl *)(a->addr))), sizeof(ether_host)); break; } #elif defined(AF_PACKET) /* this is Linux-like */ - if (a->addr->sa_family == AF_PACKET) { + if (a->addr && a->addr->sa_family == AF_PACKET) { memcpy(ether_host, ((struct sockaddr_ll *)(a->addr))->sll_addr, sizeof(ether_host)); break; } @@ -403,15 +411,29 @@ void init_ether() { snprintf(filter_exp, sizeof(filter_exp), "ether proto 0x600 and (ether multicast or ether dst %02x:%02x:%02x:%02x:%02x:%02x)", ether_host[0], ether_host[1], ether_host[2], ether_host[3], ether_host[4], ether_host[5]); pcap_rval = pcap_compile(pcap_handle, &filter_match_xns, filter_exp, 0, PCAP_NETMASK_UNKNOWN); - if (pcap_rval == -1) { + if (pcap_rval == PCAP_ERROR) { fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle)); pcap_close(pcap_handle); return; } pcap_rval = pcap_setfilter(pcap_handle, &filter_match_xns); - + if (pcap_rval == PCAP_ERROR) { + fprintf(stderr, "Couldn't set filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle)); + pcap_close(pcap_handle); + return; + } pcap_rval = pcap_setnonblock(pcap_handle, 1, errbuf); + if (pcap_rval == PCAP_ERROR) { + fprintf(stderr, "%s\n", errbuf); + pcap_close(pcap_handle); + return; + } ether_fd = pcap_get_selectable_fd(pcap_handle); + if (ether_fd == -1) { + fprintf(stderr, "Couldn't get selectable fd for pcap\n"); + pcap_close(pcap_handle); + return; + } FD_SET(ether_fd, &LispReadFds); printf("Ethernet starts on interface %s at %02x:%02x:%02x:%02x:%02x:%02x\n", From 6f277ed06ff4c97acfdd21346dca9fd2db6cbacd Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 13:38:35 -0700 Subject: [PATCH 14/49] Addresses additional error handling and setup order complaints * report errors and warnings from pcap_create() * reformat error messages slightly * move initial packet filter setting to after pcap activation, as required by the pcap API. --- src/ether_pcap.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 4d70befd..39c9a57c 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -391,23 +391,29 @@ void init_ether() { pcap_freealldevs(alldevs); } pcap_handle = pcap_create(ether_ifname, errbuf); - if (strlen(errbuf) > 0) { - fprintf(stderr, "%s\n", errbuf); + if (pcap_handle == NULL) { + fprintf(stderr, "pcap_create failed: %s\n", errbuf); return; } + if (strlen(errbuf) > 0) { + fprintf(stderr, "pcap_create warning: %s\n", errbuf); + } /* set up properties on the pcap_handle and then activate it */ pcap_rval = pcap_set_immediate_mode(pcap_handle, 1); pcap_rval = pcap_set_buffer_size(pcap_handle, 65536); pcap_rval = pcap_set_snaplen(pcap_handle, 1518); - pcap_rval = pcap_setfilter(pcap_handle, &filter_match_none); pcap_rval = pcap_activate(pcap_handle); if (pcap_rval != 0) { - pcap_perror(pcap_handle, "pcap_activate: "); + pcap_perror(pcap_handle, "pcap_activate"); } if (pcap_rval < 0) { pcap_close(pcap_handle); return; } + pcap_rval = pcap_setfilter(pcap_handle, &filter_match_none); + if (pcap_rval != 0) { + pcap_perror(pcap_handle, "pcap_setfilter"); + } snprintf(filter_exp, sizeof(filter_exp), "ether proto 0x600 and (ether multicast or ether dst %02x:%02x:%02x:%02x:%02x:%02x)", ether_host[0], ether_host[1], ether_host[2], ether_host[3], ether_host[4], ether_host[5]); pcap_rval = pcap_compile(pcap_handle, &filter_match_xns, filter_exp, 0, PCAP_NETMASK_UNKNOWN); From 30389063b9cefd5ad63c20b649666beafd8a2262 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 14:33:11 -0700 Subject: [PATCH 15/49] Cleanly update PENDINGINTERRUPT when a frame has been extended --- src/xc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xc.c b/src/xc.c index 4237451a..e3c2c7cc 100644 --- a/src/xc.c +++ b/src/xc.c @@ -1129,7 +1129,9 @@ op_ufn : { need_irq = (Irq_Stk_End == 0) || extended_frame; Irq_Stk_Check = (UNSIGNED)EndSTKP - STK_MIN(FuncObj); Irq_Stk_End = (UNSIGNED)EndSTKP; - *PENDINGINTERRUPT68k |= extended_frame ? ATOM_T : 0; + if (extended_frame) { + *PENDINGINTERRUPT68k = ATOM_T; + } } /* clear the flags set by the OS interrupt handlers that would From 959b523039f76b051a57c34410ac6c26b1a88e13 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 15:54:44 -0700 Subject: [PATCH 16/49] Introduces XrmValueCopy to safely copy a value{address, size} into a C string --- src/xrdopt.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index 07af1556..f7cdb1cb 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -14,7 +14,8 @@ #include // for XPointer, True, XParseGeometry, XResource... #include // for XrmoptionSepArg, XrmGetResource, Xrmoptio... #include // for errno -#include // for PATH_MAX +// #include // for PATH_MAX +#include // for MAXPATHLEN #include // for fprintf, NULL, stderr, sscanf #include // for getenv, exit, strtol #include // for strncpy, strlcat, strlcpy, strcmp @@ -91,8 +92,8 @@ extern char backgroundColorName[64]; extern char windowTitle[255]; -extern char sysout_name_cl[]; -extern char sysout_name_xrm[]; +extern char sysout_name_cl[MAXPATHLEN]; +extern char sysout_name_xrm[MAXPATHLEN]; extern unsigned sysout_size; extern int for_makeinit, please_fork, noscroll; /* diagnostic flag for sysout dumping */ @@ -148,6 +149,12 @@ void print_Xusage(const char *prog) exit(EXIT_FAILURE); } /* end print_Xusage() */ +static void XrmValueCopy(char *dst, XrmValue value, size_t dstSize) { + size_t len = (value.size < dstSize) ? value.size : dstSize - 1; + memcpy(dst, value.addr, len); + dst[len] = '\0'; +} + /************************************************************************/ /* */ /* r e a d _ X o p t i o n */ @@ -195,7 +202,7 @@ void read_Xoption(int *argc, char *argv[]) if (XrmGetResource(commandlineDB, "ldex.sysout", "Ldex.Sysout", str_type, &value) == True) { /* Get Sysout from command line only */ - (void)strncpy(sysout_name_cl, value.addr, value.size); + XrmValueCopy(sysout_name_cl, value, sizeof(sysout_name_cl)); } /* In order to access other DB's we have to open the main display now */ @@ -205,7 +212,7 @@ void read_Xoption(int *argc, char *argv[]) /* protocol. */ if (XrmGetResource(commandlineDB, "ldex.display", "Ldex.Display", str_type, &value) == True) { - (void)strncpy(Display_Name, value.addr, value.size); + XrmValueCopy(Display_Name, value, sizeof(Display_Name)); } else if (getenv("DISPLAY") == (char *)NULL) { (void)fprintf(stderr, "Can't find a display. Either set the shell\n"); (void)fprintf(stderr, "variable DISPLAY to an appropriate display\n"); @@ -246,48 +253,48 @@ void read_Xoption(int *argc, char *argv[]) if (XrmGetResource(rDB, "ldex.sysout", "Ldex.Sysout", str_type, &value) == True) { /* Get Sysout from x resource manager */ - (void)strncpy(sysout_name_xrm, value.addr, value.size); + XrmValueCopy(sysout_name_xrm, value, sizeof(sysout_name_xrm)); } if (XrmGetResource(rDB, "ldex.title", "Ldex.Title", str_type, &value) == True) { - (void)strncpy(windowTitle, value.addr, sizeof(windowTitle) - 1); + XrmValueCopy(windowTitle, value, sizeof(windowTitle)); } else { - (void)strncpy(windowTitle, WINDOW_NAME, sizeof(windowTitle) - 1); + (void)strlcpy(windowTitle, WINDOW_NAME, sizeof(windowTitle)); } if (XrmGetResource(rDB, "ldex.icontitle", "Ldex.icontitle", str_type, &value) == True) { - (void)strncpy(iconTitle, value.addr, value.size); + XrmValueCopy(iconTitle, value, sizeof(iconTitle)); } else { (void)strlcpy(iconTitle, "Medley", sizeof(iconTitle)); } if (XrmGetResource(rDB, "ldex.iconbitmap", "Ldex.Iconbitmap", str_type, &value) == True) { - (void)strncpy(iconpixmapfile, value.addr, value.size); + XrmValueCopy(iconpixmapfile, value, sizeof(iconpixmapfile)); } /* Old style geometry definition. */ if (XrmGetResource(rDB, "ldex.geometry", "Ldex.geometry", str_type, &value) == True) { /* Get Geometry */ - (void)strncpy(tmp, value.addr, value.size); + XrmValueCopy(tmp, value, sizeof(tmp)); bitmask = XParseGeometry(tmp, &LispWindowRequestedX, &LispWindowRequestedY, &LispWindowRequestedWidth, &LispWindowRequestedHeight); } if (XrmGetResource(rDB, "ldex.screen", "Ldex.screen", str_type, &value) == True) { /* Get Geometry */ - (void)strncpy(tmp, value.addr, value.size); + XrmValueCopy(tmp, value, sizeof(tmp)); bitmask = XParseGeometry(tmp, &LispDisplayRequestedX, &LispDisplayRequestedY, &LispDisplayRequestedWidth, &LispDisplayRequestedHeight); } if (XrmGetResource(rDB, "ldex.cursorColor", "Ldex.cursorColor", str_type, &value) == True) { - (void)strncpy(cursorColor, value.addr, sizeof(cursorColor) - 1); + XrmValueCopy(cursorColor, value, sizeof(cursorColor)); } if (XrmGetResource(rDB, "ldex.foreground", "Ldex.foreground", str_type, &value) == True) { - (void)strncpy(foregroundColorName, value.addr, sizeof(foregroundColorName) - 1); + XrmValueCopy(foregroundColorName, value, sizeof(foregroundColorName)); } if (XrmGetResource(rDB, "ldex.background", "Ldex.background", str_type, &value) == True) { - (void)strncpy(backgroundColorName, value.addr, sizeof(backgroundColorName) - 1); + XrmValueCopy(backgroundColorName, value, sizeof(backgroundColorName)); } if (XrmGetResource(rDB, "ldex.NoFork", "Ldex.NoFork", str_type, &value) == True) { @@ -299,7 +306,7 @@ void read_Xoption(int *argc, char *argv[]) } if (XrmGetResource(rDB, "ldex.timer", "Ldex.timer", str_type, &value) == True) { - (void)strncpy(tmp, value.addr, value.size); + XrmValueCopy(tmp, value, sizeof(tmp)); errno = 0; i = (int)strtol(tmp, (char **)NULL, 10); if (errno == 0 && i > 0) @@ -316,7 +323,7 @@ void read_Xoption(int *argc, char *argv[]) } */ if (XrmGetResource(rDB, "ldex.memory", "Ldex.memory", str_type, &value) == True) { - (void)strncpy(tmp, value.addr, value.size); + XrmValueCopy(tmp, value, sizeof(tmp)); errno = 0; i = (int)strtol(tmp, (char **)NULL, 10); if (errno == 0 && i > 0) @@ -330,7 +337,7 @@ void read_Xoption(int *argc, char *argv[]) #if defined(MAIKO_ENABLE_ETHERNET) && defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) if (XrmGetResource(rDB, "ldex.EtherNet", "Ldex.EtherNet", str_type, &value) == True) { int b0, b1, b2, b3, b4, b5; - (void)strncpy(tmp, value.addr, value.size); + XrmValueCopy(tmp, value, sizeof(tmp)); #if defined(USE_DLPI) if (sscanf(tmp, "%d:%x:%x:%x:%x:%x:%x", ðer_fd, &b0, &b1, &b2, &b3, &b4, &b5) == 7) #elif defined(USE_NIT) @@ -356,7 +363,7 @@ void read_Xoption(int *argc, char *argv[]) if (XrmGetResource(rDB, "ldex.EtherNet", "Ldex.EtherNet", str_type, &value) == True) { int b0, b1, b2, b3, b4, b5, fields; char ifname[32]; - (void)strncpy(tmp, value.addr, value.size); + XrmValueCopy(tmp, value, sizeof(tmp)); fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%31s", &b0, &b1, &b2, &b3, &b4, &b5, ifname); if (fields == 6 || fields == 7) { ether_enabled = 1; From e874b3163129d415210a543d70223fd54fa02931 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 15:55:54 -0700 Subject: [PATCH 17/49] Cleans up signedness mismatch on ether_ifname string --- src/ether_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ether_common.c b/src/ether_common.c index ae943814..80078da7 100644 --- a/src/ether_common.c +++ b/src/ether_common.c @@ -25,7 +25,7 @@ extern int ether_enabled; extern int ether_fd; extern u_char ether_host[6]; -extern u_char ether_ifname[32]; +extern char ether_ifname[32]; extern const u_char broadcast[6]; extern int ether_bsize; extern u_char *ether_buf; @@ -33,7 +33,7 @@ extern u_char *ether_buf; int ether_enabled = 0; /* ethernet disabled unless we ask for it */ int ether_fd = -1; /* file descriptor for ether socket */ u_char ether_host[6] = {0, 0, 0, 0, 0, 0}; /* 48 bit address of this node */ -u_char ether_ifname[32] = {0}; /* interface name (pcap, perhaps others) */ +char ether_ifname[32] = "\0"; /* interface name (pcap, perhaps others) */ const u_char broadcast[6] = {255, 255, 255, 255, 255, 255}; int ether_bsize = 0; /* if nonzero then a receive is pending */ u_char *ether_buf = NULL; /* address of receive buffer */ From ba914df87e75dcd6d6607b12ee5cffa434df6e9d Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 16:40:46 -0700 Subject: [PATCH 18/49] Add comments re ideas on -E option parsing and restructure slightly --- src/main.c | 1 + src/xrdopt.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 307de3e5..81ccb3ab 100644 --- a/src/main.c +++ b/src/main.c @@ -611,6 +611,7 @@ int main(int argc, char *argv[]) int b[6]; char ifname[32] = {0}; fields = sscanf(argv[i], "%x:%x:%x:%x:%x:%x%%%31s", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], ifname); + /* TBD: see comments in xrdopts.c regarding determining ifname and MAC address */ if (fields == 6 || fields == 7) { for (int x = 0; x < 6; x++) ether_host[x] = b[x] & 0xFF; if (fields == 7) diff --git a/src/xrdopt.c b/src/xrdopt.c index f7cdb1cb..a4d40fbf 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -365,6 +365,11 @@ void read_Xoption(int *argc, char *argv[]) char ifname[32]; XrmValueCopy(tmp, value, sizeof(tmp)); fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%31s", &b0, &b1, &b2, &b3, &b4, &b5, ifname); + /* TBD: if we have just a single atom, no colons, it could be an interface name. + we should save it, enable the ethernet, and adjust the code in ether_pcap.c:init_ether + so that given an all zero ether_host it sees if there is a matching interface + from which it can extract the MAC address. + */ if (fields == 6 || fields == 7) { ether_enabled = 1; ether_host[0] = b0; @@ -375,10 +380,10 @@ void read_Xoption(int *argc, char *argv[]) ether_host[5] = b5; if (fields == 7) strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); - } else { - (void)fprintf(stderr, "Invalid argument for -E (pcap)\n"); - exit(1); + return; } + (void)fprintf(stderr, "Invalid argument for -E %s (X/pcap)\n", tmp); + exit(1); } #endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) */ } /* end readXoption */ From 36ce42707492c45f8bdf5682ea0be7c3cd8e6bef Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 16:42:13 -0700 Subject: [PATCH 19/49] Improves robustness of handling pcap_next_ex() results and error reporting for finding suitable ethernet interface --- src/ether_pcap.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 39c9a57c..0d84218c 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -124,14 +124,13 @@ static int recvPacket() { const uint8_t *packet = NULL; struct pcap_pkthdr *header = NULL; - switch (pcap_next_ex(pcap_handle, &header, (void *)&packet)) { - case 0: - return (0); - case PCAP_ERROR: - case PCAP_ERROR_BREAK: + pcap_rval = pcap_next_ex(pcap_handle, &header, (void *)&packet); + if (pcap_rval == 0) return(0); + if (pcap_rval != 1) { pcap_perror(pcap_handle, "recvPacket"); return (0); } + hlen = header->len; if (hlen > ether_bsize || hlen == 0) return (0); @@ -390,6 +389,10 @@ void init_ether() { } pcap_freealldevs(alldevs); } + if(strlen(ether_ifname) == 0) { + fprintf(stderr, "No suitable network interface found\n"); + return; + } pcap_handle = pcap_create(ether_ifname, errbuf); if (pcap_handle == NULL) { fprintf(stderr, "pcap_create failed: %s\n", errbuf); From 1de5296ad43658e45fd0d6eb5eac1768ce00ea3a Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 16:44:33 -0700 Subject: [PATCH 20/49] Handle case where PCAP selectable fd is greater than FD_SETSIZE --- src/ether_pcap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 0d84218c..84e4c0a7 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -438,8 +438,9 @@ void init_ether() { return; } ether_fd = pcap_get_selectable_fd(pcap_handle); - if (ether_fd == -1) { - fprintf(stderr, "Couldn't get selectable fd for pcap\n"); + if (ether_fd == -1 || ether_fd >= FD_SETSIZE) { + fprintf(stderr, "Couldn't get valid selectable fd for pcap\n"); + ether_fd = -1; pcap_close(pcap_handle); return; } From e3f65ba8e7c061439ac912bff8d5d95f116402ff Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 16:47:48 -0700 Subject: [PATCH 21/49] Update comments to help Gemini get over its mistaken idea of the max XNS packet size from Medley --- src/ether_pcap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 84e4c0a7..dd3bbb4b 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -251,7 +251,10 @@ LispPTR ether_get(LispPTR args[]) * send a packet **********************************************************************/ -/* normally an XNS packet would be no bigger than 576 bytes */ +/* We assert than the packets passed to ether_send() will never be + longer than 300 16-bit words. Limit is defined by ETHERPACKET + datatype in Lisp source. +*/ #define MAXETHERPACKETWORDS 300 LispPTR ether_send(LispPTR args[]) From de1ce7ba31bcf2976a6264e8acd905ff64ce5c89 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 17:20:25 -0700 Subject: [PATCH 22/49] Fixes uninitialized fd set in SunOS/Solaris check_ether code. --- src/ether_sunos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ether_sunos.c b/src/ether_sunos.c index d27d4c3a..33217147 100644 --- a/src/ether_sunos.c +++ b/src/ether_sunos.c @@ -492,7 +492,7 @@ LispPTR check_ether(void) { char ctlbuf[2000]; #endif /* PKTFILTER */ if (ether_fd < 0) return (NIL); - + FD_ZERO(&rfds); FD_SET(ether_fd, &rfds); #ifndef PKTFILTER i = 2; From b410f13a4e01f6673113f81ed511c0b121b0e93d Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 1 Jun 2026 17:22:19 -0700 Subject: [PATCH 23/49] Handles errors (unlikely) from pcap_inject(); updates comment on XNS packet filter --- src/ether_pcap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index dd3bbb4b..61d6e4f8 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -274,7 +274,10 @@ LispPTR ether_send(LispPTR args[]) } bufferAddr = networkOrderBuffer; #endif - pcap_inject(pcap_handle, bufferAddr, 2 * wordCount); + if (pcap_inject(pcap_handle, bufferAddr, 2 * wordCount) < 0) { + pcap_perror(pcap_handle, "ether_send"); + return (NIL); + } ether_out++; return (ATOM_T); } /* ether_send */ @@ -420,6 +423,7 @@ void init_ether() { if (pcap_rval != 0) { pcap_perror(pcap_handle, "pcap_setfilter"); } + /* filter for XNS - may want to do PUP later */ snprintf(filter_exp, sizeof(filter_exp), "ether proto 0x600 and (ether multicast or ether dst %02x:%02x:%02x:%02x:%02x:%02x)", ether_host[0], ether_host[1], ether_host[2], ether_host[3], ether_host[4], ether_host[5]); pcap_rval = pcap_compile(pcap_handle, &filter_match_xns, filter_exp, 0, PCAP_NETMASK_UNKNOWN); From 443f356f159db141a3140044393294fa4adaef4c Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 2 Jun 2026 09:41:08 -0700 Subject: [PATCH 24/49] Adds safety check to XrmValueCopy for passing NULL for dst or 0 for dstSize --- src/xrdopt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index a4d40fbf..fe45bf6d 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -150,7 +150,9 @@ void print_Xusage(const char *prog) } /* end print_Xusage() */ static void XrmValueCopy(char *dst, XrmValue value, size_t dstSize) { - size_t len = (value.size < dstSize) ? value.size : dstSize - 1; + size_t len; + if (dst == NULL || dstSize == 0) return; /* placate gemini */ + len = (value.size < dstSize) ? value.size : dstSize - 1; memcpy(dst, value.addr, len); dst[len] = '\0'; } From 2c39b39d7f6594fdd4d74551edaab4a48a2085b8 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 2 Jun 2026 09:42:00 -0700 Subject: [PATCH 25/49] Removes unnecessary include nlist.h from ether_pcap.c --- src/ether_pcap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 61d6e4f8..803b3062 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -39,7 +39,6 @@ #include #include -#include #include #include "commondefs.h" From f7e605e461889c127365d7a6d1ed4f4af5d89416 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 2 Jun 2026 09:43:39 -0700 Subject: [PATCH 26/49] Use common style for declaration of ethernet addresses in ether_addr_equal() --- inc/etherdefs.h | 3 ++- src/ether_common.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/inc/etherdefs.h b/inc/etherdefs.h index 971c0157..0d5cb456 100644 --- a/inc/etherdefs.h +++ b/inc/etherdefs.h @@ -1,5 +1,6 @@ #ifndef ETHERDEFS_H #define ETHERDEFS_H 1 +#include /* for u_char */ #include "lispemul.h" /* for LispPTR */ LispPTR ether_suspend(LispPTR args[]); LispPTR ether_resume(LispPTR args[]); @@ -14,7 +15,7 @@ LispPTR check_ether(void); void init_ifpage_ether(void); void init_ether(void); LispPTR check_sum(LispPTR *args); -int ether_addr_equal(const uint8_t addr1[6], const uint8_t addr2[6]); +int ether_addr_equal(const u_char addr1[6], const u_char addr2[6]); void setNethubHost(char* host); void setNethubPort(int port); void setNethubMac(int m0, int m1, int m2, int m3, int m4, int m5); diff --git a/src/ether_common.c b/src/ether_common.c index 80078da7..a43a8ebf 100644 --- a/src/ether_common.c +++ b/src/ether_common.c @@ -108,7 +108,7 @@ LispPTR check_sum(LispPTR *args) * checks ethernet addresses equality **********************************************************************/ -int ether_addr_equal(const uint8_t addr1[6], const uint8_t addr2[6]) +int ether_addr_equal(const u_char addr1[6], const u_char addr2[6]) { return (0 == memcmp(addr1, addr2, 6)); } From f970d24de4e6f0d11f5f00127fe3f32578c53f6a Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 2 Jun 2026 14:38:54 -0700 Subject: [PATCH 27/49] Corrects erroneous use of bitwise-and in place of logical and. --- src/keyevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyevent.c b/src/keyevent.c index 4c5870c5..0f80f089 100644 --- a/src/keyevent.c +++ b/src/keyevent.c @@ -274,7 +274,7 @@ void process_io_events(void) #endif iflags = 0; for (i = 0; i < 32; i++) - if (FD_ISSET(i, &rfds) & FD_ISSET(i, &LispIOFds)) iflags |= 1 << i; + if (FD_ISSET(i, &rfds) && FD_ISSET(i, &LispIOFds)) iflags |= 1 << i; if (iflags) { /* There's activity on a Lisp-opened FD. Tell Lisp. */ u_int *flags; flags = (u_int *)NativeAligned4FromLAddr(*IOINTERRUPTFLAGS_word); From eee15b1fb3a19547c7dd2fc188b6957af56cc8a6 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 2 Jun 2026 14:40:08 -0700 Subject: [PATCH 28/49] Fixes missing void in parameterless procedure decl. Removes unused variable devname. --- src/ether_pcap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 803b3062..5df88db4 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -117,7 +117,7 @@ static int ether_out = 0; /* number of packets sent */ * length in bytes of the packet if one was read. * **********************************************************************/ -static int recvPacket() { +static int recvPacket(void) { int pcap_rval = 0; bpf_u_int32 hlen; const uint8_t *packet = NULL; @@ -344,8 +344,6 @@ void init_ether() { */ int pcap_rval = 0; - // char *etherdev = getenv("LDEETHERDEV"); /* name of interface we want */ - char devname[32] = {0}; char errbuf[PCAP_ERRBUF_SIZE] = {0}; char filter_exp[256]; From b50f976399bcc8d493cc4ee06ad6fbf3cd01a5da Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 2 Jun 2026 17:29:13 -0700 Subject: [PATCH 29/49] Improves ease-of-use of -E option (pcap) by allowing -E interface-name On systems where PCAP can determine all the interface names, specifying -E interface-name will search for that interface and use the ethernet MAC address from the interface, instead of the user having to extract it from ifconfig/ipadm/... to pass it in. Minor cleanup to parsing of -E option when giving a full MAC address --- src/ether_pcap.c | 20 ++++++++++++++++---- src/main.c | 21 +++++++++++++-------- src/xrdopt.c | 49 +++++++++++++++++++++--------------------------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 5df88db4..ad0162c5 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -343,15 +343,21 @@ void init_ether() { * pcap_inject/pcap_sendpacket => transmit a packet */ + static const u_char ether_zero[6] = {0}; int pcap_rval = 0; char errbuf[PCAP_ERRBUF_SIZE] = {0}; char filter_exp[256]; - + int find_ifname; + int find_ifaddr; + /* ethernet may already be initialized - don't do it again */ if (ether_fd >= 0 || ether_enabled == 0) return; - /* select an ethernet interface if one was not provided */ - if (strlen(ether_ifname) == 0) { + /* select an ethernet interface/address if it was not fully specified */ + find_ifname = strlen(ether_ifname) == 0; + find_ifaddr = ether_addr_equal(ether_host, ether_zero); + + if (find_ifname || find_ifaddr) { pcap_if_t *alldevs = NULL; pcap_if_t *dev = NULL; pcap_rval = pcap_findalldevs(&alldevs, errbuf); @@ -360,7 +366,13 @@ void init_ether() { return; } for (pcap_if_t *d = alldevs; d; d = d->next) { - if ((d->flags & PCAP_IF_UP) && (d->flags & PCAP_IF_RUNNING) && !(d->flags & PCAP_IF_LOOPBACK)) { + /* if only looking for the address, and not looking for a name */ + if (find_ifaddr && !find_ifname) { + if (strcmp(d->name, ether_ifname) == 0) { + dev = d; + break; + } + } else if ((d->flags & PCAP_IF_UP) && (d->flags & PCAP_IF_RUNNING) && !(d->flags & PCAP_IF_LOOPBACK)) { dev = d; break; } diff --git a/src/main.c b/src/main.c index 81ccb3ab..8eb650dd 100644 --- a/src/main.c +++ b/src/main.c @@ -610,15 +610,20 @@ int main(int argc, char *argv[]) int fields; int b[6]; char ifname[32] = {0}; - fields = sscanf(argv[i], "%x:%x:%x:%x:%x:%x%%%31s", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], ifname); - /* TBD: see comments in xrdopts.c regarding determining ifname and MAC address */ - if (fields == 6 || fields == 7) { - for (int x = 0; x < 6; x++) ether_host[x] = b[x] & 0xFF; - if (fields == 7) - strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); + if (strchr(argv[i], ':') == NULL && strchr(argv[i], '%') == NULL) { + /* assume it's an interface name for which we do not know the address */ + strlcpy(ether_ifname, argv[i], sizeof(ether_ifname)); } else { - (void)fprintf(stderr, "Invalid argument for -E (pcap)\n"); - exit(1); + fields = sscanf(argv[i], "%x:%x:%x:%x:%x:%x%%%31s", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], ifname); + /* TBD: see comments in xrdopts.c regarding determining ifname and MAC address */ + if (fields == 6 || fields == 7) { + for (int x = 0; x < 6; x++) ether_host[x] = b[x] & 0xFF; + if (fields == 7) + strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); + } else { + (void)fprintf(stderr, "Invalid argument for -E (pcap)\n"); + exit(1); + } } } else { (void)fprintf(stderr, "Missing argument after -E\n"); diff --git a/src/xrdopt.c b/src/xrdopt.c index fe45bf6d..9b34b176 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -338,21 +338,17 @@ void read_Xoption(int *argc, char *argv[]) #if defined(MAIKO_ENABLE_ETHERNET) && defined(MAIKO_OS_SOLARIS) && (defined(USE_DLPI) || defined(USE_NIT)) if (XrmGetResource(rDB, "ldex.EtherNet", "Ldex.EtherNet", str_type, &value) == True) { - int b0, b1, b2, b3, b4, b5; + int b[6]; XrmValueCopy(tmp, value, sizeof(tmp)); #if defined(USE_DLPI) - if (sscanf(tmp, "%d:%x:%x:%x:%x:%x:%x", ðer_fd, &b0, &b1, &b2, &b3, &b4, &b5) == 7) + if (sscanf(tmp, "%d:%x:%x:%x:%x:%x:%x", ðer_fd, &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]) == 7) #elif defined(USE_NIT) - if (sscanf(tmp, "%d:%x:%x:%x:%x:%x:%x:%s", ðer_fd, &b0, &b1, &b2, &b3, &b4, &b5, + if (sscanf(tmp, "%d:%x:%x:%x:%x:%x:%x:%s", ðer_fd, &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], snit.snit_ifname) == 8) #endif { - ether_host[0] = b0; - ether_host[1] = b1; - ether_host[2] = b2; - ether_host[3] = b3; - ether_host[4] = b4; - ether_host[5] = b5; + for (int i = 0; i < 6; i++) + ether_host[i] = b[i] & 0xff; } else { (void)fprintf(stderr, "Missing or bogus -E argument\n"); ether_fd = -1; @@ -363,29 +359,26 @@ void read_Xoption(int *argc, char *argv[]) #if defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) if (XrmGetResource(rDB, "ldex.EtherNet", "Ldex.EtherNet", str_type, &value) == True) { - int b0, b1, b2, b3, b4, b5, fields; + int b[6], fields; char ifname[32]; XrmValueCopy(tmp, value, sizeof(tmp)); - fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%31s", &b0, &b1, &b2, &b3, &b4, &b5, ifname); - /* TBD: if we have just a single atom, no colons, it could be an interface name. - we should save it, enable the ethernet, and adjust the code in ether_pcap.c:init_ether - so that given an all zero ether_host it sees if there is a matching interface - from which it can extract the MAC address. - */ - if (fields == 6 || fields == 7) { + if (strchr(tmp, ':') == NULL && strchr(tmp, '%') == NULL) { + /* assume it's an interface name for which we do not know the address */ ether_enabled = 1; - ether_host[0] = b0; - ether_host[1] = b1; - ether_host[2] = b2; - ether_host[3] = b3; - ether_host[4] = b4; - ether_host[5] = b5; - if (fields == 7) - strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); - return; + strlcpy(ether_ifname, tmp, sizeof(ether_ifname)); + } else { + fields = sscanf(tmp, "%x:%x:%x:%x:%x:%x%%%31s", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], ifname); + if (fields == 6 || fields == 7) { + ether_enabled = 1; + for (int i = 0; i < 6; i++) + ether_host[i] = b[i] & 0xff; + if (fields == 7) + strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); + } else { + (void)fprintf(stderr, "Invalid argument for -E %s (X/pcap)\n", tmp); + exit(1); + } } - (void)fprintf(stderr, "Invalid argument for -E %s (X/pcap)\n", tmp); - exit(1); } #endif /* defined(MAIKO_ENABLE_ETHERNET) && defined(USE_PCAP) */ } /* end readXoption */ From 9761836e2bd770adcda0f3017c253ae9e741f7a8 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 22 Jun 2026 13:58:27 +0100 Subject: [PATCH 30/49] Minor cleanup for pcap_next_ex() packet type, safety check on addr length --- src/ether_pcap.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index ad0162c5..20a0187e 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -120,10 +120,10 @@ static int ether_out = 0; /* number of packets sent */ static int recvPacket(void) { int pcap_rval = 0; bpf_u_int32 hlen; - const uint8_t *packet = NULL; + const u_char *packet = NULL; struct pcap_pkthdr *header = NULL; - pcap_rval = pcap_next_ex(pcap_handle, &header, (void *)&packet); + pcap_rval = pcap_next_ex(pcap_handle, &header, &packet); if (pcap_rval == 0) return(0); if (pcap_rval != 1) { pcap_perror(pcap_handle, "recvPacket"); @@ -388,14 +388,20 @@ void init_ether() { #elif defined(AF_LINK) /* this is BSD-like, macOS? */ if (a->addr && a->addr->sa_family == AF_LINK) { - memcpy(ether_host, LLADDR(((struct sockaddr_dl *)(a->addr))), sizeof(ether_host)); - break; + struct sockaddr_dl *sdl = (struct sockaddr_dl *)(a->addr); + if (sdl->sdl_alen == sizeof(ether_host)) { + memcpy(ether_host, LLADDR(sdl), sizeof(ether_host)); + break; + } } #elif defined(AF_PACKET) /* this is Linux-like */ if (a->addr && a->addr->sa_family == AF_PACKET) { - memcpy(ether_host, ((struct sockaddr_ll *)(a->addr))->sll_addr, sizeof(ether_host)); - break; + struct sockaddr_ll *sll = (struct sockaddr_ll*)(a->addr); + if (sll->sll_halen == sizeof(ether_host)) { + memcpy(ether_host, sll->sll_addr, sizeof(ether_host)); + break; + } } #else #warning Neither AF_LINK nor AF_PACKET address families defined From f7284f22c474109d52cf1352e166eb6fe3c3cb44 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 22 Jun 2026 14:11:13 +0100 Subject: [PATCH 31/49] Remove unused xfd in X_init, setting async i/o has to be deferred. --- src/xinit.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/xinit.c b/src/xinit.c index 07a1f718..34697755 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -17,7 +17,6 @@ #include // for false, bool, true #include // for NULL #include // for exit -#include // for fcntl, O_ASYNC, ... #include // for getpid #include "adr68k.h" // for NativeAligned4FromLAddr #include "dbprint.h" // for TPRINT @@ -250,7 +249,6 @@ DspInterface X_init(DspInterface dsp, LispPTR lispbitmap, unsigned width_hint, u unsigned depth_hint) { Screen *Xscreen; - int xfd; dsp->identifier = Display_Name; /* This is a hack. The display name */ /* has to dealt with in a more */ From c964877e758eb81ecfea4eb687570f1323e2e6ad Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 22 Jun 2026 23:36:55 +0100 Subject: [PATCH 32/49] improves accuracy for periodic interrupt frequency calculation (maybe) --- src/xc.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/xc.c b/src/xc.c index e3c2c7cc..7eae1da4 100644 --- a/src/xc.c +++ b/src/xc.c @@ -1168,14 +1168,9 @@ op_ufn : { period_cnt = 0; else period_cnt = - (*PERIODIC_INTERRUPT_FREQUENCY68k & 0xffff) * (1000000 / 60) / TIMER_INTERVAL; + ((*PERIODIC_INTERRUPT_FREQUENCY68k & 0xffff) * 1000000UL) / (60 * TIMER_INTERVAL); /* number of 1/60 second periods between interrupts (really??) - TIMER_INTERVAL is the number of microseconds between - timer interrupts. The calculation here avoids some - overflow errors although there is some roundoff - if the interrupt frequency number is too low, - it will bottom out and just set period_cnt to 0 - Rewrite as ((*PIF & 0xffff) * 1000000UL) / (60 * TIMER_INTERVAL) + TIMER_INTERVAL is the number of microseconds between timer interrupts. */ } } From c5790848f87e86d165ef32f9a0c2d72e832007d9 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 22 Jun 2026 23:38:07 +0100 Subject: [PATCH 33/49] Improves the error messages for bad -E/ldex.EtherNet resources --- src/xrdopt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index 9b34b176..0cb77e76 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -350,7 +350,7 @@ void read_Xoption(int *argc, char *argv[]) for (int i = 0; i < 6; i++) ether_host[i] = b[i] & 0xff; } else { - (void)fprintf(stderr, "Missing or bogus -E argument\n"); + (void)fprintf(stderr, "Missing or bogus -E or ldex.EtherNet resource argument\n"); ether_fd = -1; exit(1); } @@ -375,7 +375,7 @@ void read_Xoption(int *argc, char *argv[]) if (fields == 7) strlcpy(ether_ifname, ifname, sizeof(ether_ifname)); } else { - (void)fprintf(stderr, "Invalid argument for -E %s (X/pcap)\n", tmp); + (void)fprintf(stderr, "Invalid argument for -E or ldex.EtherNet resource: %s (X/pcap)\n", tmp); exit(1); } } From b0706d42dafb0097a6d2485c3f267ad8b76d6bb9 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 09:56:44 +0100 Subject: [PATCH 34/49] Eliminates strncpy() in main.c in favor of snprintf() --- src/main.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main.c b/src/main.c index 8eb650dd..d44c1b75 100644 --- a/src/main.c +++ b/src/main.c @@ -373,7 +373,7 @@ int main(int argc, char *argv[]) // and save it away if it is in case the X windows // arg processing changes argc/argv if (argc > 1 && argv[1][0] != '-') { - strncpy(sysout_name_first_arg, argv[1], MAXPATHLEN); + snprintf(sysout_name_first_arg, MAXPATHLEN, "%s", argv[1]); } @@ -406,7 +406,7 @@ int main(int argc, char *argv[]) /* Check for -sysout arg */ if (!strcmp(argv[i], "-sysout")) { if (argc > ++i) { - strncpy(sysout_name_cl, argv[i], MAXPATHLEN); + snprintf(sysout_name_cl, MAXPATHLEN, "%s", argv[i]); } } @@ -499,21 +499,21 @@ int main(int argc, char *argv[]) } else if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "-T") == 0) || (strcmp(argv[i], "-title") == 0) || (strcmp(argv[i], "-TITLE") == 0)) { if (argc > ++i) { - strncpy(windowTitle, argv[i], sizeof(windowTitle) - 1); + snprintf(windowTitle, sizeof(windowTitle), "%s", argv[i]); } else { (void)fprintf(stderr, "Missing argument after -title\n"); exit(1); } } else if (strcmp(argv[i], "-fg") == 0 || strcmp(argv[i], "-foreground") == 0) { if (argc > ++i) { - strncpy(foregroundColorName, argv[i], sizeof(foregroundColorName) - 1); + snprintf(foregroundColorName, sizeof(foregroundColorName), "%s", argv[i]); } else { (void)fprintf(stderr, "Missing argument after -fg/-foreground\n"); exit(1); } } else if (strcmp(argv[i], "-bg") == 0 || strcmp(argv[i], "-background") == 0) { if (argc > ++i) { - strncpy(backgroundColorName, argv[i], sizeof(backgroundColorName) - 1); + snprintf(backgroundColorName, sizeof(backgroundColorName), "%s", argv[i]); } else { (void)fprintf(stderr, "Missing argument after -bg/-background\n"); exit(1); @@ -678,18 +678,17 @@ int main(int argc, char *argv[]) // 5. Value as determined by X resource manager, if any // 6. Value of $HOME/lisp.virtualmem (or lisp.vm for DOS) // - if (sysout_name_cl[0] != '\0') { strncpy(sysout_name, sysout_name_cl, MAXPATHLEN); } - else if (sysout_name_first_arg[0] != '\0') { strncpy(sysout_name, sysout_name_first_arg, MAXPATHLEN); } - else if ((envname = getenv("LDESRCESYSOUT")) != NULL) { strncpy(sysout_name, envname, MAXPATHLEN); } - else if ((envname = getenv("LDESOURCESYSOUT")) != NULL) { strncpy(sysout_name, envname, MAXPATHLEN); } - else if (sysout_name_xrm[0] != '\0') { strncpy(sysout_name, sysout_name_xrm, MAXPATHLEN); } + if (sysout_name_cl[0] != '\0') { snprintf(sysout_name, MAXPATHLEN, "%s", sysout_name_cl); } + else if (sysout_name_first_arg[0] != '\0') { snprintf(sysout_name, MAXPATHLEN, "%s", sysout_name_first_arg); } + else if ((envname = getenv("LDESRCESYSOUT")) != NULL) { snprintf(sysout_name, MAXPATHLEN, "%s", envname); } + else if ((envname = getenv("LDESOURCESYSOUT")) != NULL) { snprintf(sysout_name, MAXPATHLEN, "%s", envname); } + else if (sysout_name_xrm[0] != '\0') { snprintf(sysout_name, MAXPATHLEN, "%s", sysout_name_xrm); } else { #ifdef DOS - strncpy(sysout_name, "lisp.vm", MAXPATHLEN); + snprintf(sysout_name, MAXPATHLEN, "%s", "lisp.vm"); #else if ((envname = getenv("HOME")) != NULL) { - strncpy(sysout_name, envname, MAXPATHLEN); - strncat(sysout_name, "/lisp.virtualmem", MAXPATHLEN - 17); + snprintf(sysout_name, MAXPATHLEN, "%s/lisp.virtualmem", envname); } #endif /* DOS */ } From 9812285778a79f484cda9a97b85721f63a3ac307 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 10:43:10 +0100 Subject: [PATCH 35/49] Reinstates maxpages limit X resource on contiguous pages dumped in sysout writes --- src/xrdopt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index 0cb77e76..db66f5ec 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -97,7 +97,7 @@ extern char sysout_name_xrm[MAXPATHLEN]; extern unsigned sysout_size; extern int for_makeinit, please_fork, noscroll; /* diagnostic flag for sysout dumping */ -/* extern unsigned maxpages; */ +extern unsigned maxpages; /*** Ethernet stuff (JRB) **/ #ifdef MAIKO_ENABLE_ETHERNET @@ -315,15 +315,14 @@ void read_Xoption(int *argc, char *argv[]) TIMER_INTERVAL = i; } - /* if (XrmGetResource(rDB, - "ldex.maxpages", - "Ldex.maxpages", - str_type, &value) == True) { - (void)strncpy(tmp, value.addr, value.size); - maxpages = (unsigned)strtol((tmp, (char **)NULL, 10); - // should check no error here - } - */ + if (XrmGetResource(rDB, "ldex.maxpages", "Ldex.maxpages", str_type, &value) == True) { + XrmValueCopy(tmp, value, sizeof(tmp)); + errno = 0; + i = (int)strtol(tmp, (char **)NULL, 10); + if (errno == 0 && i > 0) + maxpages = i; + } + if (XrmGetResource(rDB, "ldex.memory", "Ldex.memory", str_type, &value) == True) { XrmValueCopy(tmp, value, sizeof(tmp)); errno = 0; From 1a5196ce05afb5616205d6ab60e4dcca19e4d299 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 11:29:17 +0100 Subject: [PATCH 36/49] Eliminates strncpy in favor of memcpy for moving non null-terminated strings --- src/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dir.c b/src/dir.c index 97e9da5e..3bc3a721 100644 --- a/src/dir.c +++ b/src/dir.c @@ -2309,7 +2309,7 @@ LispPTR COM_next_file(LispPTR *args) laddr = gfsp->name; STRING_BASE(laddr, base); #ifndef BYTESWAP - strncpy(base, fp->lname, fp->lname_len); + memcpy(base, fp->lname, fp->lname_len); #else MemCpyToLispFromNative(base, fp->lname, fp->lname_len); #endif /* BYTESWAP */ @@ -2325,7 +2325,7 @@ LispPTR COM_next_file(LispPTR *args) laddr = gfsp->author; STRING_BASE(laddr, base); #ifndef BYTESWAP - strncpy(base, pp->author, pp->au_len); + memcpy(base, pp->author, pp->au_len); #else MemCpyToLispFromNative(base, pp->author, pp->au_len); #endif /* BYTESWAP */ From 374a41e98a7ca565efec56c967292b32e28cf657 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 22:22:17 +0100 Subject: [PATCH 37/49] Eliminates strncpy() in favor of memcpy()/snprintf() Where the target is a Lisp string, not null terminated, use memcpy() to better reflect the intent. Where the target is null terminated, but the source is not, use snprintf() with calculated string length. --- src/dsk.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/dsk.c b/src/dsk.c index 0074cfa5..3d5c8ea9 100644 --- a/src/dsk.c +++ b/src/dsk.c @@ -14,7 +14,7 @@ #include // for NULL, snprintf, size_t, rename, SEEK_SET #include // for ptrdiff_t #include // for strtoul, qsort -#include // for strlcpy, strcmp, strlen, strncpy, strchr +#include // for strlcpy, strcmp, strlen, memcpy, strchr #include // for stat, fstat, mkdir, S_ISREG, st_atime, chmod #include // for ino_t, time_t, off_t #include // for unlink, close, link, lseek, access, chdir @@ -1030,7 +1030,7 @@ LispPTR DSK_getfilename(LispPTR *args) len = strlen(lfname); #ifndef BYTESWAP - strncpy(base, lfname, len); + memcpy(base, lfname, len); #else MemCpyToLispFromNative(base, lfname, len); #endif /* BYTESWAP */ @@ -1066,7 +1066,7 @@ LispPTR DSK_getfilename(LispPTR *args) len = strlen(lfname); #ifndef BYTESWAP - strncpy(base, lfname, len); + memcpy(base, lfname, len); #else MemCpyToLispFromNative(base, lfname, len); #endif /* BYTESWAP */ @@ -1504,7 +1504,7 @@ LispPTR DSK_directorynamep(LispPTR *args) STRING_BASE(args[1], base); #ifndef BYTESWAP - strncpy(base, dirname, len); + memcpy(base, dirname, len); #else MemCpyToLispFromNative(base, dirname, len); #endif /* BYTESWAP */ @@ -1667,7 +1667,7 @@ LispPTR COM_getfileinfo(LispPTR *args) STRING_BASE(args[2], base); len = strlen(pwd->pw_name); #ifndef BYTESWAP - strncpy(base, pwd->pw_name, len); + memcpy(base, pwd->pw_name, len); #else MemCpyToLispFromNative(base, pwd->pw_name, len); #endif /* BYTESWAP */ @@ -1714,7 +1714,7 @@ LispPTR COM_getfileinfo(LispPTR *args) STRING_BASE(laddr, base); len = strlen(pwd->pw_name); #ifndef BYTESWAP - strncpy(base, pwd->pw_name, len); + memcpy(base, pwd->pw_name, len); #else MemCpyToLispFromNative(base, pwd->pw_name, len); #endif /* BYTESWAP */ @@ -2335,7 +2335,7 @@ void separate_version(char *name, size_t namesize, char *ver, size_t versize, in { char *start, *end, *cp; unsigned ver_no; - size_t len; + ptrdiff_t len; char ver_buf[VERSIONLEN]; if ((end = (char *)strchr(name, '~')) != (char *)NULL) { @@ -2355,8 +2355,7 @@ void separate_version(char *name, size_t namesize, char *ver, size_t versize, in * ### are all numbers or not, if checkp is 1. */ len = (end - start) - 1; - strncpy(ver_buf, start + 1, len); - ver_buf[len] = '\0'; + snprintf(ver_buf, sizeof(ver_buf), "%.*s", (int)len, start + 1); if (checkp) { NumericStringP(ver_buf, YES, NO); YES: From 81d993dcdb73db9bd618feb457ec3ce884e1eea9 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 22:50:15 +0100 Subject: [PATCH 38/49] Eliminates strncpy() in favor of memcpy() for body of BCPL string. --- src/initsout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/initsout.c b/src/initsout.c index 623c9ad9..00cc0128 100644 --- a/src/initsout.c +++ b/src/initsout.c @@ -22,7 +22,7 @@ #endif #include // for fprintf, NULL, stderr #include // for malloc, exit -#include // for strlen, strncpy +#include // for strlen, memcpy #include // for time_t #include // for gethostid, getuid #include "adr68k.h" // for NativeAligned2FromLAddr, NativeAligned4FromLAddr @@ -164,7 +164,7 @@ are null terminated instead */ /* Lisp reserves 32 words for the BCPL String */ len = (len < 32 * BYTESPER_DLWORD) ? len : 32 * BYTESPER_DLWORD - 1; *s = (char)len; - strncpy(s + 1, pwd->pw_name, len); + memcpy(s + 1, pwd->pw_name, len); #ifdef BYTESWAP /* we must swap the area we have written into, starting at 0155000 */ /* rounding up to 4-byte words */ From af4a1f6680564964d3bd961c85e5ad96e38d4a3e Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 22:57:52 +0100 Subject: [PATCH 39/49] Eliminates a stpncpy/strncpy pair in favor of an snprintf() --- src/ldeboot.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ldeboot.c b/src/ldeboot.c index e850ee1f..e756b895 100644 --- a/src/ldeboot.c +++ b/src/ldeboot.c @@ -199,11 +199,9 @@ int main(int argc, char *argv[]) { if (dirsepp == NULL) { argv[0] = filetorun; } else { - /* copy up to and including the final "/" in the path */ - dirsepp = stpncpy(filetorunpath, argv[0], dirsepp + 1 - argv[0]); - - /* dirsepp now points to the trailing null in the copy */ - strncpy(dirsepp, filetorun, PATH_MAX - (dirsepp - filetorunpath)); + /* copy directory prefix (up to and including the final "/") then filename */ + snprintf(filetorunpath, PATH_MAX, "%.*s%s", + (int)(dirsepp + 1 - argv[0]), argv[0], filetorun); argv[0] = filetorunpath; } execvp(argv[0], argv); From ba7709793514cd9a8931b47abf073947ed4a6013 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 23:26:45 +0100 Subject: [PATCH 40/49] Eliminates strncpy() in favor of memcpy() since not a null-terminated string. --- src/ufs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ufs.c b/src/ufs.c index c34a1d65..969cfb65 100644 --- a/src/ufs.c +++ b/src/ufs.c @@ -217,7 +217,7 @@ LispPTR UFS_getfilename(LispPTR *args) len = strlen(lfname); #ifndef BYTESWAP - strncpy(base, lfname, len); + memcpy(base, lfname, len); #else MemCpyToLispFromNative(base, lfname, len); #endif /* BYTESWAP */ @@ -421,7 +421,7 @@ LispPTR UFS_directorynamep(LispPTR *args) STRING_BASE(args[1], base); #ifndef BYTESWAP - strncpy(base, dirname, len); + memcpy(base, dirname, len); #else MemCpyToLispFromNative(base, dirname, len); #endif /* BYTESWAP */ From c7d267603717f0f442eaf8a22600bc5a49962707 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 23:35:49 +0100 Subject: [PATCH 41/49] Eliminates strcpy()/strncpy() in favor of memcpy() --- src/uutils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uutils.c b/src/uutils.c index 3d660de3..67477396 100644 --- a/src/uutils.c +++ b/src/uutils.c @@ -25,7 +25,7 @@ #include // for size_t #include // for printf, NULL, snprintf, size_t #include // for getenv -#include // for strcmp, strcpy, strlen, strncpy +#include // for strcmp, strlen, memcpy #include // for getuid, gethostid, gethostname, getpgrp #include "adr68k.h" // for NativeAligned4FromLAddr #include "keyboard.h" // for KBEVENT, KB_ALLUP, RING, KEYEVENTSIZE, MAXKE... @@ -59,7 +59,7 @@ static int lisp_string_to_c_string(LispPTR Lisp, char *C, size_t length) { case THIN_CHAR_TYPENUMBER: base = ((char *)NativeAligned2FromLAddr(arrayp->base)) + ((int)(arrayp->offset)); #ifndef BYTESWAP - strncpy(C, base, arrayp->fillpointer); + memcpy(C, base, arrayp->fillpointer); #else { size_t l = arrayp->fillpointer; @@ -104,7 +104,7 @@ static int c_string_to_lisp_string(char *C, LispPTR Lisp) { case THIN_CHAR_TYPENUMBER: base = ((char *)NativeAligned2FromLAddr(arrayp->base)) + ((int)(arrayp->offset)); #ifndef BYTESWAP - strcpy(base, C); + memcpy(base, C, length + 1); #else { char *dp = C; From f8f4ddf3767e8c7b0525ce35b74242e98c9c60f9 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 23 Jun 2026 23:53:02 +0100 Subject: [PATCH 42/49] Eliminate unnecessry strlcpy()/strlcat() calls, protect from no HOME env var --- src/xrdopt.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index db66f5ec..e601278b 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -18,7 +18,7 @@ #include // for MAXPATHLEN #include // for fprintf, NULL, stderr, sscanf #include // for getenv, exit, strtol -#include // for strncpy, strlcat, strlcpy, strcmp +#include // for memcpy, strlcpy, strcmp #include // for u_char #include // for access, R_OK #include "xdefs.h" // for WINDOW_NAME @@ -227,8 +227,7 @@ void read_Xoption(int *argc, char *argv[]) if ((xdisplay = XOpenDisplay(Display_Name)) != NULL) { /* read the other databases */ /* Start with app-defaults/medley */ - (void)strlcpy(tmp, "/usr/lib/X11/app-defaults/", sizeof(tmp)); - (void)strlcat(tmp, "medley", sizeof(tmp)); + (void)strlcpy(tmp, "/usr/lib/X11/app-defaults/medley", sizeof(tmp)); applicationDB = XrmGetFileDatabase(tmp); if (applicationDB != NULL) { (void)XrmMergeDatabases(applicationDB, &rDB); } /* Then try the displays defaults */ @@ -243,13 +242,13 @@ void read_Xoption(int *argc, char *argv[]) } envname = getenv("HOME"); - (void)strlcpy(tmp, envname, sizeof(tmp)); - (void)strlcat(tmp, "/.Xdefaults", sizeof(tmp)); - if (access(tmp, R_OK) != 0) { - serverDB = XrmGetFileDatabase(tmp); - if (serverDB != NULL) { (void)XrmMergeDatabases(serverDB, &rDB); } + if (envname != NULL) { + snprintf(tmp, sizeof(tmp), "%s/.Xdefaults", envname); + if (access(tmp, R_OK) != 0) { + serverDB = XrmGetFileDatabase(tmp); + if (serverDB != NULL) { (void)XrmMergeDatabases(serverDB, &rDB); } + } } - /* Now for the commandline */ (void)XrmMergeDatabases(commandlineDB, &rDB); From 5164feff771f7c7350d1273cbff31326ec4861f7 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Wed, 24 Jun 2026 15:38:35 +0100 Subject: [PATCH 43/49] Eliminate strcpy/strncat in favor of snprintf() --- src/dlpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dlpi.c b/src/dlpi.c index 61b88abf..2a9be882 100644 --- a/src/dlpi.c +++ b/src/dlpi.c @@ -157,8 +157,8 @@ int setup_dlpi_dev(char *device) */ if ((p = strpbrk(device, "0123456789")) == NULL) return (-1); - strcpy(devname, DLPI_DEVDIR); - strncat(devname, device, p - device); + snprintf(devname, sizeof(devname), "%s%.*s", + DLPI_DEVDIR, (int)(p - device), device); devppa = atoi(p); /* From 74cea1789a2da32bb75f2cb3d5981cc537a228c0 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Wed, 24 Jun 2026 15:40:46 +0100 Subject: [PATCH 44/49] Eliminate strcpy in favor of memcpy into a Lisp string --- src/inet.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/inet.c b/src/inet.c index 141e75db..986a84f9 100644 --- a/src/inet.c +++ b/src/inet.c @@ -77,6 +77,7 @@ LispPTR subr_TCP_ops(int op, LispPTR nameConn, LispPTR proto, LispPTR length, Li { #ifndef DOS int sock, len, buflen, res; + size_t namelen; unsigned ures; char namestring[100]; char servstring[50]; @@ -252,8 +253,10 @@ LispPTR subr_TCP_ops(int op, LispPTR nameConn, LispPTR proto, LispPTR length, Li ures = sizeof(addr); getpeername(sock, (struct sockaddr *)&addr, &ures); host = gethostbyaddr((const char *)&addr, ures, AF_INET); - strcpy((char *)buffer, host->h_name); - return (GetSmallp(strlen(host->h_name))); + if (!host) return (GetSmallp(0)); + namelen = strlen(host->h_name); + memcpy((char *)buffer, host->h_name, namelen); + return (GetSmallp(namelen)); case INETgetname: /* host addr, buffer for name string */ sock = LispNumToCInt(nameConn); @@ -262,8 +265,9 @@ LispPTR subr_TCP_ops(int op, LispPTR nameConn, LispPTR proto, LispPTR length, Li addr.sin_addr.s_addr = htonl(sock); host = gethostbyaddr((const char *)&addr, ures, 0); if (!host) return (GetSmallp(0)); - strcpy((char *)buffer, host->h_name); - return (GetSmallp(strlen(host->h_name))); + namelen = strlen(host->h_name); + memcpy((char *)buffer, host->h_name, namelen); + return (GetSmallp(namelen)); case UDPListen: /* socket# to listen on */ sock = LispNumToCInt(nameConn); From 4558c8b02f89966f2c9b6816656f7075a0b2f523 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 5 Jul 2026 21:38:31 +0100 Subject: [PATCH 45/49] Fixes inverted sense of check for access OK on user .Xdefaults file --- src/xrdopt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xrdopt.c b/src/xrdopt.c index e601278b..b4a8ca00 100644 --- a/src/xrdopt.c +++ b/src/xrdopt.c @@ -244,7 +244,7 @@ void read_Xoption(int *argc, char *argv[]) envname = getenv("HOME"); if (envname != NULL) { snprintf(tmp, sizeof(tmp), "%s/.Xdefaults", envname); - if (access(tmp, R_OK) != 0) { + if (access(tmp, R_OK) == 0) { serverDB = XrmGetFileDatabase(tmp); if (serverDB != NULL) { (void)XrmMergeDatabases(serverDB, &rDB); } } From ce4f791daacb9f6ed7f6ee58bc6d7ac23ac20e92 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 5 Jul 2026 21:46:06 +0100 Subject: [PATCH 46/49] Ensure captured packet is complete, and of usable size. --- src/ether_pcap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 20a0187e..1cbd47c2 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -130,8 +130,9 @@ static int recvPacket(void) { return (0); } + /* ignore packets that are too big, empty, or not captured completely */ hlen = header->len; - if (hlen > ether_bsize || hlen == 0) return (0); + if (hlen > ether_bsize || hlen == 0 || hlen != header->caplen) return (0); #ifdef BYTESWAP for (int i = 0; i < hlen / 2; i++) { From 10724d0b8180092216ec6d96368508a5e43725ff Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 5 Jul 2026 21:48:41 +0100 Subject: [PATCH 47/49] Really force 64-bit arithmetic for periodic timer count on all architectures. --- src/xc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xc.c b/src/xc.c index 7eae1da4..438fbc2c 100644 --- a/src/xc.c +++ b/src/xc.c @@ -1168,7 +1168,7 @@ op_ufn : { period_cnt = 0; else period_cnt = - ((*PERIODIC_INTERRUPT_FREQUENCY68k & 0xffff) * 1000000UL) / (60 * TIMER_INTERVAL); + ((*PERIODIC_INTERRUPT_FREQUENCY68k & 0xffff) * 1000000ULL) / (60 * TIMER_INTERVAL); /* number of 1/60 second periods between interrupts (really??) TIMER_INTERVAL is the number of microseconds between timer interrupts. */ From f8d1f4c84bc74839bac2a1a73e7282140c221e83 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 5 Jul 2026 21:55:40 +0100 Subject: [PATCH 48/49] Frees compiled packet match filter on error return from init_pcap --- src/ether_pcap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index 1cbd47c2..c393f3e0 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -451,12 +451,14 @@ void init_ether() { pcap_rval = pcap_setfilter(pcap_handle, &filter_match_xns); if (pcap_rval == PCAP_ERROR) { fprintf(stderr, "Couldn't set filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle)); + pcap_freecode(&filter_match_xns); pcap_close(pcap_handle); return; } pcap_rval = pcap_setnonblock(pcap_handle, 1, errbuf); if (pcap_rval == PCAP_ERROR) { fprintf(stderr, "%s\n", errbuf); + pcap_freecode(&filter_match_xns); pcap_close(pcap_handle); return; } @@ -464,6 +466,7 @@ void init_ether() { if (ether_fd == -1 || ether_fd >= FD_SETSIZE) { fprintf(stderr, "Couldn't get valid selectable fd for pcap\n"); ether_fd = -1; + pcap_freecode(&filter_match_xns); pcap_close(pcap_handle); return; } From 4f7be2940e8bf85b3f9fb5428567c056eacdcb9a Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Mon, 6 Jul 2026 11:13:42 +0100 Subject: [PATCH 49/49] Updates comments on how the interface name/address finding should be rewritten. --- src/ether_pcap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ether_pcap.c b/src/ether_pcap.c index c393f3e0..a4f63bdd 100644 --- a/src/ether_pcap.c +++ b/src/ether_pcap.c @@ -358,6 +358,11 @@ void init_ether() { find_ifname = strlen(ether_ifname) == 0; find_ifaddr = ether_addr_equal(ether_host, ether_zero); + /* XXX: should be rewritten so that if given an interface name but no address it finds the address, + if given an address but no interface name it finds the interface name, + if given both, it checks that they're consistent + if given neither it finds the first up, running, non-loopback interface and its address + */ if (find_ifname || find_ifaddr) { pcap_if_t *alldevs = NULL; pcap_if_t *dev = NULL;