/** * This file is part of Erjang - A JVM-based Erlang VM * * Copyright (c) 2009 by Trifork * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package erjang.driver; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import kilim.Pausable; import kilim.Task; import erjang.EAtom; import erjang.EBinList; import erjang.EBinary; import erjang.EBitString; import erjang.ECons; import erjang.EHandle; import erjang.EObject; import erjang.EPort; import erjang.EProc; import erjang.ERT; import erjang.ESeq; import erjang.EString; import erjang.ETask; import erjang.ETuple2; import erjang.ErlangError; import erjang.NotImplemented; import erjang.m.erlang.ErlPort; /** * UNUSED CLASS I KEEP AROUND BECAUSE IT HAS SOME CODE I MAY USE LATER * * A n EPort instance that corresponds to an external executable */ public class EExecDriverTask extends EDriverTask { private Process process; private DataOutputStream out; private InputStream in; private DataInputStream err; private ETuple2 name; private EObject command; public EObject getName() { return command; } /** * @param owner * @param name * @param portSetting */ public EExecDriverTask(EProc owner, ETuple2 name, EObject command, EObject portSetting) { super(owner.self_handle(), new ExecDriverInstance(name)); this.command = command; // argument can be any list, ... turn it into a string ESeq es = name.elem2.testString(); if (es == null) { ECons cons; EAtom am; if ((cons = name.elem2.testCons()) != null) { es = EString.make(cons); } else if ((am = name.elem2.testAtom()) != null) { es = EString.fromString(am.getName()); } else { throw ERT.badarg(name, portSetting); } } String full_cmd = es.stringValue(); String[] cmd; if (name.elem1 == ErlPort.am_spawn) { cmd = split_with_quotes(full_cmd); } else { cmd = new String[] { full_cmd }; } parseOptions(cmd, portSetting); File f = new File(cmd[0]); if (f.isAbsolute()) { // ok // } else { String cmd_path = env.get("PATH"); if (cmd_path != null) { for (String elm : cmd_path.split(File.pathSeparator)) { File dir = ERT.newFile(elm); f = new File(dir, cmd[0]); if (f.exists()) { cmd[0] = f.getAbsolutePath(); break; } else { f = null; } } } } /* System.err.println("** launching "); System.err.println( " name = " + name); System.err.println( " cmd = " + command); System.err.println( " opts = " + portSetting); for (int i = 0; i < cmd.length; i++) { System.err.println(" cmd["+i+"]=" + cmd[i]); } */ if (f == null) { throw new ErlangError(ETuple2.make_tuple(EAtom.intern("enoent"), new EString(cmd[0]))); } if (!f.canExecute()) { throw new ErlangError(EAtom.intern("eaccess")); } super.setupInstance(); } private String[] split_with_quotes(String cmd) { List<String> res = new ArrayList<String>(); int length = cmd.length(); for (int i = skip_space(cmd, 0); i < length; i = skip_space(cmd, i)) { char ch = cmd.charAt(i); if (ch == '"' || ch == '\'') { i = parse_qarg(i, res, cmd, ch); } else { int start = i; while (i < length && !Character.isSpaceChar( cmd.charAt(i) )) i++; String arg = cmd.substring(start, i); res.add(arg); } } return res.toArray(new String[res.size()]); } private int skip_space(String cmd, int i) { int l = cmd.length(); while (i < l && Character.isSpaceChar( cmd.charAt(i) )) i++; return i; } int parse_qarg(int i, List<String> args, String cmd, char q) { assert(cmd.charAt(i) == q); StringBuffer arg = new StringBuffer(); char ch; while (++i < cmd.length() && (ch = cmd.charAt(i)) != q) { if (ch == '\\') { i += 1; if (i == cmd.length()) throw ERT.badarg(); arg.append( cmd.charAt(i)); } else { arg.append( ch ); } } args.add( arg.toString() ); return i+1; } /* (non-Javadoc) * @see kilim.Task#toString() */ @Override public String toString() { return String.valueOf(name) + "::" + super.toString(); } }