Skip to content

Commit

Permalink
util: ucom - micro serial console
Browse files Browse the repository at this point in the history
  • Loading branch information
veremenko-y committed Oct 17, 2024
1 parent fba1b32 commit d94449a
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 0 deletions.
1 change: 1 addition & 0 deletions Applications/util/Makefile.generic
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ SRCS = \
mail.c \
man.c \
manscan.c \
ucom.c \
mkfs.c \
mode.c \
more.c \
Expand Down
2 changes: 2 additions & 0 deletions Applications/util/fuzix-util.pkg
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ f 0755 /bin/uniq uniq
f 0755 /bin/uptime uptime
f 0755 /bin/uud uud
f 0755 /bin/uue uue
f 0755 /bin/ucom ucom
f 0755 /bin/vile vile
l /bin/vile /bin/vi
f 0755 /bin/wc wc
Expand All @@ -130,3 +131,4 @@ f 0755 /bin/write write
f 0755 /bin/xargs xargs
f 0755 /bin/yes yes

f 0655 /usr/man/man1/ucom.1 ucom.1
49 changes: 49 additions & 0 deletions Applications/util/ucom.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.TH ucom 1 "FUZIX System Utilities" "FUZIX"
.SH NAME
ucom \- simple serial console.
.SH SYNOPSIS
.B ucom
[\-s speed] device
.SH DESCRIPTION
Simple and minimal terminal emulator program, to use with modems and alike.
.P
Just like other terminal emulator progrms
.B ucom
supports escape sequence to execute a command in
.B ucom
itself.
.SH OPTIONS
.TP
.B "-s speed"
Set speed of the
.B device
in baud before connecting.

.SH COMMANDS
Commands are executed by first inputing
.I escape character
(
.B ESC
) which by default is
.B ^A.

.TP
.B "ESC q"
Quit program and restore
.B device termios
to the previous settings.

.TP
.B "ESC ESC"
Print escape character verbatim.

.SH EXAMPLES
.P
ucom /dev/tty2
.P
man -s 300 /dev/tty2
.SH BUGS
To be found.
.SH AUTHORS
Yaroslav Veremenko
.SH SEE ALSO
223 changes: 223 additions & 0 deletions Applications/util/ucom.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/* ucom.c - Simple serial console.
*
* Copyright (C) 2024 Yaroslav Veremenko, All rights reserved.
*
* This file is part of FUZIX Operating System.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#include <stdio.h>
#include <signal.h>
#include <termios.h>

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <termio.h>
#include <errno.h>
#include <getopt.h>
#include <sys/wait.h>

static struct termios termsave[2];
static struct termios termcur[2];
static int remotefd = -1;
static speed_t speed = 0;
static char escape = 1;
static int opt, i;
static char buf[2];
static pid_t child;
static char *remotename;

static int baud[] = {
50, /* B50 */
75, /* B75 */
110, /* B110 */
134, /* B134 */
150, /* B150 */
300, /* B300 */
600, /* B600 */
1200, /* B1200 */
2400, /* B2400 */
4800, /* B4800 */
9600, /* B9600 */
19200, /* B19200 */
38400, /* B38400 */
57600, /* B57600 */
115200, /* B115200 */
};

static speed_t baudflg[] = {
B50,
B75,
B110,
B134,
B150,
B300,
B600,
B1200,
B2400,
B4800,
B9600,
B19200,
B38400,
B57600,
B115200,
};

#ifndef uint_fast8_t
#define uint_fast8_t char
#endif

#define TTY 0
#define REMOTE 1

static void term_raw(int fd, int type)
{
tcgetattr(fd, &termsave[type]);
memcpy(&termcur[type], &termsave[type], sizeof(struct termios));
cfmakeraw(&termcur[type]);
termcur[type].c_cc[VMIN] = 1;
termcur[type].c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &termcur[type]);
}

static void restore()
{
tcsetattr(0, TCSAFLUSH, &termsave[TTY]);
if (remotefd >= 0)
{
tcsetattr(remotefd, TCSAFLUSH, &termsave[REMOTE]);
close(remotefd);
}
}

static void quit()
{
int status;
kill(child, SIGHUP);
wait(&status);
}

static void usage()
{
fputs("Micro terminal program.\n"
"Usage: ucom [-s SPEED] DEVICE\n\n"
" DEVICE\t- tty or other character device\n"
" -s SPEED\t- set device speed in baud\n"
" ^A\t\t- default escape character\n"
" ESC q\t\t- exit terminal\n", stderr);
}

int main(int argc, char *argv[])
{
if (isatty(0) != 1)
{
fputs("fd 0 is not tty\n", stderr);
exit(1);
}

while ((opt = getopt(argc, argv, "s:")) != -1)
{
switch (opt)
{
case 's':
speed = atoi(optarg);
for (i = 0; i < sizeof(baud); i++)
{
if (baud[i] == speed)
{
speed = baudflg[i];
break;
}
}
break;
default:
usage();
exit(1);
break;
}
}

argv += optind;
argc -= optind;

if (argc != 1)
{
usage();
exit(1);
}

remotename = *argv;
remotefd = open(remotename, O_RDWR | O_NOCTTY);

if (remotefd < 0)
{
perror(remotename);
exit(1);
}

term_raw(0, TTY);
term_raw(remotefd, REMOTE);

if (speed > 0)
{
if (cfsetospeed(&termcur[REMOTE], (speed_t)speed) < 0 ||
tcsetattr(remotefd, TCSAFLUSH, &termcur[REMOTE]) < 0)
{
restore();
perror("speed");
exit(1);
}
}

child = fork();
if (child < 0)
{
restore();
perror("fork");
exit(1);
}
if (child == 0)
{
while (read(remotefd, &buf[0], 1) > 0)
{
write(0, &buf[0], 1);
}
fputs("Disconnected\r\n", stderr);
}
else
{
uint_fast8_t isEscape = 0;
atexit(restore);
fprintf(stderr, "Connected. Escape character ^%c\r\n", '@' + escape);
while (read(0, &buf[1], 1) > 0)
{
if (!isEscape && buf[1] == escape)
{
isEscape = 1;
continue;
}
if (isEscape && buf[1] == 'q')
{
break;
}
isEscape = 0;
write(remotefd, &buf[1], 1);
}
quit();
}
}

0 comments on commit d94449a

Please sign in to comment.