1 21 22 package org.armedbear.lisp; 23 24 import java.io.BufferedReader ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.InputStreamReader ; 28 import java.util.ArrayList ; 29 import java.util.List ; 30 31 public final class ShellCommand extends Lisp implements Runnable 32 { 33 private final String command; 34 private final String directory; 35 private final StringBuffer output = new StringBuffer (); 36 37 private int exitValue = -1; 38 39 private ShellCommand(String command, String directory) 40 throws ConditionThrowable 41 { 42 this.command = command; 43 this.directory = directory; 44 } 45 46 private final String getOutput() 47 { 48 return output.toString(); 49 } 50 51 private final int exitValue() 52 { 53 return exitValue; 54 } 55 56 private void appendOutput(String s) 57 { 58 output.append(s); 59 } 60 61 public void run() 62 { 63 Process process = null; 64 try { 65 if (command != null) { 66 if (Utilities.isPlatformUnix()) { 67 if (directory != null) { 68 StringBuffer sb = new StringBuffer ("\\cd \""); 69 sb.append(directory); 70 sb.append("\" && "); 71 sb.append(command); 72 String [] cmdarray = {"/bin/sh", "-c", sb.toString()}; 73 process = Runtime.getRuntime().exec(cmdarray); 74 } else { 75 String [] cmdarray = {"/bin/sh", "-c", command}; 76 process = Runtime.getRuntime().exec(cmdarray); 77 } 78 } else if (Utilities.isPlatformWindows()) { 79 ArrayList list = new ArrayList (); 80 list.add("cmd.exe"); 81 list.add("/c"); 82 if (directory != null) { 83 StringBuffer sb = new StringBuffer ("cd /d \""); 84 sb.append(directory); 85 sb.append("\" && "); 86 sb.append(command); 87 list.addAll(tokenize(sb.toString())); 88 } else 89 list.addAll(tokenize(command)); 90 final int size = list.size(); 91 String [] cmdarray = new String [size]; 92 for (int i = 0; i < size; i++) 93 cmdarray[i] = (String ) list.get(i); 94 process = Runtime.getRuntime().exec(cmdarray); 95 } 96 } 97 } 98 catch (IOException e) { 99 Debug.trace(e); 100 } 101 if (process != null) { 102 ReaderThread stdoutThread = 103 new ReaderThread(process.getInputStream()); 104 stdoutThread.start(); 105 ReaderThread stderrThread = 106 new ReaderThread(process.getErrorStream()); 107 stderrThread.start(); 108 try { 109 exitValue = process.waitFor(); 110 } 111 catch (InterruptedException e) { 112 Debug.trace(e); 113 } 114 try { 115 stdoutThread.join(); 116 } 117 catch (InterruptedException e) { 118 Debug.trace(e); 119 } 120 try { 121 stderrThread.join(); 122 } 123 catch (InterruptedException e) { 124 Debug.trace(e); 125 } 126 } 127 } 128 129 private static List tokenize(String s) 131 { 132 ArrayList list = new ArrayList (); 133 StringBuffer sb = new StringBuffer (); 134 boolean inQuote = false; 135 final int limit = s.length(); 136 for (int i = 0; i < limit; i++) { 137 char c = s.charAt(i); 138 switch (c) { 139 case ' ': 140 if (inQuote) 141 sb.append(c); 142 else if (sb.length() > 0) { 143 list.add(sb.toString()); 144 sb.setLength(0); 145 } 146 break; 147 case '"': 148 if (inQuote) { 149 if (sb.length() > 0) { 150 list.add(sb.toString()); 151 sb.setLength(0); 152 } 153 inQuote = false; 154 } else 155 inQuote = true; 156 break; 157 default: 158 sb.append(c); 159 break; 160 } 161 } 162 if (sb.length() > 0) 163 list.add(sb.toString()); 164 return list; 165 } 166 167 private class ReaderThread extends Thread 168 { 169 private char[] buf = new char[4096]; 170 private final InputStream inputStream; 171 private final BufferedReader reader; 172 private boolean done = false; 173 174 public ReaderThread(InputStream inputStream) 175 { 176 this.inputStream = inputStream; 177 reader = new BufferedReader (new InputStreamReader (inputStream)); 178 } 179 180 public void run() 181 { 182 while (!done) { 183 String s = read(); 184 if (s == null) 185 return; 186 appendOutput(s); 187 } 188 } 189 190 private String read() 191 { 192 StringBuffer sb = new StringBuffer (); 193 try { 194 do { 195 int numChars = reader.read(buf, 0, buf.length); if (numChars < 0) { 197 done = true; 198 break; 199 } 200 if (numChars > 0) 201 sb.append(buf, 0, numChars); 202 Thread.sleep(10); 203 } while (reader.ready()); 204 } 205 catch (IOException e) { 206 return null; 207 } 208 catch (InterruptedException e) { 209 return null; 210 } 211 catch (Throwable t) { 212 return null; 213 } 214 return sb.toString(); 215 } 216 } 217 218 private static final Primitive _RUN_SHELL_COMMAND = 221 new Primitive("%run-shell-command", PACKAGE_SYS, false) 222 { 223 public LispObject execute(LispObject[] args) throws ConditionThrowable 224 { 225 if (args.length != 3) 226 signal(new WrongNumberOfArgumentsException(this)); 227 String command = args[0].getStringValue(); 228 LispObject directory = args[1]; 229 LispObject output = args[2]; 230 String namestring = null; 231 Stream outputStream = null; 232 if (directory != NIL) { 233 Pathname pathname = Pathname.coerceToPathname(directory); 234 namestring = pathname.getNamestring(); 235 if (namestring == null) { 236 return signal(new SimpleError("Pathname has no namestring: " + 237 pathname)); 238 } 239 } 240 if (output != NIL) 241 outputStream = checkStream(output); 242 ShellCommand shellCommand = new ShellCommand(command, namestring); 243 shellCommand.run(); 244 if (outputStream != null) 245 outputStream._writeString(shellCommand.getOutput()); 246 return number(shellCommand.exitValue()); 247 } 248 }; 249 } 250 | Popular Tags |