/*---------------------------------------------------------------------------- * imonc.c - imond client for Linux * * Copyright (c) 2000-2001 Frank Meyer * * 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 of the License, or * (at your option) any later version. * * Creation: 06.06.2000 fm * Last Update: 25.01.2001 fm *---------------------------------------------------------------------------- */ #include <errno.h> #include <stdio.h> #ifdef FLI4L /* imonc on fli4-router */ #include <sys/types.h> #include <termio.h> #else # ifdef linux # include <ncurses.h> # else # include <curses.h> # endif #endif /* not FLI4L */ #include <string.h> #include <ctype.h> #include <time.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> /* decl of inet_addr() */ #include <sys/socket.h> /*---------------------------------------------------------------------------- * some mini curses functions for fli4l router without curses library *---------------------------------------------------------------------------- */ #ifdef FLI4L /* imonc on fli4-router */ #define A_NORMAL 0 #define A_REVERSE 1 #define ERR (-1) #define FALSE 0 #define TRUE 1 #define OK 0 #define KEY_BACKSPACE 8 #define KEY_DC 127 #define stdscr 0 #define LINES 24 #define getyx(d,y,x) y = cur_y, x = cur_x static struct termio oldmode; static struct termio newmode; static int cur_y; static int cur_x; static int addch (ch) int ch; { putchar (ch); if (ch == 8) { if (cur_x > 0) { cur_x--; } } else { cur_x++; } return (OK); } /* addch (ch) */ static int addstr (str) char * str; { fputs (str, stdout); cur_x += strlen (str); return (OK); } /* addstr (str) */ static int attrset (attr) int attr; { if (attr == A_REVERSE) { fputs ("\033[7m", stdout); } else { fputs ("\033[0m", stdout); } return (OK); } /* attrset (attr) */ static int cbreak () { return (OK); } /* cbreak () */ static int clrtobot () { fputs ("\033[J", stdout); return (OK); } /* clrtobot () */ static int clrtoeol () { fputs ("\033[K", stdout); return (OK); } /* clrtoeol () */ static int move (y, x) int y; int x; { printf ("\033[%d;%dH", y + 1, x + 1); cur_y = y; cur_x = x; return (OK); } /* move (y, x) */ static int getch () { int ch; fflush (stdout); ch = getchar (); return (ch); } /* getch () */ static int halfdelay (tenths) int tenths; { if (tenths <= 0) { newmode.c_cc[VMIN] = 1; /* block input: */ newmode.c_cc[VTIME] = 0; /* one character */ } else { if (tenths > 255) { tenths = 255; } newmode.c_cc[VMIN] = 0; /* set timeout */ newmode.c_cc[VTIME] = tenths; /* in tenths of sec */ } (void) ioctl (0, TCSETAW, &newmode); return (OK); } /* halfdelay (tenths) */ static int keypad (dummy1, dummy2) int dummy1; int dummy2; { return (OK); } /* keypad (dummy1, dummy2) */ static int noecho () { newmode.c_lflag &= ~ECHO; (void) ioctl (0, TCSETAW, &newmode); return (OK); } /* noecho () */ static int nonl () { newmode.c_oflag &= ~ONLCR; newmode.c_oflag &= ~ONLRET; (void) ioctl (0, TCSETAW, &newmode); } /* nonl () */ #define VARARG ,v1,v2,v3,v4,v5,v6,v7,v8,v9 /* that's a bad dirty trick */ static int printw (fmt VARARG) char * fmt; { char str_buf[256]; (void) sprintf (str_buf, fmt VARARG); (void) addstr (str_buf); return (OK); } /* printw (fmt VARARG) */ static int refresh () { (void) fflush (stdout); return (OK); } /* refresh () */ static int initscr () { (void) ioctl (0, TCGETA, &oldmode); (void) ioctl (0, TCGETA, &newmode); newmode.c_lflag &= ~ICANON; (void) ioctl (0, TCSETAW, &newmode); fputs ("\033[1;1H\033[2J", stdout); fflush (stdout); return (OK); } /* initscr () */ static int endwin () { move (LINES - 1, 0); (void) ioctl (0, TCSETAW, &oldmode); return (OK); } #endif /* FLI4L */ /*---------------------------------------------------------------------------- * service_connect (host_name, port) - connect to tcp-service *---------------------------------------------------------------------------- */ int service_connect (host_name, port) char * host_name; int port; { struct sockaddr_in addr; struct hostent * host_p; int fd; int opt = 1; (void) memset ((char *) &addr, 0, sizeof (addr)); if ((addr.sin_addr.s_addr = inet_addr ((char *) host_name)) == INADDR_NONE) { host_p = gethostbyname (host_name); if (! host_p) { fprintf (stderr, "%s: host not found\n", host_name); return (-1); } (void) memcpy ((char *) (&addr.sin_addr), host_p->h_addr, host_p->h_length); } addr.sin_family = AF_INET; addr.sin_port = htons ((unsigned short) port); if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { /* open socket */ perror ("socket"); return (-1); } (void) setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, sizeof (opt)); if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) != 0) { (void) close (fd); perror (host_name); return (-1); } return (fd); } /* service_connect (host_name, port) */ /*---------------------------------------------------------------------------- * service_disconnect (fd) - disconnect from service *---------------------------------------------------------------------------- */ void service_disconnect (fd) int fd; { (void) close (fd); return; } /* service_disconnect (fd) */ void send_command (fd, str) int fd; char * str; { char buf[256]; int len = strlen (str); sprintf (buf, "%s\r\n", str); write (fd, buf, len + 2); return; } /* send_command (fd, str) */ char * get_answer (fd) { static char buf[8192]; int len; len = read (fd, buf, 8192); if (len <= 0) { return ((char *) NULL); } while (len > 1 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) { buf[len - 1] = '\0'; len--; } if (! strncmp (buf, "OK ", 3)) /* OK xxxx */ { return (buf + 3); } else if (len > 2 && ! strcmp (buf + len - 2, "OK")) { *(buf + len - 2) = '\0'; return (buf); } else if (len == 2 && ! strcmp (buf + len - 2, "OK")) { return (buf); } return ((char *) NULL); /* ERR xxxx */ } /* get_answer (fd) */ static int n_channels; static int n_circuits; #define MAX_CIRCUITS 16 static char circuits[MAX_CIRCUITS][25]; static int passwd_getstr (buf, maxlen) char * buf; int maxlen; { int ch; char * p = buf; int cnt = 0; int y; int x; *p = '\0'; while ((ch = getch ()) != '\n' && ch != '\r') { if (cnt < maxlen && ch >= 32 && ch != 127 && ch < 256) { addch ('*'); *p++ = ch; cnt++; } else if ((ch == 8 || ch == 127 || ch == KEY_BACKSPACE || ch == KEY_DC) && cnt > 0) { getyx (stdscr, y, x); x--; move (y, x); addch (' '); move (y, x); *--p = '\0'; cnt--; } } *p = '\0'; return (OK); } /* passwd_getstr (buf, maxlen) */ int init_status (fd) int fd; { char pass[64]; char buf[64]; char * answer; int i; send_command (fd, "pass"); answer = get_answer (fd); if (answer && ! strcmp (answer, "1")) { int password_correct = FALSE; move (LINES - 1, 0); attrset (A_REVERSE); addstr (" Password: "); attrset (A_NORMAL); addch (' '); if (passwd_getstr (pass, 63) != ERR) { sprintf (buf, "pass %s", pass); send_command (fd, buf); answer = get_answer (fd); if (answer) /* OK */ { password_correct = TRUE; } } if (password_correct == FALSE) { move (LINES - 2, 0); addstr ("Password incorrect"); return (ERR); } } send_command (fd, "channels"); answer = get_answer (fd); if (answer) { n_channels = atoi (answer); } send_command (fd, "circuits"); answer = get_answer (fd); if (answer) { n_circuits = atoi (answer); for (i = 1; i <= n_circuits && i <= MAX_CIRCUITS; i++) { sprintf (buf, "circuit %d", i); send_command (fd, buf); answer = get_answer (fd); if (answer) { move (i - 1, 0); strcpy (circuits[i - 1], answer); printw ("Circuit %2d %s", i, answer); } } } move (n_circuits + 1, 0); addstr ("No. DriverId Name Dir Time ChTime Charge"); move (n_circuits + 2, 0); addstr ("--------------------------------------------------------------------"); return (OK); } /* init_status (fd) */ void get_and_set_answer (fd, cmd, arg, buf) int fd; char * cmd; int arg; char * buf; { char cmd_buf[128]; char * answer; if (arg >= 0) { sprintf (cmd_buf, "%s %d", cmd, arg); send_command (fd, cmd_buf); } else { send_command (fd, cmd); } if ((answer = get_answer (fd)) != (char *) NULL) { strcpy (buf, answer); } else { *buf = '\0'; } return; } /* get_and_set_answer (fd, cmd, arg, buf) */ int print_status (fd) int fd; { char driver_id[64]; char name[64]; char direction[64]; char online_time[64]; char charge_time [64]; char charge[64]; char * answer; int i; send_command (fd, "date"); answer = get_answer (fd); move (0, 38); printw ("fli4l date: %s", answer); send_command (fd, "route"); answer = get_answer (fd); if (answer) { i = atoi (answer); move (1, 38); addstr ("default route: "); if (i == 0) { addstr ("Automatic"); } else { i--; if (i < MAX_CIRCUITS) { addstr (circuits[i]); } else { addstr ("..."); } } clrtoeol (); } for (i = 0; i < n_channels; i++) { get_and_set_answer (fd, "driverid", i + 1, driver_id); get_and_set_answer (fd, "phone", i + 1, name); get_and_set_answer (fd, "direction", i + 1, direction); get_and_set_answer (fd, "time", i + 1, online_time); get_and_set_answer (fd, "chargetime", i + 1, charge_time); get_and_set_answer (fd, "charge", i + 1, charge); move (n_circuits + 3 + i, 0); printw ("%2d %-10s %-20s %-4s %-8s %-8s %6s", i, driver_id, name, direction, online_time, charge_time, charge); } refresh (); return (OK); } int print_answer (cmd, answer, wanted_rtc, wait_for_any_key) char * cmd; char * answer; char * wanted_rtc; int wait_for_any_key; { char * p; int first_answer_line = TRUE; int start_y = n_channels + n_circuits + 4; int y; if (! strcmp (cmd, "Help")) { start_y++; } y = start_y; move (y, 0); addstr (cmd); addstr (": "); clrtobot (); if (answer) { while ((p = strchr (answer, '\n')) != (char *) NULL) { if (first_answer_line) { start_y++; y++; move (y, 0); first_answer_line = FALSE; } *p = '\0'; addstr (answer); answer = p + 1; y++; if (y >= LINES - 2) { move (LINES - 1, 0); attrset (A_REVERSE); addstr (" More ... "); attrset (A_NORMAL); while (getch () <= 0) { ; } y = start_y; move (y, 0); clrtobot (); } move (y, 0); } if (wanted_rtc) { if (! strcmp (wanted_rtc, answer)) { addstr ("ok"); } else { addstr ("failed, return code: "); addstr (answer); } } else { addstr (answer); } if (wait_for_any_key == TRUE) { move (LINES - 1, 0); attrset (A_REVERSE); addstr (" Press any key "); attrset (A_NORMAL); while (getch () <= 0) { ; } move (start_y, 0); clrtobot (); } return (OK); } addstr ("ERROR"); return (ERR); } /* print_answer (cmd, answer, wanted_rtc, wait_for_any_key) */ int get_and_print_answer (fd, cmd, wanted_rtc, wait_for_any_key) int fd; char * cmd; char * wanted_rtc; int wait_for_any_key; { char * answer; int rtc; send_command (fd, cmd); if (wait_for_any_key) { /* HACK IN PRE VERSION (TIMETABLE COMMAND): WAIT FOR FLUSH OF IMOND */ sleep (1); } answer = get_answer (fd); rtc = print_answer (cmd, answer, wanted_rtc, wait_for_any_key); return (rtc); } /* get_and_print_answer (fd, cmd, wanted_rtc, wait_for_any_key) */ void catch_sigpipe (sig) int sig; { move (LINES - 1, 0); clrtoeol (); refresh (); endwin (); fputs ("Connection lost.\n", stderr); exit (1); } /* catch_sigpipe (sig) */ int main (argc, argv) int argc; char * argv[]; { char answer[4096]; int port = 5000; int fd; int ch; int cnt = 1; char * cmd = (char *) NULL; #ifdef FLI4L FILE * fp; if (argc > 1) { cmd = argv[1]; } fp = fopen ("/var/run/imond.port", "r"); if (fp) { (void) fscanf (fp, "%d", &port); fclose (fp); } if ((fd = service_connect ("127.0.0.1", port)) < 0) { exit (1); } #else if (argc == 3) { port = atoi (argv[2]); } else if (argc != 2) { fprintf (stderr, "usage: %s host [port]\n", argv[0]); exit (1); } if ((fd = service_connect (argv[1], port)) < 0) { exit (1); } #endif if (cmd) { if (! strcmp (cmd, "enable") || ! strcmp (cmd, "disable") || ! strcmp (cmd, "dial") || ! strcmp (cmd, "hangup") || ! strcmp (cmd, "reboot")) { char * ap; send_command (fd, cmd); ap = get_answer (fd); if (ap) { printf ("%s\n", ap); return (0); } fprintf (stderr, "%s: no answer\n", argv[0]); return (1); } fprintf (stderr, "%s: unknown command: %s\n", argv[0], cmd); return (1); } signal (SIGPIPE, catch_sigpipe); initscr(); noecho(); nonl(); refresh(); cbreak(); keypad(stdscr,TRUE); if (init_status (fd) == OK) { halfdelay(20); /* wait 2.0 seconds before timeout */ do { print_status (fd); strcpy (answer, " 0 quit 5 reboot\n"); strcat (answer, " 1 enable 6 timetable\n"); strcat (answer, " 2 disable 7 set default route circuit\n"); strcat (answer, " 3 dial 8 add channel link\n"); strcat (answer, " 4 hangup 9 remove channel link\n"); print_answer ("Help", answer, (unsigned char *) NULL, FALSE); ch = getch (); if (isascii (ch)) { ch = tolower (ch); } switch (ch) { case '0': break; case '1': get_and_print_answer (fd, "enable", "0", FALSE); break; case '2': get_and_print_answer (fd, "disable", "0", FALSE); break; case '3': get_and_print_answer (fd, "dial", "0", FALSE); break; case '4': get_and_print_answer (fd, "hangup", "0", FALSE); break; case '5': move (LINES - 1, 0); addstr ("Really reboot (y/n) ? "); clrtoeol (); do { ch = getch (); } while (ch != 'y' && ch != 'n'); if (ch == 'y') { get_and_print_answer (fd, "reboot", "0", FALSE); } break; case '6': get_and_print_answer (fd, "timetable", (unsigned char *) NULL, TRUE); break; case '7': if (n_circuits > 0) { move (LINES - 1, 0); printw ("circuit: 0 automatic, 1 - %d manual: ", n_circuits); clrtoeol (); *answer = '\0'; do { ch = getch (); } while (ch < '0' || ch > '9'); if (ch >= '0' && ch <= '0' + n_circuits) { sprintf (answer, "route %c", ch); get_and_print_answer (fd, answer, (char *) NULL, FALSE); } ch = -1; } break; case '8': if (n_circuits > 0) { printw ("Add link to circuit: 1 - %d (0 = Cancel): ", n_circuits); clrtoeol (); *answer = '\0'; do { ch = getch (); } while (ch < '0' || ch > '9'); if (ch >= '1' && ch <= '0' + n_circuits) { sprintf (answer, "addlink %c", ch); get_and_print_answer (fd, answer, (char *) NULL, FALSE); } ch = -1; } break; case '9': if (n_circuits > 0) { printw ("remove link from circuit: 1 - %d (0 = Cancel): ", n_circuits); clrtoeol (); *answer = '\0'; do { ch = getch (); } while (ch < '0' || ch > '9'); if (ch >= '1' && ch <= '0' + n_circuits) { sprintf (answer, "removelink %c", ch); get_and_print_answer (fd, answer, (char *) NULL, FALSE); } ch = -1; } break; case -1: break; default: break; } cnt++; } while (ch != 'q' && ch != '0'); } move (LINES - 1, 0); clrtoeol (); refresh (); endwin (); service_disconnect (fd); return (0); } /* main (argc, argv) */