/////////////////////////////////////////////////////////////////////// public static bool HasFlags( MapOpenAccess access, MapOpenAccess flags, bool all ) { if (all) { return((access & flags) == flags); } else { return((access & flags) != MapOpenAccess.Default); } }
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); }