/** * 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.m.os; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.Map; import erjang.BIF; import erjang.EAtom; import erjang.ENative; import erjang.EObject; import erjang.ERT; import erjang.EString; import erjang.ETuple2; import erjang.ETuple3; import erjang.ECons; import erjang.ErjangConfig; import erjang.NotImplemented; /** * Native methods (BIFs) for the Erlang module 'os'. * * The fact that this class represents the module os is deduced from the package * name, */ public class Native extends ENative { /** * */ private static final EAtom am_unix = EAtom.intern("unix"); private static final EAtom am_win32 = EAtom.intern("win32"); private static final EAtom am_darwin = EAtom.intern("darwin"); private static final EAtom am_linux = EAtom.intern("linux"); private static final EAtom am_sunos = EAtom.intern("sunos"); private static final EAtom am_windows = EAtom.intern("windows"); private static final EAtom am_nt = EAtom.intern("nt"); private static final ETuple2 OS_TYPE_MACOS = new ETuple2(am_unix, am_darwin); private static final ETuple2 OS_TYPE_LINUX = new ETuple2(am_unix, am_linux); private static final ETuple2 OS_TYPE_SUNOS = new ETuple2(am_unix, am_sunos); private static final ETuple2 OS_TYPE_WINDOWS = new ETuple2(am_win32, am_windows); private static final ETuple2 OS_TYPE_WINNT = new ETuple2(am_win32, am_nt); /** os:putenv(string(), string()) -> true */ @BIF public static EObject putenv(EObject o1, EObject o2) { EString str1 = o1.testString(); EString str2 = o2.testString(); if (str1 == null || str2 == null) throw ERT.badarg(o1, o2); ErjangConfig.setenv(str1.stringValue(), str2.stringValue()); return ERT.TRUE; } /** os:getenv(string()) -> string() | false */ @BIF public static EObject getenv(EObject o) { EString str = o.testString(); if (str == null) throw ERT.badarg(o); String value; value = ErjangConfig.getenv(str.stringValue()); if (value != null) { return EString.fromString(value); } value = System.getenv(str.stringValue()); if (value == null) { return ERT.FALSE; } else { return EString.fromString(value); } } /** os:getenv() -> [string()] */ @BIF public static EObject getenv() { Map<String,String> env = System.getenv(); ECons res = ERT.NIL; for (Map.Entry<String,String> entry : env.entrySet()) { String s = entry.getKey() + "=" + entry.getValue(); res = res.cons(EString.fromString(s)); } return res; } @BIF public static ETuple2 type() { String osname = System.getProperty("os.name"); /* * TODO: On unices, the second element should always be lowercase of * `uname -s`. For now, we recognize a fixed set. */ if ("Mac OS".equals(osname) || "Mac OS X".equals(osname)) return OS_TYPE_MACOS; if ("Linux".equals(osname)) return OS_TYPE_LINUX; if ("Solaris".equals(osname) || "SunOS".equals(osname)) return OS_TYPE_SUNOS; if ("Windows 95".equals(osname) || "Windows 98".equals(osname) || "Windows Me".equals(osname)) return OS_TYPE_WINDOWS; if ("Windows NT".equals(osname) || "Windows 2000".equals(osname) || "Windows XP".equals(osname)) return OS_TYPE_WINNT; // Fallback: return OS_TYPE_MACOS; } @BIF public static EObject getpid() { RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean(); String processName = rtb.getName(); Integer pid = tryPattern1(processName); if (pid == null) { throw new NotImplemented(); } return EString.fromString(String.valueOf(pid)); } /** from http://golesny.de/wiki/code:javahowtogetpid; that site has more suggestions if this fails...*/ private static Integer tryPattern1(String processName) { Integer result = null; /* tested on: */ /* - windows xp sp 2, java 1.5.0_13 */ /* - mac os x 10.4.10, java 1.5.0 */ /* - debian linux, java 1.5.0_13 */ /* all return pid@host, e.g 2204@antonius */ Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(processName); if (matcher.matches()) { result = new Integer(Integer.parseInt(matcher.group(1))); } return result; } @BIF static public ETuple3 timestamp() { long now = erjang.m.erlang.ErlTime.now_raw_micros(); int micros = (int)(now % 1000000); now /= 1000000; int secs = (int)(now % 1000000); now /= 1000000; int megas = (int)now; ETuple3 res = new ETuple3(); res.elem1 = ERT.box(megas); res.elem2 = ERT.box(secs); res.elem3 = ERT.box(micros); return res; } }