Complete.Org: Mailing Lists: Archives: freeciv-dev: May 1999:
[Freeciv-Dev] patch: provide snprintf
Home

[Freeciv-Dev] patch: provide snprintf

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] patch: provide snprintf
From: David Pfitzner <dwp@xxxxxxxxxxxxxx>
Date: Sun, 30 May 1999 15:10:52 +1000 (EST)

This patch provides (v)snprintf functions to freeciv for platforms 
where these functions are missing.   The implementation is by 
Theo de Raadt, via gnome-libs/support.  I haven't really tested
it beyond checking that it complies and runs (including if I edit 
config.h; systems I have access to already have these functions).

For minimal testing, this patch replaces vsprintf with vsnprintf
in freelog(). 

Incidently, I think I am right in saying that these functions do
not guarantee null-termination if the printf would have written
more than n chars.  So should probably either null-terminate
explicitly or if using a static array, use (n-1).

I've made configure check individually for both snprintf and
vsnprintf, which may be overkill (if have one have both?) but
shouldn't hurt...

I have not yet tackled also providing (v)asprintf (a malloc-ing 
version).  That would be possible in a similar fashion, but lets
do this one step at a time...

A select-based usleep() replacement should be similar and easy.

Regards,
-- David
diff -N -u -r --exclude-from exclude freeciv-cvs/common/Makefile.am 
fc-adv/common/Makefile.am
--- freeciv-cvs/common/Makefile.am      Mon May 10 18:28:30 1999
+++ fc-adv/common/Makefile.am   Sat May 29 18:17:17 1999
@@ -35,7 +35,10 @@
                shared.h        \
                spaceship.c     \
                spaceship.h     \
+               support.h       \
                tech.c          \
                tech.h          \
                unit.c          \
-               unit.h
+               unit.h          \
+               vsnprintf.c
+
diff -N -u -r --exclude-from exclude freeciv-cvs/common/Makefile.in 
fc-adv/common/Makefile.in
--- freeciv-cvs/common/Makefile.in      Mon May 10 18:28:30 1999
+++ fc-adv/common/Makefile.in   Sat May 29 18:18:49 1999
@@ -115,10 +115,12 @@
                shared.h        \
                spaceship.c     \
                spaceship.h     \
+               support.h       \
                tech.c          \
                tech.h          \
                unit.c          \
-               unit.h
+               unit.h          \
+               vsnprintf.c
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = ../config.h
 CONFIG_CLEAN_FILES = 
@@ -136,7 +138,7 @@
 libcivcommon_a_LIBADD = 
 libcivcommon_a_OBJECTS =  capability.o city.o diptreaty.o game.o \
 genlist.o log.o map.o packets.o player.o mem.o registry.o sbuffer.o \
-shared.o spaceship.o tech.o unit.o
+shared.o spaceship.o tech.o unit.o vsnprintf.o
 AR = ar
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -151,7 +153,8 @@
 DEP_FILES =  .deps/capability.P .deps/city.P .deps/diptreaty.P \
 .deps/game.P .deps/genlist.P .deps/log.P .deps/map.P .deps/mem.P \
 .deps/packets.P .deps/player.P .deps/registry.P .deps/sbuffer.P \
-.deps/shared.P .deps/spaceship.P .deps/tech.P .deps/unit.P
+.deps/shared.P .deps/spaceship.P .deps/tech.P .deps/unit.P \
+.deps/vsnprintf.P
 SOURCES = $(libcivcommon_a_SOURCES)
 OBJECTS = $(libcivcommon_a_OBJECTS)
 
diff -N -u -r --exclude-from exclude freeciv-cvs/common/log.c 
fc-adv/common/log.c
--- freeciv-cvs/common/log.c    Tue Apr 27 22:13:07 1999
+++ fc-adv/common/log.c Sat May 29 18:21:37 1999
@@ -14,7 +14,8 @@
 #include <stdarg.h>
 #include <string.h>
 
-#include <log.h>
+#include "log.h"
+#include "support.h"           /* vsnprintf */
 
 int log_level;
 char *log_filename;
@@ -87,7 +88,7 @@
     else fs=stderr;
 
     va_start(args, message);
-    vsprintf(bufbuf[whichbuf], message, args);
+    vsnprintf(bufbuf[whichbuf], 511, message, args);
     va_end(args);
     
     if(level==prev_level && 0==strncmp(bufbuf[0],bufbuf[1],511)){
Binary files freeciv-cvs/common/stzPLKop and fc-adv/common/stzPLKop differ
diff -N -u -r --exclude-from exclude freeciv-cvs/common/support.h 
fc-adv/common/support.h
--- freeciv-cvs/common/support.h        Thu Jan  1 10:00:00 1970
+++ fc-adv/common/support.h     Sat May 29 18:37:33 1999
@@ -0,0 +1,49 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+#ifndef FC__SUPPORT_H
+#define FC__SUPPORT_H
+
+/* This "support" module is intended for functions which may be
+   in libc, for which we provide implementations for systems where
+   they are missing.  This file "support.h" provides prototypes
+   for such functions.  Note that function bodies may be provided
+   in files other than "support.c", because they typically come
+   from outside Freeciv, so this is easier for noting copyrights,
+   keeping them up-to-date, etc.   (--dwp)
+*/
+
+/* Need to know what functions they system already provides: */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>            /* size_t */
+
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+
+/* snprintf() and vsnprintf(), bodies in vsnprintf.c:
+   Like sprintf() and vsprintf(), but write at most n characters.
+   Note these do not guarantee null-termination if the maximum
+   number of chars get written! (?)
+*/
+#ifndef HAVE_VSNPRINTF
+int vsnprintf(char *str, size_t n, const char *format, va_list ap );
+#endif 
+#ifndef HAVE_SNPRINTF
+int snprintf(char *str, size_t n, const char *format, ... );
+#endif 
+
+#endif /* FC__SUPPORT_H */
+
diff -N -u -r --exclude-from exclude freeciv-cvs/common/vsnprintf.c 
fc-adv/common/vsnprintf.c
--- freeciv-cvs/common/vsnprintf.c      Thu Jan  1 10:00:00 1970
+++ fc-adv/common/vsnprintf.c   Sat May 29 18:49:13 1999
@@ -0,0 +1,209 @@
+/*
+ * Revision 12: http://theos.com/~deraadt/snprintf.c
+ *
+ * Copyright (c) 1997 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Freeciv:
+   This version taken from gnome-libs-1.0.9/support/vsnprintf.c
+   Relevant entries from gnome-libs-1.0.9/support/ChangeLog:
+    
+1998-05-19  Martin Baulig  <martin@xxxxxxxxxxxxxxxxx>
+
+       * vsnprintf.c (vsnprintf): Changed declaration of this
+       function on systems defining __STDC__ to avoid clash
+       with prototype in system header file.
+
+       * vsnprintf.c (snprintf): Moved toward the end of the
+       file, so that the compiler sees correct declaration for
+       vsnprintf().
+
+1998-03-11  Raja R Harinath  <harinath@xxxxxxxxxx>
+
+       * vsnprintf.c: Actually fill it in.  It is from
+       <URL:http://theos.com/~deraadt/snprintf.c>, with one small fix to
+       actually make it compile.
+
+   Changes for Freeciv: use HAVE_CONFIG_ symbols from config.h
+   for conditional compilation.
+   Added unistd.h, string.h
+   static var "caught" was unused.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if (!defined(HAVE_VSNPRINTF)) || (!defined(HAVE_SNPRINTF))
+/* else don't compile anything */
+
+#ifdef HAVE_VSNPRINTF
+
+/* Only protos needed by snprintf in terms of vsnprintf: */
+
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#include <stdlib.h>
+#else
+#include <varargs.h>
+#endif
+
+#else
+
+/* Everything for vsnprintf: */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#include <stdlib.h>
+#else
+#include <varargs.h>
+#endif
+#include <setjmp.h>
+#include <unistd.h>            /* getpagesize() */
+#include <string.h>            /* strncpy() */
+
+#ifndef roundup
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#endif
+
+static int pgsize;
+static char *curobj;
+/* static int caught; */
+static sigjmp_buf bail;
+
+#define EXTRABYTES     2       /* XXX: why 2? you don't want to know */
+
+static char *
+msetup(str, n)
+       char *str;
+       size_t n;
+{
+       char *e;
+
+       if (n == 0)
+               return NULL;
+       if (pgsize == 0)
+               pgsize = getpagesize();
+       curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2);
+       if (curobj == NULL)
+               return NULL;
+       e = curobj + n + EXTRABYTES;
+       e = (char *)roundup((unsigned long)e, pgsize);
+       if (mprotect(e, pgsize, PROT_NONE) == -1) {
+               free(curobj);
+               curobj = NULL;
+               return NULL;
+       }
+       e = e - n - EXTRABYTES;
+       *e = '\0';
+       return (e);
+}
+
+static void
+mcatch()
+{
+       siglongjmp(bail, 1);
+}
+
+static void
+mcleanup(str, n, p)
+       char *str;
+       size_t n;
+       char *p;
+{
+       strncpy(str, p, n-1);
+       str[n-1] = '\0';
+       if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
+           PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
+               mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
+                   PROT_READ|PROT_WRITE);
+       free(curobj);
+}
+
+int
+#if __STDC__
+vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
+#else
+vsnprintf(str, n, fmt, ap)
+       char *str;
+       size_t n;
+       char *fmt;
+       char *ap;
+#endif
+{
+       struct sigaction osa, nsa;
+       char *p;
+       int ret = n + 1;        /* if we bail, indicated we overflowed */
+
+       memset(&nsa, 0, sizeof nsa);
+       nsa.sa_handler = mcatch;
+       sigemptyset(&nsa.sa_mask);
+
+       p = msetup(str, n);
+       if (p == NULL) {
+               *str = '\0';
+               return 0;
+       }
+       if (sigsetjmp(bail, 1) == 0) {
+               if (sigaction(SIGSEGV, &nsa, &osa) == -1) {
+                       mcleanup(str, n, p);
+                       return (0);
+               }
+               ret = vsprintf(p, fmt, ap);
+       }
+       mcleanup(str, n, p);
+       (void) sigaction(SIGSEGV, &osa, NULL);
+       return (ret);
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifndef HAVE_SNPRINTF
+int
+#if __STDC__
+snprintf(char *str, size_t n, char const *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+       char *str;
+       size_t n;
+       char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+
+       return (vsnprintf(str, n, fmt, ap));
+       va_end(ap);
+}
+#endif /* HAVE_SNPRINTF */
+
+#endif /* (!defined(HAVE_VSNPRINTF)) || (!defined(HAVE_SNPRINTF)) */
diff -N -u -r --exclude-from exclude freeciv-cvs/config.h.in fc-adv/config.h.in
--- freeciv-cvs/config.h.in     Sun Mar 14 11:23:59 1999
+++ fc-adv/config.h.in  Sat May 29 18:18:57 1999
@@ -52,11 +52,17 @@
 /* Define if you have the select function.  */
 #undef HAVE_SELECT
 
+/* Define if you have the snprintf function.  */
+#undef HAVE_SNPRINTF
+
 /* Define if you have the strerror function.  */
 #undef HAVE_STRERROR
 
 /* Define if you have the strstr function.  */
 #undef HAVE_STRSTR
+
+/* Define if you have the vsnprintf function.  */
+#undef HAVE_VSNPRINTF
 
 /* Define if you have the <sys/ioctl.h> header file.  */
 #undef HAVE_SYS_IOCTL_H
diff -N -u -r --exclude-from exclude freeciv-cvs/configure fc-adv/configure
--- freeciv-cvs/configure       Sat May 22 14:39:35 1999
+++ fc-adv/configure    Sat May 29 18:18:59 1999
@@ -3780,7 +3780,7 @@
 
 fi
 
-for ac_func in gethostname select strerror strstr
+for ac_func in gethostname select strerror strstr snprintf vsnprintf
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 echo "configure:3787: checking for $ac_func" >&5
diff -N -u -r --exclude-from exclude freeciv-cvs/configure.in 
fc-adv/configure.in
--- freeciv-cvs/configure.in    Sat May 22 14:39:35 1999
+++ fc-adv/configure.in Sat May 29 18:17:43 1999
@@ -234,7 +234,7 @@
 dnl Checks for library functions.
 AC_TYPE_SIGNAL
 AC_FUNC_VPRINTF
-AC_CHECK_FUNCS(gethostname select strerror strstr)
+AC_CHECK_FUNCS(gethostname select strerror strstr snprintf vsnprintf)
 
 dnl autoscan also recommends gettimeofday in AC_CHECK_FUNCS, but in the code
 dnl that is already protected by ifdef CHRONO, and is for selective

[Prev in Thread] Current Thread [Next in Thread]