113 113 JIM_NOTUSED(interp);
114 114
115 115 if (!(af->OpenFlags & AIO_KEEPOPEN))
116 116 fclose(af->fp);
117 117 if (!af->OpenFlags == AIO_FDOPEN) // fp = fdopen(fd) !!
118 118 close(af->fd);
119 119 if (af->rEvent) { // remove existing EventHandlers
120 -
Jim_DeleteFileHandler(interp,af->fp);
121 -
Jim_DecrRefCount(interp,af->rEvent);
120 +
Jim_DeleteFileHandler(interp,af->fp);
121 +
Jim_DecrRefCount(interp,af->rEvent);
122 122 }
123 123 if (af->wEvent) {
124 -
Jim_DeleteFileHandler(interp,af->fp);
124 +
Jim_DeleteFileHandler(interp,af->fp);
125 125 Jim_DecrRefCount(interp,af->wEvent);
126 126 }
127 127 if (af->eEvent) {
128 -
Jim_DeleteFileHandler(interp,af->fp);
128 +
Jim_DeleteFileHandler(interp,af->fp);
129 129 Jim_DecrRefCount(interp,af->eEvent);
130 130 }
131 131 Jim_Free(af);
132 132 }
133 133
134 134 /* Calls to [aio.file] create commands that are implemented by this
135 135 * C command. */
................................................................................
150 150 };
151 151 enum {OPT_CLOSE,
152 152 OPT_SEEK, OPT_TELL,
153 153 OPT_GETS, OPT_READ, OPT_PUTS,
154 154 OPT_FLUSH, OPT_EOF,
155 155 OPT_NDELAY,
156 156 OPT_READABLE, OPT_WRITABLE, OPT_EXCEPTION,
157 -
OPT_ACCEPT
157 +
OPT_ACCEPT,
158 158 };
159 159
160 160 if (argc < 2) {
161 161 Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?");
162 162 return JIM_ERR;
163 163 }
164 164 if (Jim_GetEnum(interp, argv[1], options, &option, "AIO method",
................................................................................
447 447 Jim_SetResult(interp,*scrListObjpp);
448 448 return JIM_OK;
449 449 default:
450 450 Jim_WrongNumArgs(interp, 2, argv, "");
451 451 return JIM_ERR;
452 452 }
453 453 } else if (option == OPT_ACCEPT) {
454 -
int ret;
455 -
ret = JimAioAcceptHelper(interp,af);
456 -
return (ret);
454 +
return JimAioAcceptHelper(interp,af);
457 455 }
458 456 return JIM_OK;
459 457 }
460 458
461 459 static int JimAioOpenCommand(Jim_Interp *interp, int argc,
462 460 Jim_Obj *const *argv)
463 461 {
464 462 FILE *fp;
465 463 AioFile *af;
466 464 char buf[AIO_CMD_LEN];
467 465 const char *mode = "r";
468 -
Jim_Obj *objPtr;
469 466 long fileId;
470 467 const char *options[] = {"input", "output", "error", NULL};
471 468 enum {OPT_INPUT, OPT_OUTPUT, OPT_ERROR};
472 469 int OpenFlags = 0;
473 470 int modeLen;
471 +
const char *cmdname = buf;
474 472
475 473 if (argc != 2 && argc != 3) {
476 474 Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
477 475 return JIM_ERR;
478 476 }
479 477 if (argc == 3)
480 478 mode = Jim_GetString(argv[2], &modeLen);
................................................................................
482 480 modeLen >= 3) {
483 481 int option;
484 482 if (Jim_GetEnum(interp, argv[2], options, &option, "standard channel",
485 483 JIM_ERRMSG) != JIM_OK)
486 484 return JIM_ERR;
487 485 OpenFlags |= AIO_KEEPOPEN;
488 486 switch (option) {
489 -
case OPT_INPUT: fp = stdin; break;
490 -
case OPT_OUTPUT: fp = stdout; break;
491 -
case OPT_ERROR: fp = stderr; break;
487 +
case OPT_INPUT: fp = stdin; cmdname = "stdin"; break;
488 +
case OPT_OUTPUT: fp = stdout; cmdname = "stdout"; break;
489 +
case OPT_ERROR: fp = stderr; cmdname = "stderr"; break;
492 490 default: fp = NULL; Jim_Panic(interp,"default reached in JimAioOpenCommand()");
493 491 break;
494 492 }
495 493 } else {
496 494 fp = fopen(Jim_GetString(argv[1], NULL), mode);
497 495 if (fp == NULL) {
498 496 JimAioSetError(interp);
499 497 return JIM_ERR;
500 498 }
499 +
/* Get the next file id */
500 +
fileId = Jim_GetId(interp);
501 +
sprintf(buf, "aio.handle%ld", fileId);
501 502 }
502 -
/* Get the next file id */
503 -
if (Jim_EvalGlobal(interp,
504 -
"if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK)
505 -
return JIM_ERR;
506 -
objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG);
507 -
if (objPtr == NULL) return JIM_ERR;
508 -
if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR;
509 503
510 504 /* Create the file command */
511 505 af = Jim_Alloc(sizeof(*af));
512 506 af->fp = fp;
513 507 af->fd = fileno(fp);
514 508 af->flags = fcntl(af->fd,F_GETFL);
515 509 af->OpenFlags = OpenFlags;
516 510 af->rEvent = NULL;
517 511 af->wEvent = NULL;
518 512 af->eEvent = NULL;
519 -
sprintf(buf, "aio.handle%ld", fileId);
520 -
Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
521 -
Jim_SetResultString(interp, buf, -1);
513 +
Jim_CreateCommand(interp, cmdname, JimAioHandlerCommand, af, JimAioDelProc);
514 +
Jim_SetResultString(interp, cmdname, -1);
522 515 return JIM_OK;
523 516 }
524 517
525 518 static int JimAioSockCommand(Jim_Interp *interp, int argc,
526 519 Jim_Obj *const *argv)
527 520 {
528 521 FILE *fp;
529 522 AioFile *af;
530 523 char buf[AIO_CMD_LEN];
531 -
char *hdlfmt = "unknown";
532 -
Jim_Obj *objPtr;
524 +
char *hdlfmt = "aio.unknown%ld";
533 525 long fileId;
534 526 const char *socktypes[] = {
535 527 "file",
536 528 "pipe",
537 529 "tty",
538 530 "domain",
539 531 "dgram",
................................................................................
637 629 fp = fdopen(sock, "r+" );
638 630 if (fp == NULL) {
639 631 close(sock);
640 632 JimAioSetError(interp);
641 633 return JIM_ERR;
642 634 }
643 635 /* Get the next file id */
644 -
if (Jim_EvalGlobal(interp,
645 -
"if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK)
646 -
return JIM_ERR;
647 -
objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG);
648 -
if (objPtr == NULL) return JIM_ERR;
649 -
if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR;
636 +
fileId = Jim_GetId(interp);
650 637
651 638 /* Create the file command */
652 639 af = Jim_Alloc(sizeof(*af));
653 640 af->fp = fp;
654 641 af->fd = sock;
655 642 af->OpenFlags = AIO_FDOPEN;
656 643 af->flags = fcntl(af->fd,F_GETFL);
................................................................................
665 652
666 653 static int JimAioAcceptHelper(Jim_Interp *interp, AioFile *serv_af )
667 654 {
668 655 int sock;
669 656 int addrlen = sizeof(struct sockaddr_in);
670 657 AioFile *af;
671 658 char buf[AIO_CMD_LEN];
672 -
Jim_Obj *objPtr;
673 659 long fileId;
674 660 sock = accept(serv_af->fd,(struct sockaddr*)&serv_af->sa,&addrlen);
675 661 if (sock < 0)
676 662 return JIM_ERR;
677 663
678 664 /* Get the next file id */
679 -
if (Jim_EvalGlobal(interp,
680 -
"if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK)
681 -
return JIM_ERR;
682 -
objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG);
683 -
if (objPtr == NULL) return JIM_ERR;
684 -
if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR;
665 +
fileId = Jim_GetId(interp);
685 666
686 667 /* Create the file command */
687 668 af = Jim_Alloc(sizeof(*af));
688 669 af->fd = sock;
689 670 af->fp = fdopen(sock,"r+");
690 671 af->OpenFlags = AIO_FDOPEN;
691 672 af->flags = fcntl(af->fd,F_GETFL);
................................................................................
694 675 af->eEvent = NULL;
695 676 sprintf(buf, "aio.sockstream%ld", fileId);
696 677 Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
697 678 Jim_SetResultString(interp, buf, -1);
698 679 return JIM_OK;
699 680 }
700 681
682 +
FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
683 +
{
684 +
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
685 +
686 +
if (cmdPtr && cmdPtr->cmdProc == JimAioHandlerCommand) {
687 +
return ((AioFile *)cmdPtr->privData)->fp;
688 +
}
689 +
return NULL;
690 +
}
691 +
692 +
#ifdef JIM_TCL_COMPAT
693 +
static int JimAioTclCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
694 +
{
695 +
Jim_Obj **newargv = Jim_Alloc(sizeof(Jim_Obj*)*argc);
696 +
int ret;
697 +
int i;
698 +
699 +
/* cmd channel ?args? */
700 +
newargv[0] = argv[1];
701 +
newargv[1] = argv[0];
702 +
703 +
for (i = 2; i < argc; i++) {
704 +
newargv[i] = argv[i];
705 +
}
706 +
707 +
ret = Jim_EvalObjVector(interp, argc, newargv);
708 +
709 +
Jim_Free(newargv);
710 +
711 +
return ret;
712 +
}
713 +
714 +
static int JimAioPutsCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
715 +
{
716 +
Jim_Obj *newargv[4];
717 +
718 +
int off = 1;
719 +
720 +
/* "puts" */
721 +
newargv[off++] = argv[0];
722 +
723 +
/* puts ?-nonewline? ?channel? msg */
724 +
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) {
725 +
newargv[off++] = argv[1];
726 +
argv++;
727 +
argc--;
728 +
}
729 +
730 +
if (argc == 2) {
731 +
/* Missing channel, so use stdout */
732 +
newargv[0] = Jim_NewStringObj(interp, "stdout", -1);
733 +
newargv[off++] = argv[1];
734 +
}
735 +
else {
736 +
newargv[0] = argv[1];
737 +
newargv[off++] = argv[2];
738 +
}
739 +
return Jim_EvalObjVector(interp, off, newargv);
740 +
}
741 +
742 +
static void JimAioTclCompat(Jim_Interp *interp)
743 +
{
744 +
static const char *tclcmds[] = { "read", "gets", "flush", "close", "eof", "seek", "tell", 0};
745 +
int i;
746 +
747 +
for (i = 0; tclcmds[i]; i++) {
748 +
Jim_CreateCommand(interp, tclcmds[i], JimAioTclCmd, NULL, NULL);
749 +
}
750 +
Jim_CreateCommand(interp, "puts", JimAioPutsCmd, NULL, NULL);
751 +
Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
752 +
}
753 +
#endif
754 +
701 755 int
702 756 Jim_aioInit(Jim_Interp *interp)
703 757 {
704 758 if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG) != JIM_OK)
705 759 return JIM_ERR;
706 760 Jim_CreateCommand(interp, "aio.open", JimAioOpenCommand, NULL, NULL);
707 761 Jim_CreateCommand(interp, "aio.socket", JimAioSockCommand, NULL, NULL);
762 +
763 +
/* Takeover stdin, stdout and stderr */
764 +
Jim_EvalGlobal(interp,
765 +
"aio.open standard input; aio.open standard output; aio.open standard error");
766 +
767 +
#ifdef JIM_TCL_COMPAT
768 +
JimAioTclCompat(interp);
769 +
#endif
770 +
708 771 return JIM_OK;
709 772 }
710 773
711 774 // end
712 775