From 0fceb64d25ff3d9586549bb43d971c5eef904330 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Jun 1999 10:23:42 +0200 Subject: Import ax25-apps 0.0.1 from tarball --- call/call.c | 1941 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1941 insertions(+) create mode 100644 call/call.c (limited to 'call/call.c') diff --git a/call/call.c b/call/call.c new file mode 100644 index 0000000..aed1aa5 --- /dev/null +++ b/call/call.c @@ -0,0 +1,1941 @@ +/* 03.04.1995 add binary download "#BIN#-Protocol" Alexander Tietzel */ +/* 01.05.1995 talkmode Alexander Tietzel (DG6XA) */ +/* 15.07.1995 Pull-Down-Menus Alexander Tietzel (DG6XA) */ +/* 17.07.1995 auto7+ newer #BIN#-Protocol Alexander Tietzel(DG6XA) */ +/* 18.07.1995 Remote commands Alexander Tietzel (DG6XA) */ +/* 19.07.1995 statusline Alexander Tietzel (DG6XA) */ +/* 25.07.1995 some bug-fixes Alexander Tietzel (DG6XA) */ +/* 14.08.1995 merged with mainstream call.c code Jonathan Naylor (G4KLX) */ +/* 01.03.1996 support for different screen sizes, fixed 7plus download (DL1BKE) + */ +/* 19.08.1996 fixed enter key handling (G4KLX) */ +/* 27.08.1996 added Rose support (G4KLX) */ +/* 30.11.1996 added the called user in the call windows and set talk mode as + default (IW0FBB) */ +/* 07.12.1996 updated status line to cope with callsign, bits and status + message (VK2KTJ) */ +/* 02.02.1997 removed NETROM_PACLEN setting to match Jonathon removing it + from kernel (VK2KTJ) */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "../pathnames.h" + +#include "call.h" +#include "crc.h" +#include "menu.h" + +#define CTRL_C 0x03 + +#define MAX_PACKETLEN 512 +#define MAX_BUFLEN 2*MAX_PACKETLEN +#define MAX_CMPSTRLEN MAX_PACKETLEN + +#define STD_DWN_DIR "/var/spool/ax25/" + +#define FLAG_RECONNECT 0x01 + +#define STATW_BITS 12 +#define STATW_STAT 20 + +static int backoff = -1; +static int ax25mode = -1; + +static int debug = FALSE; +static int af_mode = AF_AX25; +static int window = 0; +static char *port = NULL; + +int interrupted = FALSE; +int paclen = 0; +int fd; + +typedef struct { + char file_name[255]; + long dwn_cnt; + int dwn_file; + int file_crc; + int calc_crc; + struct utimbuf ut; + int new_header; +} t_gp; + +typedef struct { + WINDOW *ptr; + int max_y; + int max_x; + char string[MAX_BUFLEN]; + int bytes; + int curs_pos; +} t_win; + +#define TALKMODE 001 /* two windows (outgoing and incoming) with menu */ +#define SLAVEMODE 002 /* Menu mode */ +#define RAWMODE 004 /* mode used by earlier versions */ + +WINDOW *win; +const char *key_words[] = +{"//", + "#BIN#", + " go_7+. ", + " stop_7+. ", + "\0" +}; +#define MAXCMDLEN 10 + +void convert_cr_lf(char *buf, int len) +{ + while (len--) { + if (*buf == '\r') + *buf = '\n'; + buf++; + } +} + +void convert_lf_cr(char *buf, int len) +{ + while (len--) { + if (*buf == '\n') + *buf = '\r'; + buf++; + } +} + +void convert_upper_lower(char *buf, int len) +{ + while (len--) { + *buf = tolower(*buf); + buf++; + } +} + +static int nr_convert_call(char *address, struct full_sockaddr_ax25 *addr) +{ + char buffer[100], *call, *alias; + FILE *fp; + int addrlen; + + for (call = address; *call != '\0'; call++) + *call = toupper(*call); + + if ((fp = fopen(PROC_NR_NODES_FILE, "r")) == NULL) { + fprintf(stderr, "call: NET/ROM not included in the kernel\n"); + return -1; + } + fgets(buffer, 100, fp); + + while (fgets(buffer, 100, fp) != NULL) { + call = strtok(buffer, " \t\n\r"); + alias = strtok(NULL, " \t\n\r"); + + if (strcmp(address, call) == 0 || strcmp(address, alias) == 0) { + addrlen = ax25_aton(call, addr); + fclose(fp); + return (addrlen == -1) ? -1 : sizeof(struct sockaddr_ax25); + } + } + + fclose(fp); + + fprintf(stderr, "call: NET/ROM callsign or alias not found\n"); + + return -1; +} + +static int connect_to(char *address[]) +{ + int fd = 0; + int addrlen = 0; + union { + struct full_sockaddr_ax25 ax25; + struct sockaddr_rose rose; + } sockaddr; + char *digi; + int one = debug; + + switch (af_mode) { + case AF_ROSE: + if (address[0] == NULL || address[1] == NULL) { + fprintf(stderr, "call: too few arguments for Rose\n"); + return (-1); + } + if ((fd = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { + perror("socket"); + return (-1); + } + break; + + case AF_NETROM: + if (address[0] == NULL) { + fprintf(stderr, "call: too few arguments for NET/ROM\n"); + return (-1); + } + if ((fd = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) { + perror("socket"); + return (-1); + } + ax25_aton(nr_config_get_addr(port), &sockaddr.ax25); + sockaddr.ax25.fsa_ax25.sax25_family = AF_NETROM; + addrlen = sizeof(struct full_sockaddr_ax25); + break; + + case AF_AX25: + if (address[0] == NULL) { + fprintf(stderr, "call: too few arguments for AX.25\n"); + return (-1); + } + if ((fd = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { + perror("socket"); + return (-1); + } + ax25_aton(ax25_config_get_addr(port), &sockaddr.ax25); + sockaddr.ax25.fsa_ax25.sax25_family = AF_AX25; + addrlen = sizeof(struct full_sockaddr_ax25); + + if (setsockopt(fd, SOL_AX25, AX25_WINDOW, &window, sizeof(window)) == -1) { + perror("AX25_WINDOW"); + close(fd); + return (-1); + } + if (setsockopt(fd, SOL_AX25, AX25_PACLEN, &paclen, sizeof(paclen)) == -1) { + perror("AX25_PACLEN"); + close(fd); + return (-1); + } + if (backoff != -1) { + if (setsockopt(fd, SOL_AX25, AX25_BACKOFF, &backoff, sizeof(backoff)) == -1) { + perror("AX25_BACKOFF"); + close(fd); + return (-1); + } + } + if (ax25mode != -1) { + if (setsockopt(fd, SOL_AX25, AX25_EXTSEQ, &ax25mode, sizeof(ax25mode)) == -1) { + perror("AX25_EXTSEQ"); + close(fd); + return (-1); + } + } + break; + } + + if (debug && setsockopt(fd, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) == -1) { + perror("SO_DEBUG"); + close(fd); + return (-1); + } + if (af_mode != AF_ROSE) { /* Let Rose autobind */ + if (bind(fd, (struct sockaddr *) &sockaddr, addrlen) == -1) { + perror("bind"); + close(fd); + return (-1); + } + } + switch (af_mode) { + case AF_ROSE: + memset(&sockaddr.rose, 0x00, sizeof(struct sockaddr_rose)); + + if (ax25_aton_entry(address[0], sockaddr.rose.srose_call.ax25_call) == -1) { + close(fd); + return (-1); + } + if (rose_aton(address[1], sockaddr.rose.srose_addr.rose_addr) == -1) { + close(fd); + return (-1); + } + if (address[2] != NULL) { + digi = address[2]; + if (strcasecmp(address[2], "VIA") == 0) { + if (address[3] == NULL) { + fprintf(stderr, "call: callsign must follow 'via'\n"); + close(fd); + return (-1); + } + digi = address[3]; + } + if (ax25_aton_entry(digi, sockaddr.rose.srose_digi.ax25_call) == -1) { + close(fd); + return (-1); + } + sockaddr.rose.srose_ndigis = 1; + } + sockaddr.rose.srose_family = AF_ROSE; + addrlen = sizeof(struct sockaddr_rose); + break; + + case AF_NETROM: + if (nr_convert_call(address[0], &sockaddr.ax25) == -1) { + close(fd); + return (-1); + } + sockaddr.rose.srose_family = AF_NETROM; + addrlen = sizeof(struct sockaddr_ax25); + break; + + case AF_AX25: + if (ax25_aton_arglist(address, &sockaddr.ax25) == -1) { + close(fd); + return (-1); + } + sockaddr.rose.srose_family = AF_AX25; + addrlen = sizeof(struct full_sockaddr_ax25); + break; + } + + printf("Trying...\r"); + fflush(stdout); + + if (connect(fd, (struct sockaddr *) &sockaddr, addrlen)) { + printf("\n"); + perror("connect"); + close(fd); + return (-1); + } + printf("*** Connected to %s\n", address[0]); + + return (fd); +} + +void cmd_intr(int sig) +{ + signal(SIGQUIT, cmd_intr); + interrupted = TRUE; +} + +void statline(int mode, char *s) +{ + static int oldlen = 0; + int l, cnt; + + if (*s == '\0') { + if (mode == RAWMODE) + return; + if (oldlen > 0) { + move(0, STATW_STAT); + attron(A_REVERSE); + for (cnt = 0; cnt < oldlen; cnt++) + addch(' '); + oldlen = 0; + attroff(A_REVERSE); + refresh(); + } + return; + } + if (mode == RAWMODE) { + printf(">>%s\n", s); + return; + } + if (strlen(s) > 80 - STATW_STAT) + s[80 - STATW_STAT] = '\0'; + + move(0, STATW_STAT); + + attron(A_REVERSE); + addstr(s); + + if (oldlen > strlen(s)) { + l = oldlen - strlen(s); + for (cnt = 0; cnt < l; cnt++) + addch(' '); + } + attroff(A_REVERSE); + oldlen = strlen(s); + refresh(); +} + +WINDOW * + opnstatw(int mode, wint * wintab, char *s, int lines, int cols) +{ + WINDOW *win; + + if (mode == RAWMODE) { + printf(">>%s\n", s); + return NULL; + } + win = winopen(wintab, lines, cols, ((LINES - 1) - lines) / 2, ((COLS) - cols) / 2, TRUE); + mvwaddstr(win, 1, 1 + (cols - strlen(s)) / 2, s); + wmove(win, 3, 2); + + return win; +} + +void wrdstatw(WINDOW * win, char s[]) +{ + int y, x; + + if (win == NULL) { + printf(" %s\n", s); + return; + } + waddstr(win, s); + getyx(win, y, x); + wmove(win, y + 1, 2); + wrefresh(win); +} + +void dupdstatw(WINDOW * win, char *s, int add) +{ + static char infostr[80]; + static int y, x; + static oldlen; + int l, cnt; + + if (add) { + oldlen = 0; + strcpy(infostr, s); + + if (win == NULL) { + printf(" %s", s); + return; + } + waddstr(win, s); + getyx(win, y, x); + wrefresh(win); + + return; + } + if (win == NULL) { + printf("\r %s%s", infostr, s); + } else { + mvwaddstr(win, y, x, s); + } + + if (oldlen > strlen(s)) { + l = oldlen - strlen(s); + for (cnt = 0; cnt < l; cnt++) + if (win == NULL) + printf(" "); + else + waddch(win, ' '); + } + if (win == NULL) { + fflush(stdout); + } else { + wrefresh(win); + } + + oldlen = strlen(s); +} + +int start_ab_download(int mode, WINDOW ** swin, wint * wintab, char parms[], int parmsbytes, char buf[], int bytes, t_gp * gp, char *address[]) +{ + int crcst; /* startposition crc-field */ + int datest = 0; /* startposition date-field */ + int namest = 0; /* startposition name-field */ + int cnt; + int date = 0; + struct tm ft; + char s[80]; + + for (crcst = 2; (!(parms[crcst - 2] == '#' + && parms[crcst - 1] == '|') + && crcst < parmsbytes - 1); crcst++); + + if (crcst < parmsbytes - 1) { + gp->file_crc = atoi(parms + crcst); + + for (datest = crcst; (!(parms[datest - 2] == '#' + && parms[datest - 1] == '$')); datest++); + + date = (int) strtol(parms + datest, NULL, 16); + ft.tm_sec = (date & 0x1F) * 2; + date >>= 5; + ft.tm_min = date & 0x3F; + date >>= 6; + ft.tm_hour = date & 0x1F; + date >>= 5; + ft.tm_mday = date & 0x1F; + date >>= 5; + ft.tm_mon = date & 0x0F; + date >>= 4; + ft.tm_year = (date & 0x7F) + 70; + ft.tm_isdst = 0; + ft.tm_yday = 0; + ft.tm_wday = 0; + gp->ut.actime = mktime(&ft); + gp->ut.modtime = gp->ut.actime; + + for (namest = datest; (parms[namest - 1] != '#' && + namest < parmsbytes - 1); namest++); + } else { + gp->ut.actime = 0; + gp->ut.modtime = 0; + } + + gp->dwn_cnt = atol(parms); + strcpy(gp->file_name, STD_DWN_DIR); + + if (crcst == parmsbytes - 1 || datest - crcst > 7 || namest - datest > 10) { + *swin = opnstatw(mode, wintab, "Remote starts AutoBin transfer", 6, 52); + gp->new_header = FALSE; + wrdstatw(*swin, "old styled Header (no filename)"); + strcat(gp->file_name, address[0]); + strcat(gp->file_name, ".dwnfile"); + } else { + *swin = opnstatw(mode, wintab, "Remote starts AutoBin transfer", 10, 52); + gp->new_header = TRUE; + for (cnt = parmsbytes - namest; !(parms[cnt + namest - 1] == '\\' || parms[cnt + namest - 1] == '/') && cnt > 0; cnt--); + strncpy(s, &parms[namest + cnt], parmsbytes - namest - cnt); + convert_upper_lower(s, parmsbytes - namest - cnt); + strncat(gp->file_name, s, parmsbytes - namest - cnt); + gp->file_name[strlen(gp->file_name) + parmsbytes - namest - cnt - 1] = 0; + + sprintf(s, "size of file : %u", (unsigned int) gp->dwn_cnt); + wrdstatw(*swin, s); + sprintf(s, "filename : %s", gp->file_name); + wrdstatw(*swin, s); + sprintf(s, "last mod. date : %02i.%02i.%04i", ft.tm_mday, ft.tm_mon, ft.tm_year + 1900); + wrdstatw(*swin, s); + sprintf(s, "last mod. time : %02i:%02i:%02i", ft.tm_hour, ft.tm_min, ft.tm_sec); + wrdstatw(*swin, s); + } + + dupdstatw(*swin, "Bytes to receive: ", TRUE); + + if ((gp->dwn_file = open(gp->file_name, O_RDWR | O_CREAT, 0666)) == -1) { + sprintf(s, "Unable to open %s", gp->file_name); + statline(mode, s); + if (write(fd, "#ABORT#\r", 8) == -1) { + perror("write"); + gp->dwn_cnt = 0; + gp->file_name[0] = '\0'; + return -1; + } + } + if (bytes == 1) { + if (write(fd, "#OK#\r", 5) == -1) { + perror("write"); + gp->dwn_cnt = 0; + gp->file_name[0] = '\0'; + return -1; + } + gp->calc_crc = 0; + } else { + write(gp->dwn_file, buf, bytes); + gp->calc_crc = calc_crc(buf, bytes, 0); + gp->dwn_cnt -= bytes; + } + + return 0; +} + +int ab_down(int mode, WINDOW * swin, wint * wintab, char buf[], int *bytes, t_gp * gp) +{ + int extrach = 0; + char s[80]; + + if (strncmp(buf, "#ABORT#\r", 8) == 0 && *bytes == 8) { + gp->dwn_cnt = 0; + close(gp->dwn_file); + statline(mode, "Remote aborts AutoBin transfer!"); + *bytes = 0; + if (mode != RAWMODE) { + delwin(swin); + winclose(wintab); + } else { + printf("\n"); + } + + return 0; + } + if (gp->dwn_cnt < *bytes) { + extrach = *bytes - gp->dwn_cnt; + *bytes = gp->dwn_cnt; + } + if (write(gp->dwn_file, buf, *bytes) != *bytes) { + close(gp->dwn_file); + gp->dwn_cnt = 0; + statline(mode, "Error while writing download file. Download aborted."); + + if (mode != RAWMODE) { + delwin(swin); + winclose(wintab); + } else { + printf("\n"); + } + } else { + gp->calc_crc = calc_crc(buf, *bytes, gp->calc_crc); + gp->dwn_cnt -= *bytes; + + if (gp->dwn_cnt == 0) { + if (mode != RAWMODE) { + delwin(swin); + winclose(wintab); + } else + printf("\n"); + + strcpy(s, "AutoBin download finished "); + if (gp->new_header) + if (gp->calc_crc == gp->file_crc) + strcat(s, "CRC check ok"); + else { + strcat(s, "CRC check failed!"); + } else { + sprintf(s + strlen(s), "CRC=%u", gp->calc_crc); + } + statline(mode, s); + close(gp->dwn_file); + utime(gp->file_name, &gp->ut); + if (extrach != 0) { + memmove(buf, buf + *bytes, extrach); + *bytes = extrach; + } else + *bytes = 0; + } else { + sprintf(s, "%u", (unsigned int) gp->dwn_cnt); + dupdstatw(swin, s, FALSE); + *bytes = 0; + } + } + return 0; +} + +int start_screen(char *call[]) +{ + int cnt; + char idString[11]; + sprintf(idString, " %8s ", call[0]); + + if ((win = initscr()) == NULL) + return -1; + + attron(A_REVERSE); + move(0, 0); + addstr(idString); + addch(ACS_VLINE); + addstr("--------"); + addch(ACS_VLINE); + for (cnt = STATW_STAT; cnt <= 80; cnt++) + addch(' '); + attroff(A_REVERSE); + + noecho(); + raw(); + nodelay(win, TRUE); + keypad(win, TRUE); + refresh(); + + return 0; +} + +int start_slave_mode(wint * wintab, t_win * win_in, t_win * win_out) +{ + win_in->max_y = LINES - 2; + win_in->max_x = COLS; + win_in->ptr = winopen(wintab, win_in->max_y + 1, win_in->max_x, 1, 0, FALSE); + win_out->ptr = win_in->ptr; + + scrollok(win_in->ptr, TRUE); + + wclear(win_out->ptr); + wrefresh(win_out->ptr); + + win_out->bytes = 0; + win_out->curs_pos = 0; + win_in->bytes = 0; + win_in->curs_pos = 0; + + return 0; +} + +int start_talk_mode(wint * wintab, t_win * win_in, t_win * win_out) +{ + int cnt; + WINDOW *win; + + win_out->max_y = 4; /* TXLINES */ + win_out->max_x = COLS; + win_in->max_y = (LINES - 4) - win_out->max_y; + win_in->max_x = COLS; + + win_out->ptr = winopen(wintab, win_out->max_y + 1, win_out->max_x, (win_in->max_y + 3), 0, FALSE); + win_in->ptr = winopen(wintab, win_in->max_y + 1, win_in->max_x, 1, 0, FALSE); + win = winopen(wintab, 1, win_out->max_x, win_in->max_y + 2, 0, FALSE); + + for (cnt = 0; cnt < COLS; cnt++) + waddch(win, '-'); + wrefresh(win); + + scrollok(win_in->ptr, TRUE); + scrollok(win_out->ptr, TRUE); + + wclear(win_out->ptr); + wrefresh(win_out->ptr); + wclear(win_in->ptr); + wrefresh(win_in->ptr); + + win_out->bytes = 0; + win_out->curs_pos = 0; + win_in->bytes = 0; + win_out->curs_pos = 0; + + return 0; +} + +int change_mode(int oldmode, int newmode, wint * wintab, t_win * win_in, t_win * win_out, char *call[]) +{ + switch (oldmode) { + case RAWMODE: + if (newmode == TALKMODE) { + start_screen(call); + start_talk_mode(wintab, win_in, win_out); + } + if (newmode == SLAVEMODE) { + start_screen(call); + start_slave_mode(wintab, win_in, win_out); + } + break; + + case TALKMODE: + if (newmode == RAWMODE) { + wclear(win_out->ptr); + wrefresh(win_out->ptr); + wclear(win_in->ptr); + wrefresh(win_in->ptr); + wintab->next = 0; + endwin(); + } + if (newmode == SLAVEMODE) { + delwin(win_out->ptr); + delwin(win_in->ptr); + wintab->next = 0; + start_slave_mode(wintab, win_in, win_out); + } + break; + + case SLAVEMODE: + if (newmode == RAWMODE) { + wclear(win_out->ptr); + wrefresh(win_out->ptr); + wintab->next = 0; + endwin(); + } + if (newmode == TALKMODE) { + delwin(win_out->ptr); + wintab->next = 0; + start_talk_mode(wintab, win_in, win_out); + } + break; + } + + return newmode; +} + +void writeincom(int mode, t_win * win_in, unsigned char buf[], int bytes) +{ + int cnt; + + if (mode & RAWMODE) { + write(STDOUT_FILENO, buf, bytes); + return; + } + for (cnt = 0; cnt < bytes; cnt++) { + switch (buf[cnt]) { + case 201: + case 218: + waddch(win_in->ptr, ACS_ULCORNER); + break; + case 187: + case 191: + waddch(win_in->ptr, ACS_URCORNER); + break; + case 200: + case 192: + waddch(win_in->ptr, ACS_LLCORNER); + break; + case 188: + case 217: + waddch(win_in->ptr, ACS_LRCORNER); + break; + case 204: + case 195: + waddch(win_in->ptr, ACS_LTEE); + break; + case 185: + case 180: + waddch(win_in->ptr, ACS_RTEE); + break; + case 203: + case 194: + waddch(win_in->ptr, ACS_TTEE); + break; + case 202: + case 193: + waddch(win_in->ptr, ACS_BTEE); + break; + case 205: + case 196: + waddch(win_in->ptr, ACS_HLINE); + break; + case 186: + case 179: + waddch(win_in->ptr, ACS_VLINE); + break; + case 129: + waddch(win_in->ptr, 252); /*u umlaut */ + break; + case 132: + waddch(win_in->ptr, 228); /*a umlaut */ + break; + case 142: + waddch(win_in->ptr, 196); /*A umlaut */ + break; + case 148: + waddch(win_in->ptr, 246); /*o umlaut */ + break; + case 153: + waddch(win_in->ptr, 214); /*O umlaut */ + break; + case 154: + waddch(win_in->ptr, 220); /*U umlaut */ + break; + case 225: + waddch(win_in->ptr, 223); /*sz */ + break; + default: + { + if (buf[cnt] > 127) + waddch(win_in->ptr, '.'); + else + waddch(win_in->ptr, buf[cnt]); + } + } + } + +/* waddnstr(win_in->ptr, buf, bytes); */ + wrefresh(win_in->ptr); + + return; +} + +int getstring(wint * wintab, char text[], char buf[]) +{ + int c; + int ypos = 0, xpos = 0; + int bytes = 0; + + WINDOW *win = winopen(wintab, 3, COLS, 10, 0, TRUE); + + wmove(win, 1, 2); + waddstr(win, text); + wrefresh(win); + + do { + c = getch(); + if (c != ERR) { + switch (c) { + case KEY_BACKSPACE: + case 127: + { + getyx(win, ypos, xpos); + if (xpos > 0 && bytes > 0) { + wmove(win, ypos, --xpos); + waddch(win, ' '); + wmove(win, ypos, xpos); + bytes--; + } + } + break; + case (int) '\n': + case (int) '\r': + case KEY_ENTER: + { + waddch(win, '\n'); + buf[bytes++] = (char) '\n'; + wrefresh(win); + buf[bytes] = 0; + } + break; + default: + { + waddch(win, (char) c); + buf[bytes++] = (char) c; + } + } + wrefresh(win); + } + } + while (c != '\n' && c != '\r' && c != KEY_ENTER); + delwin(win); + winclose(wintab); + return 0; +} + +int readoutg(t_win * win_out, wint * wintab, menuitem * top, char buf[], int keyesc) +{ + int out_cnt; + int c; + int ypos = 0, xpos = 0; + int value; + + c = getch(); + if (c == ERR) + return 0; + + if (c == keyesc) { + if ((value = top_menu(wintab, top, 1)) == 0) + return 0; + buf[0] = '~'; + switch (value) { + case 0x01: + { + buf[1] = 'r'; + return 2; + } + case 0x02: + { + buf[1] = '.'; + return 2; + } + case 0x11: + { + buf[1] = 'o'; + getstring(wintab, "Please enter filename: ", &buf[2]); + return strlen(buf); + } + case 0x12: + { + buf[1] = 'c'; + return 2; + } + case 0x13: + case 0x14: + case 0x15: + { + switch (value) { + case 0x13: + buf[1] = 'u'; + break; + case 0x14: + buf[1] = 'b'; + break; + case 0x15: + buf[1] = 'a'; + } + getstring(wintab, "Please enter filename: ", buf + 2); + return strlen(buf); + } + case 0x21: + { + buf[1] = '1'; + return 2; + } + case 0x22: + { + buf[1] = '2'; + return 2; + } + case 0x23: + { + buf[1] = '0'; + return 2; + } + case 0x31: + return -1; + } + wrefresh(win_out->ptr); + return 2; + } + switch (c) { + case KEY_BACKSPACE: + case 127: + { + getyx(win_out->ptr, ypos, xpos); + if (win_out->bytes > 0) { + if (win_out->curs_pos < win_out->bytes) { + mvwaddnstr(win_out->ptr, ypos, --xpos, &win_out->string[win_out->curs_pos], win_out->bytes - win_out->curs_pos); + waddch(win_out->ptr, ' '); + memmove(&win_out->string[win_out->curs_pos - 1], &win_out->string[win_out->curs_pos], win_out->bytes - win_out->curs_pos); + } else + mvwaddch(win_out->ptr, ypos, --xpos, ' '); + + wmove(win_out->ptr, ypos, xpos); + win_out->bytes--; + win_out->curs_pos--; + } + } + break; + case KEY_LEFT: + if (win_out->curs_pos > 0) { + win_out->curs_pos--; + getyx(win_out->ptr, ypos, xpos); + wmove(win_out->ptr, ypos, xpos - 1); + } + break; + case KEY_RIGHT: + if (win_out->curs_pos < win_out->bytes) { + win_out->curs_pos++; + getyx(win_out->ptr, ypos, xpos); + wmove(win_out->ptr, ypos, xpos + 1); + } + break; + case KEY_ENTER: + case (int) '\n': + case (int) '\r': + { + if (win_out->curs_pos < win_out->bytes) { + getyx(win_out->ptr, ypos, xpos); + wmove(win_out->ptr, ypos, xpos + win_out->bytes - win_out->curs_pos); + } + waddch(win_out->ptr, '\n'); + win_out->string[win_out->bytes++] = (char) '\n'; + wrefresh(win_out->ptr); + strncpy(buf, win_out->string, win_out->bytes); + wrefresh(win_out->ptr); + out_cnt = win_out->bytes; + win_out->bytes = 0; + win_out->curs_pos = 0; + return out_cnt; + } + break; + default: + { + waddch(win_out->ptr, (char) c); + if (win_out->curs_pos < win_out->bytes) { + getyx(win_out->ptr, ypos, xpos); + waddnstr(win_out->ptr, &win_out->string[win_out->curs_pos], win_out->bytes - win_out->curs_pos); + memmove(&win_out->string[win_out->curs_pos + 1], &win_out->string[win_out->curs_pos], win_out->bytes - win_out->curs_pos); + win_out->string[win_out->curs_pos] = (char) c; + wmove(win_out->ptr, ypos, xpos); + } else + win_out->string[win_out->bytes] = (char) c; + + win_out->bytes++; + win_out->curs_pos++; + } + } + wrefresh(win_out->ptr); + return 0; +} +void writemsg(char fname[], char caller[]) +{ + char text_row[255]; + char *text_ptr; + char buf[255]; + FILE *f = fopen(fname, "r"); + + if (f == NULL) { + perror(fname); + return; + } + do { + if (fgets(text_row, 255, f) != 0) { + text_row[strlen(text_row) - 1] = '\r'; + text_ptr = strchr(text_row, '$'); + if (text_ptr != NULL) { + strcpy(buf, text_ptr + 2); + switch (*(text_ptr + 1)) { + case 'c': + { + strcpy(text_ptr, caller); + strcat(text_ptr, buf); + } + } + } + write(fd, text_row, strlen(text_row)); + } + } + while (!feof(f)); +} + +void remotecommand(char buf[], int bytes) +{ + int firstchar; + if (bytes == 0) + return; + + switch (buf[0]) { + case 'e': + case 'E': + { + for (firstchar = 0; buf[firstchar] != ' '; firstchar++); + firstchar++; + buf[bytes] = '\n'; + convert_lf_cr(buf + firstchar, bytes - firstchar + 1); + write(fd, buf + firstchar, bytes - firstchar + 1); + } + break; + default: + write(fd, "Unknown command\r", 16); + } +} + +int compstr(const char st1[], char st2[], int maxbytes) +{ + int cnt; + for (cnt = 0; st1[cnt] == st2[cnt] && cnt + 1 < maxbytes && st1[cnt + 1] != 0; cnt++); + if (st1[cnt] != st2[cnt]) + return -1; + + if (st1[cnt + 1] == 0) + return 0; + if (cnt == maxbytes - 1) + return -2; + + return -1; +} + +int eol(char c) +{ + + if (c == '\r' || c == '\n' || c == 0x1A) + return TRUE; + else + return FALSE; +} + +int searche_key_words(char buf[], int *bytes, char *parms, int *parmsbytes, char restbuf[], int *restbytes) +{ + static char cmpstr[MAX_CMPSTRLEN]; + static int cmpstrbyte = 0; + static int command = -1; + + int cmdstpos = 0; + int cnt = 0; + int t = 0; + + if (cmpstrbyte != 0) { + memmove(buf + cmpstrbyte, buf, *bytes); + *bytes += cmpstrbyte; + strncpy(buf, cmpstr, cmpstrbyte); + cmpstrbyte = 0; + for (cnt = 0; !eol(buf[cnt]) && cnt < *bytes - 1; cnt++); + if (cnt == *bytes - 1 && !eol(buf[cnt])) { + printf("Problem!!!\n"); + command = -1; + *restbytes = 0; + *parmsbytes = 0; + return -1; + } + } + if (command == -1) { + cnt = 0; + do { + command = 0; + cmdstpos = cnt; + + do { + if ((t = compstr(key_words[command], &buf[cnt], *bytes - cnt)) != -1) + break; + } + while (*key_words[++command] != '\0'); + + for (; !eol(buf[cnt]) && cnt < *bytes - 1; cnt++); + + if (cnt < *bytes - 1) + cnt++; + else + break; + } + while (t == -1); + if (t < 0) + command = -1; + } + if (t == -2 || (command != -1 && cnt == *bytes - 1 && !eol(buf[*bytes - 1]))) { + cmpstrbyte = *bytes - cmdstpos; + strncpy(cmpstr, &buf[cmdstpos], cmpstrbyte); + cmpstr[cmpstrbyte] = 0; + *bytes -= cmpstrbyte; + *restbytes = 0; + return -1; + } + if (t == -1) { + command = -1; + cmpstrbyte = 0; + *restbytes = 0; + return -1; + } + t = cmdstpos + strlen(key_words[command]); + *restbytes = *bytes - cnt; + strncpy(parms, &buf[t], cnt - t); + *parmsbytes = cnt - t; + strncpy(restbuf, buf + cnt, *restbytes); + *bytes = cmdstpos; + + t = command; + command = -1; + return t; +} + +int sevenplname(int mode, WINDOW ** swin, wint * wintab, int *f, int* logfile, char parms[], int parmsbytes, char buf[], int bytes) +{ + int cnt; + int part; + int nrparts; + int lines; + char orgn[13]; + char prtn[13]; + char strn[255]; + char v[20]; + char s[80]; + if (parmsbytes >= 40) + if (strcmp(" of ", &parms[3]) == 0 + || parmsbytes < 41 + || parms[10] != ' ' + || parms[23] != ' ' + || parms[31] != ' ' + || parms[36] != ' ' + || parms[40] != ' ') { + return -1; + } + part = atof(parms); + lines = (int) strtol(parms + 37, NULL, 16); + nrparts = (int) strtol(parms + 7, NULL, 10); + + strncpy(orgn, &parms[11], 12); + convert_upper_lower(orgn, 12); + for (cnt = 11; orgn[cnt] == ' '; cnt--); + orgn[cnt + 1] = 0; + if (orgn[cnt - 3] == '.') { + strncpy(prtn, orgn, cnt - 2); + if (nrparts == 1) + sprintf(prtn + cnt - 2, "7pl"); + else + sprintf(prtn + cnt - 2, "p%02x", part); + } else { + strcpy(prtn, orgn); + if (nrparts == 1) + sprintf(prtn + cnt, ".7pl"); + else + sprintf(prtn + cnt, ".p%02x", part); + } + + strcpy(strn, STD_DWN_DIR); + strcat(strn, prtn); + + for (cnt = 0; parms[cnt + 41] != ')' && cnt + 41 != parmsbytes; cnt++); + if (parms[cnt + 41] != ')') { + return -1; + } + strncpy(v, &parms[41], cnt + 1); + v[cnt + 1] = 0; + *swin = opnstatw(mode, wintab, "Remote starts 7+ Download", 11, 55); + sprintf(s, "7plus version : %s", v); + wrdstatw(*swin, s); + sprintf(s, "Name of decoded file : %s", orgn); + wrdstatw(*swin, s); + sprintf(s, "Storagename : %s", strn); + wrdstatw(*swin, s); + sprintf(s, "Parts : %i", nrparts); + wrdstatw(*swin, s); + sprintf(s, "Number of this Part : %i", part); + wrdstatw(*swin, s); + sprintf(s, "Lines : %i", lines); + wrdstatw(*swin, s); + dupdstatw(*swin, "Outstanding lines : ", TRUE); + + if (*f != -1) { + close(*f); + } + if ((*f = open(strn, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) { + sprintf(s, "Unable to open %s", strn); + statline(mode, s); + } + else + if (*logfile != -1) + { + sprintf(s, "*** 7plus download into file: %s ***\n", strn); + write(*logfile, s, strlen(s)); + } + + write(*f, key_words[2], strlen(key_words[2])); + convert_cr_lf(parms, parmsbytes); + write(*f, parms, parmsbytes); + + return lines; +} +void statbits(int mode, char stat, int m) +{ + if (mode == RAWMODE) + return; + move(0, STATW_BITS + m); + attron(A_REVERSE); + addch(stat); + attroff(A_REVERSE); + refresh(); + return; +} + + +int cmd_call(char *call[], int mode) +{ + menuitem con[] = + { + {"~Reconnect", 'R', M_ITEM, (void *) 0x01}, + {"~Exit", 'E', M_ITEM, (void *) 0x02}, + {"\0", 0, M_END, 0} + }; + + menuitem fil[] = + { + {"~Open Logfile", 'O', M_ITEM, 0}, + {"~Close Logfile", 'C', M_ITEM, 0}, + {"Send ~Textfile", 'T', M_ITEM, 0}, + {"Send ~Binary", 'B', M_ITEM, 0}, + {"Send ~AutoBin", 'A', M_ITEM, 0}, + {"\0", 0, M_END, 0} + }; + + menuitem mod[] = + { + {"~Slavemode", 'S', M_ITEM, 0}, + {"~Talkmode", 'T', M_ITEM, 0}, + {"~Rawmode", 'R', M_ITEM, 0}, + {"\0", 0, M_END, 0} + }; + + menuitem win[] = + { + {"~Clear", 'C', M_ITEM, 0}, + {"~Resize", 'R', M_ITEM, 0}, + {"\0", 0, M_END, 0} + }; + + menuitem top[] = + { + {"~Connect", 'C', M_P_DWN, con}, + {"~File", 'F', M_P_DWN, fil}, + {"~Mode", 'M', M_P_DWN, mod}, + {"~Window", 'W', M_P_DWN, win}, + {"\0", 0, M_END, 0} + }; + + wint wintab; + fd_set sock_read; + fd_set sock_write; + char buf[MAX_BUFLEN]; + char restbuf[MAX_PACKETLEN]; + char parms[256]; + int sevenplus = FALSE; + int sevenplcnt = 0; + int bytes; + int restbytes; + int parmsbytes; + int com_num; + int logfile = -1; + int uploadfile = -1; + int downloadfile = -1; + int binup = FALSE; + long uplsize = 0; + long uplpos = 0; + char uplbuf[128]; /* Upload buffer */ + int upldp = 0; + int upllen = 0; + char *c, *t; + int extrach = 0; + t_gp gp; + t_win win_in; + t_win win_out; + WINDOW *swin = 0; + int cnt; + int crc = 0; + char s[80]; + int flags = 0; + + init_crc(); + + gp.dwn_cnt = 0; + wintab.next = 0; + + if ((fd = connect_to(call)) == -1) + return FALSE; + + interrupted = FALSE; + signal(SIGQUIT, cmd_intr); + signal(SIGINT, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + + fcntl(fd, F_SETFL, O_NONBLOCK); + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + + if (mode != RAWMODE) + start_screen(call); + switch (mode) { + case TALKMODE: + start_talk_mode(&wintab, &win_in, &win_out); + break; + case SLAVEMODE: + start_slave_mode(&wintab, &win_in, &win_out); + break; + case RAWMODE: + printf("Rawmode\n"); + } + + while (TRUE) { + FD_ZERO(&sock_read); + FD_SET(STDIN_FILENO, &sock_read); + FD_SET(fd, &sock_read); + FD_ZERO(&sock_write); + + if (uploadfile != -1) + FD_SET(fd, &sock_write); + + if (select(fd + 1, &sock_read, &sock_write, NULL, NULL) == -1) { + if (!interrupted && errno == EAGAIN) + continue; + if (!interrupted) + perror("select"); + break; + } + if (FD_ISSET(fd, &sock_read)) { + bytes = read(fd, buf, 511); + if (bytes == -1 && errno != EWOULDBLOCK && errno != EAGAIN) { + if (errno != ENOTCONN) + perror("read"); + break; + } + if (gp.dwn_cnt != 0) { + ab_down(mode, swin, &wintab, buf, &bytes, &gp); + if (bytes == 0) + continue; + } + do { + com_num = searche_key_words(buf, &bytes, parms, &parmsbytes, restbuf, &restbytes); + + if (bytes != 0) { + convert_cr_lf(buf, bytes); + if (!sevenplus) { + + writeincom(mode, &win_in, buf, bytes); + } else { + for (cnt = 0; cnt < bytes; cnt++) + if (eol(buf[cnt])) + sevenplcnt--; + dupdstatw(swin, s, FALSE); + } + if (downloadfile != -1) + { + if (write(downloadfile, buf, bytes) != bytes) + { + close(downloadfile); + downloadfile = -1; + statline(mode, "Error while writing file. Downloadfile closed."); + } + } + else + if (logfile != -1) { + if (write(logfile, buf, bytes) != bytes) { + close(logfile); + logfile = -1; + statline(mode, "Error while writing log. Log closed."); + } + } + } + switch (com_num) { + case 0: + { +#ifdef 0 /* FIXME! We should, no: WE MUST be able to turn off */ + /* all remote commands to avoid mail bombs generating */ + /* offensive mails with //e while sucking the BBS */ + + remotecommand(parms, parmsbytes); +#endif + } + break; + case 1: + { + start_ab_download(mode, &swin, &wintab, parms, parmsbytes, restbuf, restbytes, &gp, call); + restbytes = 0; + extrach = 0; + } + break; + case 2: + { + if ((sevenplcnt = sevenplname(mode, &swin, &wintab, &downloadfile, &logfile, parms, parmsbytes, buf, bytes)) != -1) + sevenplus = TRUE; + } + break; + case 3: + { + if (!sevenplus) + break; + write(downloadfile, key_words[3], strlen(key_words[3])); + convert_cr_lf(parms, parmsbytes); + write(downloadfile, parms, parmsbytes); + if (mode != RAWMODE) { + delwin(swin); + winclose(&wintab); + } else + printf("\n"); + statline(mode, "7+ Download finished."); + sevenplus = FALSE; + close(downloadfile); + downloadfile = -1; + } + break; + } + + strncpy(buf, restbuf, restbytes); + bytes = restbytes; + } + while (restbytes != 0); + } + if (FD_ISSET(STDIN_FILENO, &sock_read)) { + if ((mode & RAWMODE) == RAWMODE) + bytes = read(STDIN_FILENO, buf, 511); + else { + bytes = readoutg(&win_out, &wintab, top, buf, 0x1d); + if (bytes == -1) { + wclear(win_in.ptr); + wrefresh(win_in.ptr); + wclear(win_out.ptr); + wrefresh(win_out.ptr); + bytes = 0; + } + } + if (bytes > 0) + statline(mode, ""); + + if (bytes > 1 && *buf == '~') { + buf[bytes] = 0; + + switch (buf[1]) { + case '.': + { + bytes = 0; + interrupted = TRUE; + } + break; + case '!': + change_mode(mode, RAWMODE, &wintab, &win_in, &win_out, call); + if (buf[2] != '\0' && buf[2] != '\n') { + c = buf + 2; + if ((t = strchr(c, '\n')) != NULL) + *t = '\0'; + } else { + if ((c = getenv("SHELL")) == NULL) + c = "/bin/sh"; + } + + fcntl(STDIN_FILENO, F_SETFL, 0); + printf("\n[Spawning subshell]\n"); + system(c); + printf("\n[Returned to connect]\n"); + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + change_mode(RAWMODE, mode, &wintab, &win_in, &win_out, call); + continue; + case 'z': + case 'Z': + case 'Z' - 64: + fcntl(STDIN_FILENO, F_SETFL, 0); + kill(getpid(), SIGSTOP); + statline(mode, "Resumed"); + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + continue; + case '?': + case 'h': + case 'H': + printf("\n\rTilde escapes:\n\r. close\n\r! shell\n\rZ suspend\n\rs Stop upload\n\ro Open log\n\rc Close log\n\ru Upload\n\ryd YAPP Download\n\ryu YAPP Upload\n\r"); + continue; + case 'S': + case 's': + if (uploadfile != -1) { + statline(mode, "Upload file closed"); + close(uploadfile); + uploadfile = -1; + } else { + statline(mode, "No upload in progress"); + } + continue; + case 'A': + case 'a': + case 'b': + case 'B': + case 'u': + case 'U': + if (uploadfile != -1) { + statline(mode, "Already uploading"); + continue; + } + if ((t = strchr(buf, '\n')) != NULL) + *t = '\0'; + t = buf + 2; + while (*t != '\0' && isspace(*t)) + t++; + if (*t == '\0') { + statline(mode, "Upload requires a filename"); + continue; + } + uploadfile = open(t, O_RDONLY); + if (uploadfile == -1) { + statline(mode, "Unable to open upload file"); + continue; + } + if (lseek(uploadfile, 0L, SEEK_END) != -1) + uplsize = lseek(uploadfile, 0L, SEEK_CUR); + else + uplsize = 0; + lseek(uploadfile, 0L, SEEK_SET); + uplpos = 0; + upldp = -1; + upllen = 0; + if (uplsize != -1) { + sprintf(s, "Uploading %ld bytes from %s", uplsize, t); + swin = opnstatw(mode, &wintab, s, 6, 50); + dupdstatw(swin, "bytes sent : ", TRUE); + } else { + sprintf(s, "Uploading from %s", t); + swin = opnstatw(mode, &wintab, s, 6, 50); + dupdstatw(swin, "bytes sent : ", TRUE); + } + switch (buf[1]) { + case 'a': + case 'A': + { + binup = TRUE; + crc = 0; + + do { + upllen = read(uploadfile, uplbuf, 128); + + if (upllen == -1) { + close(uploadfile); + uploadfile = -1; + delwin(swin); + winclose(&wintab); + sprintf(s, "Error reading upload file: upload aborted"); + statline(mode, s); + break; + } + crc = calc_crc(uplbuf, upllen, crc); + } + while (upllen > 0); + lseek(uploadfile, 0L, SEEK_SET); + sprintf(s, "#BIN#%ld#$%u#|000000#%s\r", uplsize, crc, t); + write(fd, s, strlen(s)); + uplpos = 0; + upldp = -1; + upllen = 0; + } + break; + case 'b': + case 'B': + binup = TRUE; + break; + case 'u': + case 'U': + binup = FALSE; + } + continue; + case 'O': + case 'o': + if ((t = strchr(buf, '\n')) != NULL) + *t = '\0'; + if (logfile != -1) { + close(logfile); + logfile = -1; + } + if (downloadfile != -1) + { + close(downloadfile); + downloadfile = -1; + } + t = buf + 2; + while (*t != '\0' && isspace(*t)) + t++; + if (*t == '\0') + t = "logfile.txt"; + if ((logfile = open(t, O_RDWR | O_APPEND | O_CREAT, 0666)) == -1) { + sprintf(s, "Unable to open %s", buf + 2); + statline(mode, s); + } else + statbits(mode, 'L', 1); + continue; + case 'C': + case 'c': + if (logfile != -1) { + close(logfile); + logfile = -1; + statbits(mode, '-', 1); + } else { + statline(mode, "Log file not open"); + } + continue; + case 'Y': + case 'y': + cmd_yapp(buf + 2, bytes - 2); + continue; + case '~': + bytes--; + memmove(buf, buf + 1, strlen(buf)); + break; + case 'R': + case 'r': + flags |= FLAG_RECONNECT; + bytes = 0; + interrupted = TRUE; + continue; + case '0': + mode = change_mode(mode, RAWMODE, &wintab, &win_in, &win_out, call); + continue; + case '1': + mode = change_mode(mode, SLAVEMODE, &wintab, &win_in, &win_out, call); + continue; + case '2': + mode = change_mode(mode, TALKMODE, &wintab, &win_in, &win_out, call); + continue; + default: + statline(mode, "Unknown '~' escape. Type ~h for a list"); + continue; + } + } + /* if (bytes == -1 && errno != EWOULDBLOCK && errno != EAGAIN) */ + /* if ((bytes == 0 && (mode & (TALKMODE|SLAVEMODE)) == 0) || (bytes == -1 && errno != EWOULDBLOCK && errno != EAGAIN)) */ + if (interrupted || (bytes == -1 && errno != EWOULDBLOCK && errno != EAGAIN)) { + if (!interrupted) + perror("input"); + break; + } + if (bytes > 0) { + sevenplus = FALSE; + if (uploadfile != -1) { + statline(mode, "Ignored. Type ~s to stop upload"); + continue; + } + convert_lf_cr(buf, bytes); + + if (write(fd, buf, bytes) == -1) { + perror("write"); + break; + } + } + if (uploadfile != -1) { + if (uplsize == 0) { + close(uploadfile); + uploadfile = -1; + delwin(swin); + winclose(&wintab); + statline(mode, "Upload complete: 0 bytes"); + continue; + } + if (upldp == -1) { + upllen = read(uploadfile, uplbuf, 128); + + if (upllen == 0) { + close(uploadfile); + uploadfile = -1; + delwin(swin); + winclose(&wintab); + sprintf(s, "Upload complete: %ld bytes", uplpos); + statline(mode, s); + continue; + } + if (upllen == -1) { + close(uploadfile); + uploadfile = -1; + delwin(swin); + winclose(&wintab); + sprintf(s, "Error reading upload file: upload aborted at %ld bytes", uplpos); + statline(mode, s); + continue; + } + if (!binup) + convert_lf_cr(uplbuf, upllen); + + upldp = 0; + } + bytes = write(fd, uplbuf + upldp, upllen - upldp); + + if ((bytes == 0 || bytes == -1) && errno != EWOULDBLOCK && errno != EAGAIN) { + sprintf(s, "Write error during upload. Connection lost"); + statline(mode, s); + perror("write"); + break; + } +/* if (uplpos / 1024 != (uplpos + bytes) / 1024) + { */ + /* printf("\r%ld bytes sent ", uplpos + bytes); */ + sprintf(s, "%ld", uplpos + bytes); + dupdstatw(swin, s, FALSE); +/* } */ + + uplpos += bytes; + upldp += bytes; + + if (upldp >= upllen) + upldp = -1; + } + } + } + + close(fd); + + if (logfile != -1) { + close(logfile); + logfile = -1; + } + if (downloadfile != -1) { + close(downloadfile); + downloadfile = -1; + } + fcntl(STDIN_FILENO, F_SETFL, 0); + + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_DFL); + + if (mode != RAWMODE) + endwin(); + + printf("*** Cleared\n"); + + if (flags & FLAG_RECONNECT) { + return TRUE; + } else { + return FALSE; + } +} + + +int main(int argc, char **argv) +{ + int p; + int mode = TALKMODE; + + while ((p = getopt(argc, argv, "b:dhm:p:rtvw:")) != -1) { + switch (p) { + case 'b': + if (*optarg != 'e' && *optarg != 'l') { + fprintf(stderr, "call: invalid argument for option '-b'\n"); + return 1; + } + backoff = *optarg == 'e'; + break; + case 'd': + debug = TRUE; + break; + case 'h': + mode = SLAVEMODE; + break; + case 'm': + if (*optarg != 's' && *optarg != 'e') { + fprintf(stderr, "call: invalid argument for option '-m'\n"); + return 1; + } + ax25mode = *optarg == 'e'; + break; + case 'p': + if ((paclen = atoi(optarg)) == 0) { + fprintf(stderr, "call: option '-p' requires a numeric argument\n"); + return 1; + } + if (paclen < 1 || paclen > 500) { + fprintf(stderr, "call: paclen must be between 1 and 500\n"); + return 1; + } + break; + case 'r': + mode = RAWMODE; + break; + case 't': + mode = TALKMODE; + break; + case 'v': + printf("call: %s\n", VERSION); + return 0; + case 'w': + if ((window = atoi(optarg)) == 0) { + fprintf(stderr, "call: option '-w' requires a numeric argument\n"); + return 1; + } + if (ax25mode) { + if (window < 1 || window > 63) { + fprintf(stderr, "call: window must be between 1 and 63 frames\n"); + return 1; + } + } else { + if (window < 1 || window > 7) { + fprintf(stderr, "call: window must be between 1 and 7 frames\n"); + return 1; + } + } + break; + case '?': + case ':': + fprintf(stderr, "usage: call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-r] [-t] [-v] [-w window] port callsign [[via] digipeaters...]\n"); + return 1; + } + } + + if (optind == argc || optind == argc - 1) { + fprintf(stderr, "usage: call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-r] [-t] [-v] [-w window] port callsign [[via] digipeaters...]\n"); + return 1; + } + port = argv[optind]; + + if (ax25_config_load_ports() == 0) { + fprintf(stderr, "call: no AX.25 port data configured\n"); + return 1; + } + if (ax25_config_get_addr(port) == NULL) { + nr_config_load_ports(); + + if (nr_config_get_addr(port) == NULL) { + rs_config_load_ports(); + + if (rs_config_get_addr(port) == NULL) { + fprintf(stderr, "call: invalid port setting\n"); + return 1; + } else { + af_mode = AF_ROSE; + } + } else { + af_mode = AF_NETROM; + } + } else { + af_mode = AF_AX25; + } + + switch (af_mode) { + case AF_ROSE: + paclen = rs_config_get_paclen(port); + break; + + case AF_NETROM: + if (paclen == 0) + paclen = nr_config_get_paclen(port); + break; + case AF_AX25: + if (window == 0) + window = ax25_config_get_window(port); + if (paclen == 0) + paclen = ax25_config_get_paclen(port); + break; + } + + printf("GW4PTS AX.25 Connect v1.11\n"); + + while (cmd_call(argv + optind + 1, mode)) { + printf("Wait 60 sec before reconnect\n"); + sleep(60); + } + + return 0; +} -- cgit v1.2.3