Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!news.gan.net.au!act.news.telstra.net!psgrain!usenet.eel.ufl.edu!spool.mu.edu!news.sol.net!news.inc.net!trellis.wwnet.com!nntp.coast.net!howland.reston.ans.net!EU.net!Germany.EU.net!Dortmund.Germany.EU.net!interface-business.de!usenet
From: j@ida.interface-business.de (J Wunsch)
Newsgroups: comp.unix.bsd.bsdi.misc,comp.unix.bsd.misc,comp.unix.misc
Subject: Re: Maintaining tty - [HELP!]
Date: 19 Mar 1996 18:50:42 GMT
Organization: interface business GmbH, Dresden
Lines: 261
Message-ID: <4imvm2$bh8@innocence.interface-business.de>
References: <4i4070$aei@fagot.techno.ru>
Reply-To: joerg_wunsch@interface-business.de (Joerg Wunsch)
NNTP-Posting-Host: ida.interface-business.de
X-Newsreader: knews 0.9.3
Xref: euryale.cc.adfa.oz.au comp.unix.bsd.bsdi.misc:2707 comp.unix.bsd.misc:565 comp.unix.misc:21408
oleg@magnum.techno.ru (Oleg Gamayunoff) writes:
> I'm not a professional C programmer, but.. please, help!
>
> I was told to wrote a short program to maintain a modem-like device (some
> sort of terminal) but I havent program anything that works with
> COM-ports/ttyXX/etc and I dunno where to read about it...
> Could anyone explain shortly these functions to me, how to hande/maintain
> DTR/DSR/etc and so on? Or maybe anyone could send me a short _commented_
> communication/terminal program?
You'll probably have a hard time.
I wrote this little program a few days ago. It serves as a modem-to-
telnet forwarder here, perhaps it might be of some use for you. It
provides the basic framework that is required to handle a tty-style
device. It also demonstrates UUCP-style tty lock file locking (ick!).
It has been written on a FreeBSD system, so i assume you can recompile
it without modification on BSD/OS.
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# comt.c
# Makefile
#
echo x - comt.c
sed 's/^X//' >comt.c << 'END-of-comt.c'
X/*
X * comt -- simple modem forwarder daemon
X *
X * Designed for being started by telnet, specifically for use by the
X * `comt' client program under winglows. Forwards the raw modem to
X * a telnet port on fd's 0 and 1.
X *
X * Obeys the UUCP lock file protocol.
X *
X * TODO: handle a stat file, to avoid spin loops in inetd.
X *
X * Author: Jörg Wunsch, interface business GmbH, Dresden
X * <joerg_wunsch@interface-business.de>
X *
X * Copyright © 1996, interface business GmbH. All Rights Reserved.
X *
X * $Id: comt.c,v 1.3 1996/03/19 18:48:01 j Exp $
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY
X * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
X * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
X * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
X * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
X * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
X * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
X * DAMAGE.
X *
X */
X
X#include <sys/types.h>
X#include <sys/time.h>
X#include <termios.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <unistd.h>
X#include <fcntl.h>
X#include <sysexits.h>
X#include <err.h>
X#include <signal.h>
X#include <syslog.h>
X#include <stdarg.h>
X#include <paths.h>
X#include <string.h>
X#include <errno.h>
X
Xstruct termios oldm, oldt;
Xint fd, lockfd;
Xchar lockfname[128];
X
X/* XXX kludge alert. Ya'know, fixed buffers are ugly. :-) */
X#define BUFFSIZE 10000
X
X/* # of tries to establish the tty lock */
X#define MAXTRIES 5
X
Xvoid
Xsighandler(int signo)
X{
X (void)tcsetattr(fd, TCSANOW, &oldm);
X if (isatty(0))
X (void)tcsetattr(0, TCSANOW, &oldt);
X (void)unlink(lockfname);
X exit(EX_OK);
X}
X
Xvoid
Xlog(int status, const char *fmt, ...)
X{
X va_list ap;
X va_start(ap, fmt);
X vsyslog(LOG_NOTICE, fmt, ap);
X va_end(ap);
X exit(status);
X}
X
X
Xint
Xmain(int argc, char **argv)
X{
X int eof = 0;
X char *cp;
X char locktempname[128], b[12];
X struct termios newm, newt;
X int tries, lockfd, locktmpfd;
X pid_t lockpid;
X
X openlog("comt", LOG_PID, LOG_USER);
X
X if (argc != 2)
X log(EX_USAGE, "usage: comt ttyname");
X
X if ((cp = strrchr(argv[1], '/')))
X cp++;
X else
X /* shouldn't happen */
X cp = argv[1];
X snprintf(locktempname, 128, "%s/LCKTMP..%d", _PATH_UUCPLOCK, getpid());
X snprintf(lockfname, 128, "%s/LCK..%s", _PATH_UUCPLOCK, cp);
X
X if ((locktmpfd = open(locktempname, O_WRONLY|O_CREAT, 0666)) == -1)
X log(EX_OSERR, "open(%s): %m", locktempname);
X
X /* Ain't the UUCP lock protocol fun? I love it, ya'know... */
X for (tries = 0; tries < MAXTRIES; tries++)
X {
X if (link(locktempname, lockfname) == -1)
X {
X if (errno != EEXIST)
X log(EX_OSERR, "link(%s, %s): %m", locktempname, lockfname);
X if ((lockfd = open(lockfname, O_RDONLY, 0666)) == -1)
X log(EX_OSERR, "open(%s): %m", lockfname);
X if (read(lockfd, b, 12) <= 0)
X log(EX_OSERR, "read(%s): %m", lockfname);
X close(lockfd);
X lockpid = atoi(b);
X if (kill(lockpid, 0) == 0 || errno != ESRCH)
X log(EX_UNAVAILABLE, "lock held for %s by PID %d", cp, lockpid);
X (void)unlink(lockfname);
X }
X else
X {
X (void)unlink(locktempname);
X lockfd = locktmpfd;
X snprintf(b, 12, "%10d\n", getpid());
X (void)write(lockfd, b, strlen(b));
X close(lockfd);
X break;
X }
X }
X if (tries >= MAXTRIES)
X log(EX_UNAVAILABLE, "failed to establish lock for %s", cp);
X
X if ((fd = open(argv[1], O_RDWR|O_NONBLOCK, 0)) == -1)
X log(EX_OSERR, "open(%s): %m", argv[1]);
X
X if (tcgetattr(fd, &oldm) == -1)
X log(EX_OSERR, "tcgetattr() %m");
X
X newm = oldm;
X cfmakeraw(&newm);
X cfsetispeed(&newm, B38400);
X cfsetospeed(&newm, B38400);
X newm.c_cflag |= (CLOCAL|CRTSCTS);
X if (tcsetattr(fd, TCSANOW, &newm) == -1)
X log(EX_OSERR, "tcsetattr() %m");
X
X if (isatty(0))
X {
X if (tcgetattr(0, &oldt) == -1)
X log(EX_OSERR, "tcgetattr() %m");
X
X newt = oldt;
X cfmakeraw(&newt);
X if (tcsetattr(0, TCSANOW, &newt) == -1)
X log(EX_OSERR, "tcsetattr() %m");
X }
X
X (void)signal(SIGINT, sighandler);
X (void)signal(SIGTERM, sighandler);
X (void)signal(SIGHUP, sighandler);
X
X while (!eof)
X {
X fd_set rfd, xfd;
X char b[BUFFSIZE];
X int i;
X
X FD_ZERO(&rfd);
X FD_ZERO(&xfd);
X FD_SET(0, &rfd);
X FD_SET(fd, &rfd);
X FD_SET(0, &xfd);
X FD_SET(fd, &xfd);
X if (select(32, &rfd, 0, &xfd, 0) == -1)
X log(EX_OSERR, "select() %m");
X
X if (FD_ISSET(0, &xfd) || FD_ISSET(fd, &xfd))
X eof++;
X
X if (!eof && FD_ISSET(0, &rfd))
X {
X if ((i = read(0, b, BUFFSIZE)) <= 0)
X eof++; /* EOF on stdin */
X else
X (void)write(fd, b, i);
X }
X
X if (!eof && FD_ISSET(fd, &rfd))
X {
X if ((i = read(fd, b, BUFFSIZE)) <= 0)
X eof++; /* EOF on modem */
X else
X (void)write(1, b, i);
X }
X }
X
X (void)tcsetattr(fd, TCSANOW, &oldm);
X if (isatty(0))
X (void)tcsetattr(0, TCSANOW, &oldt);
X (void)unlink(lockfname);
X return EX_OK;
X}
END-of-comt.c
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
XPROG= comt
XNOMAN= ohno
X
X.include <bsd.prog.mk>
END-of-Makefile
exit
--
J"org Wunsch Unix support engineer
joerg_wunsch@interface-business.de http://www.interface-business.de/~j