+ return ret;
+}
+
+void RespawnProgam(tInitProgram *Program)
+{
+ int rv = 0;
+ switch(Program->Type)
+ {
+ case PT_KTERM: rv = SpawnKTerm(Program); break;
+ case PT_STERM: rv = SpawnSTerm(Program); break;
+ case PT_DAEMON: rv = SpawnDaemon(Program); break;
+ default:
+ _SysDebug("BUGCHECK - Program Type %i unknown", Program->Type);
+ break;
+ }
+ if( !rv ) {
+ _SysDebug("Respawn failure!");
+ // TODO: Remove from list?
+ }
+}
+
+int AddKTerminal(int TerminalID, char **Command)
+{
+ // TODO: Smarter validation
+ if( TerminalID < 0 || TerminalID > 7 )
+ return -1;
+
+ tInitProgram *ent = AllocateProgram(Command, PT_KTERM, sizeof(struct sKTerm));
+ ent->TypeInfo.KTerm.ID = TerminalID;
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command)
+{
+ char dbit, parity, sbit;
+ int baud;
+
+ // Parse mode string
+ if( sscanf(ModeStr, "%1[78]%1[NOE]%1[012]%*1[bB]%d", &dbit, &parity, &sbit, &baud) != 4 ) {
+ // Oops?
+ _SysDebug("Serial mode string is invalid ('%s')", ModeStr);
+ return -1;
+ }
+
+ // Validate baud rate / build mode word
+ // TODO: Does baud rate need validation?
+ uint32_t modeword = 0;
+ modeword |= (dbit == '7' ? 1 : 0) << 0;
+ modeword |= (parity == 'O' ? 1 : (parity == 'E' ? 2 : 0)) << 1;
+ modeword |= (sbit - '0') << 3;
+
+ // Create info
+ const char DEVPREFIX[] = "/Devices/";
+ int pathlen = sizeof(DEVPREFIX) + strlen(DevPathSegment);
+ tInitProgram *ent = AllocateProgram(Command, PT_STERM, sizeof(struct sSTerm)+pathlen);
+ ent->TypeInfo.STerm.FormatBits = modeword;
+ ent->TypeInfo.STerm.BaudRate = baud;
+ strcpy(ent->TypeInfo.STerm.Path, DEVPREFIX);
+ strcat(ent->TypeInfo.STerm.Path, DevPathSegment);
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int AddDaemon(char *StdoutPath, char *StderrPath, char **Command)
+{
+ tInitProgram *ent = AllocateProgram(Command, PT_DAEMON, sizeof(struct sDaemon));
+ ent->TypeInfo.Daemon.StdoutPath = StdoutPath;
+ ent->TypeInfo.Daemon.StderrPath = StderrPath;
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV)
+{
+ int handles[] = {c_stdin, c_stdout, c_stderr};
+
+ int rv = _SysSpawn(ArgV[0], (const char **)ArgV, NULL, 3, handles, NULL);
+
+ _SysClose(c_stdin);
+ if( c_stdout != c_stdin )
+ _SysClose(c_stdout);
+ if( c_stderr != c_stdin && c_stderr != c_stdout )
+ _SysClose(c_stderr);
+
+ return rv;
+}
+
+int SpawnKTerm(tInitProgram *Program)
+{
+ const char fmt[] = "/Devices/pts/vt%ic";
+ char path[sizeof(fmt)];
+
+ snprintf(path, sizeof(path), fmt, Program->TypeInfo.KTerm.ID);
+
+ int in = _SysOpen(path, OPENFLAG_READ);
+ int out = _SysOpen(path, OPENFLAG_WRITE);
+
+ return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnSTerm(tInitProgram *Program)
+{
+ int in = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_READ);
+ int out = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_WRITE);
+
+ if(in == -1 || out == -1 ) {
+ _SysDebug("Unable to open serial port '%s'", Program->TypeInfo.STerm.Path);
+ return -1;
+ }
+
+ #if 0
+ if( _SysIOCtl(in, 0, NULL) != DRV_TYPE_SERIAL )
+ {
+ // Oops?
+ return -2;
+ }
+ _SysIOCtl(in, SERIAL_IOCTL_GETSETBAUD, &Program->TypeInfo.STerm.BaudRate);
+ _SysIOCtl(in, SERIAL_IOCTL_GETSETFORMAT, &Program->TypeInfo.STerm.FormatBits);
+ #endif
+
+ return SpawnCommand(in, out, out, Program->Command);