/** * $Id$ * $Date$ * */ package org.xmlsh.sh.core; import static org.xmlsh.core.XIOEnvironment.kSTDERR; import static org.xmlsh.core.XIOEnvironment.kSTDOUT; import java.io.IOException; import java.io.PrintWriter; import org.xmlsh.core.CoreException; import org.xmlsh.core.EvalEnv; import org.xmlsh.core.InputPort; import org.xmlsh.core.InvalidArgumentException; import org.xmlsh.core.XEnvironment; import org.xmlsh.core.XVariable; import org.xmlsh.core.io.OutputPort; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.sh.shell.Shell; import org.xmlsh.util.Util; import lombok.extern.log4j.Log4j2; @Log4j2 public class IOFile { private static final EvalEnv mFileEnv = EvalEnv.newInstance(false, true, false, false); private String mPrefix; private Word mFile; private String mPort; // portname or varname public IOFile(String prefix, Word file) { mLogger.entry(prefix,file); mPrefix = prefix; mFile = file; } public IOFile(String prefix, String port) { mLogger.entry(prefix,port); mPrefix = prefix; mPort = port; } public void print(PrintWriter out) { out.print(mPrefix); if(mFile != null) mFile.print(out); } public void exec(Shell shell, String port, SourceLocator loc) throws IOException, CoreException { mLogger.entry(port,loc); XEnvironment env = shell.getEnv(); SerializeOpts sopts = shell.getSerializeOpts(); String file = null; if(mFile == null) { if(mPort != null) file = mPort; } else file = mFile.expandString(shell, mFileEnv); mLogger.trace("file {} File: {} Port: {}" , file , mFile , mPort ); /* * File-less redirections 1>&2 2>&1 */ if(file == null) { /* * Port Duplication puts the same port in 2 slots * must manage an extra reference count to avoid over releasing */ if(mPrefix.equals("1>&2")) env.dupOutput(kSTDOUT, kSTDERR); else if(mPrefix.equals("2>&1")) env.dupOutput(kSTDERR, kSTDOUT); return; } /* * Variable IO syntax cmd <{var} * */ boolean isVar = file.startsWith("{") && file.endsWith("}"); if(isVar) { mLogger.trace("isvar file is: {}", file); String var = file.substring(1, file.length() - 1); if(Util.isBlank(var)) throw new CoreException("Invalid blank name for output variable"); XVariable vvar = env.getVar(var); if(mPrefix.equals("<")) { if(vvar == null || vvar.isNull()) throw new CoreException("Undefined variable: " + var); env.setInput(port, vvar); } else if(mPrefix.equals(">")) { env.unsetVar(var); XVariable xvar = env.declareVar(var); env.setOutput(port, xvar); } else if(mPrefix.equals(">>")) { XVariable xvar = vvar; if(xvar == null) { xvar = env.declareVar(var); } env.setOutput(port, xvar); } return; } /* * Port IO syntax cmd <(port) * */ boolean isPort = file.startsWith("(") && file.endsWith(")"); if(isPort) { String portname = file.substring(1, file.length() - 1); mLogger.trace("isPort prefix: {} portname: {}", mPrefix, portname ); if(mPrefix.equals("<")) { InputPort inp = env.getInputPort(portname); if(inp == null) throw new InvalidArgumentException( "Input port not found: " + portname); env.setInput(port, inp); } else if(mPrefix.equals(">")) { OutputPort outp = env.getOutputPort(portname, false); if(outp == null) throw new InvalidArgumentException( "Output port not found: " + portname); env.setOutput(port, outp); } else if(mPrefix.equals(">>")) { OutputPort outp = env.getOutputPort(portname, true); if(outp == null) throw new InvalidArgumentException( "Output port not found: " + portname); env.setOutput(port, outp); } else if(mPrefix.equals(">&")) { env.dupOutput(port, portname); } else if(mPrefix.equals("<&")) { env.dupInput(port, portname); } else mLogger.warn("SNH - unexpectd redirect: mFile: {} mPrefix {} file: {} isVar: {} isPort: {}", mFile,mPrefix,file,isVar,isPort ); return; } if(mPrefix.equals("<")) { mLogger.trace("Redirect input to port: {} from file: ", port , file); InputPort in = env.setInput(port, shell.newInputPort(file)); in.setSystemId(file); } else if(mPrefix.equals("2>")){ env.setStderr(shell.newOutputPort(file, false)); } else if(mPrefix.equals("2>>")){ env.setStderr(shell.newOutputPort(file, true)); } else if(mPrefix.equals(">")){ env.setOutput(port, shell.newOutputPort(file, false)); } else if(mPrefix.equals(">>")){ env.setOutput(port, shell.newOutputPort(file, true)); } else { mLogger.warn("SNH redirect unknown mPrefix: {} mFile: {} port: {} file: {} isVar: {} isPort: {}:", mPrefix,mFile,port,file,isVar,isPort ); } } } // // // Copyright (C) 2008-2014 David A. Lee. // // The contents of this file are subject to the "Simplified BSD License" (the // "License"); // you may not use this file except in compliance with the License. You may // obtain a copy of the // License at http://www.opensource.org/licenses/bsd-license.php // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. // See the License for the specific language governing rights and limitations // under the License. // // The Original Code is: all this file. // // The Initial Developer of the Original Code is David A. Lee // // Portions created by (your name) are Copyright (C) (your legal entity). All // Rights Reserved. // // Contributor(s): none. //