Esempio n. 1
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    if (arguments.Count >= 2)
                    {
                        string subCommand = arguments[1];
                        bool   tried      = false;

                        code = ScriptOps.TryExecuteSubCommandFromEnsemble(
                            interpreter, this, clientData, arguments, false,
                            false, ref subCommand, ref tried, ref result);

                        if ((code == ReturnCode.Ok) && !tried)
                        {
                            switch (subCommand)
                            {
                            case "active":
                            {
                                if (arguments.Count == 2)
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        result = eventManager.Active;
                                        code   = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after active\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "cancel":
                            {
                                if (arguments.Count >= 3)
                                {
                                    string text;

                                    if (arguments.Count == 3)
                                    {
                                        text = arguments[2];
                                    }
                                    else
                                    {
                                        text = ListOps.Concat(arguments, 2);
                                    }

                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        code = eventManager.CancelEvents(
                                            text, false, false, ref result);
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after cancel arg ?arg ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "clear":
                            {
                                if (arguments.Count == 2)
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        code = eventManager.ClearEvents(ref result);

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = String.Empty;
                                        }
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after clear\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "counts":
                            {
                                if (arguments.Count == 2)
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        result = StringList.MakeList(
                                            "enabled", eventManager.Enabled,
                                            "active", eventManager.Active,
                                            "createEventCount", Event.CreateCount,
                                            "disposeEventCount", Event.DisposeCount,
                                            "queueEventCount", eventManager.QueueEventCount,
                                            "queueIdleEventCount", eventManager.QueueIdleEventCount,
                                            "eventCount", eventManager.EventCount,
                                            "idleEventCount", eventManager.IdleEventCount,
                                            "totalEventCount", eventManager.TotalEventCount,
                                            "maximumEventCount", eventManager.MaximumEventCount,
                                            "maximumIdleEventCount", eventManager.MaximumIdleEventCount,
                                            "maybeDisposeEventCount", eventManager.MaybeDisposeEventCount,
                                            "reallyDisposeEventCount", eventManager.ReallyDisposeEventCount,
                                            "interpreterEventCount", interpreter.EventCount,
#if NATIVE && TCL
                                            "interpreterTclEventCount", interpreter.TclEventCount,
#endif
                                            "interpreterWaitCount", interpreter.WaitCount,
                                            "interpreterWaitSpinCount", interpreter.WaitSpinCount);

                                        code = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after counts\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "dump":
                            {
                                if (arguments.Count == 2)
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        code = eventManager.Dump(ref result);
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after dump\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "enable":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        if (arguments.Count == 3)
                                        {
                                            bool enabled = false;

                                            code = Value.GetBoolean2(
                                                arguments[2], ValueFlags.AnyBoolean,
                                                interpreter.CultureInfo, ref enabled, ref result);

                                            if (code == ReturnCode.Ok)
                                            {
                                                eventManager.Enabled = enabled;
                                            }
                                        }

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = eventManager.Enabled;
                                        }
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after enable ?enabled?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "flags":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    lock (interpreter.SyncRoot)         /* TRANSACTIONAL */
                                    {
                                        if (arguments.Count == 3)
                                        {
                                            object enumValue = EnumOps.TryParseFlagsEnum(
                                                interpreter, typeof(EventFlags),
                                                interpreter.AfterEventFlags.ToString(),
                                                arguments[2], interpreter.CultureInfo,
                                                true, true, true, ref result);

                                            if (enumValue is EventFlags)
                                            {
                                                interpreter.AfterEventFlags = (EventFlags)enumValue;
                                            }
                                            else
                                            {
                                                code = ReturnCode.Error;
                                            }
                                        }

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = interpreter.AfterEventFlags;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after flags ?flags?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "idle":
                            {
                                if (arguments.Count >= 3)
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        //
                                        // FIXME: PRI 5: Somewhat arbitrary, we cannot be "idle" with no
                                        //        windows message loop.
                                        //
                                        string   name     = FormatOps.Id(this.Name, null, interpreter.NextId());
                                        DateTime now      = TimeOps.GetUtcNow();
                                        DateTime dateTime = now.AddMilliseconds(EventManager.MinimumIdleWaitTime);
                                        string   text;

                                        if (arguments.Count == 3)
                                        {
                                            text = arguments[2];
                                        }
                                        else
                                        {
                                            text = ListOps.Concat(arguments, 2);
                                        }

                                        IScript script = interpreter.CreateAfterScript(
                                            name, null, null, ScriptTypes.Idle, text,
                                            now, EngineMode.EvaluateScript, ScriptFlags.None,
                                            clientData, true);

                                        code = eventManager.QueueScript(
                                            name, dateTime, script, script.EventFlags,
                                            EventPriority.Idle, ref result);

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = name;
                                        }
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after idle arg ?arg ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "info":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    IEventManager eventManager = interpreter.EventManager;

                                    if (EventOps.ManagerIsOk(eventManager))
                                    {
                                        if (arguments.Count == 3)
                                        {
                                            IEvent @event = null;

                                            code = eventManager.GetEvent(
                                                arguments[2], ref @event, ref result);

                                            if (code == ReturnCode.Ok)
                                            {
                                                if (EventManager.IsScriptEvent(@event))
                                                {
                                                    if (@event.ClientData != null)
                                                    {
                                                        IScript script = @event.ClientData.Data as IScript;

                                                        if (script != null)
                                                        {
                                                            result = script.ToString();
                                                        }
                                                        else
                                                        {
                                                            result = String.Format(
                                                                "event \"{0}\" clientData is not a script",
                                                                arguments[2]);

                                                            code = ReturnCode.Error;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        result = String.Format(
                                                            "event \"{0}\" has invalid clientData",
                                                            arguments[2]);

                                                        code = ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    result = String.Format(
                                                        "event \"{0}\" is not an after event",
                                                        arguments[2]);

                                                    code = ReturnCode.Error;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            StringList list = null;

                                            code = eventManager.ListEvents(null, false, ref list, ref result);

                                            if (code == ReturnCode.Ok)
                                            {
                                                result = list;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        result = "event manager not available";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"after info ?id?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            default:
                            {
                                long milliseconds = 0;         // for idle, execute the script right now.

                                code = Value.GetWideInteger2(
                                    subCommand, ValueFlags.AnyWideInteger,
                                    interpreter.CultureInfo, ref milliseconds, ref result);

                                if (code == ReturnCode.Ok)
                                {
                                    if (arguments.Count == 2)
                                    {
                                        //
                                        // BUGBUG: This call will never timeout if we cannot obtain
                                        //         the interpreter lock.
                                        //
                                        code = EventOps.Wait(
                                            interpreter, PerformanceOps.GetMicroseconds(milliseconds),
                                            false, false, ref result);

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = String.Empty;
                                        }
                                    }
                                    else if (arguments.Count >= 3)
                                    {
                                        IEventManager eventManager = interpreter.EventManager;

                                        if (EventOps.ManagerIsOk(eventManager))
                                        {
                                            string   name     = FormatOps.Id(this.Name, null, interpreter.NextId());
                                            DateTime now      = TimeOps.GetUtcNow();
                                            DateTime dateTime = now.AddMilliseconds(milliseconds);
                                            string   text;

                                            if (arguments.Count == 3)
                                            {
                                                text = arguments[2];
                                            }
                                            else
                                            {
                                                text = ListOps.Concat(arguments, 2);
                                            }

                                            IScript script = interpreter.CreateAfterScript(
                                                name, null, null, ScriptTypes.Timer, text,
                                                now, EngineMode.EvaluateScript, ScriptFlags.None,
                                                clientData, false);

                                            code = eventManager.QueueScript(
                                                name, dateTime, script, script.EventFlags,
                                                EventPriority.After, ref result);

                                            if (code == ReturnCode.Ok)
                                            {
                                                result = name;
                                            }
                                        }
                                        else
                                        {
                                            result = "event manager not available";
                                            code   = ReturnCode.Error;
                                        }
                                    }
                                    else
                                    {
                                        result = "wrong # args: should be \"after milliseconds arg ?arg ...?\"";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = ScriptOps.BadSubCommand(
                                        interpreter, null, "argument", subCommand, this, null, ", or a number");
                                }
                                break;
                            }
                            }
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"after option ?arg ...?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Esempio n. 2
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    if (arguments.Count >= 2)
                    {
                        string fileName = arguments[1];

                        if (interpreter.HasChannels(ref result))
                        {
                            MapOpenAccess access      = MapOpenAccess.Default;
                            int           permissions = 0; // NOTE: This is ONLY parsed, NOT used for opening the file.
                            string        type        = null;

                            if (arguments.Count >= 3)
                            {
                                Result enumString = arguments[2];

                                if (!String.IsNullOrEmpty(enumString))
                                {
                                    //
                                    // HACK: Translate illegal mode char "+" to what our Enum uses.
                                    //       This strategy will backfire later if we ever decide to
                                    //       allow parsing of the access mode as "flags" (via GetOptions).
                                    //
                                    enumString = enumString.Replace(Characters.PlusSign.ToString(), "Plus");
                                }

                                code = StringOps.StringToEnumList(interpreter, enumString, ref enumString);

                                if (code == ReturnCode.Ok)
                                {
                                    object enumValue = EnumOps.TryParseEnum(
                                        typeof(MapOpenAccess), enumString,
                                        true, true);

                                    if (enumValue is MapOpenAccess)
                                    {
                                        access = (MapOpenAccess)enumValue;
                                    }
                                    else
                                    {
                                        enumString = ScriptOps.BadValue(
                                            "invalid", "access mode", arguments[2],
                                            Enum.GetNames(typeof(MapOpenAccess)), null, null);

                                        code = ReturnCode.Error;
                                    }
                                }

                                if (code != ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Transfer local result from above and add to the error info.
                                    //
                                    result = enumString;

                                    Engine.AddErrorInformation(interpreter, result,
                                                               String.Format("{0}    while processing open access modes \"{1}\"",
                                                                             Environment.NewLine, FormatOps.Ellipsis(arguments[2])));
                                }
                            }

                            if ((code == ReturnCode.Ok) && (arguments.Count >= 4))
                            {
                                code = Value.GetInteger2(
                                    (IGetValue)arguments[3], ValueFlags.AnyInteger,
                                    interpreter.CultureInfo, ref permissions, ref result);
                            }

                            if (code == ReturnCode.Ok)
                            {
                                if (arguments.Count >= 5)
                                {
                                    type = arguments[4];
                                }

                                OptionDictionary options = new OptionDictionary(
                                    new IOption[] {
#if CONSOLE
                                    new Option(null, OptionFlags.None, 1, Index.Invalid, "-stdin", null),
                                    new Option(null, OptionFlags.None, 1, Index.Invalid, "-stdout", null),
                                    new Option(null, OptionFlags.None, 1, Index.Invalid, "-stderr", null),
#else
                                    new Option(null, OptionFlags.Unsupported, 1, Index.Invalid, "-stdin", null),
                                    new Option(null, OptionFlags.Unsupported, 1, Index.Invalid, "-stdout", null),
                                    new Option(null, OptionFlags.Unsupported, 1, Index.Invalid, "-stderr", null),
#endif
                                    new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-channelid", null),
                                    new Option(null, OptionFlags.MustHaveIntegerValue, Index.Invalid, Index.Invalid, "-buffersize", null),
                                    new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-autoflush", null),
                                    new Option(typeof(HostStreamFlags), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-streamflags",
                                               new Variant(HostStreamFlags.Default)),
                                    new Option(typeof(FileOptions), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-options",
                                               new Variant(FileOptions.None)),
                                    new Option(typeof(FileShare), OptionFlags.MustHaveEnumValue, Index.Invalid, Index.Invalid, "-share",
                                               new Variant(FileShare.Read))
                                });

                                int argumentIndex = Index.Invalid;

                                if (arguments.Count > 5)
                                {
                                    code = interpreter.GetOptions(options, arguments, 0, 5, Index.Invalid, true, ref argumentIndex, ref result);
                                }
                                else
                                {
                                    code = ReturnCode.Ok;
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    if (argumentIndex == Index.Invalid)
                                    {
                                        Variant value     = null;
                                        string  channelId = null;

                                        if (options.IsPresent("-channelid", ref value))
                                        {
                                            channelId = value.ToString();
                                        }

                                        if ((channelId == null) ||
                                            (interpreter.DoesChannelExist(channelId) != ReturnCode.Ok))
                                        {
#if CONSOLE
                                            if (options.IsPresent("-stdin"))
                                            {
                                                //
                                                // NOTE: Enforce the proper access for the standard input
                                                //       channel.
                                                //
                                                if (access == MapOpenAccess.RdOnly)
                                                {
                                                    try
                                                    {
                                                        IStreamHost streamHost = interpreter.Host;

                                                        //
                                                        // NOTE: *WARNING* This option causes the "fileName",
                                                        //       "access", "permissions", and "type" arguments
                                                        //       to be ignored.
                                                        //
                                                        lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                                                        {
                                                            if (streamHost.In == null)
                                                            {
                                                                int?bufferSize = null;

                                                                if (options.IsPresent("-buffersize", ref value))
                                                                {
                                                                    bufferSize = (int)value.Value;
                                                                }

                                                                streamHost.In = (bufferSize != null) ?
                                                                                Console.OpenStandardInput((int)bufferSize) :
                                                                                Console.OpenStandardInput();
                                                            }
                                                        }

                                                        code = interpreter.ModifyStandardChannels(
                                                            streamHost, channelId, ChannelType.Input |
                                                            ChannelType.ErrorOnExist, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            result = (channelId != null) ? channelId : StandardChannel.Input;
                                                        }
                                                    }
                                                    catch (Exception e)
                                                    {
                                                        Engine.SetExceptionErrorCode(interpreter, e);

                                                        result = e;
                                                        code   = ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    result = String.Format(
                                                        "illegal access mode \"{0}\", standard input " +
                                                        "can only be opened using access mode \"{1}\"",
                                                        access, MapOpenAccess.RdOnly);

                                                    code = ReturnCode.Error;
                                                }
                                            }
                                            else if (options.IsPresent("-stdout"))
                                            {
                                                //
                                                // NOTE: Enforce the proper access for the standard output
                                                //       channel.
                                                //
                                                if (access == MapOpenAccess.WrOnly)
                                                {
                                                    try
                                                    {
                                                        IStreamHost streamHost = interpreter.Host;

                                                        //
                                                        // NOTE: *WARNING* This option causes the "fileName",
                                                        //       "access", "permissions", and "type" arguments
                                                        //       to be ignored.
                                                        //
                                                        lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                                                        {
                                                            if (streamHost.Out == null)
                                                            {
                                                                int?bufferSize = null;

                                                                if (options.IsPresent("-buffersize", ref value))
                                                                {
                                                                    bufferSize = (int)value.Value;
                                                                }

                                                                streamHost.Out = (bufferSize != null) ?
                                                                                 Console.OpenStandardOutput((int)bufferSize) :
                                                                                 Console.OpenStandardOutput();
                                                            }
                                                        }

                                                        code = interpreter.ModifyStandardChannels(
                                                            streamHost, channelId, ChannelType.Output |
                                                            ChannelType.ErrorOnExist, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            result = (channelId != null) ? channelId : StandardChannel.Output;
                                                        }
                                                    }
                                                    catch (Exception e)
                                                    {
                                                        Engine.SetExceptionErrorCode(interpreter, e);

                                                        result = e;
                                                        code   = ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    result = String.Format(
                                                        "illegal access mode \"{0}\", standard output " +
                                                        "can only be opened using access mode \"{1}\"",
                                                        access, MapOpenAccess.WrOnly);

                                                    code = ReturnCode.Error;
                                                }
                                            }
                                            else if (options.IsPresent("-stderr"))
                                            {
                                                //
                                                // NOTE: Enforce the proper access for the standard error
                                                //       channel.
                                                //
                                                if (access == MapOpenAccess.WrOnly)
                                                {
                                                    try
                                                    {
                                                        IStreamHost streamHost = interpreter.Host;

                                                        //
                                                        // NOTE: *WARNING* This option causes the "fileName",
                                                        //       "access", "permissions", and "type" arguments
                                                        //       to be ignored.
                                                        //
                                                        lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                                                        {
                                                            if (streamHost.Error == null)
                                                            {
                                                                int?bufferSize = null;

                                                                if (options.IsPresent("-buffersize", ref value))
                                                                {
                                                                    bufferSize = (int)value.Value;
                                                                }

                                                                streamHost.Error = (bufferSize != null) ?
                                                                                   Console.OpenStandardError((int)bufferSize) :
                                                                                   Console.OpenStandardError();
                                                            }
                                                        }

                                                        code = interpreter.ModifyStandardChannels(
                                                            streamHost, channelId, ChannelType.Error |
                                                            ChannelType.ErrorOnExist, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            result = (channelId != null) ? channelId : StandardChannel.Error;
                                                        }
                                                    }
                                                    catch (Exception e)
                                                    {
                                                        Engine.SetExceptionErrorCode(interpreter, e);

                                                        result = e;
                                                        code   = ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    result = String.Format(
                                                        "illegal access mode \"{0}\", standard error " +
                                                        "can only be opened using access mode \"{1}\"",
                                                        access, MapOpenAccess.WrOnly);

                                                    code = ReturnCode.Error;
                                                }
                                            }
                                            else
#endif
                                            {
                                                Stream stream    = null;
                                                bool   autoFlush = false;

                                                switch (type)
                                                {
                                                case null:                      /* FALL-THROUGH */
                                                case /* String.Empty */ "":     /* FALL-THROUGH */
                                                case "file":
                                                {
                                                    try
                                                    {
                                                        HostStreamFlags hostStreamFlags = HostStreamFlags.OpenCommand;
                                                        FileAccess      fileAccess      = FileOps.FileAccessFromAccess(access);
                                                        FileMode        fileMode        = FileOps.FileModeFromAccess(access);
                                                        FileShare       fileShare       = FileShare.Read;

                                                        if (options.IsPresent("-streamflags", ref value))
                                                        {
                                                            hostStreamFlags = (HostStreamFlags)value.Value;
                                                        }

                                                        if (options.IsPresent("-share", ref value))
                                                        {
                                                            fileShare = (FileShare)value.Value;
                                                        }

                                                        int bufferSize = Channel.DefaultBufferSize;

                                                        if (options.IsPresent("-buffersize", ref value))
                                                        {
                                                            bufferSize = (int)value.Value;
                                                        }

                                                        FileOptions fileOptions = FileOptions.None;

                                                        if (options.IsPresent("-options", ref value))
                                                        {
                                                            fileOptions = (FileOptions)value.Value;
                                                        }

                                                        if (options.IsPresent("-autoflush"))
                                                        {
                                                            autoFlush = true;
                                                        }

                                                        bool seekToEof = false;

                                                        //
                                                        // HACK: Check for special case where they want to Append
                                                        //       and Read/ReadWrite.
                                                        //
                                                        if (((fileAccess == FileAccess.Read) ||
                                                             (fileAccess == FileAccess.ReadWrite)) &&
                                                            (FlagOps.HasFlags(access, MapOpenAccess.SeekToEof, true) ||
                                                             FlagOps.HasFlags(access, MapOpenAccess.Append, true)))
                                                        {
                                                            seekToEof = true;
                                                        }

                                                        code = interpreter.GetStream(
                                                            fileName, fileMode, fileAccess, fileShare, bufferSize,
                                                            fileOptions, Channel.StrictGetStream, ref hostStreamFlags,
                                                            ref stream, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            if ((stream != null) && seekToEof)
                                                            {
                                                                stream.Seek(0, SeekOrigin.End);
                                                            }
                                                        }
                                                    }
                                                    catch (Exception e)
                                                    {
                                                        Engine.SetExceptionErrorCode(interpreter, e);

                                                        result = e;
                                                        code   = ReturnCode.Error;
                                                    }
                                                    break;
                                                }

                                                default:
                                                {
                                                    result = String.Format(
                                                        "unsupported channel type \"{0}\"",
                                                        type);

                                                    code = ReturnCode.Error;
                                                    break;
                                                }
                                                }

                                                //
                                                // NOTE: Did we manage to open the file successfully?
                                                //
                                                if (code == ReturnCode.Ok)
                                                {
                                                    StreamFlags flags = StreamFlags.PreventClose;

                                                    if (channelId == null)
                                                    {
                                                        channelId = FormatOps.Id("file", null, interpreter.NextId());
                                                    }

                                                    code = interpreter.AddFileOrSocketChannel(
                                                        channelId, stream, options, flags,
                                                        FlagOps.HasFlags(access, MapOpenAccess.Append, true),
                                                        autoFlush, null, ref result);

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        result = channelId;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "can't add \"{0}\": channel already exists",
                                                channelId);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                    else
                                    {
                                        result = "wrong # args: should be \"open fileName ?access? ?permissions? ?type? ?options?\"";
                                        code   = ReturnCode.Error;
                                    }
                                }
                            }
                        }
                        else
                        {
                            code = ReturnCode.Error;
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"open fileName ?access? ?permissions? ?type? ?options?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Esempio n. 3
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    if (arguments.Count >= 3)
                    {
                        if (interpreter.HasChannels(ref result))
                        {
                            OptionDictionary options = new OptionDictionary(
                                new IOption[] {
                                new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-server", null),                // server only
                                new Option(null, OptionFlags.MustHaveIntegerValue, Index.Invalid, Index.Invalid, "-buffer", null),         // client & server
                                new Option(null, OptionFlags.MustHaveIntegerValue, Index.Invalid, Index.Invalid, "-timeout", null),        // client & server
                                new Option(null, OptionFlags.MustHaveIntegerValue, Index.Invalid, Index.Invalid, "-sendtimeout", null),    // client & server
                                new Option(null, OptionFlags.MustHaveIntegerValue, Index.Invalid, Index.Invalid, "-receivetimeout", null), // client & server
                                new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-myaddr", null),                // client & server
                                new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-myport", null),                // client only
                                new Option(null, OptionFlags.Unsupported, Index.Invalid, Index.Invalid, "-async", null),                   // client only
                                new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-channelid", null),             // client & server
                                new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nodelay", null),                        // client only
                                new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-noexclusive", null),                    // server only
                                new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null)
                            });

                            int argumentIndex = Index.Invalid;

                            code = interpreter.GetOptions(options, arguments, 0, 1, Index.Invalid, true, ref argumentIndex, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: There must be at least one argument after the options
                                //       and there can never be more than two.
                                //
                                if ((argumentIndex != Index.Invalid) && ((argumentIndex + 2) >= arguments.Count))
                                {
                                    Variant value   = null;
                                    string  command = null;

                                    if (options.IsPresent("-server", ref value))
                                    {
                                        command = value.ToString();
                                    }

                                    string myAddress = null;

                                    if (options.IsPresent("-myaddr", ref value))
                                    {
                                        myAddress = value.ToString();
                                    }

                                    string myPort = null;

                                    if (options.IsPresent("-myport", ref value))
                                    {
                                        myPort = value.ToString();
                                    }

                                    int buffer = 0;

                                    if (options.IsPresent("-buffer", ref value))
                                    {
                                        buffer = (int)value.Value;
                                    }

                                    int sendTimeout = _Timeout.None;

                                    if (options.IsPresent("-sendtimeout", ref value))
                                    {
                                        sendTimeout = (int)value.Value;
                                    }

                                    int receiveTimeout = _Timeout.None;

                                    if (options.IsPresent("-receivetimeout", ref value))
                                    {
                                        receiveTimeout = (int)value.Value;
                                    }

                                    int timeout = _Timeout.None;

                                    if (options.IsPresent("-timeout", ref value))
                                    {
                                        timeout = (int)value.Value;
                                    }

                                    bool asynchronous = false;

                                    if (options.IsPresent("-async"))
                                    {
                                        asynchronous = true; /* NOT YET IMPLEMENTED */
                                    }
                                    bool noDelay = false;

                                    if (options.IsPresent("-nodelay"))
                                    {
                                        noDelay = true;
                                    }

                                    bool exclusive = true; /* TODO: Good default? */

                                    if (options.IsPresent("-noexclusive"))
                                    {
                                        exclusive = false;
                                    }

                                    string channelId = null;

                                    if (options.IsPresent("-channelid", ref value))
                                    {
                                        channelId = value.ToString();
                                    }

                                    if ((channelId == null) ||
                                        (interpreter.DoesChannelExist(channelId) != ReturnCode.Ok))
                                    {
                                        if (command != null)
                                        {
                                            if ((argumentIndex + 1) == arguments.Count)
                                            {
                                                if (myPort == null)
                                                {
                                                    code = interpreter.StartServerSocket(
                                                        options, timeout, myAddress,
                                                        arguments[argumentIndex], exclusive,
                                                        command, ref result);
                                                }
                                                else
                                                {
                                                    goto wrongNumArgs;
                                                }
                                            }
                                            else
                                            {
                                                goto wrongNumArgs;
                                            }
                                        }
                                        else
                                        {
                                            if ((argumentIndex + 2) == arguments.Count)
                                            {
                                                if (!asynchronous)
                                                {
                                                    TcpClient client = SocketOps.NewTcpClient(myAddress, myPort,
                                                                                              interpreter.CultureInfo, ref result);

                                                    if (client != null)
                                                    {
                                                        try
                                                        {
                                                            client.NoDelay = noDelay;

                                                            if (timeout != _Timeout.None)
                                                            {
                                                                client.SendTimeout    = timeout;
                                                                client.ReceiveTimeout = timeout;
                                                            }

                                                            if (sendTimeout != _Timeout.None)
                                                            {
                                                                client.SendTimeout = sendTimeout;
                                                            }

                                                            if (receiveTimeout != _Timeout.None)
                                                            {
                                                                client.ReceiveTimeout = receiveTimeout;
                                                            }

                                                            if (buffer != 0)
                                                            {
                                                                client.SendBufferSize    = buffer;
                                                                client.ReceiveBufferSize = buffer;
                                                            }

                                                            code = ReturnCode.Ok;
                                                        }
                                                        catch (Exception e)
                                                        {
                                                            Engine.SetExceptionErrorCode(interpreter, e);

                                                            result = e;
                                                            code   = ReturnCode.Error;
                                                        }

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            code = SocketOps.Connect(client, arguments[argumentIndex],
                                                                                     arguments[argumentIndex + 1], interpreter.CultureInfo,
                                                                                     ref result);

                                                            if (code == ReturnCode.Ok)
                                                            {
                                                                StreamFlags flags = StreamFlags.PreventClose |
                                                                                    StreamFlags.Socket | StreamFlags.Client;

                                                                if (channelId == null)
                                                                {
                                                                    channelId = FormatOps.Id("clientSocket", null, interpreter.NextId());
                                                                }

                                                                code = interpreter.AddFileOrSocketChannel(
                                                                    channelId, client.GetStream(), options, flags, false,
                                                                    false, new ClientData(client), ref result);

                                                                if (code == ReturnCode.Ok)
                                                                {
                                                                    result = channelId;
                                                                }
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        code = ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    result = "asynchronous sockets are not implemented";
                                                    code   = ReturnCode.Error;
                                                }
                                            }
                                            else
                                            {
                                                goto wrongNumArgs;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "can't add \"{0}\": channel already exists",
                                            channelId);

                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    if ((argumentIndex != Index.Invalid) &&
                                        Option.LooksLikeOption(arguments[argumentIndex]))
                                    {
                                        result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                                        code   = ReturnCode.Error;
                                    }
                                    else
                                    {
                                        goto wrongNumArgs;
                                    }
                                }
                            }
                        }
                        else
                        {
                            code = ReturnCode.Error;
                        }
                    }
                    else
                    {
                        goto wrongNumArgs;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);

wrongNumArgs:
            result = "wrong # args: should be \"socket ?-myaddr addr? ?-myport myport? ?-async? host port\" " +
                     "or \"socket -server command ?-myaddr addr? port\"";

            return(ReturnCode.Error);
        }