// joi/10/juno/Juno.java // // // Copyright 2003 Bill Campbell and Ethan Bolker import java.io.*; import java.util.*; import java.lang.*; /** * Juno (Juno's Unix NOt) mimics a command line operating system * such as Unix. *
* A Juno system has a name, a set of Users, a JFile system, * a login process and a set of shell commands. * * @see User * @see JFile * @see ShellCommand * * @version 10 **/ public class Juno implements Serializable { private final static String OS = "Juno"; private final static String VERSION = "10"; private String hostName; // host machine name private Map users; // lookup table for Users private transient OutputInterface console; private Directory slash; // root of JFile system private Directory userHomes; // for home directories private ShellCommandTable commandTable; // shell commands // file containing Juno state private transient String fileName = null; // port used by Juno server for remote login private int junoPort = 2001; /** * Construct a Juno (operating system) object. * * @param hostName the name of the host on which it's running. * @param echoInput should all input be echoed as output? * @param isGUI graphical user interface? * @param isRemote running as a server? */ public Juno( String hostName, boolean echoInput, boolean isGUI, boolean isRemote ) { // Initialize the Juno environment ... this.hostName = hostName; users = new TreeMap(); commandTable = new ShellCommandTable(); // the file system slash = new Directory( "", null, null ); User root = new User( "root", "swordfish", slash, "Rick Martin" ); users.put( "root", root ); slash.setOwner(root); userHomes = new Directory( "users", root, slash ); } // Set up the correct console: // command line (default), graphical or remote. private void setupConsole( boolean echoInput, boolean isGUI, boolean isRemote ) { LoginInterpreter interpreter = new LoginInterpreter( this, null ); if (isGUI) { console = new GUILoginConsole( hostName, this, interpreter, echoInput); } else if (isRemote) { console = new RemoteConsole( this, echoInput, junoPort ); } else { console = new JunoTerminal( echoInput ); } // Tell the interpreter about the console interpreter.setConsole( console ); // If we're using a simple command line interface, // start that. (Constructing a GUI starts the GUI.) // Shut down Juno when done if (!isGUI && !isRemote) { interpreter.CLILogin(); shutDown(); } } /** * Shut down this Juno system. * * Save state if required. */ public void shutDown( ) { if (fileName != null) { writeJuno( ); } } /** * Set the name of file in which system state is kept. * * @param fileName the file name. */ public void setFileName(String fileName) { this.fileName = fileName; } /** * The name of the host computer on which this system * is running. * * @return the host computer name. */ public String getHostName() { return hostName; } /** * The name of this operating system. * * @return the operating system name. */ public String getOS() { return OS; } /** * The version number for this system. * * @return the version number. */ public String getVersion() { return VERSION; } /** * The directory containing all user homes for this system. * * @return the directory containing user homes. */ public Directory getUserHomes() { return userHomes; } /** * The shell command table for this system. * * @return the shell command table. */ public ShellCommandTable getCommandTable() { return commandTable; } /** * Look up a user by user name. * * @param username the user's name. * @return the appropriate User object. */ public User lookupUser( String username ) { return (User) users.get( username ); } /** * Create a new User. * * @param userName the User's login name. * @param home her home Directory. * @param password her password. * @param realName her real name. * @return newly created User. */ public User createUser( String userName, Directory home, String password, String realName ) { User newUser = new User( userName, password, home, realName ); users.put( userName, newUser ); return newUser; } /** * The Juno system may be given the following command line * arguments: * * -e: Echo all input (useful for testing). * * -version: Report the version number and exit. * * -g: Support a GUI console. * * -remote Start Juno server. * * -f filename File to read/write system state from/to * * [hostname]: The name of the host on which * Juno is running (optional). */ public static void main( String[] args ) { // Parse command line options boolean echoInput = false; boolean versionQuery = false; boolean isGUI = false; boolean isRemote = false; String hostName = "mars"; String junoFileName = null; for (int i=0; i < args.length; i++) { if (args[i].equals("-e")) { echoInput = true; } else if (args[i].equals("-version")) { versionQuery = true; } else if (args[i].equals("-g")) { isGUI = true; } else if (args[i].equals( "-remote" )) { isRemote = true; } else if (args[i].equals("-f")) { junoFileName = args[++i]; } else { hostName = args[i]; } } // If it's a version query give the version and exit if ( versionQuery ) { System.out.println( OS + " version " + VERSION ); System.exit(0); } // Create a new Juno or read one from a file. Juno junoSystem = null; if (junoFileName != null) { junoSystem = readJuno( junoFileName ); } if (junoSystem == null) { junoSystem = new Juno( hostName, echoInput, isGUI, isRemote ); } junoSystem.setFileName( junoFileName ); junoSystem.setupConsole( echoInput, isGUI, isRemote ); } // Read Juno state from a file. // // @param junoFileName the name of the file containing the system. // @return the system, null if file does not exist. private static Juno readJuno(String junoFileName) { File file = new File( junoFileName ); if (!file.exists()) { return null; } ObjectInputStream inStream = null; try { inStream = new ObjectInputStream( new FileInputStream( file ) ); Juno juno = (Juno)inStream.readObject(); System.out.println( "Juno state read from file " + junoFileName); return juno; } catch (Exception e ) { System.err.println("Problem reading " + junoFileName ); System.err.println(e); System.exit(1); } finally { try { inStream.close(); } catch (Exception e) { } } return null; // you can never get here } // Write Juno state to a file. private void writeJuno() { ObjectOutputStream outStream = null; try { outStream = new ObjectOutputStream( new FileOutputStream( fileName ) ); outStream.writeObject( this ); System.out.println( "Juno state written to file " + fileName); } catch (Exception e ) { System.err.println("Problem writing " + fileName); System.err.println(e); } finally { try { outStream.close(); } catch (Exception e ) { } } } }