www.pudn.com > commutil.zip > CONFIG.CPP


// ******************************************************************** // 
//                                                                      // 
//      CONFIG.CPP                                                      // 
//      Copyright (c) 1993, Michael Holmes and Bob Flanders             // 
//      C++ Communication Utilities                                     // 
//                                                                      // 
//      Chapter 7: Receiving a FAX                                      // 
//      Last changed in chapter 4                                       // 
//                                                                      // 
//      This file contains the functions that are under the             // 
//      Alt-Configure on the main menu.  These functions manage         // 
//      the selection and line setup of the communications ports.       // 
//                                                                      // 
// ******************************************************************** // 
 
 
/* ******************************************************************** * 
 * 
 *  ports() -- port selection menu routine 
 * 
 * ******************************************************************** */ 
 
int     ports(int c, int r)                 // column and row for window 
{ 
int     i,                                  // loop counter 
        k,                                  // keyboard input 
        idx,                                // line index 
        old_port;                           // starting port number 
char    b[20];                              // work buffer 
Window  port_win(c, r, c + 19,              // define temporary window 
            r + nbr_ports + 1,              // ..to hold port list 
            menu_cn, menu_cr);              // ..using system colors 
 
 
port_win.Open(double_line);                 // open window with a border 
idx = old_port = comport;                   // save current port number 
 
while(1)                                    // loop till user exits 
    { 
    for (i = 0, k = 1;                      // walk thru port table 
            i < COUNT(com_ports); i++)      // ..displaying available ones 
        { 
        if (NOT com_ports[i].available)     // q. port available? 
            continue;                       // a. no .. skip to next port 
 
        sprintf(b, "%c %s %X IRQ%d",        // format a buffer 
                i == comport ? 0xfe : 0xfa, // ..for each port, showing 
                com_ports[i].name,          // ..selected port flag, 
                com_ports[i].port,          // ..port name, base 
                com_ports[i].irq);          // ..address and irq number 
 
        port_win.GotoXY(2, k++);            // cursor to start of line 
 
        if (i == idx)                       // q. selected line? 
            port_win.DisplayReverse(b);     // a. yes .. highlight line 
         else 
            port_win.Display(b);            // else .. just display it 
        } 
 
    while (NOT (k = get_key(NO_ALT)))       // wait for a key 
        ;                                   // ..before continuing 
 
    switch (k)                              // based on keyboard input 
        { 
        case SPACE:                         // select current item 
        case CR:                            // . . . . 
            comport = idx;                  // set entry as active 
            status_line();                  // update the status line 
            break;                          // ..and wait for next key 
 
        case UP:                            // move up list 
            for (i = idx - 1; i >= 0; i--)  // search to top of list 
                if (com_ports[i].available) // q. find available one? 
                    { 
                    idx = i;                // a. yes .. set up index 
                    break;                  // ..and exit this loop 
                    } 
 
            if (idx == i)                   // q. find a new port? 
                break;                      // a. yes .. wait for next key 
 
            for (i = COUNT(com_ports) - 1;  // now search from bottom 
                    i >= 0; i--) 
                if (com_ports[i].available) // q. find available one? 
                    { 
                    idx = i;               // a. yes .. set up index 
                    break;                 // ..and exit this loop 
                    } 
 
            break;                          // wait for next key 
 
        case DOWN:                          // move down list 
            for (i = idx + 1;               // search to bottom 
                    i < COUNT(com_ports); i++) 
                if (com_ports[i].available) // q. find available one? 
                    { 
                    idx = i;                // a. yes .. set up index 
                    break;                  // ..and exit this loop 
                    } 
 
            if (idx == i)                   // q. find a new port? 
                break;                      // a. yes .. wait for next key 
 
            for (i = 0;                     // now from the top 
                    i < COUNT(com_ports); i++) 
                if (com_ports[i].available) // q. find available one? 
                    { 
                    idx = i;                // a. yes .. set up index 
                    break;                  // ..and exit this loop 
                    } 
 
            break;                          // wait for next key 
 
        case ESC:                           // escape from this menu 
            k = 0;                          // set key value to zero 
                                            // ..and fall into next case 
 
        case LEFT:                          // move left 
        case RIGHT:                         // ..or move right 
            if (old_port != comport)        // q. change ports? 
                build_comm();               // a. yes .. build new Comm 
 
            return(k);                      // then rtn with the keystroke 
 
        default:                            // error case 
            printf(BELL);                   // ..just ring the bell 
        } 
    } 
 
return(0);                                  // help keep MSC happy 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  comm_parms() -- communications parameters menu routine 
 * 
 * ******************************************************************** */ 
 
int     comm_parms(int c, int r)            // column and row for window 
{ 
int     chg,                                // change flag 
        i,                                  // loop variable 
        k,                                  // keyboard input 
        idx = 0;                            // line index 
char    b[20];                              // work buffer 
Window  comm_win(c, r, c + 18, r + 5,       // define temporary window 
            menu_cn, menu_cr);              // ..using system colors 
 
 
comm_win.Open(double_line);                 // open window with a border 
 
while(1)                                    // loop till user exits 
    { 
    for (i = 0; i < 4; i++)                 // display each parm 
        { 
        sprintf(b, "%-9s %5s",              // format a buffer 
                line[i].name,               // ..for each line parameter 
                line[i].lp->parm);          // ..and its selected option 
 
        comm_win.GotoXY(2, i + 1);          // cursor to start of line 
 
        if (i == idx)                       // q. selected line? 
            comm_win.DisplayReverse(b);     // a. yes .. highlight line 
         else 
            comm_win.Display(b);            // else .. just display it 
        } 
 
    while (NOT (k = get_key(NO_ALT)))       // wait for a key 
        ;                                   // ..before continuing 
 
    switch (k)                              // based on keyboard input 
        { 
        case SPACE:                         // change to next item 
        case CR:                            // . . . . 
            line[idx].lp =                  // find next item in the list 
                    &line_parms[line[idx].lp->next]; 
            status_line();                  // update the status line 
            chg = 1;                        // post change flag 
            break;                          // ..and wait for next key 
 
        case UP:                            // move up list 
            if (--idx < 0)                  // q. reach past top of list? 
                idx = 3;                    // a. yes .. reset at bottom 
 
            break;                          // ..and wait for next key 
 
        case DOWN:                          // move down list 
            if (++idx > 3)                  // q. reaching past bottom? 
                idx = 0;                    // a. yes .. reset to top 
 
            break;                          // ..and wait for next key 
 
        case ESC:                           // escape from this menu 
            k = 0;                          // set key value to zero 
                                            // ..and fall into next case 
 
        case LEFT:                          // move left 
        case RIGHT:                         // ..or move right 
            if (chg)                        // q. parms changed? 
                { 
                comm->SetSpeed(             // a. yes .. set baud rate 
                        line[SPEED].lp->value); 
                comm->SetLine(              // ..and line ctrl register 
                        line[PARITY].lp->value |    // ..for parity 
                        line[DATA].lp->value |      // ..data bits 
                        line[STOP].lp->value);      // ..and stop bits 
                } 
 
            return(k);                      // return with the keystroke 
 
        default:                            // error case 
            printf(BELL);                   // ..just ring the bell 
        } 
    } 
 
return(0);                                  // keep MSC happy 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  load_config() -- load modem configuration file 
 * 
 * ******************************************************************** */ 
 
void    load_config(char *s)                // modem configuration file 
{ 
int     i, j;                               // work integer 
char    buf[256],                           // file buffer 
        c_path[MAX_PATH],                   // config file w/path 
       *p, *q,                              // work character pointer 
        userfile = 0;                       // user filename flag 
long    v;                                  // value of comsetting token 
FILE   *f;                                  // config file handle 
 
 
if (NOT s)                                  // q. filename given? 
   s = cfg_file;                            // a. no .. use default name 
 else 
   userfile = 1;                            // else .. cfg file specified 
 
strcpy(buf, s);                             // copy filename to work area 
s = buf;                                    // ..and reset pointer 
 
if (NOT strchr(s, '.'))                     // q. file extension given? 
    strcat(s, cfg_extension);               // a. no .. append one 
 
_searchenv(s, "PATH", c_path);              // find the config file 
 
if (*c_path)                                // q. find a config file? 
    {                                       // a. yes .. process file 
    if (NOT (f = fopen(c_path, "r")))       // q. file open ok? 
        quit_with(open_error, c_path);      // a. no .. quit w/error msg 
 
    printf(loading_cfg, c_path);            // else .. inform user 
    } 
 else if (userfile)                         // q. user specify file? 
    quit_with(no_config, s);                // a. yes .. quit w/error msg 
 else 
    return;                                 // else .. just use defaults 
 
while(NOT feof(f) &&                        // read thru whole file 
            fgets(buf, sizeof(buf), f))     // ..and while still data 
    { 
    if (*(first_nonblank(buf)) == ';')      // q. find a comment? 
        continue;                           // a. yes .. get next line 
 
    if ((p = strtok(buf, delimit_1)) == 0)  // q. find a token? 
        continue;                           // a. no .. get next line 
 
    if (NOT stricmp(p, COMPORT))            // q. get the COMPORT parm? 
        { 
        p = strtok(0, delimit_1);           // a. yes .. get next token 
        i = atoi(p);                        // ..then get port number 
 
        if (i >= 1 && i <= 8)               // q. in the right range? 
            comport = --i;                  // a. yes .. save index 
         else 
            quit_with(bad_setting,          // else .. quit w/error msg 
                COMPORT, p);                // ..telling them the problem 
        } 
 
     else if (NOT stricmp(p, COMSETTING))   // q. COMSETTING command? 
        { 
        p = strtok(0, delimit_3);           // a. yes .. get operands 
        p += strspn(p, delimit_1);          // find first token 
 
        for (i = 0;; i++)                   // loop thru sub-tokens 
            { 
            p = strtok(i == 0 ? p : 0,      // get a sub-token from the 
                    delimit_2);             // ..command 
 
            if (NOT p)                      // q. out of sub-tokens? 
                break;                      // a. yes .. exit loop 
 
            v = atol(p);                    // check if numeric token 
 
            for (j = 0;                     // validate line parameters 
                    j < COUNT(line_parms); j++) 
                if ((v && NOT stricmp(p,    // q. does numeric token 
                        line_parms[j].parm))// ..match the table entry? 
                        || (NOT v && NOT    // ..or does non-numeric match 
                        strnicmp(p,         // ..some portion of the 
                        line_parms[j].parm, // ..table entry? 
                        strlen(p)))) 
                    { 
                    line[line_parms[j].idx].lp  // a. yes .. point to the 
                        = &line_parms[j];       // ..table entry for later 
                    break;                      // ..and do next parameter 
                    } 
 
            if (j == COUNT (line_parms))    // q. find parameter? 
                quit_with(bad_parm, p);     // a. no .. quit w/error msg 
            } 
        } 
 
     else if (NOT stricmp(p, NOCOMCHECK))   // q. NOCOMCHECK command? 
        comcheck = 0;                       // a. yes .. don't check ports 
 
     else if (NOT stricmp(p, FLOWCTL))      // q. FLOWCTL command? 
        { 
        p = strtok(0, delimit_1);           // a. yes .. get next token 
 
        if (NOT stricmp(p, ON))             // q. user specify "on"? 
            flowctl = 1;                    // a. yes .. set flag 
         else if (NOT stricmp(p, OFF))      // q. did they say "off"? 
            flowctl = 0;                    // a. yes .. clear flag 
         else 
            quit_with(bad_setting,          // else .. quit w/error msg 
                    FLOWCTL, p);            // ..telling them the problem 
        } 
 
     else if (NOT strnicmp(p, COM, 3) &&    // q. COMn command 
            (p[3] >= '1' && p[3] <= '8') && // ..in the right range 
            NOT p[4])                       // ..and the right format? 
        { 
        j = p[3] - '1';                     // a. yes .. get index 
 
        p = strtok(0, delimit_3);           // get remainder of operands 
        p += strspn(p, delimit_1);          // skip white space 
        p = strtok(p, delimit_2);           // get next token 
        sscanf(p, "%x", &i);                // ..which is port base addr 
 
        if (i >= 0x100 && i <= 0x7f8        // q. in the right range 
                || i == 0)                  // ..or zero? 
            com_ports[j].port = i;          // a. yes .. save number 
         else 
            quit_with(bad_port, j + 1, p);  // else .. quit w/error msg 
 
        p = strtok(0, delimit_2);           // get next token 
        i = atoi(p);                        // ..get interrupt number 
 
        if (i >= 2 && i <= 7                // q. in the right range 
                || i == 0)                  // ..or zero? 
            com_ports[j].irq = i;           // a. yes .. save number 
         else 
            quit_with(bad_irq, j + 1, p);   // else .. quit w/error msg 
        } 
 
     else if (NOT strnicmp(p, PC, 3))       // q. user command (PC:)? 
        {                                   // a. yes .. process statement 
        if (NOT strlen(&p[3]))              // q. missing the cmd name? 
            quit_with(bad_pc_cmd);          // a. yes .. quit w/error msg 
 
        q = strtok(0, delimit_eol);         // get rest of the line 
        q = ascii_encode(q);                // ..compress ctrl sequences 
        new List(&user_commands, &p[3], q); // ..and store in list 
        } 
 
     else 
        { 
        for (i = 0;                         // for each entry in the list 
                i < COUNT(commands); i++) 
            { 
            if (NOT stricmp(p,              // q. find the command 
                    commands[i][0]))        // ..in the list? 
                { 
                p = strtok(0, delimit_eol); // a. yes .. get next token 
                commands[i][1] =            // get a copy of the 
                    strdup(ascii_encode(p));// ..packed ctrl chars 
                break;                      // ..and exit loop 
                } 
            } 
 
        if (i == (COUNT(commands) / 2))     // q. find command in table? 
            quit_with(unknown_cmd, p);      // a. no .. quit w/error msg 
        } 
    } 
 
fclose(f);                                  // close config file 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  check_port() -- check one comm port for presence and type 
 * 
 * ******************************************************************** */ 
 
port_type check_port(int base)              // base port address 
{ 
char    mcr,                                // modem control register 
        msr;                                // modem status register 
 
 
if (comcheck)                               // q. check comports? 
    {                                       // a. yes .. proceed 
    mcr = IN(MCR);                          // get current MCR contents 
    OUT(MCR, 0x18);                         // set local loop mode 
    msr = IN(MSR);                          // ..and read delta bits 
    OUT(MCR, mcr);                          // restore modem control reg 
 
    if ((msr & 0xf0) != 0x80)               // q. state proper now? 
        return(no_port);                    // a. no .. no UART available 
    } 
                                            // check for UART type 
OUT(SCR, 0x55);                             // write to scratch register 
 
if (IN(SCR) != 0x55)                        // q. scratch register work? 
    return(std_uart);                       // a. no .. must be 8250 
 
OUT(FCR, 0xcf);                             // try to enable FIFOs 
 
if ((IN(IIR) & 0xc0) != 0xc0)               // q. FIFO bits found? 
    return(std_uart);                       // a. no .. must be 16450 
 
OUT(FCR, 0);                                // turn off FIFOs 
return(fifo_uart);                          // ..show it is a 1655x 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  check_ports() -- check for availability of comm ports 
 * 
 * ******************************************************************** */ 
 
void    check_ports(void) 
{ 
int     i,                                  // loop control 
        first = -1,                         // first found port 
        p;                                  // base port address 
 
 
for (i = 0; i < COUNT(com_ports); i++)      // search thru port array .. 
    { 
    p = com_ports[i].port;                  // get base port address 
 
    if (p == 0 || com_ports[i].irq == 0)    // q. good table entry? 
        continue;                           // a. no .. skip to next port 
 
    if ((com_ports[i].available =           // q. comm port there? 
            check_port(p)) == no_port)      // 
        continue;                           // a. no .. continue 
 
    nbr_ports++;                            // bump port counter 
 
    if (comport == -1)                      // q. selected a port yet? 
        comport = i;                        // a. no .. use this one 
 
    if (first == -1)                        // q. found first port yet? 
        first = i;                          // a. no .. use this one 
    } 
 
if (NOT nbr_ports)                          // q. any ports found? 
    quit_with(no_ports);                    // a. no .. quit w/error msg 
 
if (NOT com_ports[comport].available)       // q. req'd port unavailable? 
    comport = first;                        // a. yes .. use first found 
 
}