001: /*
002: * <copyright>
003: *
004: * Copyright 2003-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.tools.server.system.linux;
027:
028: import java.io.IOException;
029: import java.io.InputStream;
030:
031: import org.cougaar.tools.server.system.ProcessLauncher;
032:
033: /**
034: * Linux-specific implementation of a
035: * <code>ProcessLauncher</code>.
036: *
037: * @see ProcessLauncher
038: * @see org.cougaar.tools.server.system.SystemAccessFactory
039: */
040: public class LinuxProcessLauncher implements ProcessLauncher {
041:
042: private static final byte START_BYTE = (byte) '{';
043: private static final byte END_BYTE = (byte) '}';
044:
045: private static final String[] LINUX_EXEC = new String[] {
046: "sh",
047: "-c",
048: "echo -n " + ((char) START_BYTE) + "$$" + ((char) END_BYTE)
049: + "; exec ", // +cmd
050: };
051:
052: public LinuxProcessLauncher() {
053: // check "os.name"?
054: }
055:
056: public String[] getCommandLine(String[] cmd) {
057: // need to flatten the array... this *should* be okay.
058: //
059: // FIXME: what about whitespace!!!
060: StringBuffer sb = new StringBuffer();
061: int n = cmd.length;
062: for (int i = 0; i < n; i++) {
063: String si = cmd[i];
064: //
065: // might need to wrap si in quotes here!
066: //
067: sb.append(si);
068: if (i < (n - 1)) {
069: sb.append(" ");
070: }
071: }
072: String fullCmd = sb.toString();
073:
074: return getCommandLine(fullCmd);
075: }
076:
077: public String[] getCommandLine(String fullCmd) {
078: // tack on the full-cmd after the "exec"
079: int n = LINUX_EXEC.length;
080: String[] cmd = new String[n];
081: for (int i = 0; i < n; i++) {
082: cmd[i] = LINUX_EXEC[i];
083: }
084: cmd[n - 1] = cmd[n - 1] + fullCmd;
085: return cmd;
086: }
087:
088: public long parseProcessIdentifier(InputStream in) throws Exception {
089: return parseProcessIdentifier(in, START_BYTE, END_BYTE);
090: }
091:
092: /**
093: * Read a "startByte + NUMBER + endByte" from a stream,
094: * such as "{123}".
095: */
096: private static long parseProcessIdentifier(InputStream in,
097: byte startByte, byte endByte) throws IOException {
098:
099: // read start byte
100: int t0 = in.read();
101: if (t0 < 0) {
102: throw new IOException(
103: "Unexpected empty Stream, expecting the PID header \""
104: + ((char) startByte) + "<NUMBER>"
105: + ((char) endByte) + "\"");
106: }
107: byte b0 = (byte) t0;
108: if (!(b0 == startByte)) {
109: throw new IOException(
110: "Stream doesn't start with the expected PID header \""
111: + ((char) startByte) + "<NUMBER>"
112: + ((char) endByte) + "\": \"" + ((char) b0)
113: + "..\"");
114: }
115:
116: // read a number, up to 32 digits max (sanity check)
117: byte[] buf = new byte[32];
118: int i = 0;
119: while (true) {
120: int ti = in.read();
121: if (ti < 0) {
122: throw new IOException(
123: "Unexpected end of Stream, expecting futher PID digits"
124: + " or \"" + ((char) endByte) + "\"");
125: }
126: byte bi = (byte) ti;
127: if ((bi >= '0') && (bi <= '9')) {
128: // another digit
129: try {
130: buf[i++] = bi;
131: } catch (ArrayIndexOutOfBoundsException ae) {
132: throw new IOException(
133: "Error -- PID is too long to be valid: \""
134: + (new String(buf)) + "\"");
135: }
136: } else if (bi == endByte) {
137: // end of digits
138: break;
139: } else {
140: // ERROR!
141: throw new IOException(
142: "Stream contains an unexpected byte \""
143: + ((char) bi)
144: + "\", expecting a digit or \""
145: + ((char) endByte) + "\"");
146: }
147: }
148:
149: // parse the number
150: String snum = new String(buf, 0, i);
151: long lnum = Long.parseLong(snum);
152:
153: return lnum;
154: }
155: }
|