Example #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 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);
        }
Example #2
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);
        }