forked from Telodendria/Telodendria
Site now pulls built man pages.
This commit is contained in:
parent
f819093b7d
commit
e0c94d7bd2
9 changed files with 296 additions and 82 deletions
8
TODO.txt
8
TODO.txt
|
@ -23,17 +23,17 @@ Milestone: v0.3.0
|
||||||
[ ] Documentation
|
[ ] Documentation
|
||||||
[x] Array
|
[x] Array
|
||||||
[x] Io
|
[x] Io
|
||||||
[ ] Stream
|
[x] Stream
|
||||||
[ ] Tls
|
[x] Tls
|
||||||
[x] HttpClient
|
[x] HttpClient
|
||||||
[ ] Uri
|
[x] Uri
|
||||||
[ ] td
|
[ ] td
|
||||||
[ ] tt
|
[ ] tt
|
||||||
[ ] http-debug-server
|
[ ] http-debug-server
|
||||||
[ ] tp
|
[ ] tp
|
||||||
[ ] send-patch
|
[ ] send-patch
|
||||||
[x] Log
|
[x] Log
|
||||||
[ ] TelodendriaConfig -> Config
|
[x] TelodendriaConfig -> Config
|
||||||
[x] HashMap
|
[x] HashMap
|
||||||
[x] HttpRouter
|
[x] HttpRouter
|
||||||
[x] Html
|
[x] Html
|
||||||
|
|
|
@ -511,7 +511,8 @@ HeaderParse(Stream * stream, HeaderExpr * expr)
|
||||||
|
|
||||||
if (strcmp(word, "struct") == 0 ||
|
if (strcmp(word, "struct") == 0 ||
|
||||||
strcmp(word, "enum") == 0 ||
|
strcmp(word, "enum") == 0 ||
|
||||||
strcmp(word, "const") == 0)
|
strcmp(word, "const") == 0 ||
|
||||||
|
strcmp(word, "unsigned") == 0)
|
||||||
{
|
{
|
||||||
Free(word);
|
Free(word);
|
||||||
word = HeaderConsumeWord(expr);
|
word = HeaderConsumeWord(expr);
|
||||||
|
|
|
@ -120,14 +120,14 @@ typedef struct Config
|
||||||
* set the ok flag to 0. The caller should always check the ok flag,
|
* set the ok flag to 0. The caller should always check the ok flag,
|
||||||
* and if there is an error, it should display the error to the user.
|
* and if there is an error, it should display the error to the user.
|
||||||
*/
|
*/
|
||||||
Config * ConfigParse(HashMap *);
|
extern Config * ConfigParse(HashMap *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free all the values inside of the given configuration structure,
|
* Free all the values inside of the given configuration structure,
|
||||||
* as well as the structure itself, such that it is completely invalid
|
* as well as the structure itself, such that it is completely invalid
|
||||||
* when this function returns.
|
* when this function returns.
|
||||||
*/
|
*/
|
||||||
void ConfigFree(Config *);
|
extern void ConfigFree(Config *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether or not the configuration exists in the database,
|
* Check whether or not the configuration exists in the database,
|
||||||
|
|
|
@ -24,76 +24,200 @@
|
||||||
#ifndef TELODENDRIA_STREAM_H
|
#ifndef TELODENDRIA_STREAM_H
|
||||||
#define TELODENDRIA_STREAM_H
|
#define TELODENDRIA_STREAM_H
|
||||||
|
|
||||||
|
/***
|
||||||
|
* @Nm Stream
|
||||||
|
* @Nd An abstraction over the Io API that implements standard C I/O.
|
||||||
|
* @Dd April 29 2023
|
||||||
|
* @Xr Io
|
||||||
|
*
|
||||||
|
* .Nm
|
||||||
|
* implements an abstraction layer over the Io API. This layer buffers
|
||||||
|
* I/O and makes it much easier to work with, mimicking the standard
|
||||||
|
* C library and offering some more convenience features.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <Io.h>
|
#include <Io.h>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An opaque structure analogous to C's FILE pointers.
|
||||||
|
*/
|
||||||
typedef struct Stream Stream;
|
typedef struct Stream Stream;
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamIo(Io * io);
|
* Create a new stream using the specified Io for underlying I/O
|
||||||
|
* operations.
|
||||||
|
*/
|
||||||
|
extern Stream * StreamIo(Io * io);
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamFd(int);
|
* Create a new stream using the specified POSIX file descriptor.
|
||||||
|
* This is a convenience function for calling
|
||||||
|
* .Fn IoFd
|
||||||
|
* and then passing the result into
|
||||||
|
* .Fn StreamIo .
|
||||||
|
*/
|
||||||
|
extern Stream * StreamFd(int);
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamFile(FILE *);
|
* Create a new stream using the specified C FILE pointer. This is a
|
||||||
|
* convenience function for calling
|
||||||
|
* .Fn IoFile
|
||||||
|
* and then passing the result into
|
||||||
|
* .Fn StreamIo .
|
||||||
|
*/
|
||||||
|
extern Stream * StreamFile(FILE *);
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamOpen(const char *, const char *);
|
* Create a new stream using the specified path and mode. This is a
|
||||||
|
* convenience function for calling
|
||||||
|
* .Xr fopen 3
|
||||||
|
* and then passing the result into
|
||||||
|
* .Fn StreamFile .
|
||||||
|
*/
|
||||||
|
extern Stream * StreamOpen(const char *, const char *);
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamStdout(void);
|
* Get a stream that writes to the standard output.
|
||||||
|
*/
|
||||||
|
extern Stream * StreamStdout(void);
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamStderr(void);
|
* Get a stream that writes to the standard error.
|
||||||
|
*/
|
||||||
|
extern Stream * StreamStderr(void);
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
StreamStdin(void);
|
* Get a stream that reads from the standard input.
|
||||||
|
*/
|
||||||
|
extern Stream * StreamStdin(void);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamClose(Stream *);
|
* Close the stream. This flushes the buffers and closes the underlying
|
||||||
|
* Io. It is analogous to the standard
|
||||||
|
* .Xr fclose 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamClose(Stream *);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamVprintf(Stream *, const char *, va_list);
|
* Print a formatted string. This function is analogous to the standard
|
||||||
|
* .Xr vfprintf 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamVprintf(Stream *, const char *, va_list);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamPrintf(Stream *, const char *,...);
|
* Print a formatted string. This function is analogous to the
|
||||||
|
* standard
|
||||||
|
* .Xr fprintf 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamPrintf(Stream *, const char *,...);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamGetc(Stream *);
|
* Get a single character from a stream. This function is analogous to
|
||||||
|
* the standard
|
||||||
|
* .Xr fgetc 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamGetc(Stream *);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamUngetc(Stream *, int);
|
* Push a character back onto the input stream. This function is
|
||||||
|
* analogous to the standard
|
||||||
|
* .Xr ungetc 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamUngetc(Stream *, int);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamPutc(Stream *, int);
|
* Write a single character to the stream. This function is analogous
|
||||||
|
* to the standard
|
||||||
|
* .Xr fputc 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamPutc(Stream *, int);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamPuts(Stream *, char *);
|
* Write a null-terminated string to the stream. This function is
|
||||||
|
* analogous to the standard
|
||||||
|
* .Xr fputs 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamPuts(Stream *, char *);
|
||||||
|
|
||||||
extern char *
|
/**
|
||||||
StreamGets(Stream *, char *, int);
|
* Read at most the specified number of characters minus 1 from the
|
||||||
|
* specified stream and store them at the memory located at the
|
||||||
|
* specified pointer. This function is analogous to the standard
|
||||||
|
* .Xr fgets 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern char * StreamGets(Stream *, char *, int);
|
||||||
|
|
||||||
extern off_t
|
/**
|
||||||
StreamSeek(Stream *, off_t, int);
|
* Set the file position indicator for the specified stream. This
|
||||||
|
* function is analogous to the standard
|
||||||
|
* .Xr fseeko
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern off_t StreamSeek(Stream *, off_t, int);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamEof(Stream *);
|
* Test the end-of-file indicator for the given stream, returning a
|
||||||
|
* boolean value indicating whether or not it is set. This is analogous
|
||||||
|
* to the standard
|
||||||
|
* .Xr feof 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamEof(Stream *);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamError(Stream *);
|
* Test the stream for an error condition, returning a boolean value
|
||||||
|
* indicating whether or not one is present. This is analogous to the
|
||||||
|
* standard
|
||||||
|
* .Xr ferror 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamError(Stream *);
|
||||||
|
|
||||||
extern void
|
/**
|
||||||
StreamClearError(Stream *);
|
* Clear the error condition associated with the given stream, allowing
|
||||||
|
* future reads or writes to potentially be successful. This functio
|
||||||
|
* is analogous to the standard
|
||||||
|
* .Xr clearerr 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern void StreamClearError(Stream *);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamFlush(Stream *);
|
* Flush all buffered data using the streams underlying write function.
|
||||||
|
* This function is analogous to the standard
|
||||||
|
* .Xr fflush 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamFlush(Stream *);
|
||||||
|
|
||||||
extern ssize_t
|
/**
|
||||||
StreamCopy(Stream *, Stream *);
|
* Read all the bytes from the first stream and write them to the
|
||||||
|
* second stream. This is analogous to
|
||||||
|
* .Fn IoCopy ,
|
||||||
|
* but it uses the internal buffers of the streams. It is probably
|
||||||
|
* less efficient than doing a
|
||||||
|
* .Fn IoCopy
|
||||||
|
* instead, but it is more convenient.
|
||||||
|
*/
|
||||||
|
extern ssize_t StreamCopy(Stream *, Stream *);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
StreamFileno(Stream *);
|
* Get the file descriptor associated with the given stream, or -1 if
|
||||||
|
* the stream is not associated with any file descriptor. This function
|
||||||
|
* is analogous to the standard
|
||||||
|
* .Xr fileno 3
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
extern int StreamFileno(Stream *);
|
||||||
|
|
||||||
#endif /* TELODENDRIA_STREAM_H */
|
#endif /* TELODENDRIA_STREAM_H */
|
||||||
|
|
|
@ -24,34 +24,86 @@
|
||||||
#ifndef TELODENDRIA_TLS_H
|
#ifndef TELODENDRIA_TLS_H
|
||||||
#define TELODENDRIA_TLS_H
|
#define TELODENDRIA_TLS_H
|
||||||
|
|
||||||
|
/***
|
||||||
|
* @Nm Tls
|
||||||
|
* @Nd Interface to platform-dependent TLS libraries.
|
||||||
|
* @Dd April 29 2023
|
||||||
|
* @Xr Stream Io
|
||||||
|
*
|
||||||
|
* .Nm
|
||||||
|
* provides an interface to platform-dependent TLS libraries. It allows
|
||||||
|
* Telodendria to support any TLS library with no changes to existing
|
||||||
|
* code. Support for additional TLS libraries is added by creating a
|
||||||
|
* new compilation unit that implements all the functions here, with
|
||||||
|
* the exception of a few, which are noted.
|
||||||
|
* .Pp
|
||||||
|
* Currently, Telodendria has support for the following TLS libraries:
|
||||||
|
* .Bl -bullet -offset indent
|
||||||
|
* .It
|
||||||
|
* LibreSSL
|
||||||
|
* .It
|
||||||
|
* OpenSSL
|
||||||
|
* .El
|
||||||
|
*/
|
||||||
|
|
||||||
#include <Stream.h>
|
#include <Stream.h>
|
||||||
|
|
||||||
#define TLS_LIBRESSL 2
|
#define TLS_LIBRESSL 2
|
||||||
#define TLS_OPENSSL 3
|
#define TLS_OPENSSL 3
|
||||||
|
|
||||||
extern Stream *
|
/**
|
||||||
TlsClientStream(int, const char *);
|
* Create a new TLS client stream using the given file descriptor and
|
||||||
|
* the given server hostname. The hostname should be used to verify
|
||||||
extern Stream *
|
* that the server actually is who it says it is.
|
||||||
TlsServerStream(int, const char *, const char *);
|
* .Pp
|
||||||
|
* This function does not need to be implemented by the individual
|
||||||
/*
|
* TLS support stubs.
|
||||||
* These are provided by individual TLS implementations.
|
|
||||||
*/
|
*/
|
||||||
|
extern Stream * TlsClientStream(int, const char *);
|
||||||
|
|
||||||
extern void *
|
/**
|
||||||
TlsInitClient(int, const char *);
|
* Create a new TLS server stream using the given certificate and key
|
||||||
|
* file, in the format natively supported by the TLS library.
|
||||||
|
* .Pp
|
||||||
|
* This function does not need to be implemented by the individual
|
||||||
|
* TLS support stubs.
|
||||||
|
*/
|
||||||
|
extern Stream * TlsServerStream(int, const char *, const char *);
|
||||||
|
|
||||||
extern void *
|
/**
|
||||||
TlsInitServer(int, const char *, const char *);
|
* Initialize a cookie that stores information about the given client
|
||||||
|
* connection. This cookie will be passed into the other functions
|
||||||
|
* defined by this API.
|
||||||
|
*/
|
||||||
|
extern void * TlsInitClient(int, const char *);
|
||||||
|
|
||||||
extern ssize_t
|
/**
|
||||||
TlsRead(void *, void *, size_t);
|
* Initialize a cookie that stores information about the given
|
||||||
|
* server connection. This cookie will be passed into the other
|
||||||
|
* functions defined by this API.
|
||||||
|
*/
|
||||||
|
extern void * TlsInitServer(int, const char *, const char *);
|
||||||
|
|
||||||
extern ssize_t
|
/**
|
||||||
TlsWrite(void *, void *, size_t);
|
* Read from a TLS stream, decrypting it and storing the result in the
|
||||||
|
* specified buffer. This function takes the cookie, buffer, and
|
||||||
|
* number of decrypted bytes to read into it. See the documentation for
|
||||||
|
* .Fn IoRead .
|
||||||
|
*/
|
||||||
|
extern ssize_t TlsRead(void *, void *, size_t);
|
||||||
|
|
||||||
extern int
|
/**
|
||||||
TlsClose(void *);
|
* Write to a TLS stream, encrypting the buffer. This function takes
|
||||||
|
* the cookie, buffer, and number of unencrypted bytes to write to
|
||||||
|
* the stream. See the documentation for
|
||||||
|
* .Fn IoWrite .
|
||||||
|
*/
|
||||||
|
extern ssize_t TlsWrite(void *, void *, size_t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the TLS stream, also freeing all memory associated with the
|
||||||
|
* cookie.
|
||||||
|
*/
|
||||||
|
extern int TlsClose(void *);
|
||||||
|
|
||||||
#endif /* TELODENDRIA_TLS_H */
|
#endif /* TELODENDRIA_TLS_H */
|
||||||
|
|
|
@ -24,10 +24,28 @@
|
||||||
#ifndef TELODENDRIA_URI_H
|
#ifndef TELODENDRIA_URI_H
|
||||||
#define TELODENDRIA_URI_H
|
#define TELODENDRIA_URI_H
|
||||||
|
|
||||||
|
/***
|
||||||
|
* @Nm Uri
|
||||||
|
* @Nd Parse a URI. Typically used to parse HTTP(s) URLs.
|
||||||
|
* @Dd April 29 2023
|
||||||
|
* @Xr Http
|
||||||
|
*
|
||||||
|
* .Nm
|
||||||
|
* provides a simple mechanism for parsing URIs. This is an extremely
|
||||||
|
* basic parser that (ab)uses
|
||||||
|
* .Xr sscanf 3
|
||||||
|
* to parse URIs, so it may not be the most reliable, but it should
|
||||||
|
* work in most cases and on reasonable URIs that aren't too long, as
|
||||||
|
* the _MAX definitions are modest.
|
||||||
|
*/
|
||||||
|
|
||||||
#define URI_PROTO_MAX 8
|
#define URI_PROTO_MAX 8
|
||||||
#define URI_HOST_MAX 128
|
#define URI_HOST_MAX 128
|
||||||
#define URI_PATH_MAX 256
|
#define URI_PATH_MAX 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parsed URI is stored in this structure.
|
||||||
|
*/
|
||||||
typedef struct Uri
|
typedef struct Uri
|
||||||
{
|
{
|
||||||
char proto[URI_PROTO_MAX];
|
char proto[URI_PROTO_MAX];
|
||||||
|
@ -36,10 +54,16 @@ typedef struct Uri
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
} Uri;
|
} Uri;
|
||||||
|
|
||||||
extern Uri *
|
/**
|
||||||
UriParse(const char *);
|
* Parse a URI string into the Uri structure as described above, or
|
||||||
|
* return NULL if there was a parsing error.
|
||||||
|
*/
|
||||||
|
extern Uri * UriParse(const char *);
|
||||||
|
|
||||||
extern void
|
/**
|
||||||
UriFree(Uri *);
|
* Free the memory associated with a Uri structure returned by
|
||||||
|
* .Fn UriParse .
|
||||||
|
*/
|
||||||
|
extern void UriFree(Uri *);
|
||||||
|
|
||||||
#endif /* TELODENDRIA_URI_H */
|
#endif /* TELODENDRIA_URI_H */
|
||||||
|
|
|
@ -181,9 +181,6 @@ extern int UserCheckPassword(User *, char *);
|
||||||
*/
|
*/
|
||||||
extern int UserSetPassword(User *, char *);
|
extern int UserSetPassword(User *, char *);
|
||||||
|
|
||||||
extern int
|
|
||||||
UserDeactivate(User *);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immediately deactivate the given user account such that it can no
|
* Immediately deactivate the given user account such that it can no
|
||||||
* longer be used to log in, but the username is still reserved. This
|
* longer be used to log in, but the username is still reserved. This
|
||||||
|
@ -191,6 +188,14 @@ extern int
|
||||||
* of a given localpart. The user is logged out; all access tokens are
|
* of a given localpart. The user is logged out; all access tokens are
|
||||||
* invalidated.
|
* invalidated.
|
||||||
*/
|
*/
|
||||||
|
extern int UserDeactivate(User *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a boolean value indicating whether or not the user was
|
||||||
|
* deactivated using
|
||||||
|
* .Fn UserDeactivate .
|
||||||
|
* Note that once deactivated, users cannot be reactivated.
|
||||||
|
*/
|
||||||
extern int UserDeactivated(User *);
|
extern int UserDeactivated(User *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,7 @@ printf "<th>Man Page</th>"
|
||||||
printf "<th>Description</th>"
|
printf "<th>Description</th>"
|
||||||
printf "</tr>"
|
printf "</tr>"
|
||||||
|
|
||||||
find man -type f -name '*.[1-9]' | sort -r | while IFS= read -r file; do
|
find man build/man -type f -name '*.[1-9]' | sort -r | while IFS= read -r file; do
|
||||||
base=$(basename "$file")
|
base=$(basename "$file")
|
||||||
|
|
||||||
name=$(echo "$base" | rev | cut -d '.' -f 2- | rev)
|
name=$(echo "$base" | rev | cut -d '.' -f 2- | rev)
|
||||||
|
|
18
tools/bin/td
18
tools/bin/td
|
@ -123,6 +123,10 @@ recipe_docs() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if which makewhatis 2>&1 > /dev/null; then
|
||||||
|
makewhatis "$(pwd)/man"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Build the source code, and generate the 'build/telodendria'
|
# Build the source code, and generate the 'build/telodendria'
|
||||||
|
@ -178,6 +182,8 @@ recipe_build() {
|
||||||
if ! intcheck; then
|
if ! intcheck; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
recipe_docs
|
||||||
}
|
}
|
||||||
|
|
||||||
recipe_run() {
|
recipe_run() {
|
||||||
|
@ -239,6 +245,8 @@ recipe_site() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
recipe_docs
|
||||||
|
|
||||||
# Set some variables that may be replaced in the files.
|
# Set some variables that may be replaced in the files.
|
||||||
DATE=$(date)
|
DATE=$(date)
|
||||||
USER_DOCS=$(man-table user)
|
USER_DOCS=$(man-table user)
|
||||||
|
@ -256,15 +264,15 @@ recipe_site() {
|
||||||
done
|
done
|
||||||
cd - >/dev/null
|
cd - >/dev/null
|
||||||
|
|
||||||
find man/ -name '*.[1-9]' | while IFS= read -r man; do
|
find man/ build/man/ -name '*.[1-9]' | while IFS= read -r man; do
|
||||||
dir=$(dirname "$man")
|
section=$(basename "$man" | rev | cut -d '.' -f 1 | rev)
|
||||||
html=$(basename "$man")
|
html=$(basename "$man")
|
||||||
|
|
||||||
mkdir -p "$TELODENDRIA_PUB/$dir/"
|
mkdir -p "$TELODENDRIA_PUB/man/man$section/"
|
||||||
mandoc -Thtml \
|
mandoc -Thtml \
|
||||||
-O style=/style.css,man=/man/man%S/%N.%S.html "$man" \
|
-O style=/style.css,man=/man/man%S/%N.%S.html "$man" \
|
||||||
>"$TELODENDRIA_PUB/$dir/$html.html"
|
>"$TELODENDRIA_PUB/man/man$section/$html.html"
|
||||||
echo "$TELODENDRIA_PUB/$dir/$html.html"
|
echo "$TELODENDRIA_PUB/man/man$section/$html.html"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue