Annotation of embedaddon/trafshow/colormask.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     Copyright (c) 1993-1997,2004 Rinet Corp., Novosibirsk, Russia
                      3:  *
                      4:  * Redistribution and use in source forms, with and without modification,
                      5:  * are permitted provided that this entire comment appears intact.
                      6:  * Redistribution in binary form may occur without any restrictions.
                      7:  *
                      8:  * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
                      9:  */
                     10: 
                     11: #ifdef HAVE_CONFIG_H
                     12: #include <config.h>
                     13: #endif
                     14: 
                     15: #ifdef HAVE_HAS_COLORS
                     16: 
                     17: #ifdef HAVE_SLCURSES
                     18: #include <slcurses.h>
                     19: #elif  HAVE_NCURSES
                     20: #include <ncurses.h>
                     21: #else
                     22: #include <curses.h>
                     23: #endif
                     24: #include <sys/param.h>
                     25: #include <sys/types.h>
                     26: #include <sys/socket.h>
                     27: #include <netinet/in.h>
                     28: #include <arpa/inet.h>
                     29: #include <stdio.h>
                     30: #include <stdlib.h>
                     31: #include <string.h>
                     32: #include <unistd.h>
                     33: #include <ctype.h>
                     34: #include <netdb.h>
                     35: #include <errno.h>
                     36: 
                     37: #include "colormask.h"
                     38: #include "trafshow.h"
                     39: #include "netstat.h"
                     40: #ifdef DEBUG
                     41: #include "show_stat.h" /* just for hdr2str() */
                     42: #endif
                     43: 
                     44: /* mask entry */
                     45: struct cm_entry {
                     46:        struct internet_header in_hdr;
                     47:        int src_mask;           /* source ip address mask */
                     48:        int dst_mask;           /* destination ip address mask */
                     49: 
                     50:        short   pair;           /* color-pair */
                     51:        int     attr;           /* video attributes; bold, blink, etc */
                     52: };
                     53: 
                     54: static struct cm_entry *color_mask = NULL;
                     55: static int n_masks = 0;
                     56: static int n_pairs = 0;
                     57: static const char *rc_file = 0;
                     58: static int rc_line;
                     59: 
                     60: /* SLcurses can't handle attributes as well; so hack it */
                     61: #ifdef HAVE_SLCURSES
                     62: static void
                     63: slang_init_pair(short pair, short fc, short bc, int at)
                     64: {
                     65:        SLtt_set_color_object(pair, ((fc | (bc << 8)) << 8) | at);
                     66: }
                     67: 
                     68: static int
                     69: slang_pair_content(short pair, short *fc, short *bc)
                     70: {
                     71:        int attr;
                     72:        SLtt_Char_Type at;
                     73: 
                     74:        at = SLtt_get_color_object(pair);
                     75:        attr = at & (A_BOLD | A_BLINK);
                     76:        at &= ~(A_BOLD | A_BLINK);
                     77:        at >>= 8;
                     78:        *fc = at & 0xff;
                     79:        *bc = (at >> 8) & 0xff;
                     80: 
                     81:        return attr;
                     82: }
                     83: #endif /* HAVE_SLCURSES */
                     84: 
                     85: static short
                     86: findpair(short f, short b, int a)
                     87: {
                     88:        int i;
                     89:        short f1 = -1, b1 = -1;
                     90:        struct cm_entry *cm;
                     91: 
                     92:        for (cm = color_mask, i = 0; cm != NULL && i < n_masks-1; cm++, i++) {
                     93: #ifdef HAVE_SLCURSES
                     94:                int a1 = slang_pair_content(cm->pair, &f1, &b1);
                     95:                if (f1 >= COLORS) f1 = -1;
                     96:                if (b1 >= COLORS) b1 = -1;
                     97:                if (f == f1 && b == b1 && a == a1) return cm->pair;
                     98: #else
                     99:                pair_content(cm->pair, &f1, &b1);
                    100:                if (f1 >= COLORS) f1 = -1;
                    101:                if (b1 >= COLORS) b1 = -1;
                    102:                if (f == f1 && b == b1) return cm->pair;
                    103: #endif
                    104:        }
                    105:        return 0;
                    106: }
                    107: 
                    108: static int
                    109: add_colormask(const char *s, struct cm_entry *m)
                    110: {
                    111:        int i, attr = 0;
                    112:        short fc, bc;
                    113:        char f[100], *b;
                    114:        static char *ctab[8] = { "black", "red", "green", "yellow",
                    115:                                "blue", "magenta", "cyan", "white" };
                    116: #ifdef HAVE_USE_DEFAULT_COLORS
                    117:        static short fc_def = -1, bc_def = -1;
                    118: #else
                    119:        static short fc_def = COLOR_WHITE, bc_def = COLOR_BLACK;
                    120: #endif
                    121: 
                    122:        if ((b = strchr(strcpy(f, s), ':')) != NULL) *b++ = '\0';
                    123: 
                    124:        if (*f) {
                    125:                for (i = 0; i < 8; i++)
                    126:                        if (!strcasecmp(ctab[i], f)) break;
                    127:                if (i < 8) fc = i;
                    128:                else {
                    129:                        fc = atoi(f);
                    130:                        if (fc < 1 || fc > COLORS) {
                    131:                                fprintf(stderr, "%s: line %d: Unknown color `%s'\n",
                    132:                                        rc_file, rc_line, f);
                    133:                                return -1;
                    134:                        }
                    135:                }
                    136:                if (isupper((int)*f)) attr |= A_BOLD;
                    137:        } else fc = fc_def;
                    138: 
                    139:        if (b && *b) {
                    140:                for (i = 0; i < 8; i++)
                    141:                        if (!strcasecmp(ctab[i], b)) break;
                    142:                if (i < 8) bc = i;
                    143:                else {
                    144:                        bc = atoi(b);
                    145:                        if (bc < 1 || bc > COLORS) {
                    146:                                fprintf(stderr, "%s: line %d: Unknown color `%s'\n",
                    147:                                        rc_file, rc_line, b);
                    148:                                return -1;
                    149:                        }
                    150:                }
                    151:                if (isupper((int)*b)) attr |= A_BLINK;
                    152:        } else bc = bc_def;
                    153: 
                    154:        if (m != NULL) {
                    155:                if ((color_mask = realloc(color_mask, ++n_masks * sizeof(struct cm_entry))) == NULL) {
                    156:                        fprintf(stderr, "add_colormask: realloc: Out of memory?\n");
                    157:                        return -1;
                    158:                }
                    159:                if ((m->pair = findpair(fc, bc, attr)) == 0) {
                    160:                        if (++n_pairs < COLOR_PAIRS-1) {
                    161: #ifdef HAVE_SLCURSES
                    162:                                slang_init_pair(n_pairs, fc, bc, attr);
                    163: #else
                    164:                                init_pair(n_pairs, fc, bc);
                    165: #endif
                    166:                        } else {
                    167:                                fprintf(stderr, "%s: line %d: Max %d color-pairs can be used\n",
                    168:                                        rc_file, rc_line, COLOR_PAIRS-1);
                    169:                                return -1;
                    170:                        }
                    171:                        m->pair = n_pairs;
                    172:                }
                    173:                m->attr = attr;
                    174:                memcpy(color_mask + (n_masks-1), m, sizeof(struct cm_entry));
                    175:        } else {        /* default colors */
                    176: #ifdef HAVE_SLCURSES
                    177:                slang_init_pair(0, fc, bc, attr);
                    178: #else
                    179: #ifdef HAVE_BKGD
                    180:                init_pair(COLOR_PAIRS-1, fc, bc);
                    181:                bkgd(COLOR_PAIR(COLOR_PAIRS-1) | attr);
                    182: #elif  HAVE_WBKGD
                    183:                init_pair(COLOR_PAIRS-1, fc, bc);
                    184:                wbkgd(stdscr, COLOR_PAIR(COLOR_PAIRS-1) | attr);
                    185: #else /* assume the color-pair 0 is background for whole screen */
                    186:                init_pair(0, fc, bc);
                    187: #endif
                    188: #endif
                    189:                fc_def = fc;
                    190:                bc_def = bc;
                    191:        }
                    192:        return 0;
                    193: }
                    194: 
                    195: static int
                    196: is_any(const char *s)
                    197: {
                    198:        if (!s || !*s) return 0;
                    199:        return (!strcmp(s, "*") || !strcasecmp(s, "any") || !strcasecmp(s, "all"));
                    200: }
                    201: 
                    202: static int
                    203: is_number(const char *s)
                    204: {
                    205:        if (!s || !*s) return 0;
                    206:        for (; *s; s++) {
                    207:                if (!isdigit((int)*s)) return 0;
                    208:        }
                    209:        return 1;
                    210: }
                    211: 
                    212: static char *
                    213: str2proto(const char *str, int *proto)
                    214: {
                    215:        int num;
                    216:        struct protoent *pe;
                    217: 
                    218:        if (is_any(str)) {
                    219:                *proto = 0;
                    220:                return "";
                    221:        }
                    222:        if (is_number(str)) {
                    223:                num = atoi(str);
                    224:                if (num > 0 && num <= 0xff) {
                    225:                        if ((pe = getprotobynumber(num)) != 0) {
                    226:                                *proto = pe->p_proto;
                    227:                                return pe->p_name;
                    228:                        }
                    229:                        *proto = num;
                    230:                        return "";
                    231:                }
                    232:        }
                    233:        if ((pe = getprotobyname(str)) != 0) {
                    234:                *proto = pe->p_proto;
                    235:                return pe->p_name;
                    236:        }
                    237:        fprintf(stderr, "%s: line %d: Unknown protocol `%s'\n",
                    238:                rc_file, rc_line, str);
                    239:        return 0;
                    240: }
                    241: 
                    242: static int
                    243: str2port(const char *str, const char *proto)
                    244: {
                    245:        int num;
                    246:        struct servent *se;
                    247: 
                    248:        if (is_any(str))
                    249:                return 0;
                    250: 
                    251:        num = atoi(str);
                    252:        if (num > 0 && num <= 0xffff)
                    253:                return htons((u_int16_t)num);
                    254: 
                    255:        if ((se = getservbyname(str, (proto && *proto) ? proto : 0)) != 0)
                    256:                return se->s_port;
                    257: 
                    258:        if (proto && *proto) {
                    259:                fprintf(stderr, "%s: line %d: Unknown port `%s' at protocol `%s'\n",
                    260:                        rc_file, rc_line, str, proto);
                    261:        } else {
                    262:                fprintf(stderr, "%s: line %d: Unknown port `%s'\n",
                    263:                        rc_file, rc_line, str);
                    264:        }
                    265:        return -1;
                    266: }
                    267: 
                    268: static int
                    269: str2addr(const char *str, const char *proto, struct ip_address *addr, int *mask)
                    270: {
                    271:        int op, ver = 0;
                    272:        char buf[256], *cp, *mp, *pp;
                    273: 
                    274:        if (proto && !strcasecmp(proto, "IPv6")) {
                    275: #ifdef INET6
                    276:                ver = 6;
                    277: #else
                    278:                fprintf(stderr, "%s: line %d: IPv6 is unsupported at this system\n",
                    279:                        rc_file, rc_line);
                    280:                return -1;
                    281: #endif
                    282:        }
                    283:        cp = strcpy(buf, str);
                    284:        if ((mp = strchr(cp, '/')) != 0) {
                    285:                *mp++ = '\0';
                    286:                cp = mp;
                    287:        }
                    288:        if ((pp = strchr(cp, ',')) != 0) {
                    289:                *pp++ = '\0';
                    290:        }
                    291:        if (mp && !is_number(mp)) {
                    292:                fprintf(stderr, "%s: line %d: %s: Mask must be number of bits\n",
                    293:                        rc_file, rc_line, mp);
                    294:                return -1;
                    295:        }
                    296:        if (!is_any(buf)) {
                    297:                op = 0;
                    298: #ifdef INET6
                    299:                if (ver == 6 || strchr(buf, ':')) {
                    300:                        ver = 6;
                    301:                        op = inet_pton(AF_INET6, buf, &addr->ip6_addr);
                    302:                        if (op < 0) {
                    303:                                fprintf(stderr, "%s: line %d: %s: %s\n",
                    304:                                        rc_file, rc_line, buf, strerror(errno));
                    305:                                return -1;
                    306:                        }
                    307:                }
                    308: #endif
                    309:                if (!op) {
                    310:                        ver = 4;
                    311:                        op = inet_pton(AF_INET, buf, &addr->ip_addr);
                    312:                        if (op < 0) {
                    313:                                fprintf(stderr, "%s: line %d: %s: %s\n",
                    314:                                        rc_file, rc_line, buf, strerror(errno));
                    315:                                return -1;
                    316:                        }
                    317:                }
                    318:                if (!op) {
                    319:                        struct hostent *he;
                    320:                        if ((he = gethostbyname(buf)) == 0) {
                    321:                                fprintf(stderr, "%s: line %d: %s: Unknown host\n",
                    322:                                        rc_file, rc_line, buf);
                    323:                                return -1;
                    324:                        }
                    325:                        if (he->h_addrtype == AF_INET) {
                    326:                                ver = 4;
                    327:                                memcpy(&addr->ip_addr, he->h_addr,
                    328:                                       MIN(sizeof(addr->ip_addr), he->h_length));
                    329:                        }
                    330: #ifdef INET6
                    331:                        else if (he->h_addrtype == AF_INET6) {
                    332:                                ver = 6;
                    333:                                memcpy(&addr->ip6_addr, he->h_addr,
                    334:                                       MIN(sizeof(addr->ip6_addr), he->h_length));
                    335:                        }
                    336: #endif
                    337:                        else {
                    338:                                fprintf(stderr, "%s: line %d: %s: Unknown address family\n",
                    339:                                        rc_file, rc_line, buf);
                    340:                                return -1;
                    341:                        }
                    342:                }
                    343:        }
                    344:        if (pp) {
                    345:                if ((op = str2port(pp, proto)) == -1)
                    346:                        return -1;
                    347:                addr->ip_port = op;
                    348:        }
                    349:        if (mask) {
                    350:                if (mp) {
                    351:                        op = atoi(mp);
                    352:                        if (op < 8 || op > 128) {
                    353:                                fprintf(stderr, "%s: line %d: %d: Wrong mask\n",
                    354:                                        rc_file, rc_line, op);
                    355:                                return -1;
                    356:                        }
                    357:                        *mask = op;
                    358:                } else  *mask = 0;
                    359:        }
                    360:        return ver;
                    361: }
                    362: 
                    363: int
                    364: init_colormask()
                    365: {
                    366:        FILE *fp;
                    367:        int num;
                    368:        struct cm_entry me, *cm;
                    369:        char *cp, buf[1024];
                    370:        char s1[256], s2[256], s3[256], s4[256];
                    371: 
                    372:        if (rc_file) {
                    373:                free((char *)rc_file);
                    374:                rc_file = 0;
                    375:        }
                    376:        if (!color_conf) {
                    377:                if ((cp = getenv("HOME")) != 0) {
                    378:                        (void)strcpy(buf, cp);
                    379:                        (void)strcat(buf, "/");
                    380:                } else  buf[0] = '\0';
                    381:                (void)strcat(buf, ".");
                    382:                (void)strcat(buf, progname);
                    383:                if ((fp = fopen(buf, "r")) == NULL) {
                    384:                        (void)strcpy(buf, "/etc/");
                    385:                        (void)strcat(buf, progname);
                    386:                        if ((fp = fopen(buf, "r")) == NULL) return 0;
                    387:                }
                    388:                rc_file = strdup(buf);
                    389:        } else {
                    390:                if ((fp = fopen(color_conf, "r")) == NULL) {
                    391:                        fprintf(stderr, "%s: %s\n", color_conf, strerror(errno));
                    392:                        return -1;
                    393:                }
                    394:                rc_file = strdup(color_conf);
                    395:        }
                    396:        if (!rc_file) {
                    397:                fprintf(stderr, "init_colormask: strdup: Out of memory?\n");
                    398:                (void)fclose(fp);
                    399:                return -1;
                    400:        }
                    401:        rc_line = 0;
                    402:        cm = &me;
                    403: 
                    404: #ifdef HAVE_USE_DEFAULT_COLORS
                    405:        use_default_colors();
                    406: #endif
                    407:        while (fgets(buf, sizeof(buf), fp) != NULL) {
                    408:                rc_line++;
                    409:                if (buf[0] == '\n' || buf[0] == '#') continue;
                    410:                if ((cp = strchr(buf, '#')) != NULL) {
                    411:                        *cp++ = '\n';
                    412:                        *cp = '\0';
                    413:                }
                    414:                memset(cm, 0, sizeof(struct cm_entry));
                    415:                num = sscanf(buf, "%s %s %s %s\n", s1, s2, s3, s4);
                    416:                if (num == 2) {
                    417:                        if (strcasecmp(s1, "default")) {
                    418:                                if ((cp = strchr(s1, '/')) != 0) {
                    419:                                        *cp++ = '\0';
                    420:                                        if ((cp = str2proto(cp, &num)) == 0) {
                    421:                                                (void)fclose(fp);
                    422:                                                return -1;
                    423:                                        }
                    424:                                        cm->in_hdr.proto = num;
                    425:                                }
                    426:                                if ((num = str2port(s1, cp)) == -1) {
                    427:                                        (void)fclose(fp);
                    428:                                        return -1;
                    429:                                }
                    430:                                cm->in_hdr.src.ip_port = num;
                    431:                                cm->in_hdr.dst.ip_port = 0;
                    432:                                if (add_colormask(s2, cm) < 0) {
                    433:                                        (void)fclose(fp);
                    434:                                        return -1;
                    435:                                }
                    436:                                cm->in_hdr.src.ip_port = 0;
                    437:                                cm->in_hdr.dst.ip_port = num;
                    438:                                if (add_colormask(s2, cm) < 0) {
                    439:                                        (void)fclose(fp);
                    440:                                        return -1;
                    441:                                }
                    442:                        } else if (add_colormask(s2, 0) < 0) {
                    443:                                (void)fclose(fp);
                    444:                                return -1;
                    445:                        }
                    446:                } else if (num == 3) {
                    447:                        num = str2addr(s1, 0, &cm->in_hdr.src, &cm->src_mask);
                    448:                        if (num == -1) {
                    449:                                (void)fclose(fp);
                    450:                                return -1;
                    451:                        }
                    452:                        cm->in_hdr.ver = num;
                    453:                        num = str2addr(s2, 0, &cm->in_hdr.dst, &cm->dst_mask);
                    454:                        if (num == -1) {
                    455:                                (void)fclose(fp);
                    456:                                return -1;
                    457:                        }
                    458:                        if (!cm->in_hdr.ver) {
                    459:                                cm->in_hdr.ver = num;
                    460:                        } else if (num && num != cm->in_hdr.ver) {
                    461:                                fprintf(stderr, "%s: line %d: Addresses family mismatch\n",
                    462:                                        rc_file, rc_line);
                    463:                                (void)fclose(fp);
                    464:                                return -1;
                    465:                        }
                    466:                        if (add_colormask(s3, cm) < 0) {
                    467:                                (void)fclose(fp);
                    468:                                return -1;
                    469:                        }
                    470:                } else if (num == 4) {
                    471:                        if ((cp = str2proto(s1, &num)) == 0) {
                    472:                                (void)fclose(fp);
                    473:                                return -1;
                    474:                        }
                    475:                        cm->in_hdr.proto = num;
                    476:                        num = str2addr(s2, cp, &cm->in_hdr.src, &cm->src_mask);
                    477:                        if (num == -1) {
                    478:                                (void)fclose(fp);
                    479:                                return -1;
                    480:                        }
                    481:                        cm->in_hdr.ver = num;
                    482:                        num = str2addr(s3, cp, &cm->in_hdr.dst, &cm->dst_mask);
                    483:                        if (num == -1) {
                    484:                                (void)fclose(fp);
                    485:                                return -1;
                    486:                        }
                    487:                        if (!cm->in_hdr.ver) {
                    488:                                cm->in_hdr.ver = num;
                    489:                        } else if (num && num != cm->in_hdr.ver) {
                    490:                                fprintf(stderr, "%s: line %d: Addresses family mismatch\n",
                    491:                                        rc_file, rc_line);
                    492:                                (void)fclose(fp);
                    493:                                return -1;
                    494:                        }
                    495:                        if (add_colormask(s4, cm) < 0) {
                    496:                                (void)fclose(fp);
                    497:                                return -1;
                    498:                        }
                    499:                } else {
                    500:                        fprintf(stderr, "%s: line %d: Bad format\n",
                    501:                                rc_file, rc_line);
                    502:                        (void)fclose(fp);
                    503:                        return -1;
                    504:                }
                    505:        }
                    506:        (void)fclose(fp);
                    507: #ifdef DEBUG
                    508:        for (cm = color_mask, num = 0; cm && num < n_masks; cm++, num++) {
                    509:                struct netstat_header nh;
                    510:                memset(&nh, 0, sizeof(nh));
                    511:                nh.in_hdr = cm->in_hdr;
                    512:                hdr2str(&nh, s1, sizeof(s1), s2, sizeof(s2), s3, sizeof(s3));
                    513:                fprintf(stderr, "%d:", num+1);
                    514:                fprintf(stderr, " proto=%s", s3);
                    515:                fprintf(stderr, " src=%s", s1);
                    516:                fprintf(stderr, " src_mask=%d", cm->src_mask);
                    517:                fprintf(stderr, " dst=%s", s2);
                    518:                fprintf(stderr, " dst_mask=%d", cm->dst_mask);
                    519:                fprintf(stderr, " color_pair=%d\r\n", (int)cm->pair);
                    520:        }
                    521:        fflush(stderr);
                    522:        pause();
                    523: #endif
                    524:        return n_masks;
                    525: }
                    526: 
                    527: static u_int32_t
                    528: netmask(int bits)
                    529: {
                    530:        register u_int32_t mask = 0;
                    531:        int i;
                    532:        for (i = 0; i < bits; i++) {
                    533:                mask >>= 1;
                    534:                mask |= 0x80000000L;
                    535:        }
                    536:        return (u_int32_t)htonl(mask);
                    537: }
                    538: 
                    539: int
                    540: colormask(nh)
                    541:        const struct netstat_header *nh;
                    542: {
                    543:        /* sanity check */
                    544:        if (!nh) return A_NORMAL;
                    545: 
                    546:        if (nh->in_hdr.ver) {
                    547:                register const struct cm_entry *cm;
                    548:                int i;
                    549:                for (cm = color_mask, i = 0; cm && i < n_masks; cm++, i++) {
                    550:                        /* IP version */
                    551:                        if (cm->in_hdr.ver) {
                    552:                                if (nh->in_hdr.ver != cm->in_hdr.ver)
                    553:                                        continue;
                    554:                        }
                    555:                        /* IP protocol */
                    556:                        if (cm->in_hdr.proto) {
                    557:                                if (nh->in_hdr.proto != cm->in_hdr.proto)
                    558:                                        continue;
                    559:                        }
                    560:                        /* IP source address */
                    561:                        if (cm->in_hdr.src.ip_addr.s_addr) {
                    562:                                if (cm->src_mask) {
                    563:                                        u_int32_t mask = netmask(cm->src_mask);
                    564:                                        if ((nh->in_hdr.src.ip_addr.s_addr & mask) ^
                    565:                                            (cm->in_hdr.src.ip_addr.s_addr & mask))
                    566:                                                continue;
                    567:                                } else if (nh->in_hdr.src.ip_addr.s_addr !=
                    568:                                           cm->in_hdr.src.ip_addr.s_addr)
                    569:                                        continue;
                    570:                        }
                    571:                        /* IP source port */
                    572:                        if (cm->in_hdr.src.ip_port) {
                    573:                                if (nh->in_hdr.src.ip_port != cm->in_hdr.src.ip_port)
                    574:                                        continue;
                    575:                        }
                    576:                        /* IP destination address */
                    577:                        if (cm->in_hdr.dst.ip_addr.s_addr) {
                    578:                                if (cm->dst_mask) {
                    579:                                        u_int32_t mask = netmask(cm->dst_mask);
                    580:                                        if ((nh->in_hdr.dst.ip_addr.s_addr & mask) ^
                    581:                                            (cm->in_hdr.dst.ip_addr.s_addr & mask))
                    582:                                                continue;
                    583:                                } else if (nh->in_hdr.dst.ip_addr.s_addr !=
                    584:                                           cm->in_hdr.dst.ip_addr.s_addr)
                    585:                                        continue;
                    586:                        }
                    587:                        /* IP destination port */
                    588:                        if (cm->in_hdr.dst.ip_port) {
                    589:                                if (nh->in_hdr.dst.ip_port != cm->in_hdr.dst.ip_port)
                    590:                                        continue;
                    591:                        }
                    592: #ifdef HAVE_SLCURSES
                    593:                        return (COLOR_PAIR(cm->pair));
                    594: #else
                    595:                        return (COLOR_PAIR(cm->pair) | cm->attr);
                    596: #endif
                    597:                }
                    598:        }
                    599: 
                    600:        return A_NORMAL;
                    601: }
                    602: 
                    603: #endif /* HAVE_HAS_COLORS */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>