*BSD News Article 63888


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