Skip to content

Commit

Permalink
net_finger: Add support for .plan and .project.
Browse files Browse the repository at this point in the history
Display a user's .project and .plan files,
if they exist, per UNIX convention.
  • Loading branch information
InterLinked1 committed Dec 15, 2023
1 parent 83675d9 commit 5eedc9c
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
19 changes: 17 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ Additionally, regardless of how the BBS is started, the sysop console can be acc

**WARNING:** Note that anyone that can access the :code:`rsysop` program is able to perform sysop tasks on the BBS. Even if the BBS is not running as root, it should be running under an account that is secured to the sysop.

Configuration
~~~~~~~~~~~~~
System Configuration
~~~~~~~~~~~~~~~~~~~~

Configuration of LBBS and modules are done entirely through INI config files. Different parts of LBBS have their own config files, as does each module that uses one.

Expand Down Expand Up @@ -198,6 +198,21 @@ Each sample config file documents all available options. Refer to the sample con
Additionally, the MailScript rules engine uses a script file called :code:`.rules` in the root maildir and the user's root maildir for manipulating messages.
A sample MailScript rules file is in :code:`configs/.rules` (though this is not a config file, but a sample rule script file).

User Configuration
~~~~~~~~~~~~~~~~~~

User configuration goes in :code:`~/.config`, which is a subdirectory of each user's BBS home directory (unrelated to any system home directories).

Users can edit these files either via the BBS shell (if configured by the sysop) or via any enabled file transfer protocols (e.g. FTP, FTPS, SFTP).

* :code:`.imapremote` - IMAP client proxy configuration

* :code:`.oauth.conf` - OAuth authentication configuration (used for IMAP client proxy and SMTP submission)

* :code:`.plan` - UNIX .plan file, used by the Finger protocol

* :code:`.project` - UNIX .project file, used by the Finger protocol. Limited to 1 line.

Network Login Services
~~~~~~~~~~~~~~~~~~~~~~

Expand Down
6 changes: 3 additions & 3 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ FILE *bbs_mkftemp(char *template, mode_t mode);

/*!
* \brief Efficiently copy part (or all) of a file between two file descriptors
* \param srcfd File descriptor from which to copy
* \param destfd Destination file descriptor
* \param srcfd File descriptor from which to copy. Must be a regular file.
* \param destfd Destination file descriptor. Must be a regular file.
* \param start Offset from start, in bytes, from which to start copying
* \param bytes Number of bytes to copy, starting from start
* \retval -1 on failure, number of bytes copied on success
Expand All @@ -277,7 +277,7 @@ int bbs_copy_file(int srcfd, int destfd, int start, int bytes); /* gcc has fd_ar
/*!
* \brief Efficiently copy data between two file descriptors.
* \param fd_in Input fd. Must NOT be a pipe.
* \param fd_out Output fd.
* \param fd_out Output fd. Must be a pipe.
* \param len Number of bytes to copy
* \retval -1 on failure, number of bytes copied on success
*/
Expand Down
86 changes: 85 additions & 1 deletion nets/net_finger.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,75 @@
#include "include/node.h"
#include "include/user.h"

#include "include/transfer.h"

#define DEFAULT_FINGER_PORT 79

static int finger_port = DEFAULT_FINGER_PORT;

static int allusersallowed = 0;

/*!
* \brief Print a file's contents to a file descriptor
* \param wfd File descriptor to which to write.
* \param filename Name of file. Assumed to exist.
* \param endl Line endings to enforce (NULL if no conversion needed)
* \param maxlines Maximum number of lines to print. 0 for no limit. Only supported if endl is not NULL.
* \param maxbytes Maximum number of bytes to print. 0 for no limit.
* \retval 0 on success, -1 on failure
*/
static int print_file(int wfd, const char *filename, const char *endl, int maxlines, size_t maxbytes)
{
int res;

if (!endl && !maxbytes) {
res = bbs_send_file(filename, wfd) <= 0 ? -1 : 0;
} else if (!endl) {
/* maxbytes != 0 */
int fd = open(filename, O_RDONLY);
if (fd < 0) {
bbs_warning("Failed to open(%s): %s\n", filename, strerror(errno));
return -1;
}
res = bbs_sendfile(wfd, fd, NULL, maxbytes) <= 0 ? -1 : 0;
close(fd);
} else {
/* Read line by line so we can do line ending conversions. */
char buf[1024];
int lines = 0;
size_t written = 0;
size_t endlen = strlen(endl);
FILE *fp = fopen(filename, "r");
if (!fp) {
bbs_warning("Failed to fopen(%s): %s\n", filename, strerror(errno));
return -1;
}
while ((fgets(buf, sizeof(buf), fp))) {
bbs_term_line(buf);
if (maxlines && lines++ >= maxlines) {
bbs_debug(1, "Exceeded maximum lines allowed\n");
break;
}
if (maxbytes) {
size_t linebytes = strlen(buf);
written += linebytes + endlen;
/* We could truncate the line early,
* to be more precise,
* or we could just abort now. */
if (written > maxbytes) {
bbs_debug(1, "Exceeded maximum bytes allowed\n");
break;
}
}
bbs_writef(wfd, "%s%s", buf, endl);
}
res = 0;
fclose(fp);
}

return res;
}

static void *finger_handler(void *varg)
{
char buf[256];
Expand Down Expand Up @@ -97,11 +160,32 @@ static void *finger_handler(void *varg)
if (!strlen_zero(username)) {
if (bbs_user_dump(node->fd, username, 4)) {
bbs_debug(1, "No such user: %s\n", username);
} else {
char pfile[256];
unsigned int userid;
/* If user exists, also display project and plan, if available */
userid = bbs_userid_from_username(username);
if (!bbs_transfer_home_config_file(userid, ".project", pfile, sizeof(pfile))) {
bbs_node_fd_writef(node, node->fd, "Project: ");
if (print_file(node->fd, pfile, "\r\n", 1, 128)) {
/* If it failed, add a new line ourselves. */
bbs_node_fd_writef(node, node->fd, "\r\n");
}
}
if (!bbs_transfer_home_config_file(userid, ".plan", pfile, sizeof(pfile))) {
/* If the user wants the plan to begin on its own line,
* then the first line of the plan can simply be a line break. */
bbs_node_fd_writef(node, node->fd, "Plan: ");
print_file(node->fd, pfile, "\r\n", 10, 512);
/* Don't really care if there's a line break here or not */
} else {
bbs_node_fd_writef(node, node->fd, "No Plan.\r\n");
}
}
} else {
/* All users */
if (!allusersallowed) {
bbs_dprintf(node->fd, "Finger online user list denied\r\n"); /* Other finger servers don't seem to do this, but the RFC says to... */
bbs_node_fd_writef(node, node->fd, "Finger online user list denied\r\n"); /* Other finger servers don't seem to do this, but the RFC says to... */
} else {
bbs_users_dump(node->fd, 4);
}
Expand Down

0 comments on commit 5eedc9c

Please sign in to comment.