Annotation of micropolis/src/tk/tkrawtcp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * tkRawTCP.c --
                      3:  *
                      4:  *     This file contains a simple Tcl "connect" command
                      5:  *     that returns an standard Tcl File descriptor (as would
                      6:  *     be returned by Tcl_OpenCmd).
                      7:  * Extended to create servers, accept connections, shutdown parts of full
                      8:  *   duplex connections and handle UNIX domain sockets.
                      9:  *
                     10:  * Author: Pekka Nikander <[email protected]>
                     11:  * Modified: Tim MacKenzie <[email protected]) 
                     12:  *
                     13:  * Copyright 1992 Telecom Finland
                     14:  *
                     15:  * Permission to use, copy, modify, and distribute this
                     16:  * software and its documentation for any purpose and without
                     17:  * fee is hereby granted, provided that this copyright
                     18:  * notice appears in all copies.  Telecom Finland
                     19:  * makes no representations about the suitability of this
                     20:  * software for any purpose.  It is provided "as is" without
                     21:  * express or implied warranty.
                     22:  *
                     23:  * Created: Sun Mar 22 18:20:29 1992
                     24:  * based on: Last modified: Sun Mar 22 21:34:31 1992 pnr
                     25:  * Last modified: Mon Jun 29 15:25:14 EST 1992 tym
                     26:  * 
                     27:  */
                     28: 
                     29: #ifndef lint
                     30: static char rcsid[] = "...";
                     31: #endif /* not lint */
                     32: 
                     33: #include "tclint.h"
                     34: #include "tclunix.h"
                     35: 
                     36: #include <assert.h>
                     37: #include <string.h>
                     38: #include <sys/types.h>
                     39: #include <sys/socket.h>
                     40: #include <netinet/in.h>
                     41: #include <netdb.h>
                     42: #include <arpa/inet.h>
                     43: #include <sys/un.h>
                     44: 
                     45: #include <tk.h>
                     46: 
                     47: static int inet_connect _ANSI_ARGS_((char *host, char *port,int server));
                     48: static int unix_connect _ANSI_ARGS_((char *path, int server));
                     49: static void HandleSocket _ANSI_ARGS_ ((ClientData clientData, int mask));
                     50: 
                     51: typedef struct {
                     52:     Tcl_Interp *interp;
                     53:     OpenFile *filePtr;
                     54:     char *tclCmd;
                     55:     char *fileId;
                     56: } FileCmd;
                     57: 
                     58: /*
                     59:  *------------------------------------------------------------------
                     60:  *
                     61:  * Tcp_MakeOpenFile --
                     62:  *
                     63:  *    Set up on OpenFile structure in the interpreter for a newly 
                     64:  *      opened file
                     65:  *     
                     66:  * Results:
                     67:  *     none
                     68:  *
                     69:  * Side effects:
                     70:  *     Adds an OpenFile to the list.
                     71:  *------------------------------------------------------------------
                     72:  */
                     73: 
                     74: /* ARGSUSED */
                     75: void
                     76: Tcp_MakeOpenFile(interp,fd,r,w)
                     77:     Tcl_Interp *interp;
                     78:     int fd;
                     79:     int r,w;
                     80: {/* Create an OpenFile structure using f and install it in the interpreter with
                     81:   * Readable and Writable set to r and w
                     82:   */
                     83:     Interp *iPtr = (Interp *) interp;
                     84:     register OpenFile *filePtr;
                     85: 
                     86:     filePtr = (OpenFile *) ckalloc(sizeof(OpenFile));
                     87: 
                     88:     filePtr->f = NULL;
                     89:     filePtr->f2 = NULL;
                     90: 
                     91:         /* Open the file with the correct type (doesn't handle !r && !w) */
                     92: #ifdef MSDOS
                     93:     filePtr->f = fdopen(fd,(r&&w)?"rb+":(r?"rb":"wb"));
                     94: #else
                     95:     filePtr->f = fdopen(fd,(r&&w)?"r+":(r?"r":"w"));
                     96: #endif
                     97:         /* Don't do buffered communication if full-duplex... it breaks! */
                     98:         if (r&w) setbuf(filePtr->f,0);
                     99: 
                    100:     filePtr->readable = r;
                    101:     filePtr->writable = w;
                    102:     filePtr->numPids = 0;
                    103:     filePtr->pidPtr = NULL;
                    104:     filePtr->errorId = -1;
                    105: 
                    106:     /*
                    107:      * Enter this new OpenFile structure in the table for the
                    108:      * interpreter.  May have to expand the table to do this.
                    109:      */
                    110: 
                    111:     TclMakeFileTable(iPtr, fd);
                    112:     if (iPtr->filePtrArray[fd] != NULL) {
                    113:        panic("Tcl_OpenCmd found file already open");
                    114:     }
                    115:     iPtr->filePtrArray[fd] = filePtr;
                    116: }
                    117: 
                    118: /*
                    119:  *------------------------------------------------------------------
                    120:  *
                    121:  * Tcp_ConnectCmd --
                    122:  *
                    123:  *     Open a socket connection to a given host and service.
                    124:  *     
                    125:  * Results:
                    126:  *     A standard Tcl result.
                    127:  *
                    128:  * Side effects:
                    129:  *     An open socket connection.
                    130:  *      Sets the global variable connect_info(file%d) to the obtained
                    131:  *        port when setting up server.
                    132:  *------------------------------------------------------------------
                    133:  */
                    134: 
                    135: /* ARGSUSED */
                    136: int
                    137: Tcp_ConnectCmd(notUsed, interp, argc, argv)
                    138:     ClientData notUsed;
                    139:     Tcl_Interp *interp;
                    140:     int argc;
                    141:     char **argv;
                    142: {
                    143:     Interp *iPtr = (Interp *) interp;
                    144:     char *host,*port;
                    145:     int fd;
                    146:     int server=0;
                    147:     int unicks = 0;
                    148:     
                    149:     if (argc != 2 && argc != 3 &&
                    150:        (argc != 4 || (argc == 4 && strcmp(argv[1],"-server")))) {
                    151:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    152:                     "[{-server}] address_spec\"", (char *) NULL);
                    153:        return TCL_ERROR;
                    154:     }
                    155: 
                    156:     if (!strcmp(argv[1],"-server"))
                    157:        server = 1;
                    158: 
                    159:     /*
                    160:      * Create the connection
                    161:      */
                    162:     if (argc - server == 2) {/* Unix domain socket */
                    163:        unicks = 1;
                    164:        fd = unix_connect(argv[1+server],server);
                    165:     } else
                    166:        fd = inet_connect(argv[1+server], argv[2+server],server);
                    167: 
                    168:     if (fd < 0) {
                    169:        /* Tell them why it fell apart */
                    170:        if (unicks)
                    171:            if (server)
                    172:                Tcl_AppendResult(interp,
                    173:                    "Couldn't setup listening socket with path \"",
                    174:                    argv[1+server],"\" : ",Tcl_UnixError(interp),
                    175:                    (char *) NULL);
                    176:            else
                    177:                Tcl_AppendResult(interp,
                    178:                    "Couldn't connect to \"",argv[1],"\" : ",
                    179:                    Tcl_UnixError(interp),(char *) NULL);
                    180:        else
                    181:            if (server)
                    182:                Tcl_AppendResult(interp,
                    183:                    "couldn't setup listening socket on port:",
                    184:                    atoi(argv[3])==0?"any":argv[3]," using address \"",
                    185:                    strlen(argv[2])?argv[2]:"anywhere.","\": ",
                    186:                    Tcl_UnixError(interp), (char *)NULL);
                    187:            else
                    188:                Tcl_AppendResult(interp, "couldn't open connection to \"",
                    189:                                 argv[1], "\" port \"", argv[2], "\": ",
                    190:                                 Tcl_UnixError(interp), (char *) NULL);
                    191:        return TCL_ERROR;
                    192:     }
                    193: 
                    194:     sprintf(interp->result, "file%d", fd);
                    195:     if (server && !unicks) {
                    196:        /* Find out what port we got */
                    197:        char buf[50];
                    198:        struct sockaddr_in sockaddr;
                    199:        int res,len=sizeof(sockaddr);
                    200:        res =getsockname(fd,(struct sockaddr *) &sockaddr, &len);
                    201:        if (res < 0) {
                    202:            sprintf(buf,"%d",errno);
                    203:        } else 
                    204:            sprintf(buf,"%d",(int)ntohs(sockaddr.sin_port));
                    205:        Tcl_SetVar2(interp,"connect_info",interp->result,buf,TCL_GLOBAL_ONLY);
                    206:     }
                    207: 
                    208:     Tcp_MakeOpenFile(iPtr,fd,1,1-server);
                    209: 
                    210:     return TCL_OK;
                    211: }
                    212: 
                    213: /*
                    214:  *------------------------------------------------------------------
                    215:  *
                    216:  * Tcp_ShutdownCmd --
                    217:  *
                    218:  *    Shutdown a socket for reading writing or both using shutdown(2)
                    219:  *     
                    220:  * Results:
                    221:  *     standard tcl result.
                    222:  *
                    223:  * Side effects:
                    224:  *     Modifies the OpenFile structure appropriately
                    225:  *------------------------------------------------------------------
                    226:  */
                    227: 
                    228: /* ARGSUSED */
                    229: int
                    230: Tcp_ShutdownCmd(notUsed, interp, argc, argv)
                    231:     ClientData notUsed;
                    232:     Tcl_Interp *interp;
                    233:     int argc;
                    234:     char **argv;
                    235: {
                    236:     Interp *iPtr = (Interp *) interp;
                    237:     OpenFile *filePtr;
                    238:     register FILE *f;
                    239:     int fd;
                    240: 
                    241:     if (argc != 3) {
                    242:     wrong_args:
                    243:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    244:                     " fileid <option>\"", (char *) NULL);
                    245:        return TCL_ERROR;
                    246:     }
                    247: 
                    248:     if (TclGetOpenFile(interp, argv[1], &filePtr) != TCL_OK) {
                    249:         return TCL_ERROR;
                    250:     }
                    251: 
                    252:     f = filePtr->f;
                    253:     fd = fileno(filePtr->f);
                    254:     if (!strcmp(argv[2],"0") || !strcmp(argv[2],"receives") || 
                    255:            !strcmp(argv[2],"read")) {
                    256:        if (!filePtr->readable) {
                    257:            Tcl_AppendResult(interp, "File is not readable",(char *) NULL);
                    258:            return TCL_ERROR;
                    259:        }
                    260:        if (shutdown(fd,0)) {
                    261:            Tcl_AppendResult(interp, "shutdown: ", Tcl_UnixError(interp),
                    262:                (char *) NULL);
                    263:            return TCL_ERROR;
                    264:        }
                    265:        filePtr->readable=0;
                    266:     } else if (!strcmp(argv[2],"1") || !strcmp(argv[2],"sends") ||
                    267:            !strcmp(argv[2],"write")) {
                    268:        if (!filePtr->writable) {
                    269:            Tcl_AppendResult(interp, "File is not writable",(char *) NULL);
                    270:            return TCL_ERROR;
                    271:        }
                    272:        if (shutdown(fd,1)) {
                    273:            Tcl_AppendResult(interp, "shutdown: ", Tcl_UnixError(interp),
                    274:                (char *) NULL);
                    275:            return TCL_ERROR;
                    276:        }
                    277:        filePtr->writable=0;
                    278:     } else if (!strcmp(argv[2],"2") || !strcmp(argv[2],"all") ||
                    279:            !strcmp(argv[2],"both")) {
                    280:        if (shutdown(fd,2)) {
                    281:            Tcl_AppendResult(interp, "shutdown: ", Tcl_UnixError(interp),
                    282:                (char *) NULL);
                    283:            return TCL_ERROR;
                    284:        }
                    285:        filePtr->writable=0;
                    286:        filePtr->readable=0;
                    287:     } else
                    288:        goto wrong_args;
                    289:     return TCL_OK;
                    290: }
                    291:        
                    292: 
                    293:                
                    294: /*
                    295:  *------------------------------------------------------------------
                    296:  *
                    297:  * Tcp_AcceptCmd --
                    298:  *
                    299:  *    Accept a connection on a listening socket
                    300:  *     
                    301:  * Results:
                    302:  *     a standard tcl result
                    303:  *
                    304:  * Side effects:
                    305:  *     Opens a new file.
                    306:  *      Sets the global variable connect_info(file%d) to a list
                    307:  *         containing the remote address (host ip, port) of the
                    308:  *         connector.
                    309:  *------------------------------------------------------------------
                    310:  */
                    311: 
                    312: /* ARGSUSED */
                    313: int
                    314: Tcp_AcceptCmd(notUsed, interp, argc, argv)
                    315:     ClientData notUsed;
                    316:     Tcl_Interp *interp;
                    317:     int argc;
                    318:     char **argv;
                    319: {
                    320:     Interp *iPtr = (Interp *) interp;
                    321:     struct sockaddr_in sockaddr;
                    322:     int len = sizeof sockaddr;
                    323:     OpenFile *filePtr;
                    324:     register FILE *f;
                    325:     int fd;
                    326: 
                    327:     if (argc != 2) {
                    328:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    329:                     " listening_socket\"", (char *) NULL);
                    330:        return TCL_ERROR;
                    331:     }
                    332: 
                    333:     if (TclGetOpenFile(interp, argv[1], &filePtr) != TCL_OK) {
                    334:         return TCL_ERROR;
                    335:     }
                    336:     if (!filePtr->readable) {
                    337:         Tcl_AppendResult(interp, "\"", argv[1],
                    338:                 "\" wasn't opened for reading", (char *) NULL);
                    339:         return TCL_ERROR;
                    340:     }
                    341: 
                    342:     f = filePtr->f;
                    343:     fd = fileno(filePtr->f);
                    344: 
                    345:     fd = accept(fd,(struct sockaddr *)&sockaddr,&len);
                    346:     if (fd < 0) {
                    347:        Tcl_AppendResult(interp, "system error in accept()", (char *)NULL);
                    348:        return TCL_ERROR;
                    349:     }
                    350: 
                    351:     {/* Set the global connect_info */
                    352:        char buf[100];
                    353:        char nm[10];
                    354:        if (sockaddr.sin_family == AF_INET)
                    355:            sprintf(buf,"%s %d",inet_ntoa(sockaddr.sin_addr),
                    356:                   ntohs(sockaddr.sin_port));
                    357:        else
                    358:            buf[0]=0;  /* Empty string for UNIX domain sockets */
                    359:        sprintf(nm,"file%d",fd);
                    360:        Tcl_SetVar2(interp,"connect_info",nm,buf,TCL_GLOBAL_ONLY);
                    361:     }
                    362: 
                    363:     /*
                    364:      * Create the FILE*
                    365:      */
                    366:     Tcp_MakeOpenFile(iPtr,fd,1,1);
                    367: 
                    368:     sprintf(interp->result, "file%d", fd);
                    369:     return TCL_OK;
                    370: }
                    371: 
                    372: /*
                    373:  *----------------------------------------------------------------
                    374:  *
                    375:  * unix_connect --
                    376:  *
                    377:  *     Create a (unix_domain) fd connection using given rendeavous
                    378:  *
                    379:  * Results:
                    380:  *     An open fd or -1.
                    381:  *
                    382:  * Side effects:
                    383:  *     None.
                    384:  *----------------------------------------------------------------
                    385:  */
                    386: 
                    387: static int
                    388: unix_connect(path,server)
                    389:     char *path;                /* Path name to create or use */
                    390:     int  server;        /* 1->make server, 0->connect to server */
                    391: {
                    392:     struct sockaddr_un sockaddr;
                    393:     int sock, status;
                    394:     extern int errno;
                    395:     
                    396:     sock = socket(PF_UNIX, SOCK_STREAM, 0);
                    397:     if (sock < 0) {
                    398:        return -1;
                    399:     }
                    400:     
                    401:     sockaddr.sun_family = AF_UNIX;
                    402:     strncpy(sockaddr.sun_path,path,sizeof(sockaddr.sun_path)-1);
                    403:     sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = 0; /* Just in case */
                    404:     
                    405:     if (server)
                    406:        status = bind(sock,(struct sockaddr *) &sockaddr, sizeof(sockaddr));
                    407:     else
                    408:        status = connect(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr));
                    409:     
                    410:     if (status < 0) {
                    411:        close (sock);
                    412:        return -1;
                    413:     }
                    414: 
                    415:     if (server) {
                    416:        listen(sock,5);
                    417:        return sock;
                    418:     }
                    419:     
                    420:     return sock;
                    421: }
                    422: 
                    423: /*
                    424:  *----------------------------------------------------------------
                    425:  *
                    426:  * inet_connect --
                    427:  *
                    428:  *     Create a (inet domain) fd connection to given host and port.
                    429:  *
                    430:  * Results:
                    431:  *     An open fd or -1.
                    432:  *
                    433:  * Side effects:
                    434:  *     None.
                    435:  *----------------------------------------------------------------
                    436:  */
                    437: 
                    438: static int
                    439: inet_connect(host, service,server)
                    440:     char *host;                        /* Host to connect, name or IP address */
                    441:     char *service;             /* Port to use, service name or port number */
                    442:     int  server;
                    443: {
                    444:     struct hostent *hostent, _hostent;
                    445:     struct servent *servent, _servent;
                    446:     struct protoent *protoent;
                    447:     struct sockaddr_in sockaddr;
                    448:     int sock, status;
                    449:     int hostaddr, hostaddrPtr[2];
                    450:     int servport;
                    451:     extern int errno;
                    452:     
                    453:     hostent = gethostbyname(host);
                    454:     if (hostent == NULL) {
                    455:        hostaddr = inet_addr(host);
                    456:        if (hostaddr == -1) {
                    457:            if (server && !strlen(host)) 
                    458:                hostaddr = INADDR_ANY;
                    459:            else {
                    460:                errno = EINVAL;
                    461:                return -1;
                    462:            }
                    463:        }       
                    464:        _hostent.h_addr_list = (char **)hostaddrPtr;
                    465:        _hostent.h_addr_list[0] = (char *)&hostaddr;
                    466:        _hostent.h_addr_list[1] = NULL;
                    467:        _hostent.h_length = sizeof(hostaddr);
                    468:        _hostent.h_addrtype = AF_INET;
                    469:        hostent = &_hostent;
                    470:     }
                    471:     servent = getservbyname(service, "tcp");
                    472:     if (servent == NULL) {
                    473:        servport = htons(atoi(service));
                    474:        if (servport == -1) { 
                    475:            errno = EINVAL;
                    476:            return -1;
                    477:        }
                    478:        _servent.s_port = servport;
                    479:        _servent.s_proto = "tcp";
                    480:        servent = &_servent;
                    481:     }
                    482:     protoent = getprotobyname(servent->s_proto);
                    483:     if (protoent == NULL) {
                    484:        errno = EINVAL;
                    485:        return -1;
                    486:     }
                    487:     
                    488:     sock = socket(PF_INET, SOCK_STREAM, protoent->p_proto);
                    489:     if (sock < 0) {
                    490:        return -1;
                    491:     }
                    492:     
                    493:     sockaddr.sin_family = AF_INET;
                    494:     memcpy((char *)&(sockaddr.sin_addr.s_addr),
                    495:           (char *) hostent->h_addr_list[0],
                    496:           (size_t) hostent->h_length);
                    497:     sockaddr.sin_port = servent->s_port;
                    498:     
                    499:     if (server)
                    500:        status = bind(sock,(struct sockaddr *) &sockaddr, sizeof(sockaddr));
                    501:     else
                    502:        status = connect(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr));
                    503:     
                    504:     if (status < 0) {
                    505:        close (sock);
                    506:        return -1;
                    507:     }
                    508: 
                    509:     if (server) {
                    510:        listen(sock,5);
                    511:        return sock;
                    512:     }
                    513:     
                    514:     return sock;
                    515: }
                    516: 
                    517: /*
                    518:  *----------------------------------------------------------------
                    519:  *
                    520:  * Tcp_FileHandlerCmd --
                    521:  *
                    522:  *     Register a file handler with an open file.  If there is
                    523:  *     already and existing handler, it will be no longer called.
                    524:  *     If no mask and command are given, any existing handler
                    525:  *     will be deleted.
                    526:  *
                    527:  * Results:
                    528:  *     A standard Tcl result. (Always OK).
                    529:  *
                    530:  * Side effects:
                    531:  *     A new file handler is associated with a give TCL open file.
                    532:  *     Whenever the file is readable, writeable and/or there is
                    533:  *     an expection condition on the file, a user supplied TCL
                    534:  *     command is called.
                    535:  *
                    536:  *----------------------------------------------------------------
                    537:  */
                    538: 
                    539: /* ARGSUSED */
                    540: int
                    541: Tcp_FileHandlerCmd(notUsed, interp, argc, argv)
                    542:     ClientData notUsed;
                    543:     Tcl_Interp *interp;
                    544:     int argc;
                    545:     char **argv;
                    546: {
                    547:     FileCmd *cmdPtr;
                    548:     OpenFile *filePtr;
                    549:     int mask;
                    550: 
                    551:     if (argc != 2 && argc != 4) {
                    552:        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                    553:                  " fileId ?mode command?\"", (char *) NULL);
                    554:        return TCL_ERROR;
                    555:     }
                    556: 
                    557:     if (TclGetOpenFile(interp, argv[1], &filePtr) != TCL_OK) {
                    558:        return TCL_ERROR;
                    559:     }
                    560: 
                    561:     if (argc == 2) {
                    562:        /*
                    563:         * NOTE!  Currently the cmdPtr structure will be left
                    564:         *        *unfreed* if the file handler is deleted
                    565:         *        via this code.  Tough.  Would need a hash table
                    566:         *        or something...
                    567:         */
                    568:        Tk_DeleteFileHandler(fileno(filePtr->f));
                    569:        return TCL_OK;
                    570:     }
                    571:     
                    572:     /*
                    573:      * Find out on what situations the user is interested in.
                    574:      * This is not the most elegant or efficient way to do this,
                    575:      * but who cares?  (I do, but not much enough :-)
                    576:      */
                    577:     mask = 0;
                    578:     if (strchr(argv[2], 'r')) {
                    579:        mask |= TK_READABLE;
                    580:     }
                    581:     if (strchr(argv[2], 'w')) {
                    582:        mask |= TK_WRITABLE;
                    583:     }
                    584:     if (strchr(argv[2], 'e')) {
                    585:        mask |= TK_EXCEPTION;
                    586:     }
                    587:     if (mask == 0 || (strlen(argv[2]) != strspn(argv[2], "rwe"))) {
                    588:        Tcl_AppendResult(interp, "bad mask argument \"", argv[2],
                    589:                 "\": should be any combination of \"r\", \"w\" and \"e\"",
                    590:                         (char *) NULL);
                    591:        fclose(filePtr->f);
                    592:        return TCL_ERROR;
                    593:     }
                    594: 
                    595:     cmdPtr = (FileCmd *)ckalloc(sizeof(FileCmd));
                    596:     cmdPtr->interp = interp;
                    597:     cmdPtr->filePtr = filePtr;
                    598:     cmdPtr->tclCmd = ckalloc(strlen(argv[3]) + 1);
                    599:     strcpy(cmdPtr->tclCmd, argv[3]);
                    600:     cmdPtr->fileId = ckalloc(strlen(argv[1]) + 1);
                    601:     strcpy(cmdPtr->fileId, argv[1]);
                    602:     
                    603:     /*
                    604:      * NOTE! There may be an earlier file handler.   Should do something.
                    605:      */
                    606:     Tk_CreateFileHandler(fileno(filePtr->f), mask, HandleSocket,
                    607:                         (ClientData) cmdPtr);
                    608: 
                    609:     return TCL_OK;
                    610: }
                    611: /*
                    612:  *----------------------------------------------------------------
                    613:  *
                    614:  * HandleSocket --
                    615:  *
                    616:  *     This procedure is called from Tk_DoOneEvent whenever there is
                    617:  *     a desired condition on a given open socket.  An Tcl command
                    618:  *     given by the user is executed to handle the connection.  If
                    619:  *     and EOF or ERROR condition is noticed, all memory resources
                    620:  *     associated with the socket are released and the socket is closed.
                    621:  *
                    622:  * Results:
                    623:  *     None.
                    624:  *
                    625:  * Side effects:
                    626:  *     The user supplied command can do anything.
                    627:  *
                    628:  *----------------------------------------------------------------
                    629:  */
                    630: 
                    631: static void
                    632: HandleSocket(clientData, mask)
                    633:     ClientData clientData;
                    634:     int mask;
                    635: {
                    636:     int result;
                    637:     FileCmd *cmdPtr = (FileCmd *) clientData;
                    638:     OpenFile *filePtr = cmdPtr->filePtr;
                    639:     Tcl_Interp *interp = cmdPtr->interp;
                    640:     OpenFile *dummy;
                    641:     int delete;
                    642:     int fd = fileno(filePtr->f);
                    643: 
                    644:     Tk_Preserve((ClientData)cmdPtr);
                    645: 
                    646:     delete = 0;
                    647:     if (TclGetOpenFile(interp, cmdPtr->fileId, &dummy) != TCL_OK) {
                    648:        /* File is closed! */
                    649:        Tcl_ResetResult(interp);
                    650:        delete = 1;
                    651:     } else {
                    652:        assert(dummy == cmdPtr->filePtr);
                    653: 
                    654:        if (mask & TK_READABLE) {
                    655:            result = Tcl_VarEval(interp, cmdPtr->tclCmd, " r ", cmdPtr->fileId,
                    656:                                 (char *) NULL);
                    657:            if (result != TCL_OK) {
                    658:                TkBindError(interp);
                    659:            }
                    660:        }
                    661:        if (mask & TK_WRITABLE) {
                    662:            result = Tcl_VarEval(interp, cmdPtr->tclCmd, " w ", cmdPtr->fileId,
                    663:                                 (char *) NULL);
                    664:            if (result != TCL_OK) {
                    665:                TkBindError(interp);
                    666:            }
                    667:        }
                    668:        if (mask & TK_EXCEPTION) {
                    669:            result = Tcl_VarEval(interp, cmdPtr->tclCmd, " e ", cmdPtr->fileId,
                    670:                                 (char *) NULL);
                    671:            if (result != TCL_OK) {
                    672:                TkBindError(interp);
                    673:            }
                    674:        }
                    675: 
                    676:        if (feof(filePtr->f) || ferror(filePtr->f)) {
                    677:            result = Tcl_VarEval(interp, "close ", cmdPtr->fileId,
                    678:                                 (char *) NULL);
                    679:            if (result != TCL_OK) {
                    680:                TkBindError(interp);
                    681:            }
                    682:            delete = 1;
                    683:        }
                    684:     }
                    685: 
                    686:     Tk_Release((ClientData)cmdPtr);
                    687: 
                    688:     if (delete) {
                    689:        Tk_DeleteFileHandler(fd);
                    690:        Tk_EventuallyFree((ClientData)cmdPtr, (Tk_FreeProc *)free);
                    691:     }
                    692: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.