чување 75006bfb2b148789953ba9ec66f26712367eafab
родитељ 9f26df4d8d247754f750b2885b4ec40b5df014e2
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Wed, 10 Apr 2024 21:56:08 +0200
Sync with slweb 0.9.6
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 33, додавања: 813(+), брисања: 777(-)
diff --git a/INSTALL b/INSTALL
@@ -1,14 +1,13 @@
Prerequisites
=============
-* C compiler - defaults in config.redo
+* C compiler - defaults in config.mk
Optional dependencies
---------------------
* git (for {git-log})
-* gzip (autodetected, for manpage compression)
Install
@@ -17,33 +16,31 @@ Install
$ git clone https://git.sr.ht/~strahinja/slw2gmi
$ cd slw2gmi
$ su
-
-If you have djb redo:
-
- # redo install
-
-if you don't:
-
- # ./do install
+ # make install
Persistent build configuration file
-----------------------------------
-The file config.redo will be sourced when building targets which also accept
+The file config.mk will be sourced when building targets which also accept
configuration through environment variables. For example, CC and PREFIX
-are specified in config.redo.
+are specified in config.mk.
OpenBSD
-------
-Replace gcc in CC with cc and add -D_BSD_SOURCE, eg:
+Before running make(1), comment the CPPFLAGS definition in config.mk above the
+line with the "OpenBSD" comment and uncomment the one below it:
- # CC='cc -g -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L
- -D_XOPEN_SOURCE=700 -D_BSD_SOURCE}' \
- ./do install
+ #CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \
+ # -D_XOPEN_SOURCE=700
+ # OpenBSD
+ CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \
+ -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
-and change MANPREFIX to
+Also, do the same for MANPREFIX:
- MANPREFIX=$PREFIX/man
+ #MANPREFIX = $(PREFIX)/share/man
+ # OpenBSD
+ MANPREFIX = $(PREFIX)/man
diff --git a/Makefile b/Makefile
@@ -0,0 +1,65 @@
+.POSIX:
+
+include config.mk
+
+.SUFFIXES: .1.in .1 .h.in .h .c .o
+
+.1.in.1:
+ sh lib/replacepat $< $@
+
+.h.in.h:
+ sh lib/replacepat $< $@
+
+all: makedate makeversion $(PROG) $(MANPAGE)
+ if [ -f .rebuild ]; then rm .rebuild; make -e all; else true; fi
+
+date:
+ sh lib/makedate
+
+version:
+ sh lib/makeversion
+
+makedate:
+ sh lib/makedate -l
+
+makeversion:
+ sh lib/makeversion -l
+
+slw2gmi.o: slw2gmi.c defs.h utf8.h version.h
+
+$(MANPAGE): $(MANPAGE).in date version
+
+version.h: version.h.in date version
+
+utf8.o: utf8.c utf8.h
+
+$(PROG): $(OBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+clean:
+ rm -f version date version.h *.o *.xz *~ $(PROG) $(MANPAGE)
+
+install: all
+ umask 022
+ $(INSTALL) -Dm 0644 $(MANPAGE) $(MANPREFIX)/man1/$(MANPAGE)
+ $(INSTALL) -Dm 0644 README $(DOCDIR)/README
+ $(INSTALL) -Dm 0644 LICENSE $(DOCDIR)/LICENSE
+ $(INSTALL) -Dm 0755 $(PROG) $(BINDIR)/$(PROG)
+
+uninstall:
+ rm -f $(MANPREFIX)/man1/$(MANPAGE)
+ rmdir $(MANPREFIX)/man1 2>/dev/null || true
+ rmdir $(MANPREFIX) 2>/dev/null || true
+ rm -f $(DOCDIR)/README
+ rm -f $(DOCDIR)/LICENSE
+ rmdir $(DOCDIR) 2>/dev/null || true
+ rm -f $(PROG) $(BINDIR)/$(PROG)
+ rmdir $(BINDIR) 2>/dev/null || true
+
+test: all
+ sh lib/runtests
+
+pack: all version
+ sh -x lib/mkpack
+
+.PHONY: all clean examples install makedate makeversion pack test uninstall
diff --git a/README b/README
@@ -19,7 +19,7 @@ License
-------
slw2gmi - slweb to Gemini converter
-Copyright (C) 2021-2023 Страхиња Радић
+Copyright (C) 2021-2024 Страхиња Радић
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
diff --git a/all.do b/all.do
@@ -1,2 +0,0 @@
-. ./config.redo
-redo-ifchange slw2gmi slw2gmi.1"$MANSUFFIX"
diff --git a/clean b/clean
diff --git a/clean.do b/clean.do
@@ -1,2 +0,0 @@
-. ./config.redo
-rm -f *.o *~ slw2gmi $MANPAGES *.1 version.h version date *.pdf
diff --git a/config.mk b/config.mk
@@ -0,0 +1,20 @@
+#CC = cc
+CFLAGS = -Os -Wall -pedantic -std=c99
+#CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \
+# -D_XOPEN_SOURCE=700
+# OpenBSD
+CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \
+ -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
+INSTALL = install
+LIBS =
+OBJS = slw2gmi.o strlcat.o strlcpy.o utf8.o
+PREFIX = /usr/local
+PROG = slw2gmi
+
+# Derived macros
+BINDIR = $(PREFIX)/bin
+DOCDIR = $(PREFIX)/share/doc/$(PROG)
+#MANPREFIX = $(PREFIX)/share/man
+# OpenBSD
+MANPREFIX = $(PREFIX)/man
+MANPAGE = $(PROG).1
diff --git a/config.redo b/config.redo
@@ -2,20 +2,20 @@ PREFIX=${PREFIX:-/usr/local}
BINDIR=$PREFIX/bin
DOCDIR=$PREFIX/share/doc/slw2gmi
-MANPREFIX=$PREFIX/share/man
+#MANPREFIX=$PREFIX/share/man
# OpenBSD
-#MANPREFIX=$PREFIX/man
+MANPREFIX=$PREFIX/man
PROGS="slw2gmi"
DOCS="README LICENSE"
MANSUFFIX=${MANSUFFIX-$(command -v gzip >/dev/null && printf ".gz")}
MANPAGES="slw2gmi.1${MANSUFFIX}"
-CC=${CC:-gcc -g -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L \
--D_XOPEN_SOURCE=700}
+#CC=${CC:-gcc -g -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L \
+#-D_XOPEN_SOURCE=700}
STRIP=${STRIP:-:}
# OpenBSD
-#CC=${CC:-cc -g -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L \
-#-D_XOPEN_SOURCE=700 -D_BSD_SOURCE}
+CC=${CC:-cc -g -Wall -pedantic -std=c99 -D_POSIX_C_SOURCE=200809L \
+-D_XOPEN_SOURCE=700 -D_BSD_SOURCE}
diff --git a/date.do b/date.do
@@ -1,20 +0,0 @@
-FALLBACKDATE=${FALLBACKDATE:-unknown}
-LC_ALL=C
-export LC_ALL
-user=$(unalias ls >/dev/null 2>&1 || true; \
- command ls -ld . | awk '{print $3}')
-e_user=$(id -un)
-if [ -d .git ] && command -v git >/dev/null 2>&1; then
- if [ "$e_user" = "$user" ]; then
- git log --format=format:%cd \
- --date=format:"%B %d, %Y" -1 @ >$3
- else
- su "${user}" -c 'env LC_ALL=C git log --format=format:%cd \
- --date=format:"%B %d, %Y" -1 @' >$3
- fi
- echo >>$3
-else
- printf "%s\n" "$FALLBACKDATE" >$3
-fi
-redo-always
-redo-stamp <$3
diff --git a/default.do b/default.do
@@ -1,10 +0,0 @@
-if [ -r $1.in ]; then
- redo-ifchange $1.in version date
- read VERSION <version
- read DATE <date
- sed -e "s/%VERSION%/$VERSION/g" \
- -e "s/%DATE%/$DATE/g" <$1.in
-else
- echo "$0: don't know how to build '$1'" >&2
- exit 99
-fi
diff --git a/default.gz.do b/default.gz.do
@@ -1,2 +0,0 @@
-redo-ifchange $2
-gzip -cf $2 >$3
diff --git a/default.o.do b/default.o.do
@@ -1,5 +0,0 @@
-sed -n 's/^#include "\([^"]*\)"/\1/p' ${2%.o}.c | \
- xargs redo-ifchange
-redo-ifchange $2.c
-. ./config.redo
-${CC} -o $3 -c $2.c
diff --git a/default.pdf.do b/default.pdf.do
@@ -1,2 +0,0 @@
-redo-ifchange $2.1
-groff -mandoc -t -T pdf $2.1 >$3
diff --git a/defs.h b/defs.h
@@ -1,5 +1,5 @@
/* This program is licensed under the terms of GNU GPL v3 or (at your option)
- * any later version. Copyright (C) 2021-2023 Страхиња Радић.
+ * any later version. Copyright (C) 2021-2024 Страхиња Радић.
* See the file LICENSE for exact copyright and license details. */
#ifndef __DEFS_H
@@ -8,21 +8,28 @@
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
-#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#ifndef strlcpy
+size_t strlcpy(char *dst, const char *src, size_t dsize);
+#endif
+#ifndef strlcat
+size_t strlcat(char *dst, const char *src, size_t dsize);
+#endif
+
#include "version.h"
#include "utf8.h"
-#define COPYRIGHTYEAR "2021-2023"
+#define COPYRIGHTYEAR "2021-2024"
#define MADEBY_URL "gemini://gemini.strahinja.org/slw2gmi/"
#define BUFSIZE 1024
diff --git a/do b/do
@@ -1,446 +0,0 @@
-#!/usr/bin/env sh
-#
-# A minimal alternative to djb redo that doesn't support incremental builds.
-# For the full version, visit http://github.com/apenwarr/redo
-#
-# The author disclaims copyright to this source file and hereby places it in
-# the public domain. (2010 12 14; updated 2019 02 24)
-#
-USAGE="
-usage: do [-d] [-x] [-v] [-c] <targets...>
- -d print extra debug messages (mostly about dependency checks)
- -v run .do files with 'set -v'
- -x run .do files with 'set -x'
- -c clean up all old targets before starting
-
- Note: do is an implementation of redo that does *not* check dependencies.
- It will never rebuild a target it has already built, unless you use -c.
-"
-
-# CDPATH apparently causes unexpected 'cd' output on some platforms.
-unset CDPATH
-
-# By default, no output coloring.
-green=""
-bold=""
-plain=""
-
-if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then
- green="$(printf '\033[32m')"
- bold="$(printf '\033[1m')"
- plain="$(printf '\033[m')"
-fi
-
-# The 'seq' command is not available on all platforms.
-_seq() {
- local x=0 max="$1"
- while [ "$x" -lt "$max" ]; do
- x=$((x + 1))
- echo "$x"
- done
-}
-
-# Split $1 into a dir part ($_dirsplit_dir) and base filename ($_dirsplit_base)
-_dirsplit() {
- _dirsplit_base=${1##*/}
- _dirsplit_dir=${1%$_dirsplit_base}
-}
-
-# Like /usr/bin/dirname, but avoids a fork and uses _dirsplit semantics.
-qdirname() (
- _dirsplit "$1"
- dir=${_dirsplit_dir%/}
- echo "${dir:-.}"
-)
-
-_dirsplit "$0"
-REDO=$(cd "$(pwd -P)" &&
- cd "${_dirsplit_dir:-.}" &&
- echo "$PWD/$_dirsplit_base")
-export REDO
-_cmd=$_dirsplit_base
-
-DO_TOP=
-if [ -z "$DO_BUILT" ]; then
- export _do_opt_debug=
- export _do_opt_exec=
- export _do_opt_verbose=
- export _do_opt_clean=
-fi
-while getopts 'dxvcj:h?' _opt; do
- case $_opt in
- d) _do_opt_debug=1 ;;
- x) _do_opt_exec=x ;;
- v) _do_opt_verbose=v ;;
- c) _do_opt_clean=1 ;;
- j) ;; # silently ignore, for compat with real redo
- \?|h|*) printf "%s" "$USAGE" >&2
- exit 99
- ;;
- esac
-done
-shift "$((OPTIND - 1))"
-_debug() {
- [ -z "$_do_opt_debug" ] || echo "$@" >&2
-}
-
-if [ -z "$DO_BUILT" -a "$_cmd" != "redo-whichdo" ]; then
- DO_TOP=1
- if [ "$#" -eq 0 ] && [ "$_cmd" = "do" -o "$_cmd" = "redo" ]; then
- set all # only toplevel redo has a default target
- fi
- export DO_STARTDIR="$(pwd -P)"
- # If starting /bin/pwd != $PWD, this will fix it.
- # That can happen when $PWD contains symlinks that the shell is
- # trying helpfully (but unsuccessfully) to hide from the user.
- cd "$DO_STARTDIR" || exit 99
- export DO_BUILT="$PWD/.do_built"
- if [ -z "$_do_opt_clean" -a -e "$DO_BUILT" ]; then
- echo "do: Incremental mode. Use -c for clean rebuild." >&2
- fi
- : >>"$DO_BUILT"
- sort -u "$DO_BUILT" >"$DO_BUILT.new"
- while read f; do
- [ -n "$_do_opt_clean" ] && printf "%s\0%s.did\0" "$f" "$f"
- printf "%s.did.tmp\0" "$f"
- done <"$DO_BUILT.new" |
- xargs -0 rm -f 2>/dev/null
- mv "$DO_BUILT.new" "$DO_BUILT"
- export DO_PATH="$DO_BUILT.dir"
- export PATH="$DO_PATH:$PATH"
- rm -rf "$DO_PATH"
- mkdir "$DO_PATH"
- for d in redo redo-ifchange redo-whichdo; do
- ln -s "$REDO" "$DO_PATH/$d"
- done
- for d in redo-ifcreate redo-stamp redo-always redo-ood \
- redo-targets redo-sources; do
- echo "#!/bin/sh" >"$DO_PATH/$d"
- chmod a+rx "$DO_PATH/$d"
- done
-fi
-
-
-# Chop the "file" part off a /path/to/file pathname.
-# Note that if the filename already ends in a /, we just remove the slash.
-_updir()
-{
- local v="${1%/*}"
- [ "$v" != "$1" ] && echo "$v"
- # else "empty" which means we went past the root
-}
-
-
-# Returns true if $1 starts with $2.
-_startswith()
-{
- [ "${1#"$2"}" != "$1" ]
-}
-
-
-# Returns true if $1 ends with $2.
-_endswith()
-{
- [ "${1%"$2"}" != "$1" ]
-}
-
-
-# Prints $1 if it's absolute, or $2/$1 if $1 is not absolute.
-_abspath()
-{
- local here="$2" there="$1"
- if _startswith "$1" "/"; then
- echo "$1"
- else
- echo "$2/$1"
- fi
-}
-
-
-# Prints $1 as a path relative to $PWD (not starting with /).
-# If it already doesn't start with a /, doesn't change the string.
-_relpath()
-{
- local here="$2" there="$1" out= hadslash=
- #echo "RP start '$there' hs='$hadslash'" >&2
- _startswith "$there" "/" || { echo "$there" && return; }
- [ "$there" != "/" ] && _endswith "$there" "/" && hadslash=/
- here=${here%/}/
- while [ -n "$here" ]; do
- #echo "RP out='$out' here='$here' there='$there'" >&2
- [ "${here%/}" = "${there%/}" ] && there= && break;
- [ "${there#$here}" != "$there" ] && break
- out=../$out
- _dirsplit "${here%/}"
- here=$_dirsplit_dir
- done
- there=${there#$here}
- if [ -n "$there" ]; then
- echo "$out${there%/}$hadslash"
- else
- echo "${out%/}$hadslash"
- fi
-}
-
-
-# Prints a "normalized relative" path, with ".." resolved where possible.
-# For example, a/b/../c will be reduced to just a/c.
-_normpath()
-(
- local path="$1" relto="$2" out= isabs=
- #echo "NP start '$path'" >&2
- if _startswith "$path" "/"; then
- isabs=1
- else
- path="${relto%/}/$path"
- fi
- set -f
- IFS=/
- for d in ${path%/}; do
- #echo "NP out='$out' d='$d'" >&2
- if [ "$d" = ".." ]; then
- out=$(_updir "${out%/}")/
- else
- out=$out$d/
- fi
- done
- #echo "NP out='$out' (done)" >&2
- out=${out%/}
- if [ -n "$isabs" ]; then
- echo "${out:-/}"
- else
- _relpath "${out:-/}" "$relto"
- fi
-)
-
-
-# Prints a "real" path, with all symlinks resolved where possible.
-_realpath()
-{
- local path="$1" relto="$2" isabs= rest=
- if _startswith "$path" "/"; then
- isabs=1
- else
- path="${relto%/}/$path"
- fi
- (
- for d in $(_seq 100); do
- #echo "Trying: $PWD--$path" >&2
- if cd -P "$path" 2>/dev/null; then
- # success
- pwd=$(pwd -P)
- #echo " chdir ok: $pwd--$rest" >&2
- np=$(_normpath "${pwd%/}/$rest" "$relto")
- if [ -n "$isabs" ]; then
- echo "$np"
- else
- _relpath "$np" "$relto"
- fi
- break
- fi
- _dirsplit "${path%/}"
- path=$_dirsplit_dir
- rest="$_dirsplit_base/$rest"
- done
- )
-}
-
-
-# List the possible names for default*.do files in dir $1 matching the target
-# pattern in $2. We stop searching when we find the first one that exists.
-_find_dofiles_pwd()
-{
- local dodir="$1" dofile="$2"
- _startswith "$dofile" "default." || dofile=${dofile#*.}
- while :; do
- dofile=default.${dofile#default.*.}
- echo "$dodir$dofile"
- [ -e "$dodir$dofile" ] && return 0
- [ "$dofile" = default.do ] && break
- done
- return 1
-}
-
-
-# List the possible names for default*.do files in $PWD matching the target
-# pattern in $1. We stop searching when we find the first name that works.
-# If there are no matches in $PWD, we'll search in .., and so on, to the root.
-_find_dofiles()
-{
- local target="$1" dodir= dofile= newdir=
- _debug "find_dofile: '$PWD' '$target'"
- dofile="$target.do"
- echo "$dofile"
- [ -e "$dofile" ] && return 0
-
- # Try default.*.do files, walking up the tree
- _dirsplit "$dofile"
- dodir=$_dirsplit_dir
- dofile=$_dirsplit_base
- [ -n "$dodir" ] && dodir=${dodir%/}/
- [ -e "$dodir$dofile" ] && return 0
- for i in $(_seq 100); do
- [ -n "$dodir" ] && dodir=${dodir%/}/
- #echo "_find_dofiles: '$dodir' '$dofile'" >&2
- _find_dofiles_pwd "$dodir" "$dofile" && return 0
- newdir=$(_realpath "${dodir}.." "$PWD")
- [ "$newdir" = "$dodir" ] && break
- dodir=$newdir
- done
- return 1
-}
-
-
-# Print the last .do file returned by _find_dofiles.
-# If that file exists, returns 0, else 1.
-_find_dofile()
-{
- local files="$(_find_dofiles "$1")"
- rv=$?
- #echo "files='$files'" >&2
- [ "$rv" -ne 0 ] && return $rv
- echo "$files" | {
- while read -r linex; do line=$linex; done
- printf "%s\n" "$line"
- }
-}
-
-
-# Actually run the given $dofile with the arguments in $@.
-# Note: you should always run this in a subshell.
-_run_dofile()
-{
- export DO_DEPTH="$DO_DEPTH "
- export REDO_TARGET="$PWD/$target"
- local line1
- set -e
- read line1 <"$PWD/$dofile" || true
- cmd=${line1#"#!/"}
- if [ "$cmd" != "$line1" ]; then
- set -$_do_opt_verbose$_do_opt_exec
- exec /$cmd "$PWD/$dofile" "$@"
- else
- set -$_do_opt_verbose$_do_opt_exec
- # If $dofile is empty, "." might not change $? at
- # all, so we clear it first with ":".
- :; . "$PWD/$dofile"
- fi
-}
-
-
-# Find and run the right .do file, starting in dir $1, for target $2,
-# providing a temporary output file as $3. Renames the temp file to $2 when
-# done.
-_do()
-{
- local dir="$1" target="$1$2" tmp="$1$2.redo.tmp" tdir=
- local dopath= dodir= dofile= ext=
- if [ "$_cmd" = "redo" ] ||
- ( [ ! -e "$target" -o -d "$target" ] &&
- [ ! -e "$target.did" ] ); then
- printf '%sdo %s%s%s%s\n' \
- "$green" "$DO_DEPTH" "$bold" "$target" "$plain" >&2
- dopath=$(_find_dofile "$target")
- if [ ! -e "$dopath" ]; then
- echo "do: $target: no .do file ($PWD)" >&2
- return 1
- fi
- _dirsplit "$dopath"
- dodir=$_dirsplit_dir dofile=$_dirsplit_base
- if _startswith "$dofile" "default."; then
- ext=${dofile#default}
- ext=${ext%.do}
- else
- ext=
- fi
- target=$PWD/$target
- tmp=$PWD/$tmp
- cd "$dodir" || return 99
- target=$(_relpath "$target" "$PWD") || return 98
- tmp=$(_relpath "$tmp" "$PWD") || return 97
- base=${target%$ext}
- tdir=$(qdirname "$target")
- [ ! -e "$DO_BUILT" ] || [ ! -w "$tdir/." ] ||
- : >>"$target.did.tmp"
- # $qtmp is a temporary file used to capture stdout.
- # Since it might be accidentally deleted as a .do file
- # does its work, we create it, then open two fds to it,
- # then immediately delete the name. We use one fd to
- # redirect to stdout, and the other to read from after,
- # because there's no way to fseek(fd, 0) in sh.
- qtmp=$DO_PATH/do.$$.tmp
- (
- rm -f "$qtmp"
- ( _run_dofile "$target" "$base" "$tmp" >&3 3>&- 4<&- )
- rv=$?
- if [ $rv != 0 ]; then
- printf "do: %s%s\n" "$DO_DEPTH" \
- "$target: got exit code $rv" >&2
- rm -f "$tmp.tmp" "$tmp.tmp2" "$target.did"
- return $rv
- fi
- echo "$PWD/$target" >>"$DO_BUILT"
- if [ ! -e "$tmp" ]; then
- # if $3 wasn't created, copy from stdout file
- cat <&4 >$tmp
- # if that's zero length too, forget it
- [ -s "$tmp" ] || rm -f "$tmp"
- fi
- ) 3>$qtmp 4<$qtmp # can't use "|| return" here...
- # ...because "|| return" would mess up "set -e" inside the ()
- # on some shells. Running commands in "||" context, even
- # deep inside, will stop "set -e" from functioning.
- rv=$?
- [ "$rv" = 0 ] || return "$rv"
- mv "$tmp" "$target" 2>/dev/null
- [ -e "$target.did.tmp" ] &&
- mv "$target.did.tmp" "$target.did" ||
- : >>"$target.did"
- else
- _debug "do $DO_DEPTH$target exists." >&2
- fi
-}
-
-
-# Implementation of the "redo" command.
-_redo()
-{
- local i startdir="$PWD" dir base
- set +e
- for i in "$@"; do
- i=$(_abspath "$i" "$startdir")
- (
- cd "$DO_STARTDIR" || return 99
- i=$(_realpath "$(_relpath "$i" "$PWD")" "$PWD")
- _dirsplit "$i"
- dir=$_dirsplit_dir base=$_dirsplit_base
- _do "$dir" "$base"
- )
- [ "$?" = 0 ] || return 1
- done
-}
-
-
-# Implementation of the "redo-whichdo" command.
-_whichdo()
-{
- _find_dofiles "$1"
-}
-
-
-case $_cmd in
- do|redo|redo-ifchange) _redo "$@" ;;
- redo-whichdo) _whichdo "$1" ;;
- do.test) ;;
- *) printf "do: '%s': unexpected redo command" "$_cmd" >&2; exit 99 ;;
-esac
-[ "$?" = 0 ] || exit 1
-
-if [ -n "$DO_TOP" ]; then
- if [ -n "$_do_opt_clean" ]; then
- echo "do: Removing stamp files..." >&2
- [ ! -e "$DO_BUILT" ] ||
- while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
- xargs -0 rm -f 2>/dev/null
- fi
-fi
diff --git a/install.do b/install.do
@@ -1,12 +0,0 @@
-redo-ifchange all
-. ./config.redo
-install -d "$DOCDIR" "$BINDIR" "${MANPREFIX}/man1"
-for docfile in $DOCS; do
- install -Dm 0644 "${docfile}" "${DOCDIR}/${docfile}"
-done
-for binfile in $PROGS; do
- install -Dm 0755 "${binfile}" "${BINDIR}/${binfile}"
-done
-for manfile in $MANPAGES; do
- install -Dm 0644 "${manfile}" "${MANPREFIX}/man1/${manfile}"
-done
diff --git a/lib/makedate b/lib/makedate
@@ -0,0 +1,35 @@
+#!/bin/sh -x
+# vim: set ft=bash:
+FALLBACKDATE=${FALLBACKDATE:-unknown}
+LC_ALL=C
+export LC_ALL
+user=$(unalias ls >/dev/null 2>&1 || true; \
+ command ls -ld . | awk '{print $3}')
+e_user=$(id -un)
+if [ -d .git ] && command -v git >/dev/null 2>&1; then
+ if [ "$e_user" = "$user" ]; then
+ git log --format=format:%cd \
+ --date=format:"%B %d, %Y" -1 @ >date.new
+ else
+ su "${user}" -c 'env LC_ALL=C git log --format=format:%cd \
+ --date=format:"%B %d, %Y" -1 @' >date.new
+ fi
+ echo >>date.new
+else
+ printf "%s\n" "$FALLBACKDATE" >date.new
+fi
+
+if [ -f date ]; then
+ if diff date date.new >/dev/null; then
+ rm date.new
+ else
+ mv date.new date
+ touch .rebuild
+ fi
+else
+ mv date.new date
+ touch .rebuild
+fi
+if [ "$1" = "-l" ]; then
+ printf "DATE=\"%s\"\n" "$(cat date)"
+fi
diff --git a/lib/makeversion b/lib/makeversion
@@ -0,0 +1,33 @@
+#!/bin/sh -x
+# vim: set ft=bash:
+FALLBACKVER=${FALLBACKVER:-unknown}
+LC_ALL=C
+export LC_ALL
+user=$(unalias ls >/dev/null 2>&1 || true; \
+ command ls -ld . | awk '{print $3}')
+e_user=$(id -un)
+if [ -d .git ] && command -v git >/dev/null 2>&1; then
+ if [ "$e_user" = "$user" ]; then
+ git describe 2>/dev/null | sed 's/^v//' >version.new
+ else
+ su "${user}" -c 'git describe' 2>/dev/null |
+ sed 's/^v//' >version.new
+ fi
+else
+ printf "%s\n" "$FALLBACKVER" >version.new
+fi
+
+if [ -f version ]; then
+ if diff version version.new >/dev/null; then
+ rm version.new
+ else
+ mv version.new version
+ touch .rebuild
+ fi
+else
+ mv version.new version
+ touch .rebuild
+fi
+if [ "$1" = "-l" ]; then
+ printf "VERSION=\"%s\"\n" "$(cat version)"
+fi
diff --git a/lib/mkpack b/lib/mkpack
@@ -0,0 +1,12 @@
+#!/bin/sh -x
+# vim: set ft=bash:
+DISTDIR=$(grep ^PROG config.mk |
+ sed -E 's,.*=[[:space:]]+([[:alpha:]]+),\1,')-$(cat version)
+mkdir "$DISTDIR"
+for f in $(git ls-files); do
+ d="$DISTDIR"/"$(dirname "$f")"
+ mkdir -p "$d"
+ cp "$f" "$d"/
+done
+tar -cf - "$DISTDIR" | xz -9v - > "$DISTDIR".tar.xz
+rm -fr "$DISTDIR"
diff --git a/lib/replacepat b/lib/replacepat
@@ -0,0 +1,5 @@
+#!/bin/sh -x
+# vim: set ft=bash:
+DATE=$(cat date)
+VERSION=$(cat version)
+sed -e 's|%VERSION%|'"$VERSION"'|g' -e 's|%DATE%|'"$DATE"'|g' "$1" > "$2"
diff --git a/lib/runtests b/lib/runtests
@@ -0,0 +1,24 @@
+#!/bin/sh
+testdir=tests
+cat <<! >&2
+TEST RESULTS
+===========================================================
+!
+error=''
+find "$testdir" -type f \( -perm -100 -o -perm -010 -o -perm -001 \) -exec {} \; |
+awk 'BEGIN { FS="\t"; maxlen = 60; status = 0 }
+{
+ printf "%s%*s%s\n", $1, maxlen-5-length($1), " ", $2;
+ if ($2 == "FAIL")
+ status = 1
+}
+END { exit status }' >&2 || error=1
+cat <<! >&2
+===========================================================
+!
+if [ -n "$error" ]; then
+ printf "Some tests were unsuccessful - please report\n" >&2
+ exit 99
+else
+ printf "All tests passed\n" >&2
+fi
diff --git a/pack.do b/pack.do
@@ -1,13 +0,0 @@
-redo all
-redo-ifchange version
-read VERSION <version
-VERSION=$(echo $VERSION | sed 's/^v//')
-DISTDIR=slw2gmi-$VERSION
-mkdir $DISTDIR
-for f in $(git ls-files); do
- d=$DISTDIR/$(dirname $f)
- mkdir -p $d
- cp $f $d
-done
-tar cvf $DISTDIR.tar.xz $DISTDIR >/dev/null
-rm -fr $DISTDIR
diff --git a/rebuild.do b/rebuild.do
@@ -1,2 +0,0 @@
-redo clean
-redo all
diff --git a/slw2gmi.1.in b/slw2gmi.1.in
@@ -35,7 +35,7 @@ slw2gmi \- slweb to Gemini converter
.YS
.
.SH COPYRIGHT
-slw2gmi Copyright \(co 2021, 2022, 2023 Strahinya Radich.
+slw2gmi Copyright \(co 2021\-2024 Strahinya Radich.
.br
This program is licensed under GNU GPL v3 or later. See the file
.I LICENSE
diff --git a/slw2gmi.c b/slw2gmi.c
@@ -1,5 +1,5 @@
/* This program is licensed under the terms of GNU GPL v3 or (at your option)
- * any later version. Copyright (C) 2021-2023 Страхиња Радић.
+ * any later version. Copyright (C) 2021-2024 Страхиња Радић.
* See the file LICENSE for exact copyright and license details. */
#include "defs.h"
@@ -94,15 +94,19 @@ static int incdir_only_summary = 0;
ptoken = token; \
} while (0)
+int slweb_cleanup(void);
+int usage(void);
+int version(void);
+
int
-version()
+version(void)
{
printf("%s %s, committed on %s\n", PROGRAMNAME, VERSION, DATE);
return 0;
}
int
-usage()
+usage(void)
{
printf("Usage: %s [-d|--basedir <dir>]"
" [-p|--global-link-prefix <URL>] [-h|--help]"
@@ -153,7 +157,7 @@ free_keyvalue(KeyValue** list, const size_t list_count)
}
int
-slweb_cleanup()
+slweb_cleanup(void)
{
free(basedir);
free(input_dirname);
@@ -174,6 +178,7 @@ slweb_cleanup()
return 0;
}
+u8* format_date(const u8* date_arg, const char* timestamp_format);
int simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
KeyValue** pvars);
int slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
@@ -232,7 +237,8 @@ all_numeric(const u8* start, const u8* end)
}
u8*
-get_value(KeyValue* list, const size_t list_count, const u8* key)
+get_value(KeyValue* list, const size_t list_count, const u8* key,
+ KeyValue** cursor)
{
if (!list)
return NULL;
@@ -240,9 +246,20 @@ get_value(KeyValue* list, const size_t list_count, const u8* key)
while (plist < list + list_count)
{
if (!strcmp((char*)plist->key, (char*)key))
+ {
+ if (cursor)
+ {
+ if (plist + 1 < list + list_count)
+ *cursor = plist + 1;
+ else
+ *cursor = NULL;
+ }
return plist->value;
+ }
plist++;
}
+ if (cursor)
+ *cursor = NULL;
return NULL;
}
@@ -260,9 +277,10 @@ set_basedir(char** basedir, size_t* basedir_size, const char* arg)
*basedir_size = arg_len + 1;
REALLOC(*basedir, char, *basedir_size);
}
- strcpy(*basedir, arg);
- *(*basedir + arg_len) = 0;
- basedir_len = strlen(*basedir);
+
+ if (strlcpy(*basedir, arg, *basedir_size) >= *basedir_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
+ basedir_len = strlen(*basedir);
if (*(*basedir + basedir_len - 1) == '/')
*(*basedir + basedir_len - 1) = 0;
@@ -283,7 +301,9 @@ set_global_link_prefix(char** global_link_prefix,
*global_link_prefix_size = arg_len + 1;
REALLOC(*global_link_prefix, char, *global_link_prefix_size);
}
- strcpy(*global_link_prefix, arg);
+ if (strlcpy(*global_link_prefix, arg, *global_link_prefix_size)
+ >= *global_link_prefix_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
*(*global_link_prefix + arg_len) = 0;
return 0;
@@ -326,7 +346,7 @@ print_output(FILE* output, const char* fmt, ...)
va_start(args, fmt);
var_incdir_only_summary
- = get_value(vars, vars_count, (u8*)"incdir-only-summary");
+ = get_value(vars, vars_count, (u8*)"incdir-only-summary", NULL);
incdir_only_summary
= var_incdir_only_summary && *var_incdir_only_summary == '1';
@@ -343,7 +363,10 @@ print_output(FILE* output, const char* fmt, ...)
{
csv_template_size = BUFSIZE;
CALLOC(csv_template, u8, csv_template_size);
- strcpy((char*)csv_template, buf);
+ if (strlcpy((char*)csv_template, buf, csv_template_size)
+ >= csv_template_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
}
else
{
@@ -353,7 +376,10 @@ print_output(FILE* output, const char* fmt, ...)
csv_template_size += BUFSIZE;
REALLOC(csv_template, u8, csv_template_size);
}
- strcat((char*)csv_template, buf);
+ if (strlcat((char*)csv_template, buf, csv_template_size)
+ > csv_template_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
}
else if (IN(state, ST_TSV_BODY))
@@ -365,7 +391,10 @@ print_output(FILE* output, const char* fmt, ...)
{
tsv_template_size = BUFSIZE;
CALLOC(tsv_template, u8, tsv_template_size);
- strcpy((char*)tsv_template, buf);
+ if (strlcpy((char*)tsv_template, buf, tsv_template_size)
+ >= tsv_template_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
}
else
{
@@ -375,7 +404,10 @@ print_output(FILE* output, const char* fmt, ...)
tsv_template_size += BUFSIZE;
REALLOC(tsv_template, u8, tsv_template_size);
}
- strcat((char*)tsv_template, buf);
+ if (strlcat((char*)tsv_template, buf, tsv_template_size)
+ > tsv_template_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
}
else
@@ -408,8 +440,6 @@ print_command(FILE* output, const char* command, const u8* pass_arguments[],
close(arg_pipe_fds[PIPE_WRITE_INDEX]);
close(output_pipe_fds[PIPE_READ_INDEX]);
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-
dup2(arg_pipe_fds[PIPE_READ_INDEX], STDIN_FILENO);
dup2(output_pipe_fds[PIPE_WRITE_INDEX], STDOUT_FILENO);
@@ -553,9 +583,16 @@ process_git_log(FILE* output)
pid_t result = 0;
if (slash)
- strcpy(basename, slash + 1);
+ {
+ if (strlcpy(basename, slash + 1, basename_size) >= basename_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
+ }
else
- strcpy(basename, input_filename);
+ {
+ if (strlcpy(basename, input_filename, basename_size)
+ >= basename_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
+ }
u8* pipe_args[] = {(u8*)basename, NULL};
@@ -757,7 +794,8 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback)
while (!feof(tsv) && (!tsv_iter || tsv_lineno <= tsv_iter))
{
- u8* eol = NULL;
+ u8* eol = NULL;
+ size_t res = 0;
if (!fgets((char*)bufline, BUFSIZE, tsv))
break;
eol = (u8*)strchr((char*)bufline, '\n');
@@ -776,12 +814,25 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback)
*ptoken = 0;
if (tsv_lineno > 0
&& current_register < MAX_TSV_REGISTERS)
- strcpy((char*)tsv_register[current_register++],
- (char*)token);
+ {
+ if ((res = strlcpy((char*)tsv_register
+ [current_register],
+ (char*)token, BUFSIZE))
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_register++;
+ }
else if (tsv_lineno <= 0
&& current_header < MAX_TSV_REGISTERS)
- strcpy((char*)tsv_header[current_header++],
- (char*)token);
+ {
+ if (strlcpy((char*)tsv_header[current_header],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_header++;
+ }
RESET_TOKEN(token, ptoken, token_size);
pbufline++;
break;
@@ -794,14 +845,26 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback)
if (tsv_lineno > 0)
{
if (current_register < MAX_TSV_REGISTERS)
- strcpy((char*)tsv_register[current_register++],
- (char*)token);
+ {
+ if (strlcpy((char*)tsv_register[current_register],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_register++;
+ }
}
else
{
if (current_header < MAX_TSV_REGISTERS)
- strcpy((char*)tsv_header[current_header++],
- (char*)token);
+ {
+ if (strlcpy((char*)tsv_header[current_header],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_header++;
+ }
}
RESET_TOKEN(token, ptoken, token_size);
@@ -1059,7 +1122,8 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback)
UBYTE current_header = 0;
u8* csv_register[MAX_CSV_REGISTERS];
UBYTE current_register = 0;
- u8* csv_delimiter = get_value(vars, vars_count, (u8*)"csv-delimiter");
+ u8* csv_delimiter
+ = get_value(vars, vars_count, (u8*)"csv-delimiter", NULL);
if (!(csv = fopen(filename, "rt")))
exit(error(ENOENT, (u8*)"csv: No such file: %s", filename));
@@ -1105,13 +1169,26 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback)
*ptoken = 0;
if (csv_lineno > 0
&& current_register < MAX_CSV_REGISTERS)
- strcpy((char*)csv_register
- [current_register++],
- (char*)token);
+ {
+ if (strlcpy((char*)csv_register
+ [current_register],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_register++;
+ }
else if (csv_lineno <= 0
&& current_header < MAX_CSV_REGISTERS)
- strcpy((char*)csv_header[current_header++],
- (char*)token);
+ {
+ if (strlcpy((char*)csv_header
+ [current_header],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_header++;
+ }
RESET_TOKEN(token, ptoken, token_size);
pbufline++;
}
@@ -1124,13 +1201,26 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback)
*ptoken = 0;
if (csv_lineno > 0
&& current_register < MAX_CSV_REGISTERS)
- strcpy((char*)csv_register
- [current_register++],
- (char*)token);
+ {
+ if (strlcpy((char*)csv_register
+ [current_register],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_register++;
+ }
else if (csv_lineno <= 0
&& current_header < MAX_CSV_REGISTERS)
- strcpy((char*)csv_header[current_header++],
- (char*)token);
+ {
+ if (strlcpy((char*)csv_header
+ [current_header],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_header++;
+ }
RESET_TOKEN(token, ptoken, token_size);
pbufline++;
}
@@ -1143,14 +1233,26 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback)
if (csv_lineno > 0)
{
if (current_register < MAX_CSV_REGISTERS)
- strcpy((char*)csv_register[current_register++],
- (char*)token);
+ {
+ if (strlcpy((char*)csv_register[current_register],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_register++;
+ }
}
else
{
if (current_header < MAX_CSV_REGISTERS)
- strcpy((char*)csv_header[current_header++],
- (char*)token);
+ {
+ if (strlcpy((char*)csv_header[current_header],
+ (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ current_header++;
+ }
}
RESET_TOKEN(token, ptoken, token_size);
@@ -1304,7 +1406,6 @@ process_include(FILE* output, const u8* token,
int result = 0;
FILE* child_output = NULL;
- prctl(PR_SET_PDEATHSIG, SIGTERM);
close(arg_pipe_fds[PIPE_WRITE_INDEX]);
close(output_pipe_fds[PIPE_READ_INDEX]);
if (!(child_output
@@ -1491,7 +1592,7 @@ int
process_incdir_subdir(FILE* output, const char* subdirname,
const u8* link_prefix, const int details_open, const u8* macro_body,
const u8* footer_permalink_text, const char* permalink_url,
- const int ext_in_permalink)
+ const int ext_in_permalink, const int list_only)
{
struct dirent** namelist;
struct dirent** pnamelist;
@@ -1532,17 +1633,17 @@ process_incdir_subdir(FILE* output, const char* subdirname,
int result = 0;
ULLONG saved_state = ST_NONE;
char* filename = NULL;
- char* basename = strip_ext((*pnamelist)->d_name);
char* link = NULL;
+ u8* title = NULL;
+ u8* date = NULL;
- CALLOC(link, char, BUFSIZE);
+ if (!strcmp(basedir, "."))
+ set_basedir(&basedir, &basedir_size,
+ abs_subdirname);
CALLOC(filename, char, BUFSIZE);
-
- snprintf(link, BUFSIZE, "%s/%s", subdirname, basename);
-
- set_basedir(&basedir, &basedir_size, abs_subdirname);
snprintf(filename, BUFSIZE, "%s/%s", abs_subdirname,
(*pnamelist)->d_name);
+ link = strip_ext(filename);
read_file_into_buffer(&input, &buffer, &buffer_size,
filename, &input_dirname);
@@ -1575,25 +1676,27 @@ process_incdir_subdir(FILE* output, const char* subdirname,
output_firstcol = 1;
skip_para_end = 0;
- /* Read YAML, macros and links */
+ /* First pass: read YAML, macros and links */
result = slweb_parse(output, filename, buffer, 1);
-
if (result)
{
- slweb_cleanup();
- free(filename);
- free(buffer);
- free(link);
- free(basename);
- free(abs_subdirname);
- while (names_total--)
- free(namelist[names_total]);
- free(namelist);
- return result;
+ warning(1, (u8*)"slweb_parse error");
+ goto incdir_subdir_child_cleanup;
}
- u8* date = get_value(vars, vars_count, (u8*)"date");
- u8* title = get_value(vars, vars_count, (u8*)"title");
+ title = get_value(vars, vars_count, (u8*)"title", NULL);
+ date = get_value(vars, vars_count, (u8*)"date", NULL);
+
+ incdir_subdir_child_cleanup:
+ slweb_cleanup();
+ free(link);
+ free(filename);
+ free(buffer);
+ free(abs_subdirname);
+ while (names_total--)
+ free(namelist[names_total]);
+ free(namelist);
+ exit(result);
process_timestamp(output, link_prefix, link, NULL, date,
title, ext_in_permalink);
@@ -1602,10 +1705,9 @@ process_incdir_subdir(FILE* output, const char* subdirname,
fflush(output);
slweb_cleanup();
+ free(link);
free(filename);
free(buffer);
- free(link);
- free(basename);
free(abs_subdirname);
while (names_total--)
free(namelist[names_total]);
@@ -1615,6 +1717,9 @@ process_incdir_subdir(FILE* output, const char* subdirname,
else
exit(error(1, (u8*)"Fork failed"));
+ /*if (!list_only)
+ print_output(output, "</article>\n");*/
+
pnamelist++;
names_output++;
}
@@ -1624,6 +1729,12 @@ process_incdir_subdir(FILE* output, const char* subdirname,
free(namelist);
free(abs_subdirname);
+ /*if (list_only)
+ ; / *print_output(output, "</ul>\n");* /
+ else
+ print_output(output, "</div>\n</details>\n</li>\n");*/
+
+ output_firstcol = 0;
return 0;
}
@@ -1643,6 +1754,9 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
struct dirent** pnamelist;
long names_output;
int details_open = 1;
+ int list_only = 0;
+ int pass;
+ u8* parg = NULL;
if (read_yaml_macros_and_links)
return 0;
@@ -1658,22 +1772,26 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
exit(error(1, (u8*)"incdir: First argument not string"));
incdir = strdup((char*)(arg + 1));
- *(incdir + strlen(incdir) - 1) = 0;
+ *(incdir + strlen(incdir) - 1) = 0; /* trim ending " */
+
+ pass = 0;
+incdir_next_arg:
arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
if (!arg)
- exit(error(1, (u8*)"incdir: Second argument required"));
+ goto incdir_done_args;
- if (*arg == '=')
- macro_body = get_value(macros, macros_count, arg + 1);
+ parg = arg;
+ if (*parg == '=')
+ macro_body = get_value(macros, macros_count, arg + 1, NULL);
+ else if (!strcmp((const char*)arg, "listonly"))
+ list_only = 1;
else
{
- u8* parg = arg;
while (parg && *parg)
{
if (*parg < '0' || *parg > '9')
- exit(error(1,
- (u8*)"incdir: Non-numeric argument"));
+ exit(error(1, (u8*)"incdir: Invalid argument"));
parg++;
}
errno = 0;
@@ -1681,19 +1799,13 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
if (errno)
exit(error(errno,
(u8*)"incdir: Invalid parameter 'num'"));
- arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
- if (arg)
- {
- if (*arg != '=')
- {
- free(incdir);
- exit(error(1,
- (u8*)"incdir: Third argument not "
- "macro"));
- }
- macro_body = get_value(macros, macros_count, arg + 1);
- }
}
+ pass++;
+ if (pass < 3)
+ goto incdir_next_arg;
+
+incdir_done_args:
+ /*print_output(output, "<ul class=\"incdir\">\n")*/;
if ((names_total = scandir(incdir, &namelist, &filter_subdirs,
&reverse_alphacompare))
@@ -1707,12 +1819,17 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
names_output = 0;
while (names_output < MIN(names_total, num))
{
+ /*if (list_only)
+ print_output(output, "<li>%s\n",
+ (*pnamelist)->d_name);*/
process_incdir_subdir(output, (*pnamelist)->d_name, link_prefix,
details_open, macro_body, footer_permalink_text,
- permalink_url, ext_in_permalink);
+ permalink_url, ext_in_permalink, list_only);
details_open = 0;
pnamelist++;
names_output++;
+ /*if (list_only)
+ print_output(output, "</li>\n");*/
}
/*print_output(output, "\n");*/
output_firstcol = 1;
@@ -1727,46 +1844,87 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
int url_is_local(const char* url);
-int
-process_timestamp(FILE* output, const u8* link_prefix, const char* link,
- const u8* permalink_macro, const u8* date, const u8* title,
- const int ext_in_permalink)
+u8*
+format_date(const u8* date_arg, const char* timestamp_format)
{
+ const char* ptimestamp_format = NULL;
u8* day = NULL;
u8* month = NULL;
u8* year = NULL;
u8* formatted_date = NULL;
u8* ptr = NULL;
- const char* ptimestamp_format = NULL;
- char* in_filename = NULL;
- char* in_line = NULL;
+ u8* date = NULL;
+
+ date = (u8*)strdup((const char*)date_arg);
+ if (!date)
+ goto format_date_cleanup;
CALLOC(formatted_date, u8, DATEBUFSIZE);
ptr = NULL;
year = (u8*)strtok_r((char*)date, "-", (char**)&ptr);
if (!year)
- goto process_timestamp_cleanup;
+ goto format_date_cleanup;
month = (u8*)strtok_r(NULL, "-", (char**)&ptr);
if (!month)
- goto process_timestamp_cleanup;
+ goto format_date_cleanup;
day = (u8*)strtok_r(NULL, "T", (char**)&ptr);
if (!day)
- goto process_timestamp_cleanup;
+ goto format_date_cleanup;
ptimestamp_format = timestamp_format;
while (*ptimestamp_format)
{
if (*ptimestamp_format == 'd' || *ptimestamp_format == 'D')
- strcat((char*)formatted_date, (char*)day);
+ {
+ if (strlcat((char*)formatted_date, (char*)day,
+ DATEBUFSIZE)
+ > DATEBUFSIZE)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
+ }
else if (*ptimestamp_format == 'm' || *ptimestamp_format == 'M')
- strcat((char*)formatted_date, (char*)month);
+ {
+ if (strlcat((char*)formatted_date, (char*)month,
+ DATEBUFSIZE)
+ > DATEBUFSIZE)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
+ }
else if (*ptimestamp_format == 'y' || *ptimestamp_format == 'Y')
- strcat((char*)formatted_date, (char*)year);
+ {
+ if (strlcat((char*)formatted_date, (char*)year,
+ DATEBUFSIZE)
+ > DATEBUFSIZE)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
+ }
else
*(formatted_date + strlen((char*)formatted_date))
= *ptimestamp_format;
ptimestamp_format++;
}
+ return formatted_date;
+
+format_date_cleanup:
+ free(formatted_date);
+ free(date);
+
+ return NULL;
+}
+
+int
+process_timestamp(FILE* output, const u8* link_prefix, const char* link,
+ const u8* permalink_macro, const u8* date, const u8* title,
+ const int ext_in_permalink)
+{
+ char* in_filename = NULL;
+ char* in_line = NULL;
+ u8* formatted_date = NULL;
+
+ formatted_date = format_date(date, timestamp_format);
+ if (!formatted_date)
+ goto process_timestamp_cleanup;
+
print_output(output, "=> %s%s%s%s\t%s %s\n",
url_is_local(link) && global_link_prefix
? (const char*)global_link_prefix
@@ -1776,8 +1934,8 @@ process_timestamp(FILE* output, const u8* link_prefix, const char* link,
link, ext_in_permalink ? timestamp_output_ext : "",
formatted_date, title ? (const char*)title : "");
output_firstcol = 1;
-process_timestamp_cleanup:
+process_timestamp_cleanup:
free(formatted_date);
free(in_line);
free(in_filename);
@@ -1815,7 +1973,9 @@ process_macro_def(FILE* output, const u8* token,
pmacros = macros + macros_count - 1;
}
CALLOC(pmacros->key, u8, KEYSIZE);
- strcpy((char*)pmacros->key, (char*)token + 2);
+ if (strlcpy((char*)pmacros->key, (char*)token + 2, KEYSIZE)
+ >= KEYSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
pmacros->value = NULL;
pmacros->value_size = 0;
}
@@ -1832,7 +1992,7 @@ process_macro(FILE* output, const u8* token, const int end_tag)
u8* eol;
size_t macro_body_len;
- macro_body = get_value(macros, macros_count, token + 1);
+ macro_body = get_value(macros, macros_count, token + 1, NULL);
if (!macro_body)
exit(error(1, (u8*)"Macro '%s' undefined", token + 1));
@@ -2232,8 +2392,10 @@ process_inline_footnote(const u8* token, const int read_yaml_macros_and_links,
CALLOC(inline_footnotes[inline_footnote_count - 1], u8,
token_len + 1);
- strcpy((char*)inline_footnotes[inline_footnote_count - 1],
- (char*)token);
+ if (strlcpy((char*)inline_footnotes[inline_footnote_count - 1],
+ (char*)token, token_len + 1)
+ >= token_len + 1)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
*(inline_footnotes[inline_footnote_count - 1] + token_len) = 0;
}
else
@@ -2269,7 +2431,9 @@ process_footnote(FILE* output, const u8* token, const int footnote_definition,
pfootnotes = footnotes + footnote_count - 1;
}
CALLOC(pfootnotes->key, u8, KEYSIZE);
- strcpy((char*)pfootnotes->key, (char*)token);
+ if (strlcpy((char*)pfootnotes->key, (char*)token, KEYSIZE)
+ >= KEYSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
pfootnotes->value = NULL;
pfootnotes->value_size = 0;
}
@@ -2328,8 +2492,10 @@ begin_article(FILE* output, const char* source_filename, const u8* link_prefix,
{
char* link = strip_ext((const char*)source_filename);
- if (ext_in_permalink)
- strcat(link, timestamp_output_ext);
+ if (ext_in_permalink
+ && strlcat(link, timestamp_output_ext, sizeof link)
+ > sizeof link)
+ warning(1, (u8*)"strlcat:%d: Overflow", __LINE__);
free(link);
}
@@ -2453,10 +2619,18 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
*pvars = *vars + *vars_count - 1;
}
CALLOC((*pvars)->key, u8, KEYSIZE);
- strcpy((char*)(*pvars)->key, (char*)var_key);
+ if (strlcpy((char*)(*pvars)->key, (char*)var_key,
+ KEYSIZE)
+ >= KEYSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
(*pvars)->value_size = strlen((char*)token) + 1;
CALLOC((*pvars)->value, u8, (*pvars)->value_size);
- strcpy((char*)(*pvars)->value, (char*)token);
+ if (strlcpy((char*)(*pvars)->value, (char*)token,
+ (*pvars)->value_size)
+ >= (*pvars)->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
}
}
free(var_key);
@@ -2468,22 +2642,26 @@ int
slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
const int read_yaml_macros_and_links)
{
- u8* title = NULL;
- u8* title_heading_level = NULL;
- u8* header_text = NULL;
- u8* author = NULL;
- u8* date = NULL;
- u8* permalink_url = NULL;
- u8* ext_in_permalink = NULL;
- u8* var_add_article_header = NULL;
- u8* var_add_footnote_div = NULL;
- u8* footer_permalink_text = NULL;
- u8* var_incdir_only_summary = NULL;
+ u8* title = NULL;
+ u8* title_heading_level = NULL;
+ u8* header_text = NULL;
+ u8* author = NULL;
+ u8* date = NULL;
+ u8* permalink_url = NULL;
+ u8* ext_in_permalink = NULL;
+ u8* var_add_article_header = NULL;
+ /*u8* var_add_image_links = NULL;
+ u8* var_add_figcaption = NULL;*/
+ u8* var_add_footnote_div = NULL;
+ u8* footer_permalink_text = NULL;
+ u8* var_incdir_only_summary = NULL;
+ /*u8* image_file_prefix = NULL;*/
u8* link_prefix = NULL;
const u8* pbuffer = NULL;
u8* line = NULL;
u8* pline = NULL;
size_t line_len = 0;
+ size_t line_size = 0;
u8* token = NULL;
u8* ptoken = NULL;
size_t token_size = 0;
@@ -2499,37 +2677,50 @@ slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
int previous_line_blank = 0;
int previous_line_block = 0;
int processed_start_of_line = 0;
- int add_footnote_div = 0;
- int list_para = 0;
- int footnote_at_line_start = 0;
- size_t pline_len = 0;
- int madeby_present = 0;
+ /*int add_image_links = 1;
+ int add_figcaption = 1;*/
+ int add_footnote_div = 0;
+ int list_para = 0;
+ int footnote_at_line_start = 0;
+ size_t pline_len = 0;
+ int madeby_present = 0;
+ u8* eol = NULL;
if (!buffer)
exit(error(1, (u8*)"Empty buffer"));
- title = get_value(vars, vars_count, (u8*)"title");
+ title = get_value(vars, vars_count, (u8*)"title", NULL);
title_heading_level
- = get_value(vars, vars_count, (u8*)"title-heading-level");
- header_text = get_value(vars, vars_count, (u8*)"header-text");
- author = get_value(vars, vars_count, (u8*)"author");
- date = get_value(vars, vars_count, (u8*)"date");
- permalink_url = get_value(vars, vars_count, (u8*)"permalink-url");
- ext_in_permalink = get_value(vars, vars_count, (u8*)"ext-in-permalink");
+ = get_value(vars, vars_count, (u8*)"title-heading-level", NULL);
+ header_text = get_value(vars, vars_count, (u8*)"header-text", NULL);
+ author = get_value(vars, vars_count, (u8*)"author", NULL);
+ date = get_value(vars, vars_count, (u8*)"date", NULL);
+ permalink_url = get_value(vars, vars_count, (u8*)"permalink-url", NULL);
+ /*image_file_prefix
+ = get_value(vars, vars_count, (u8*)"image-file-prefix", NULL);*/
+ ext_in_permalink
+ = get_value(vars, vars_count, (u8*)"ext-in-permalink", NULL);
var_add_article_header
- = get_value(vars, vars_count, (u8*)"add-article-header");
+ = get_value(vars, vars_count, (u8*)"add-article-header", NULL);
+ /*var_add_image_links
+ = get_value(vars, vars_count, (u8*)"add-image-links", NULL);
+ add_image_links = !(var_add_image_links && *var_add_image_links == '0');
+ var_add_figcaption
+ = get_value(vars, vars_count, (u8*)"add-figcaption", NULL);
+ add_figcaption = !(var_add_figcaption && *var_add_figcaption == '0');*/
var_add_footnote_div
- = get_value(vars, vars_count, (u8*)"add-footnote-div");
+ = get_value(vars, vars_count, (u8*)"add-footnote-div", NULL);
add_footnote_div = var_add_footnote_div && *var_add_footnote_div == '1';
- link_prefix = get_value(vars, vars_count, (u8*)"link-prefix");
+ link_prefix = get_value(vars, vars_count, (u8*)"link-prefix", NULL);
footer_permalink_text = get_value(vars, vars_count,
- (u8*)"incdir-footer-permalink-text");
+ (u8*)"incdir-footer-permalink-text", NULL);
var_incdir_only_summary
- = get_value(vars, vars_count, (u8*)"incdir-only-summary");
+ = get_value(vars, vars_count, (u8*)"incdir-only-summary", NULL);
incdir_only_summary
= var_incdir_only_summary && *var_incdir_only_summary == '1';
- CALLOC(line, u8, BUFSIZE);
+ line_size = BUFSIZE;
+ CALLOC(line, u8, line_size);
token_size = BUFSIZE;
CALLOC(token, u8, BUFSIZE);
CALLOC(link_macro, u8, BUFSIZE);
@@ -2553,15 +2744,19 @@ slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
RESET_TOKEN(token, ptoken, token_size);
output_firstcol = 1;
-do_buffer:;
- u8* eol = (u8*)strchr((char*)pbuffer, '\n');
+
+do_buffer:
+ eol = (u8*)strchr((char*)pbuffer, '\n');
if (!eol)
goto done_buffer;
pline = line;
while (pbuffer != eol)
- *pline++ = *pbuffer++;
- pbuffer++;
+ CHECKCOPY(line, pline, line_size, pbuffer);
+
+ if (pbuffer == eol)
+ pbuffer++;
+
*pline = 0;
pline = line;
line_len = strlen((char*)line);
@@ -2690,7 +2885,10 @@ do_line:
pvars = vars + vars_count - 1;
}
CALLOC(pvars->key, u8, KEYSIZE);
- strcpy((char*)pvars->key, (char*)token);
+ if (strlcpy((char*)pvars->key, (char*)token, KEYSIZE)
+ >= KEYSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
pvars->value = NULL;
pvars->value_size = 0;
@@ -2748,7 +2946,11 @@ do_line:
if (token_len + entity_len < BUFSIZE)
{
- strcat((char*)token, (char*)entity);
+ if (strlcat((char*)token, (char*)entity,
+ token_size)
+ > token_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
ptoken += entity_len;
}
}
@@ -2789,7 +2991,11 @@ do_line:
if (token_len + entity_len < BUFSIZE)
{
- strcat((char*)token, (char*)entity);
+ if (strlcat((char*)token, (char*)entity,
+ token_size)
+ > token_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
ptoken += entity_len;
}
}
@@ -2831,7 +3037,11 @@ do_line:
if (token_len + tag_len < BUFSIZE)
{
- strcat((char*)token, (char*)tag);
+ if (strlcat((char*)token, (char*)tag,
+ token_size)
+ > token_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
ptoken += tag_len;
}
}
@@ -3363,7 +3573,11 @@ do_line:
if (strlen((char*)pline) == 2 && *(pline + 1) == ' ')
{
*ptoken = 0;
- strcat((char*)ptoken, "\n");
+ if (strlcat((char*)ptoken, "\n",
+ token_size - (ptoken - token))
+ > token_size - (ptoken - token))
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
ptoken++;
output_firstcol = 1;
pline += 2;
@@ -3372,7 +3586,10 @@ do_line:
else if (IN(state, ST_LINK_MACRO))
{
*ptoken = 0;
- strncpy((char*)link_macro, (char*)token, BUFSIZE - 1);
+ if (strlcpy((char*)link_macro, (char*)token, BUFSIZE)
+ >= BUFSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
*(link_macro + strlen((char*)token)) = 0;
RESET_TOKEN(token, ptoken, token_size);
state &= ~ST_LINK_MACRO;
@@ -3427,18 +3644,24 @@ do_line:
REALLOC(pmacros->value, u8,
pmacros->value_size);
}
- strncat((char*)pmacros->value,
- (char*)token,
- pmacros->value_size - 1);
+ if (strlcat((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size)
+ > pmacros->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
else
{
pmacros->value_size = token_len + 1;
CALLOC(pmacros->value, u8,
pmacros->value_size);
- strncpy((char*)pmacros->value,
- (char*)token,
- pmacros->value_size - 1);
+ if (strlcpy((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size)
+ >= pmacros->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
}
}
}
@@ -4031,6 +4254,7 @@ do_line:
RESET_TOKEN(token, ptoken, token_size);
state &= ~(ST_LINK | ST_LINK_SECOND_ARG | ST_IMAGE
| ST_IMAGE_SECOND_ARG);
+ /* Difference from slweb: could be NULL */
if (pline)
pline++;
}
@@ -4100,7 +4324,8 @@ do_line:
{
if (!read_yaml_macros_and_links)
{
- u8* url = get_value(links, links_count, token);
+ u8* url = get_value(links, links_count, token,
+ NULL);
if (!url)
exit(error(EINVAL,
(u8*)"get_"
@@ -4144,6 +4369,7 @@ do_line:
}
RESET_TOKEN(token, ptoken, token_size);
state &= ~(ST_LINK | ST_LINK_SECOND_ARG);
+ /* Difference from slweb: could be NULL */
if (pline)
{
pline++;
@@ -4154,7 +4380,8 @@ do_line:
{
if (!read_yaml_macros_and_links)
{
- u8* url = get_value(links, links_count, token);
+ u8* url = get_value(links, links_count, token,
+ NULL);
if (!url)
exit(error(EINVAL,
(u8*)"get_"
@@ -4198,6 +4425,7 @@ do_line:
}
RESET_TOKEN(token, ptoken, token_size);
state &= ~(ST_IMAGE | ST_IMAGE_SECOND_ARG);
+ /* Difference from slweb: could be NULL */
if (pline)
{
pline++;
@@ -4224,7 +4452,11 @@ do_line:
plinks = links + links_count - 1;
}
CALLOC(plinks->key, u8, KEYSIZE);
- strcpy((char*)plinks->key, (char*)token);
+ if (strlcpy((char*)plinks->key, (char*)token,
+ KEYSIZE)
+ >= KEYSIZE)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
plinks->value = NULL;
plinks->value_size = 0;
pline += 2;
@@ -4253,7 +4485,11 @@ do_line:
link_size = token_len + 1;
CALLOC(link_text, u8, link_size);
}
- strcpy((char*)link_text, (char*)token);
+ if (strlcpy((char*)link_text, (char*)token,
+ link_size)
+ >= link_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
*(link_text + token_len) = 0;
pline += 2;
colno += 2;
@@ -4539,7 +4775,9 @@ done_line:
}
pvars->value_size = strlen((char*)token) + 1;
CALLOC(pvars->value, u8, pvars->value_size);
- strcpy((char*)pvars->value, (char*)token);
+ if (strlcpy((char*)pvars->value, (char*)token, pvars->value_size)
+ >= pvars->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow", __LINE__);
}
else if (keep_token)
{
@@ -4550,8 +4788,11 @@ done_line:
REALLOC(token, u8, token_size);
ptoken = token + old_size - 1;
}
- strcat((char*)token,
- ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n");
+ if (strlcat((char*)token,
+ ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n",
+ token_size)
+ > token_size)
+ warning(1, (u8*)"strlcat:%d: Overflow", __LINE__);
ptoken++;
*ptoken = 0;
}
@@ -4584,18 +4825,34 @@ done_line:
REALLOC(pmacros->value, u8,
pmacros->value_size);
}
- strcat((char*)pmacros->value,
- (char*)token);
- strcat((char*)pmacros->value, " ");
+ if (strlcat((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size)
+ > pmacros->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
+ if (strlcat((char*)pmacros->value, " ",
+ pmacros->value_size)
+ > pmacros->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
else
{
pmacros->value_size = BUFSIZE;
CALLOC(pmacros->value, u8,
pmacros->value_size);
- strcpy((char*)pmacros->value,
- (char*)token);
- strcat((char*)pmacros->value, " ");
+ if (strlcpy((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size)
+ >= pmacros->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ if (strlcat((char*)pmacros->value, " ",
+ pmacros->value_size)
+ > pmacros->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
skip_macro_read:;
}
@@ -4624,18 +4881,34 @@ done_line:
REALLOC(pfootnotes->value, u8,
pfootnotes->value_size);
}
- strcat((char*)pfootnotes->value,
- (char*)token);
- strcat((char*)pfootnotes->value, " ");
+ if (strlcat((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size)
+ > pfootnotes->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
+ if (strlcat((char*)pfootnotes->value,
+ " ", pfootnotes->value_size)
+ > pfootnotes->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
else
{
pfootnotes->value_size = BUFSIZE;
CALLOC(pfootnotes->value, u8,
pfootnotes->value_size);
- strcpy((char*)pfootnotes->value,
- (char*)token);
- strcat((char*)pfootnotes->value, " ");
+ if (strlcpy((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size)
+ >= pfootnotes->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
+ if (strlcat((char*)pfootnotes->value,
+ " ", pfootnotes->value_size)
+ > pfootnotes->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
*token = 0;
ptoken = token;
@@ -4658,8 +4931,12 @@ done_line:
= strlen((char*)token) + 1;
CALLOC(plinks->value, u8,
plinks->value_size);
- strcpy((char*)plinks->value,
- (char*)token);
+ if (strlcpy((char*)plinks->value,
+ (char*)token,
+ plinks->value_size)
+ >= plinks->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
}
}
else if (IN(state, ST_HEADING))
@@ -4689,11 +4966,11 @@ done_line:
{
if (IN(state, ST_PARA_OPEN))
{
- if (!read_yaml_macros_and_links)
+ /*if (!read_yaml_macros_and_links)
{
- /*print_output(output, "\n;");
- output_firstcol = 1;*/
- }
+ print_output(output, "\n;");
+ output_firstcol = 1;
+ }*/
if (IN(state, ST_LIST))
skip_eol = 1;
state &= ~ST_PARA_OPEN;
@@ -4768,16 +5045,24 @@ done_line:
REALLOC(pfootnotes->value, u8,
pfootnotes->value_size);
}
- strcat((char*)pfootnotes->value,
- (char*)token);
+ if (strlcat((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size)
+ > pfootnotes->value_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
}
else
{
pfootnotes->value_size = token_len + 1;
CALLOC(pfootnotes->value, u8,
pfootnotes->value_size);
- strcpy((char*)pfootnotes->value,
- (char*)token);
+ if (strlcpy((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size)
+ >= pfootnotes->value_size)
+ warning(1, (u8*)"strlcpy:%d: Overflow",
+ __LINE__);
}
*token = 0;
ptoken = token;
@@ -4881,16 +5166,16 @@ done_line:
if (pbuffer && *pbuffer)
goto do_buffer;
done_buffer:
- if (!read_yaml_macros_and_links
- && (footnote_count > 0 || inline_footnote_count > 0))
- end_footnotes(output, link_prefix, add_footnote_div,
- previous_line_blank, read_yaml_macros_and_links);
-
- if (!read_yaml_macros_and_links && (paralinks_count > 0))
- process_paralinks(output, link_prefix);
-
if (!read_yaml_macros_and_links)
{
+ if (footnote_count > 0 || inline_footnote_count > 0)
+ end_footnotes(output, link_prefix, add_footnote_div,
+ previous_line_blank,
+ read_yaml_macros_and_links);
+
+ if (paralinks_count > 0)
+ process_paralinks(output, link_prefix);
+
if (madeby_present)
{
process_madeby(output);
@@ -5047,7 +5332,10 @@ main(const int argc, const char** argv)
buffer_size += BUFSIZE;
REALLOC(buffer, u8, buffer_size);
}
- strcat((char*)buffer, (char*)bufline);
+ if (strlcat((char*)buffer, (char*)bufline, buffer_size)
+ > buffer_size)
+ warning(1, (u8*)"strlcat:%d: Overflow",
+ __LINE__);
buffer_len += bufline_len;
}
free(bufline);
diff --git a/slw2gmi.do b/slw2gmi.do
@@ -1,10 +0,0 @@
-. ./config.redo
-for f in *.h.in; do
- echo $f | sed -e's/\.in$//g'
-done | xargs redo-ifchange
-for f in *.h *.c; do
- echo $f
- echo $f | sed -e's/\.c$/.o/g'
-done | xargs redo-ifchange
-${CC} -o $3 slw2gmi.o utf8.o
-${STRIP} $3
diff --git a/strlcat.c b/strlcat.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: strlcat.c,v 1.9 2019/01/25 00:19:26 millert Exp $ */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left). At most dsize-1 characters
+ * will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t dsize)
+{
+ const char *odst = dst;
+ const char *osrc = src;
+ size_t n = dsize;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end. */
+ while (n-- != 0 && *dst != '\0')
+ dst++;
+ dlen = dst - odst;
+ n = dsize - dlen;
+
+ if (n-- == 0)
+ return(dlen + strlen(src));
+ while (*src != '\0') {
+ if (n != 0) {
+ *dst++ = *src;
+ n--;
+ }
+ src++;
+ }
+ *dst = '\0';
+
+ return(dlen + (src - osrc)); /* count does not include NUL */
+}
diff --git a/strlcpy.c b/strlcpy.c
@@ -0,0 +1,49 @@
+/* $OpenBSD: strlcpy.c,v 1.9 2019/01/25 00:19:26 millert Exp $ */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+
+/*
+ * Copy string src to buffer dst of size dsize. At most dsize-1
+ * chars will be copied. Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t dsize)
+{
+ const char *osrc = src;
+ size_t nleft = dsize;
+
+ /* Copy as many bytes as will fit. */
+ if (nleft != 0) {
+ while (--nleft != 0) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src. */
+ if (nleft == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+
+ return(src - osrc - 1); /* count does not include NUL */
+}
diff --git a/uninstall.do b/uninstall.do
@@ -1,10 +0,0 @@
-. ./config.redo
-for docfile in $DOCS; do
- rm -f "${DOCDIR}/${docfile}"
-done
-for binfile in $PROGS; do
- rm -f "${BINDIR}/${binfile}"
-done
-for manfile in $MANPAGES; do
- rm -f "${MANPREFIX}/man1/${manfile}"
-done
diff --git a/utf8.c b/utf8.c
@@ -1,5 +1,5 @@
/* This program is licensed under the terms of GNU GPL v3 or (at your option)
- * any later version. Copyright (C) 2021-2023 Страхиња Радић.
+ * any later version. Copyright (C) 2021-2024 Страхиња Радић.
* See the file LICENSE for exact copyright and license details. */
#include "utf8.h"
diff --git a/utf8.h b/utf8.h
@@ -1,5 +1,5 @@
/* This program is licensed under the terms of GNU GPL v3 or (at your option)
- * any later version. Copyright (C) 2021-2023 Страхиња Радић.
+ * any later version. Copyright (C) 2021-2024 Страхиња Радић.
* See the file LICENSE for exact copyright and license details. */
#include <stdint.h>
diff --git a/version.do b/version.do
@@ -1,17 +0,0 @@
-FALLBACKVER=${FALLBACKVER:-unknown}
-LC_ALL=C
-export LC_ALL
-user=$(unalias ls >/dev/null 2>&1 || true; \
- command ls -ld . | awk '{print $3}')
-e_user=$(id -un)
-if [ -d .git ] && command -v git >/dev/null 2>&1; then
- if [ "$e_user" = "$user" ]; then
- git describe 2>/dev/null | sed 's/^v//' >$3
- else
- su "${user}" -c 'git describe' 2>/dev/null | sed 's/^v//' >$3
- fi
-else
- printf "%s\n" "$FALLBACKVER" >$3
-fi
-redo-always
-redo-stamp <$3
diff --git a/version.h.in b/version.h.in
@@ -1,5 +1,5 @@
/* This program is licensed under the terms of GNU GPL v3 or (at your option)
- * any later version. Copyright (C) 2021-2023 Страхиња Радић.
+ * any later version. Copyright (C) 2021-2024 Страхиња Радић.
* See the file LICENSE for exact copyright and license details. */
#define PROGRAMNAME "slw2gmi"