Subject: v14i102: Dial out and terminal emulator, Part04/06 Newsgroups: comp.sources.unix Sender: sources Approved: rsalz@uunet.UU.NET Submitted-by: fthood!egray Posting-number: Volume 14, Issue 102 Archive-name: pcomm/part04 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # input.c # line_set.c # list_dir.c # ls_menu.c # m_lib.c # main.c # n_shell.c # p_lib.c # pexit.c # port.c # redial.c export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'input.c'" '(6599 characters)' if test -f 'input.c' then echo shar: "will not over-write existing file 'input.c'" else sed 's/^X//' << \SHAR_EOF > 'input.c' X/* X * The input routines. These routines are run as a child process to the X * main pcomm program. X */ X X#define LPR "/usr/bin/lpr" X X#define MAX_ROW 64 X#define MAX_COL 128 X X#include X#include X#include X Xjmp_buf i_jmp; Xunsigned char vs[MAX_ROW][MAX_COL+2]; Xint row, col; X X/* X * Read the serial port and write the characters to the screen. Watch X * for signals from the parent process to toggle the fancy options. X * Writes the characters received to a virtual screen buffer. X */ Xint Xinput(fd, add_lf, log, print, max_row, max_col, vs_file, log_file) Xint fd, add_lf, log, print, max_row, max_col; Xchar *vs_file, *log_file; X{ X FILE *logfp, *lprfp, *popen(); X int hold, skip_row, got_sig(); X unsigned char c; X char lf=10; X void _exit(); X /* set the trap for the signals */ X signal(SIGALRM, SIG_IGN); X signal(SIGUSR1, got_sig); X signal(SIGUSR2, got_sig); X signal(SIGINT, got_sig); X signal(SIGTERM, got_sig); X /* resonable limits */ X if (max_row > MAX_ROW) X max_row = MAX_ROW; X if (max_col > MAX_COL) X max_col = MAX_COL; X /* read previous screen */ X if (!access(vs_file, 0)) { X read_vs(vs_file, max_row, max_col); X skip_row = 0; X } X else X skip_row = 1; X X hold = 0; X /* startup file pointers */ X if (print) X lprfp = popen(LPR, "w"); X X if (log && strcmp(log_file, "NOT_DEFINED")) X logfp = fopen(log_file, "a"); X X switch(setjmp(i_jmp)) { X case 0: /* no signal */ X break; X case 1: /* toggle the data logging */ X signal(SIGUSR1, got_sig); X if (!strcmp(log_file, "NOT_DEFINED")) { X log = 0; X break; X } X log = log ? 0 : 1; X if (log) X logfp = fopen(log_file, "a"); X else X fclose(logfp); X break; X case 2: /* toggle the printer */ X signal(SIGUSR2, got_sig); X print = print ? 0 : 1; X if (print) X lprfp = popen(LPR, "w"); X else { X putc(014, lprfp); X pclose(lprfp); X } X break; X case 3: /* suspend the input */ X signal(SIGINT, got_sig); X hold = hold ? 0 : 1; X if (hold) X write_vs(vs_file, max_row, max_col); X break; X case 4: /* cleanup and go home */ X signal(SIGTERM, got_sig); X if (log) X fclose(logfp); X if (print) { X putc(014, lprfp); X pclose(lprfp); X } X _exit(0); X break; X } X /* any signal will awaken pause() */ X if (hold) X pause(); X /* clear if vs_path doesn't exist */ X if (access(vs_file, 0)) X clear_vs(max_row, max_col); X /* X * The very first screen we see after dialing has the "Connected to..." X * message at row 0, therefore we start our virtual screen at row 1. X */ X if (skip_row) { X skip_row = 0; X row = 1; X } X X while(1) { X if (read(fd, (char *) &c, 1) <= 0) X continue; X /* send to logfile */ X if (log) { X if (c == 015 && add_lf) X fwrite(&lf, 1, 1, logfp); X /* no carriage returns in logfile */ X if (c != 015) X fwrite((char *) &c, 1, 1, logfp); X } X /* send to printer too ? */ X if (print) X fwrite((char *) &c, 1, 1, lprfp); X X /* put a char in virtual screen */ X putchar_vs(c, add_lf, max_row, max_col); X X write(1, (char *) &c, 1); X /* add LF to CR ? */ X if (add_lf) X write(1, &lf, 1); X } X} X X/* X * Figure out which signal we just received, and fix the return code of X * the setjmp function above to the proper value. X */ X Xint Xgot_sig(sig) Xint sig; X{ X void longjmp(); X X switch(sig) { X case SIGUSR1: X longjmp(i_jmp, 1); X case SIGUSR2: X longjmp(i_jmp, 2); X case SIGINT: X longjmp(i_jmp, 3); X case SIGTERM: X longjmp(i_jmp, 4); X } X} X X/* X * Put a character in the virtual screen. This routine saves incoming X * character in a two dimensional buffer designed to mimic the real X * screen. CURRENTLY DOES NOT UNDERSTAND ESCAPE SEQUENCES! X */ X Xint Xputchar_vs(c, add_lf, max_row, max_col) Xunsigned char c; Xint add_lf, max_row, max_col; X{ X int tab_stop; X X switch(c) { X case 8: /* destructive back space */ X col--; X if (col < 0) X col = 0; X vs[row][col] = ' '; X break; X case 9: /* tab character */ X tab_stop = col + 8 - (col % 8); X /* if wrap around */ X if (tab_stop >= max_col) { X /* spaces up to eol */ X for (; col= max_row) X scroll_vs(max_row, max_col); X X /* the remainder of the tab */ X col = tab_stop - max_col; X } X else { X for (; col= max_row) X scroll_vs(max_row, max_col); X break; X default: /* a normal character */ X vs[row][col] = c; X col++; X /* wrap around */ X if (col >= max_col) { X col = 0; X row++; X if (row >= max_row) X scroll_vs(max_row, max_col); X } X break; X } X return; X} X X/* X * Save the virtual screen to a file. X */ X Xint Xwrite_vs(vs_file, max_row, max_col) Xchar *vs_file; Xint max_row, max_col; X{ X FILE *fp; X int i; X X if (!(fp = fopen(vs_file, "w"))) X return(1); X /* current x y coordinates */ X fprintf(fp, "%d,%d\n", row, col); X X for (i=0; i 'line_set.c' X/* X * Change the communication line settings to the new values. X */ X X#include X#include X#include "dial_dir.h" X#include "param.h" X#include "status.h" X Xvoid Xline_set() X{ X struct termio tbuf; X X /* X * The manual dial entry also serves to store the previous X * line settings. How else would the manual dial entry X * know what line setting to use? X */ X if (dir->d_cur != 0) { X dir->baud[0] = dir->baud[dir->d_cur]; X dir->parity[0] = dir->parity[dir->d_cur]; X dir->dbits[0] = dir->dbits[dir->d_cur]; X dir->sbits[0] = dir->sbits[dir->d_cur]; X } X /* nothing to do! */ X if (status->fd == -1) X return; X /* get the current settings */ X ioctl(status->fd, TCGETA, &tbuf); X /* set some beginning values */ X tbuf.c_cc[4] = 1; X tbuf.c_cc[5] = 0; X tbuf.c_oflag = 0; X tbuf.c_iflag = 0; X tbuf.c_cflag = (CREAD|HUPCL); X tbuf.c_lflag = 0; X X /* X * I don't think there's any need for output flow control... (I don't X * know about you guys, but I can't type faster than the host can X * receive!) Besides, the file transfers reset this anyway. X */ X if (*param->flow == 'X') X tbuf.c_iflag |= IXOFF; X /* strip high bit ? */ X if (*param->strip == 'Y') X tbuf.c_iflag |= ISTRIP; X /* the baud rate */ X switch (dir->baud[dir->d_cur]) { X case 300: X tbuf.c_cflag |= B300; X break; X case 1200: X tbuf.c_cflag |= B1200; X break; X case 2400: X tbuf.c_cflag |= B2400; X break; X case 4800: X tbuf.c_cflag |= B4800; X break; X case 9600: X tbuf.c_cflag |= B9600; X break; X case 19200: X /* X * Be careful here... some systems use EXTA in lieu X * of B19200. X */ X tbuf.c_cflag |= B19200; X break; X } X /* the parity */ X switch (dir->parity[dir->d_cur]) { X case 'N': X break; X case 'O': X tbuf.c_cflag |= (PARENB|PARODD); X break; X case 'E': X tbuf.c_cflag |= PARENB; X break; X } X /* the data bits */ X if (dir->dbits[dir->d_cur] == 8) X tbuf.c_cflag |= CS8; X else X tbuf.c_cflag |= CS7; X /* the stop bits */ X if (dir->sbits[dir->d_cur] == 2) X tbuf.c_cflag |= CSTOPB; X X /* now set 'em! */ X ioctl(status->fd, TCSETA, &tbuf); X ioctl(status->fd, TCFLSH, 2); X return; X} SHAR_EOF if test 2130 -ne "`wc -c < 'line_set.c'`" then echo shar: "error transmitting 'line_set.c'" '(should have been 2130 characters)' fi fi echo shar: "extracting 'list_dir.c'" '(1479 characters)' if test -f 'list_dir.c' then echo shar: "will not over-write existing file 'list_dir.c'" else sed 's/^X//' << \SHAR_EOF > 'list_dir.c' X/* X * Do a shell escape with an 'ls' command X */ X X#include X#include X#include "misc.h" X Xvoid Xlist_dir(fd) Xint fd; X{ X WINDOW *ls_win, *newwin(); X FILE *pfp, *native_popen(); X int lines, oops; X char *ans, *cwd, *getcwd(), buf[200], *get_str(); X X ls_win = newwin(6, 70, 8, 5); X X cwd = getcwd(buf, 200); X X mvwprintw(ls_win, 2, 4, "Current directory: %s", cwd); X mvwaddstr(ls_win, 3, 4, "File spec (wildcards allowed): "); X box(ls_win, '|', '-'); X X mvwattrstr(ls_win, 0, 3, A_BOLD, " List Directory "); X wmove(ls_win, 3, 35); X wrefresh(ls_win); X X if ((ans = get_str(ls_win, 60, NULL, NULL)) == NULL) { X if (fd == -1) { X werase(ls_win); X wrefresh(ls_win); X } X delwin(ls_win); X return; X } X /* popen() an ls */ X sprintf(buf, "ls -aC %s", ans); X pfp = native_popen(buf, "r"); X /* make a bigger window */ X werase(ls_win); X wrefresh(ls_win); X delwin(ls_win); X ls_win = newwin(LINES-1, COLS, 0, 0); X X oops = 0; X lines = 0; X while (fgets(buf, BUFSIZ, pfp) != NULL) { X waddstr(ls_win, buf); X lines++; X if (lines == LINES-2) { X lines = 0; X mvwaddstr(ls_win, LINES-2, 28, "Press any key for more"); X wrefresh(ls_win); X if (wgetch(ls_win) == 27) { X oops++; X break; X } X werase(ls_win); X wrefresh(ls_win); X } X } X native_pclose(pfp); X X if (!oops) { X mvwaddstr(ls_win, LINES-2, 25, "Press any key to continue"); X wrefresh(ls_win); X wgetch(ls_win); X } X if (fd == -1) { X werase(ls_win); X wrefresh(ls_win); X } X delwin(ls_win); X return; X} SHAR_EOF if test 1479 -ne "`wc -c < 'list_dir.c'`" then echo shar: "error transmitting 'list_dir.c'" '(should have been 1479 characters)' fi fi echo shar: "extracting 'ls_menu.c'" '(4820 characters)' if test -f 'ls_menu.c' then echo shar: "will not over-write existing file 'ls_menu.c'" else sed 's/^X//' << \SHAR_EOF > 'ls_menu.c' X/* X * Routines for displaying current line settings and prompting for changes. X */ X X#include X#include X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X X/* X * Display the current line settings and prompt for changes. A return X * code of 1 means settings were changed. X */ X Xint Xline_set_menu(fd) Xint fd; X{ X WINDOW *l_win, *newwin(); X int num, ret_code; X void disp_settings(); X X l_win = newwin(20, 47, 0, 16); X X mvwattrstr(l_win, 1, 16, A_BOLD, "Line Settings"); X waddstr(l_win, "\n----------------------------------------------"); X mvwaddstr(l_win, 6, 5, "1) 300,E,7,1 7) 300,N,8,1"); X mvwaddstr(l_win, 7, 5, "2) 1200,E,7,1 8) 1200,N,8,1"); X mvwaddstr(l_win, 8, 5, "3) 2400,E,7,1 9) 2400,N,8,1"); X mvwaddstr(l_win, 9, 5, "4) 4800,E,7,1 10) 4800,N,8,1"); X mvwaddstr(l_win, 10, 5, "5) 9600,E,7,1 11) 9600,N,8,1"); X mvwaddstr(l_win, 11, 5, "6) 19200,E,7,1 12) 19200,N,8,1"); X mvwaddstr(l_win, 13, 4, "Parity Data Bits Stop Bits"); X mvwaddstr(l_win, 14, 4, "13) Odd 14) 7 bits 16) 1 bit"); X mvwaddstr(l_win, 15, 18, "15) 8 bits 17) 2 bits"); X mvwaddstr(l_win, 17, 4, "18) Save Changes"); X mvwattrstr(l_win, 17, 28, A_BOLD, "YOUR CHOICE:"); X wmove(l_win, 17, 41); X box(l_win, '|', '-'); X X mvwaddstr(l_win, 19, 14, " Press ESC to return "); X /* display current settings */ X disp_settings(l_win); X wmove(l_win, 17, 41); X wrefresh(l_win); X /* get the options */ X ret_code = 0; X while ((num = get_num(l_win, 2)) != -1) { X switch(num) { X case 1: X dir->baud[dir->d_cur] = 300; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 2: X dir->baud[dir->d_cur] = 1200; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 3: X dir->baud[dir->d_cur] = 2400; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 4: X dir->baud[dir->d_cur] = 4800; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 5: X dir->baud[dir->d_cur] = 9600; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 6: X dir->baud[dir->d_cur] = 19200; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 7: X dir->baud[dir->d_cur] = 300; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 8: X dir->baud[dir->d_cur] = 1200; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 9: X dir->baud[dir->d_cur] = 2400; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 10: X dir->baud[dir->d_cur] = 4800; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 11: X dir->baud[dir->d_cur] = 9600; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 12: X dir->baud[dir->d_cur] = 19200; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 13: X dir->parity[dir->d_cur] = 'O'; X break; X case 14: X dir->dbits[dir->d_cur] = 7; X break; X case 15: X dir->dbits[dir->d_cur] = 8; X break; X case 16: X dir->sbits[dir->d_cur] = 1; X break; X case 17: X dir->sbits[dir->d_cur] = 2; X break; X case 18: X /* copy the current settings */ X param->d_baud = dir->baud[dir->d_cur]; X param->d_parity = dir->parity[dir->d_cur]; X param->d_dbits = dir->dbits[dir->d_cur]; X param->d_sbits = dir->sbits[dir->d_cur]; X /* X * We've changed the values in memory even X * if the update fails. X */ X if (update_param()) { X touchwin(l_win); X wrefresh(l_win); X } X break; X default: X beep(); X } X ret_code++; X disp_settings(l_win); X mvwaddstr(l_win, 17, 41, " "); X wmove(l_win, 17, 41); X wrefresh(l_win); X } X if (fd == -1) { X werase(l_win); X wrefresh(l_win); X } X delwin(l_win); X return(ret_code); X} X X/* X * Display the current settings. Formats the entire string at one X * time, in case you've got a magic cookie terminal. X */ X Xvoid Xdisp_settings(win) XWINDOW *win; X{ X char buf[40]; X extern int xmc; X X sprintf(buf, "Current Settings: %5d,%c,%d,%d", dir->baud[dir->d_cur], X dir->parity[dir->d_cur], dir->dbits[dir->d_cur], X dir->sbits[dir->d_cur]); X X if (xmc > 0) { X touchwin(win); X clear_line(win, 4, 8, 1); X wrefresh(win); X } X mvwattrstr(win, 4, 8, A_BOLD, buf); X return; X} SHAR_EOF if test 4820 -ne "`wc -c < 'ls_menu.c'`" then echo shar: "error transmitting 'ls_menu.c'" '(should have been 4820 characters)' fi fi echo shar: "extracting 'm_lib.c'" '(9489 characters)' if test -f 'm_lib.c' then echo shar: "will not over-write existing file 'm_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'm_lib.c' X/* X * Routines to manipulate the pcomm.modem file X */ X X#include X#include "modem.h" X#include "status.h" X X/* X * Read the modem database file. Returns a pointer to a static area X * containing the MODEM structure. All modem entries and all tty entries X * are created reguardless of the number of physical entries in the file. X */ X Xstruct MODEM * Xread_modem() X{ X FILE *fp; X int i, tty, mod, line, oops, m_line, start, stop; X char *strdup(), buf[200], message[80], token[40], *str_tok(), *str; X char *temp_token, *t_sep, *m_sep, *m_letter; X static struct MODEM m; X void error_win(); X extern char *null_ptr; X X if (!(fp = fopen(status->m_path, "r"))) { X sprintf(buf, "'%s' for read", status->m_path); X error_win(1, "Can't open modem file", buf); X } X X t_sep = ";;\n"; X m_sep = ";;;;\n;;;;;\n;;;\n"; X m_letter = "abc"; X oops = 0; X tty = 0; X mod = 0; X line = 0; X m_line = 0; X while (fgets(buf, 200, fp) != NULL) { X line++; X if (tty >= NUM_TTY || mod >= NUM_MODEM) X break; X /* get the token */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", line); X oops++; X break; X } X if (*temp_token != 'T' && *temp_token != 'M') { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* the tty database */ X if (*temp_token == 'T') { X /* X * This is similar to the "real" strtok() command X * but this one returns a null pointer on a missing X * attribute. Note the use of the field separator X * array. X */ X for (i=0; i<3; i++) { X if (!(str = str_tok((char *) NULL, t_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch(i) { X case 0: X m.tty[tty] = strdup(str); X break; X case 1: X m.tname[tty] = strdup(str); X break; X case 2: X m.mbaud[tty] = atoi(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "TTY_%d", tty+1); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X tty++; X continue; X } X /* the modem database */ X else { X sprintf(token, "MODEM_%d%c", mod+1, m_letter[m_line]); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* X * There are three lines to the modem database. They X * distinguished by the letters a, b, and, c appended X * to the entry number. X */ X switch(m_line) { X case 0: X start = 0; X stop = 5; X break; X case 1: X start = 5; X stop = 11; X break; X case 2: X start = 11; X stop = 15; X break; X } X for (i=start; i= 3) { X m_line = 0; X mod++; X } X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Modem file '%s'", status->m_path); X error_win(1, buf, message); X } X m.t_entries = tty; X m.m_entries = mod; X m.t_cur = -1; X m.m_cur = -1; X /* fill in the rest */ X for (; ttym_path, "w"))) { X sprintf(buf, "'%s'", status->m_path); X error_win(0, "No write permission on modem file", buf); X return(1); X } X /* put back the tty entries */ X for (i=0; it_entries; i++) X fprintf(fp, "TTY_%d=%s;%s;%d\n", i+1, modem->tty[i], X modem->tname[i], modem->mbaud[i]); X X /* put back the modem entries */ X for (i=0; im_entries; i++) { X fprintf(fp, "MODEM_%da=%s;%s;%s;%s;%s\n", i+1, modem->mname[i], X modem->init[i], modem->dial[i], modem->suffix[i], X modem->hangup[i]); X X fprintf(fp, "MODEM_%db=%s;%s;%s;%s;%s;%s\n", i+1, X modem->con_3[i], modem->con_12[i], modem->con_24[i], X modem->con_48[i], modem->con_96[i], modem->con_192[i]); X X fprintf(fp, "MODEM_%dc=%s;%s;%s;%s\n", i+1, modem->no_con1[i], X modem->no_con2[i], modem->no_con3[i], modem->no_con4[i]); X } X X fclose(fp); X return(0); X} X X/* X * See if the new modem is already in the database. If it's not, X * then create a slot for it and update the modem->m_cur variable. X */ X Xvoid Xcreate_modem(str) Xchar *str; X{ X int i; X char *strdup(), buf[80]; X void error_win(), free_ptr(); X /* modem entry already exists? */ X for (i=0; im_entries; i++) { X if (!strcmp(str, modem->mname[i])) X return; X } X /* empty slot available? */ X if (modem->m_entries == NUM_MODEM) { X sprintf(buf, "'%s'", status->m_path); X error_win(0, "No empty modem slots in", buf); X return; X } X /* create a new entry */ X free_ptr(modem->mname[modem->m_entries]); X modem->mname[modem->m_entries] = strdup(str); X X /* update number of entries */ X modem->m_entries++; X return; X} X X/* X * See if the modem names in the list still need to be in the database. X * If you find a "lost" entry, delete it and collapse the list. X */ X Xvoid Xdelete_modem() X{ X int i, j, match; X char *strdup(); X void free_ptr(); X extern char *null_ptr; X X for (i=0; im_entries; i++) { X match = 0; X for (j=0; jt_entries; j++) { X if (!strcmp(modem->mname[i], modem->tname[j])) { X match = 1; X break; X } X } X /* found a "lost" modem name */ X if (!match) { X for (j=i; jm_entries-1; j++) { X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hangup[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* copy the info */ X modem->mname[j] = strdup(modem->mname[j+1]); X modem->init[j] = strdup(modem->init[j+1]); X modem->dial[j] = strdup(modem->dial[j+1]); X modem->suffix[j] = strdup(modem->suffix[j+1]); X modem->hangup[j] = strdup(modem->hangup[j+1]); X X modem->con_3[j] = strdup(modem->con_3[j+1]); X modem->con_12[j] = strdup(modem->con_12[j+1]); X modem->con_24[j] = strdup(modem->con_24[j+1]); X modem->con_48[j] = strdup(modem->con_48[j+1]); X modem->con_96[j] = strdup(modem->con_96[j+1]); X modem->con_192[j] = strdup(modem->con_192[j+1]); X X modem->no_con1[j] = strdup(modem->no_con1[j+1]); X modem->no_con2[j] = strdup(modem->no_con2[j+1]); X modem->no_con3[j] = strdup(modem->no_con3[j+1]); X modem->no_con4[j] = strdup(modem->no_con4[j+1]); X } X j = modem->m_entries -1; X X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hangup[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* create an empty entry */ X modem->mname[j] = null_ptr; X modem->init[j] = null_ptr; X modem->dial[j] = null_ptr; X modem->suffix[j] = null_ptr; X modem->hangup[j] = null_ptr; X X modem->con_3[j] = null_ptr; X modem->con_12[j] = null_ptr; X modem->con_24[j] = null_ptr; X modem->con_48[j] = null_ptr; X modem->con_96[j] = null_ptr; X modem->con_192[j] = null_ptr; X X modem->no_con1[j] = null_ptr; X modem->no_con2[j] = null_ptr; X modem->no_con3[j] = null_ptr; X modem->no_con4[j] = null_ptr; X X /* update the counts */ X modem->m_entries--; X if (modem->m_cur >= modem->m_entries) X modem->m_cur = -1; X return; X } X } X return; X} SHAR_EOF if test 9489 -ne "`wc -c < 'm_lib.c'`" then echo shar: "error transmitting 'm_lib.c'" '(should have been 9489 characters)' fi fi echo shar: "extracting 'main.c'" '(4860 characters)' if test -f 'main.c' then echo shar: "will not over-write existing file 'main.c'" else sed 's/^X//' << \SHAR_EOF > 'main.c' X/* X * Pcomm is a public domain telecommunication program for Unix X * designed to operate similar to the popular MSDOS program, ProComm. X * ProComm (TM) is copyrighted by Datastorm Technologies, Inc. X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X * Beta release 7 Feb 88 X * Release 1.0 12 Mar 88 X */ X X#include X#include X#include X#ifndef OLDCURSES X#include X#endif /* OLDCURSES */ X#include X#include X#define MAIN X#include "dial_dir.h" X#include "modem.h" X#include "param.h" X#include "status.h" X X#ifdef OLDCURSES Xchar bp[1024]; X#define cbreak crmode X#endif /* OLDCURSES */ X Xstruct PARAM *param; Xstruct DIAL_DIR *dir; Xstruct STATUS *status; Xstruct MODEM *modem; Xint xmc; Xchar *null_ptr; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int c, ret_code, i, code, quit(); X char *mytty, *ttyname(), *term, *getenv(), *index, *strdup(); X char *extra_dir, buf[80], message[80]; X struct PARAM *read_param(); X struct DIAL_DIR *read_dir(); X struct STATUS *init(); X struct MODEM *read_modem(); X struct stat stbuf; X void exit(), error_win(), input_on(), free_ptr(); X extern char *optarg; X#ifdef OLDCURSES X char *tgetstr(), ocbuf[20]; X char *ocbufptr = ocbuf; X#endif /* OLDCURSES */ X X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGTERM, quit); X signal(SIGHUP, quit); X X null_ptr = ""; X index = NULL; X extra_dir = NULL; X /* the command line */ X while ((c = getopt(argc, argv, "d:f:")) != EOF) { X switch (c) { X case 'd': /* the extra directory to search */ X extra_dir = strdup(optarg); X break; X case 'f': /* the index into the dialing dir */ X index = strdup(optarg); X break; X case '?': /* default */ X fprintf(stderr, "Usage: pcomm [-d directory] [-f index]\n"); X exit(1); X break; X } X } X /* get terminal type */ X term = getenv("TERM"); X if (term == NULL || *term == NULL) { X fprintf(stderr, "Windows not supported (TERM not defined)\n"); X exit(1); X } X /* see if terminfo entry exists */ X#ifdef OLDCURSES X ret_code = tgetent(bp, term); X#else /* OLDCURSES */ X setupterm(term, 1, &ret_code); X#endif /* OLDCURSES */ X if (ret_code != 1) { X fprintf(stderr, "Windows not supported (no terminfo data for '%s')\n", term); X exit(1); X } X /* minimum screen size */ X#ifdef OLDCURSES X if (tgetnum("co") < 80 || tgetnum("li") < 24) { X#else /* OLDCURSES */ X if (columns < 80 || lines < 24) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n"); X exit(1); X } X /* must have cursor movement */ X#ifdef OLDCURSES X if (tgetstr("cm", &ocbufptr) == NULL) { X#else /* OLDCURSES */ X if (cursor_address == NULL) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (terminal too dumb)\n"); X exit(1); X } X /* load magic cookie variable */ X#ifdef OLDCURSES X xmc = tgetnum("sg"); X#else /* OLDCURSES */ X xmc = magic_cookie_glitch; X#endif /* OLDCURSES */ X /* ok... now lets go! */ X initscr(); X nonl(); X cbreak(); X noecho(); X X param = (struct PARAM *) NULL; X modem = (struct MODEM *) NULL; X dir = (struct DIAL_DIR *) NULL; X /* show the herald, return status */ X status = init(extra_dir, index); X /* get 'msgs' status */ X mytty = ttyname(0); X stat(mytty, &stbuf); X chmod(mytty, 0600); X status->msg = stbuf.st_mode & 0777; X /* read the support files */ X param = read_param(); X dir = read_dir(); X modem = read_modem(); X /* short-cut to dialing window ? */ X code = 0; X if (index != NULL) { X for (i=1; id_entries+1; i++) { X if (!strcmp(dir->index[i], index)) { X dir->q_num[0] = i; X dir->d_cur = i; X break; X } X } X /* if match is found */ X if (dir->q_num[0] != -1) X code = dial_win(); X else { X sprintf(buf, "Can't find index '%s' in dialing directory file", index); X sprintf(message, "'%s'", status->d_path); X error_win(0, buf, message); X } X free_ptr(index); X } X /* start terminal dialogue */ X terminal(code); X exit(0); X} X X/* X * Something dreadful happened... Cleanup the mess we made with the X * tty driver and release the phone line. X */ X Xint Xquit() X{ X void cleanup(); X X cleanup(1); X /* never returns... */ X return(0); X} X X/* X * Check write permission with the real UID and GID. Returns a 0 on X * permission denied, 1 on OK, and 2 on OK-but the file already exists. X */ X Xint Xcan_write(file) Xchar *file; X{ X char *p, path[200], *strcpy(), *strrchr(); X X p = strcpy(path, file); X /* dissect the path component */ X if (p = strrchr(path, '/')) X *(p++) = NULL; X else X strcpy(path, "."); X /* if it already exists */ X if (!access(file, 0)) { X if (!access(file, 2)) X return(2); X return(0); X } X /* if path is writable */ X if (!access(path, 2)) X return(1); X return(0); X} SHAR_EOF if test 4860 -ne "`wc -c < 'main.c'`" then echo shar: "error transmitting 'main.c'" '(should have been 4860 characters)' fi fi echo shar: "extracting 'n_shell.c'" '(1369 characters)' if test -f 'n_shell.c' then echo shar: "will not over-write existing file 'n_shell.c'" else sed 's/^X//' << \SHAR_EOF > 'n_shell.c' X/* X * Spawn a 'native' shell. 'Native' means the shell found in the SHELL X * environmental variable. X */ X X#include X#include X#include X Xvoid Xnative_shell() X{ X WINDOW *sh_win, *newwin(); X int (*istat)(), (*qstat)(), status, pid, w; X char *shell, *shellpath, *getenv(), *strrchr(); X unsigned int sleep(); X void _exit(); X /* a full window */ X sh_win = newwin(LINES, COLS, 0, 0); X X clear_absolute(sh_win); X waddstr(sh_win, "Pcomm <=> Unix gateway, use ^D or 'exit' to return\n"); X wrefresh(sh_win); X /* out of curses mode */ X resetterm(); X X shellpath = getenv("SHELL"); X if (shellpath == NULL || *shellpath == NULL) X shellpath = "/bin/sh"; X X shell = strrchr(shellpath, '/') + 1; X X if (!(pid = fork())) { X#ifdef SGID X setgid(getgid()); X#endif /* SGID */ X execl(shellpath, shell, "-i", 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X while ((w = wait(&status)) != pid && w != -1) X ; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* back to curses mode */ X fixterm(); X sleep(1); X X clear_absolute(stdscr); X delwin(sh_win); X return; X} X X/* X * Clear the screen absolutely! It's incrediblely hard to get curses() to X * clear the screen when it thinks its already clear. X */ X Xint Xclear_absolute(win) XWINDOW *win; X{ X clearok(curscr, 1); X wrefresh(win); X clearok(curscr, 0); X return(0); X} SHAR_EOF if test 1369 -ne "`wc -c < 'n_shell.c'`" then echo shar: "error transmitting 'n_shell.c'" '(should have been 1369 characters)' fi fi echo shar: "extracting 'p_lib.c'" '(5786 characters)' if test -f 'p_lib.c' then echo shar: "will not over-write existing file 'p_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'p_lib.c' X/* X * Routines to manipulate the pcomm.param file. X */ X X#include X#include "param.h" X#include "status.h" X X/* X * Read the parameter structure from the pcomm.param file. Returns a X * pointer to the PARAM structure. All errors are fatal. X */ X Xstruct PARAM * Xread_param() X{ X FILE *fp; X int i, oops; X char buf[80], *temp_token, *str, *strdup(); X char message[80], *str_tok(); X static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY", "D_DBITS", X "D_SBITS", "HOT", "ASCII_HOT", "D_DUPLEX", "FLOW", "CR_IN", "CR_OUT", X "LOGFILE", "DUMPFILE", "STRIP", "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", X "ESC_CHAR", "ABORT", "CDELAY", "PAUSE", "LECHO", "EXPAND", "CR_DELAY", X "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", "LF_DN", "LD_PLUS", X "LD_MINUS", "LD_AT", "LD_POUND"}; X static struct PARAM p; X void error_win(); X /* read permission already checked */ X fp = fopen(status->p_path, "r"); X X oops = 0; X for (i=0; ip_path); X error_win(1, buf, message); X } X return(&p); X} X X/* X * Write the updated param structure to disk. The values in memory should X * have already been "purified". Later, we'll update only the entries that X * have been explicitly asked for. A return code of 1 means non-fatal error. X */ X Xint Xupdate_param() X{ X FILE *fp; X char buf[80]; X void error_win(); X /* open for write */ X if (!(fp = fopen(status->p_path, "w"))) { X sprintf(buf, "'%s'", status->p_path); X error_win(0, "No write permission on parameter file", buf); X return(1); X } X X fprintf(fp, "D_BAUD=%d\n", param->d_baud); X fprintf(fp, "D_PARITY=%c\n", param->d_parity); X fprintf(fp, "D_DBITS=%d\n", param->d_dbits); X fprintf(fp, "D_SBITS=%d\n", param->d_sbits); X fprintf(fp, "HOT=%d\n", param->hot); X fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot); X fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex); X fprintf(fp, "FLOW=%s\n", param->flow); X fprintf(fp, "CR_IN=%s\n", param->cr_in); X fprintf(fp, "CR_OUT=%s\n", param->cr_out); X fprintf(fp, "LOGFILE=%s\n", param->logfile); X fprintf(fp, "DUMPFILE=%s\n", param->dumpfile); X fprintf(fp, "STRIP=%s\n", param->strip); X fprintf(fp, "PAUSE_CHAR=%c\n", param->pause_char); X fprintf(fp, "CR_CHAR=%c\n", param->cr_char); X fprintf(fp, "CTRL_CHAR=%c\n", param->ctrl_char); X fprintf(fp, "ESC_CHAR=%c\n", param->esc_char); X fprintf(fp, "ABORT=%s\n", param->abort); X fprintf(fp, "CDELAY=%d\n", param->cdelay); X fprintf(fp, "PAUSE=%d\n", param->pause); X fprintf(fp, "LECHO=%s\n", param->lecho); X fprintf(fp, "EXPAND=%s\n", param->expand); X fprintf(fp, "CR_DELAY=%d\n", param->cr_delay); X fprintf(fp, "PACE=%s\n", param->pace); X fprintf(fp, "CR_UP=%s\n", param->cr_up); X fprintf(fp, "LF_UP=%s\n", param->lf_up); X fprintf(fp, "TIMER=%d\n", param->timer); X fprintf(fp, "CR_DN=%s\n", param->cr_dn); X fprintf(fp, "LF_DN=%s\n", param->lf_dn); X fprintf(fp, "LD_PLUS=%s\n", param->ld_plus); X fprintf(fp, "LD_MINUS=%s\n", param->ld_minus); X fprintf(fp, "LD_AT=%s\n", param->ld_at); X fprintf(fp, "LD_POUND=%s\n", param->ld_pound); X X fclose(fp); X return(0); X} SHAR_EOF if test 5786 -ne "`wc -c < 'p_lib.c'`" then echo shar: "error transmitting 'p_lib.c'" '(should have been 5786 characters)' fi fi echo shar: "extracting 'pexit.c'" '(2142 characters)' if test -f 'pexit.c' then echo shar: "will not over-write existing file 'pexit.c'" else sed 's/^X//' << \SHAR_EOF > 'pexit.c' X/* X * Exit pcomm. A user requested abort. There are a lot of things to do X * before we exit! X */ X X#include X#include X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X#include "status.h" X Xvoid Xpexit(fd) Xint fd; X{ X WINDOW *ex_win, *newwin(); X void cleanup(), status_line(); X X ex_win = newwin(5, 33, 3, 7); X X box(ex_win, '|', '-'); X mvwattrstr(ex_win, 0, 3, A_BOLD, " Exit "); X if (yes_prompt(ex_win, 2, 4, A_BLINK, "Exit to Unix")) { X status_line(" exiting"); X cleanup(0); X } X if (fd == -1) { X werase(ex_win); X wrefresh(ex_win); X } X delwin(ex_win); X return; X} X X/* X * Do the cleanup detail before we exit. X */ X Xvoid Xcleanup(val) Xint val; X{ X void release_port(), input_off(), exit(), status_line(); X char *ttyname(); X /* kill the input routine */ X input_off(); X /* zap the virtual screen file */ X unlink(status->vs_path); X /* release the port */ X release_port(0); X /* erase the window we made */ X touchwin(stdscr); X clear(); X refresh(); X endwin(); X /* return the tty chmod */ X chmod(ttyname(0), status->msg); X exit(val); X} X X/* X * Open a window to display an error message. Handles both fatal and X * non-fatal errors X */ X Xvoid Xerror_win(code, line_one, line_two) Xint code; Xchar *line_one, *line_two; X{ X WINDOW *e_win, *newwin(); X void cleanup(), status_line(); X X e_win = newwin(7, 70, 9, 5); X /* display the nasty note */ X mvwaddstr(e_win, 2, 4, line_one); X mvwaddstr(e_win, 3, 4, line_two); X box(e_win, '|', '-'); X X if (code) { X mvwattrstr(e_win, 0, 4, A_BOLD, " Error "); X mvwattrstr(e_win, 5, 24, A_BLINK, "Press any key to exit"); X wmove(e_win, 5, 46); X } X else { X mvwattrstr(e_win, 0, 4, A_BOLD, " Warning "); X mvwattrstr(e_win, 5, 22, A_BLINK, "Press any key to continue"); X wmove(e_win, 5, 48); X } X beep(); X wrefresh(e_win); X X wgetch(e_win); X werase(e_win); X wrefresh(e_win); X delwin(e_win); X X if (code) { X /* X * Since this routine gets called if there is an error reading X * the support files, the dir and param structures can't be X * guaranteed to exist yet. X */ X if (dir != NULL && param != NULL) X status_line(" exiting"); X cleanup(code); X } X return; X} SHAR_EOF if test 2142 -ne "`wc -c < 'pexit.c'`" then echo shar: "error transmitting 'pexit.c'" '(should have been 2142 characters)' fi fi echo shar: "extracting 'port.c'" '(6122 characters)' if test -f 'port.c' then echo shar: "will not over-write existing file 'port.c'" else sed 's/^X//' << \SHAR_EOF > 'port.c' X/* X * Routines to get or release a tty port. X */ X X#define LOCKDIR "/usr/spool/uucp" X#undef ASCII_PID X X#include X#include X#include X#ifdef UNIXPC X#include X#endif /* UNIXPC */ X#include "dial_dir.h" X#include "modem.h" X#include "status.h" X Xint getty_status; X/* X * Finds a free (or requested) serial port. Creates a lock file to hold X * it for our use. Loads the modem database. A return code of 1 means X * all ports (or the requested port) are busy. X */ X Xint Xget_port() X{ X int i, j, k, progpid, fd, list[NUM_TTY]; X char file[80], buf[80], message[80], *strdup(); X void error_win(), line_set(), release_port(), send_str(); X void free_ptr(); X X /* X * If we already have a port, see if it is good enough for the X * current request. X */ X if (status->fd != -1) { X if (!strcmp(dir->index[dir->d_cur], modem->tty[modem->t_cur]) || X modem->mbaud[modem->t_cur] >= dir->baud[dir->d_cur]) { X /* X * Re-initialize the modem because the baud X * rate (or other parameters) may have changed. X */ X line_set(); X send_str(modem->init[modem->m_cur]); X return(0); X } X } X release_port(1); X X /* X * See if you want a specific tty port. If the index field in the X * dialing directory is a valid device name, then use that tty. X */ X sprintf(buf, "/dev/%s", dir->index[dir->d_cur]); X list[0] = -1; X /* if index is a valid device */ X if (!access(buf, 0)) { X for (i=0; it_entries; i++) { X /* and it exists in modem database */ X if (!strcmp(dir->index[dir->d_cur], modem->tty[i])) { X list[0] = i; X list[1] = -1; X break; X } X } X } X X /* X * Create a list of acceptable ttys. It searches the tty database X * for the requested baud rate. X */ X k = 0; X if (list[0] == -1) { X for (i=0; it_entries; i++) { X /* skip ports with no modems */ X if (!strcmp(modem->tname[i], "DIRECT")) X continue; X X /* can handle requested baud rate ? */ X if (modem->mbaud[i] >= dir->baud[dir->d_cur]) X list[k++] = i; X } X /* the end of list marker */ X list[k] = -1; X } X /* empty list ? */ X if (list[0] == -1) { X sprintf(message, "No modem at a %d baud rating exists in", dir->baud[dir->d_cur]); X sprintf(file, "modem file '%s'", status->m_path); X error_win(0, message, file); X return(1); X } X /* check the list for a free port */ X i = 0; X while (list[i] != -1) { X /* create a lock file name */ X sprintf(file, "%s/LCK..%s", LOCKDIR, modem->tty[list[i]]); X X /* X * See if the lock file exists... We DO NOT look to see X * if the pid in the file is still active. Maybe I'll X * change this later... X */ X if (access(file, 0)) { X getty_status = set_getty(modem->tty[list[i]], 0); X X if ((fd = open(file, O_CREAT|O_WRONLY, 0666)) < 0) { X set_getty(modem->tty[list[i]], 1); X sprintf(buf, "'%s'", file); X error_win(1, "Can't create the lockfile", buf); X } X#ifdef ASCII_PID X sprintf(buf, "%10d\n", getpid()); X write(fd, buf, 11); X#else /* ASCII_PID */ X progpid = getpid(); X write(fd, (char *)&progpid, sizeof(int)); X#endif /* ASCII_PID */ X close(fd); X /* store the new values */ X free_ptr(status->lock_path); X status->lock_path = strdup(file); X modem->t_cur = list[i]; X X /* open the device (hold DTR high) */ X sprintf(buf, "/dev/%s", modem->tty[list[i]]); X if ((fd = open(buf, O_RDWR|O_NDELAY)) < 0) { X set_getty(modem->tty[list[i]], 1); X sprintf(file, "Can't open port '%s' for read and write", buf); X error_win(1, file, NULL); X } X X /* turn off the "no delay" mode */ X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); X status->fd = fd; X /* change line settings */ X line_set(); X /* load the modem data base */ X for (j=0; jm_entries; j++) { X if (!strcmp(modem->tname[list[i]], modem->mname[j])) { X modem->m_cur = j; X break; X } X } X /* initialize the modem */ X send_str(modem->init[j]); X return(0); X } X i++; X } X error_win(0, "All ports are busy now, try again later", NULL); X return(1); X} X X/* X * Release the port. Closes the file descriptor and removes the X * lock file X */ X Xvoid Xrelease_port(verbose) Xint verbose; X{ X char buf[80]; X extern char *null_ptr; X void free_ptr(), hang_up(); X X /* X * The modem structure can't be guaranteed to exist yet. For example, X * an error in reading one of the other support files would cause X * this routine to be used before the MODEM structure gets allocated. X */ X if (modem == NULL) X return; X /* close the port */ X if (status->fd != -1) { X ioctl(status->fd, TCFLSH, 2); X /* X * Since HUPCL is set, the close() should drop the DTR and X * hang up the modem (provided you've got the modem to X * respond to DTR). Since this is not guaranteed, we send X * the hangup string first. X */ X hang_up(verbose); X close(status->fd); X } X /* remove the lock */ X if (*status->lock_path != NULL) { X if (unlink(status->lock_path)) { X sprintf(buf, "'%s'", status->lock_path); X error_win(0, "Can't remove the lock file", buf); X } X free_ptr(status->lock_path); X status->lock_path = null_ptr; X } X /* turn the getty back on? */ X if (getty_status) X set_getty(modem->tty[modem->t_cur], 1); X /* cleanup the structure */ X status->fd = -1; X modem->m_cur = -1; X modem->t_cur = -1; X return; X} X X/* X * Turn the /etc/getty on or off for the specified port. A return code X * of 1 means that the getty was on. Systems with uugetty or dedicated X * dialout ports won't need this routine. X */ X Xint Xset_getty(tty, on) Xchar *tty; Xint on; X{ X#ifdef UNIXPC X int i, ret_code; X char buf[40]; X unsigned int sleep(); X /* the last three characters */ X i = strlen(tty) -3; X X ret_code = 0; X if (on) { X sprintf(buf, "setgetty %s 1", tty+i); X system(buf); X } X else { X sprintf(buf, "setgetty %s 0", tty+i); X if (system(buf) == 512) X ret_code = 1; X sleep(1); X } X return(ret_code); X#else /* UNIXPC */ X /* X * If you don't have one of these cute little routines, you X * might wanna write one. It should check for an existing lock X * file, edit the /etc/inittab file, and issue an init -q. X * Obviously the program would be suid to root. X */ X return(0); X#endif /* UNIXPC */ X} SHAR_EOF if test 6122 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 6122 characters)' fi fi echo shar: "extracting 'redial.c'" '(2216 characters)' if test -f 'redial.c' then echo shar: "will not over-write existing file 'redial.c'" else sed 's/^X//' << \SHAR_EOF > 'redial.c' X/* X * The redial option (actually a misnomer, it's really a queuing system). X * We expect a space-separated list of dialing directory entries (although X * new users always try to put in a phone number). A return code of 1 X * means we're ready to dial. X */ X X#include X#include X#include "dial_dir.h" X#include "misc.h" X Xint Xredial(fd) Xint fd; X{ X WINDOW *rd_win, *newwin(); X char *ans, *entry, *get_str(), *strchr(), *strtok(); X int i, oops, number, ret_code; X X rd_win = newwin(6, 70, 5, 5); X X mvwaddstr(rd_win, 4, 23, "(CR for previous numbers)"); X mvwaddstr(rd_win, 2, 4, "Directory Entry Number(s): "); X box(rd_win, '|', '-'); X X mvwattrstr(rd_win, 0, 3, A_BOLD, " Redial Queue "); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X /* get the string of numbers */ X ret_code = 0; X while ((ans = get_str(rd_win, 35, "0123456789+-@# ", NULL)) != NULL) { X oops = 0; X if (*ans == NULL) { X /* use previous queue */ X if (dir->q_num[0] != -1) { X ret_code = 1; X break; X } X /* there is no previous queue */ X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "No previous numbers"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X continue; X } X /* parse the queue values */ X entry = strtok(ans, " "); X for (i=0; iq_num[i] = -1; X continue; X } X /* is there a LD code ? */ X dir->q_ld[i] = NULL; X if (strchr("+-@#", *entry)) { X dir->q_ld[i] = *entry; X entry++; X } X X /* X * Zero is valid here, because it means use X * the current entry information. X */ X number = atoi(entry); X if (number < -1 || number > NUM_DIR) { X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "Invalid directory entry number"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X clear_line(rd_win, 2, 31, 1); X wrefresh(rd_win); X oops++; X break; X } X /* store the number in the queue */ X dir->q_num[i] = number; X entry = strtok((char *) NULL, " "); X } X if (oops) X continue; X ret_code = 1; X break; X } X if (fd == -1) { X werase(rd_win); X wrefresh(rd_win); X } X delwin(rd_win); X return(ret_code); X} SHAR_EOF if test 2216 -ne "`wc -c < 'redial.c'`" then echo shar: "error transmitting 'redial.c'" '(should have been 2216 characters)' fi fi exit 0 # End of shell archive