pkg://tpp-convers-1.14.tgz:194607/convers.c
downloads
/*
* This is Tampa Ping-Pong convers/conversd derived from the wampes
* convers package written by Dieter Deyke <deyke@mdddhd.fc.hp.com>
* Modifications by Fred Baumgarten <dc6iq@insu1.etec.uni-karlsruhe.de>
*
* Modifications by Brian A. Lantz/KO4KS <brian@lantz.com>
* $Revision: 1.14 $$Date: 1995/06/16 14:47:52 $
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#if defined(_AIX) && defined(_IBMR2)
#include <time.h>
#include <sys/select.h>
#endif
#include <termios.h>
#include <unistd.h>
#ifdef PCSP
#include <linux/autoconf.h>
#if CONFIG_PCSP
#include <linux/pcsp.h>
extern int speak_open(char *device, int now);
extern int speak_string(int fd, char *str);
extern int speak_close(int fd);
extern int speak_load_samples(char *dir);
#else
#undef PCSP
#endif
#endif
#ifdef linux
#include <sys/ioctl.h>
#endif
#ifdef READLINE
#include "readline/readline.h"
#endif
#if defined(__TURBOC__) || defined(__STDC__)
#define __ARGS(x) x
#else
#define __ARGS(x) ()
#define const
#endif
#if defined(mips) /* no headerfiles for the whole stuff ? */
extern int select __ARGS((int nfsd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout));
#endif
#if defined(mips) || defined(_AIX)
extern void bzero __ARGS((char *b1, int length));
extern int getopt __ARGS((int argc, char **argv, char *optstring));
extern int socket __ARGS((int af, int type, int protocol));
extern int connect __ARGS((int s, struct sockaddr *name, int namelen));
extern int ioctl __ARGS((int d, int request, void *argp));
#endif
#if defined(hpux)
#define fd_set fd_mask /* not sure about this... comments ? */
#endif
extern struct sockaddr *build_sockaddr __ARGS((const char *name, int *addrlen));
extern char *optarg;
extern int optind;
static int issue_running = 1; /* ignore these Issue messages */
static char convtype[512];
static int outcnt = 0;
static char outbuf[20480];
static struct timeval sel_timeout;
static struct termios prev_termios;
static struct termios curr_termios;
static int echo;
static long tt;
#ifdef READLINE
extern char *rl_display_prompt;
extern Function *rl_event_hook;
extern void rl_forced_update_display __ARGS((void));
extern void add_history __ARGS((char *line));
#endif
#if defined(mips) /* select(2) is not POSIX-compatible !!! */
#undef POSIX
#endif
#ifndef POSIX
static long tt2;
#endif
#ifdef READLINE
static char prompt[] = "x";
static int chars_avail = 0;
static output = 0;
static screenwidth;
static struct winsize window_size;
#else
static void stop __ARGS((char *arg));
#endif
#ifdef PCSP
static char *audiodir = "/usr/local/lib/phonemes";
static int speak_fd = 0;
static int do_talk = 0;
#endif
#ifndef AX25
static int observer = 0;
static int restrict = 0;
#endif
/*---------------------------------------------------------------------------*/
static void stop(arg)
char *arg;
{
if (*arg) perror(arg);
tcsetattr(0, TCSANOW, &prev_termios);
exit(0);
}
/*---------------------------------------------------------------------------*/
#ifdef PCSP
void convers_speak_string(s, len)
char *s;
int len;
{
char buffer[10*1024];
int i,j;
for (i = 0,j = 0; i < len; i++) {
if (s[i] == ' ' || s[i] == '<' || s[i] == '>' ||
(s[i] >= 'a' && s[i] <= 'z') ||
(s[i] >= 'A' && s[i] <= 'Z') ||
(s[i] >= '0' && s[i] <= '9')) {
buffer[j++] = s[i];
}
}
buffer[j] = '\0';
/*
* Now split the resulting string:
*
* - if <something> look for callsign-sound
* - speak the rest
*/
if (buffer[0] == '<') {
char *rest, callsign[512], filename[512];
rest = strchr(buffer, '>');
if (rest && rest - buffer < 512) {
bzero(callsign, 20);
strncpy(callsign, buffer+1, rest-buffer-1);
rest++;
sprintf(filename, "%s/%s.au", audiodir, callsign);
/*
* now look if callsign is sampled
*/
if (!access(filename, W_OK)) { /* Garf produced a horrible code here */
sprintf(callsign, "cp %s /dev/audio", filename); /* this NEEDS rewrite... :-( */
speak_close(speak_fd);
system(callsign);
speak_fd = speak_open("/dev/audio", 1);
speak_string(speak_fd, rest);
return;
}
}
}
speak_string(speak_fd, buffer);
}
#endif
/*---------------------------------------------------------------------------*/
void do_select_call()
{
fd_set mask;
int size;
int i;
#ifndef READLINE
int incnt = 0;
char inbuf[20480];
#endif
char buffer[20480];
char c, *cp;
FD_ZERO(&mask);
FD_SET(0,&mask);
FD_SET(3,&mask);
sel_timeout.tv_sec = 0;
sel_timeout.tv_usec = 200000;
select(4, &mask, (fd_set *) 0, (fd_set *) 0, &sel_timeout);
if (FD_ISSET(0,&mask)) {
#ifdef READLINE
chars_avail = 1;
#else
do {
if ((size = read(0, buffer, sizeof(buffer))) <= 0) stop(convtype);
for (i = 0; i < size; i++) {
c = buffer[i];
if (c == '\r') c = '\n';
if (c == (char) prev_termios.c_cc[VERASE]) {
if (incnt) {
incnt--;
if (echo && write(1, "\b \b", 3) < 0) stop(convtype);
}
} else if (c == (char) prev_termios.c_cc[VKILL]) {
for (; incnt; incnt--)
if (echo && write(1, "\b \b", 3) < 0) stop(convtype);
} else if (echo && c == 18) {
if (write(1, "^R\n", 3) < 0) stop(convtype);
if (write(1, inbuf, incnt) < 0) stop(convtype);
} else {
inbuf[incnt++] = c;
if (echo && write(1, &c, 1) < 0) stop(convtype);
}
if (c == '\n' || incnt == sizeof(inbuf) - 1) {
if (inbuf[0] == '!') {
#ifndef NO_SHELL
if (inbuf[1] != '!') {
inbuf[incnt] = '\0';
if (tcsetattr(0, TCSANOW, &prev_termios)) stop(convtype);
system(inbuf + 1);
if (tcsetattr(0, TCSANOW, &curr_termios)) stop(convtype);
if (write(3, "\n", 1) < 0) stop(convtype);
} else {
if (write(3, inbuf + 1, incnt - 1) < 0) stop(convtype);
}
#endif
} else {
if (write(3, inbuf, incnt) < 0) stop(convtype);
}
incnt = 0;
#ifdef POSIX
fflush(NULL);
#endif
}
}
} while (incnt);
#endif
}
if (FD_ISSET(3,&mask)) {
size = read(3, buffer, sizeof(buffer));
if ((size <= 0) && !outcnt) stop("");
#ifdef PCSP
if (speak_fd)
convers_speak_string(buffer,size);
#endif
for (i = 0; i < size; i++) {
c = buffer[i];
if (c != '\r') outbuf[outcnt++] = c;
#ifdef READLINE
if (c > ' ') prompt[0] = c;
#endif
}
#ifndef POSIX
time(&tt);
#else
fflush(NULL);
#endif
}
#ifndef POSIX
time(&tt2);
tt2--;
#endif
if (outcnt) {
#ifdef POSIX
if ((sel_timeout.tv_sec == 0) && (sel_timeout.tv_usec == 0)) {
#else
if (tt < tt2) {
#endif
#ifdef READLINE
if (echo) {
#ifndef AX25
if (write(1, "\r", 1) < 0) stop("");
for (i = 0; (i <= rl_end) && (i < (screenwidth-1)); i++) {
if (write(1, " ", 1) < 0) stop("");
}
if (write(1, "\r", 1) < 0) stop("");
#endif
output = 1;
}
#endif
if (!issue_running) {
if (write(1, outbuf, outcnt) < 0) stop("");
} else {
cp = outbuf;
while (*cp) {
if (cp[0] != '*') {
issue_running = 0;
if (write(1, cp, outcnt) < 0) stop("");
break;
} else {
while (*cp != '\n') {
cp++;
outcnt--;
}
cp++;
outcnt--;
}
}
}
#ifdef READLINE
#ifdef AX25
if (rl_end) {
rl_display_prompt = "";
rl_forced_update_display();
}
#else
if (rl_end) {
if (write(1, "\r", 1) < 0) stop("");
rl_display_prompt = prompt;
rl_forced_update_display();
}
#endif
#endif
outcnt = 0;
#ifdef POSIX
fflush(NULL);
#endif
}
}
}
/*---------------------------------------------------------------------------*/
int main(argc, argv)
int argc;
char **argv;
{
char server[64];
char buffer[512];
char *sp;
#ifndef AX25
FILE *f;
int ch;
int channel = 0;
int errflag = 0;
char fname[512];
#endif
int addrlen;
struct sockaddr *addr;
#ifdef READLINE
char *line;
#endif
#ifdef AX25
strcpy(server, "unix:/tcp/.sockets/netcmd");
#else
sprintf(server, "%s:3600", CONVERSHOST);
#endif
time(&tt);
sp = strrchr(argv[0],'/');
if (sp) {
sp++;
} else {
sp = argv[0];
}
#ifndef AX25
strcpy(convtype, sp);
if (strstr(convtype, "kaconvers")) sprintf(server, "%s:6809", CONVERSHOST);
if (strstr(convtype, "lconvers")) sprintf(server, "%s:6810", CONVERSHOST);
if (strstr(convtype, "suconvers")) sprintf(server, "%s:6811", CONVERSHOST);
if (strstr(convtype, "wconvers")) sprintf(server, "%s:3610", CONVERSHOST);
#endif
signal(SIGPIPE, SIG_IGN);
if (tcgetattr(0, &prev_termios)) stop(convtype);
curr_termios = prev_termios;
echo = curr_termios.c_lflag & ECHO;
curr_termios.c_lflag = 0;
#ifndef READLINE
curr_termios.c_cc[VMIN] = 1;
curr_termios.c_cc[VTIME] = 0;
#else
screenwidth = 80;
#if defined (TIOCGWINSZ)
if (ioctl (0, TIOCGWINSZ, &window_size) == 0)
{
screenwidth = (int) window_size.ws_col;
}
#endif
curr_termios.c_lflag = curr_termios.c_lflag & ~ECHO;
rl_event_hook = (Function *) do_select_call;
#endif
if (tcsetattr(0, TCSANOW, &curr_termios)) stop(convtype);
#ifdef AX25
if (argc != 2) {
fprintf(stderr, "usage: ax25 call\n");
stop("");
}
#else
sp = NULL;
#ifdef SETLOGNAMES
#ifdef PCSP
while ((ch = getopt(argc, argv, "a:c:l:s:tor")) != EOF)
#else
while ((ch = getopt(argc, argv, "c:l:s:or")) != EOF)
#endif
#else
#ifdef PCSP
while ((ch = getopt(argc, argv, "a:c:s:tor")) != EOF)
#else
while ((ch = getopt(argc, argv, "c:s:or")) != EOF)
#endif
#endif
switch (ch) {
#ifdef PCSP
case 'a':
audiodir = optarg;
speak_load_samples(audiodir);
break;
#endif
case 'c':
channel = atoi(optarg);
break;
#ifdef SETLOGNAMES
case 'l':
sp = optarg;
break;
#endif
case 's':
strcpy(server, optarg);
break;
#ifdef PCSP
case 't':
do_talk = 1;
break;
#endif
case 'o':
observer = 1;
break;
case 'r':
restrict = 1;
break;
case '?':
errflag = 1;
break;
}
if (errflag || optind < argc) {
#ifdef SETLOGNAMES
#ifdef PCSP
fprintf(stderr, "usage: convers [-a audiodir] [-c channel] [-l callsign] [-s host:service] [-t]\n");
#else
fprintf(stderr, "usage: convers [-c channel] [-l callsign] [-s host:service]\n");
#endif
#else
#ifdef PCSP
fprintf(stderr, "usage: convers [-a audiodir] [-c channel] [-s host:service] [-t]\n");
#else
fprintf(stderr, "usage: convers [-c channel] [-s host:service]\n");
#endif
#endif
stop("");
}
#endif
if (!(addr = build_sockaddr(server, &addrlen))) {
stop("build_sockaddr()");
}
close(3);
if (socket(addr->sa_family, SOCK_STREAM, 0) != 3) stop("socket");
if (connect(3, addr, addrlen)) stop("connect");
#ifdef PCSP
if (do_talk) {
speak_fd = speak_open("/dev/audio",1);
}
#endif
#ifdef AX25
sprintf(buffer, "connect ax25 %s\n", argv[1]);
if (write(3, buffer, strlen(buffer)) < 0) stop("write(\"connect ax25\")");
#else
if (sp == NULL) {
sp = getlogin();
if (!sp) sp = getpwuid(getuid())->pw_name;
}
sprintf(buffer, "/%s %s %d\n", (observer) ? "OBSERVER" : (restrict) ? "RESTRICTED" : "NAME", sp, channel);
if (write(3, buffer, strlen(buffer)) < 0) stop(convtype);
/* read .conversrc */
sprintf(fname,"%s/.%src",getenv("HOME"),convtype);
if (!access(fname,R_OK)) {
f = fopen(fname,"r");
if (f != NULL) {
for (fgets(buffer,2048,f); !feof(f); fgets(buffer,2048,f)) {
if (write(3, buffer, strlen(buffer)) < 0) stop(convtype);
}
fclose(f);
}
}
#endif
for (; ; ) {
#ifdef READLINE
if (chars_avail) {
prompt[0] = '\0';
curr_termios.c_lflag = curr_termios.c_lflag | echo;
if (tcsetattr(0, TCSANOW, &curr_termios)) stop(convtype);
line = readline(prompt);
#if 0
signal(SIGALRM, SIG_IGN);
#endif
curr_termios.c_lflag = curr_termios.c_lflag & ~ECHO;
if (tcsetattr(0, TCSANOW, &curr_termios)) stop(convtype);
if (line) {
if (*line) {
add_history (line);
}
if (line[0] == '!') {
#ifndef NO_SHELL
if (line[1] != '!') {
if (tcsetattr(0, TCSANOW, &prev_termios)) stop(convtype);
system(line + 1);
if (tcsetattr(0, TCSANOW, &curr_termios)) stop(convtype);
} else {
if (write(3, line + 1, strlen(line) - 1) < 0) stop(convtype);
}
#endif
} else {
if (write(3, line, strlen(line)) < 0) stop(convtype);
}
chars_avail = 0;
if (write(3, "\n", 1) < 0) stop(convtype);
free (line);
}
rl_end = 0;
}
#endif
do_select_call();
}
}