+ if( isspace(ch) ) {
+ fseek(FP, -1, SEEK_CUR);
+ break;
+ }
+ else if( ch == '\\' )
+ mode |= 4;
+ else if( ch == '"' )
+ mode = 1;
+ else if( ch == '\'')
+ mode = 2;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+ // Double-quoted string
+ else if( mode == 1 )
+ {
+ if( ch == '"' )
+ mode = 0;
+ else if( ch == '\\' )
+ mode |= 4;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+ // Single-quoted string
+ else if( mode == 2 )
+ {
+ if( ch == '\'' )
+ mode = 0;
+ else if( ch == '\\' )
+ mode |= 4;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+
+ if( !skip )
+ {
+ if( pos == space ) {
+ space += 32;
+ void *tmp = realloc(retstr, space+1);
+ if( !tmp ) {
+ _SysDebug("ReadQuotedString - realloc(%i) failure", space+1);
+ free(retstr);
+ return NULL;
+ }
+ retstr = tmp;
+ }
+ retstr[pos++] = ch;
+ }
+ }
+ if( retstr )
+ retstr[pos] = '\0';
+ return retstr;
+}
+
+char **ReadCommand(FILE *FP)
+{
+ const int space = 8;
+ int pos = 0;
+ char **ret = malloc(space*sizeof(char*));
+ char *arg;
+ do {
+ arg = ReadQuotedString(FP);
+ if(arg == NULL)
+ break;
+ if( pos == space - 1 ) {
+ _SysDebug("Too many arguments %i", pos);
+ ret[pos] = NULL;
+ FreeCommand(ret);
+ return NULL;
+ }
+ ret[pos++] = arg;
+ } while(arg != NULL);
+
+ if( pos == 0 )
+ {
+ free(ret);
+ return NULL;
+ }
+ ret[pos] = NULL;
+ return ret;
+}
+
+void FreeCommand(char **Command)
+{
+ int pos = 0;
+ while( Command[pos] )
+ {
+ free(Command[pos]);
+ pos ++;
+ }
+ free(Command);
+}
+
+int ProcessInittab(const char *Path)
+{
+ int line_num = 0;
+ FILE *fp = fopen(Path, "r");
+
+ if( !fp )
+ return 1;
+
+ while(!feof(fp))
+ {
+ char cmdbuf[64+1];
+
+ line_num ++;
+
+ int rv;
+ if( (rv = fscanf(fp, "%64s%*[ \t]", cmdbuf)) != 1 ) {
+ _SysDebug("fscanf rv %i != exp 1", rv);
+ break;
+ }
+
+ // Clear comments
+ if( cmdbuf[0] == '#' ) {
+ while( !feof(fp) && fgetc(fp) != '\n' )
+ ;
+ continue ;
+ }
+ if( cmdbuf[0] == '\0' ) {
+ char ch = fgetc(fp);
+ if( ch != '\n' && ch != -1 ) {
+ fclose(fp);
+ _SysDebug("Unexpected char 0x%x, expecting EOL", ch);
+ return 2; // Unexpected character?
+ }
+ continue ;
+ }
+
+ // Check commands
+ if( strcmp(cmdbuf, "ktty") == 0 ) {
+ // ktty <ID> <command...>
+ // - Spins off a console on the specified kernel TTY
+ int id = 0;
+ if( fscanf(fp, "%d ", &id) != 1 ) {
+ _SysDebug("init[ktty] - TTY ID read failed");
+ goto lineError;
+ }
+ char **command = ReadCommand(fp);
+ if( !command ) {
+ _SysDebug("init[ktty] - Command read failure");
+ goto lineError;
+ }
+ AddKTerminal(id, command);
+ }
+ else if(strcmp(cmdbuf, "stty") == 0 ) {
+ // stty <devpath> [78][NOE][012][bB]<baud> <command...>
+ char path_seg[32+1];
+ char modespec[4+6+1];
+ if( fscanf(fp, "%32s %10s ", path_seg, modespec) != 2 ) {
+ goto lineError;
+ }
+ char **command = ReadCommand(fp);
+ if( !command )
+ goto lineError;
+ AddSerialTerminal(path_seg, modespec, command);
+ }
+ else if(strcmp(cmdbuf, "daemon") == 0 ) {
+ // daemon <stdout> <stderr> <command...>
+ // - Runs a daemon (respawning) that logs to the specified files
+ // - Will append a header whenever the daemon starts
+ char *stdout_path = ReadQuotedString(fp);
+ if( !stdout_path )
+ goto lineError;
+ char *stderr_path = ReadQuotedString(fp);
+ if( !stderr_path )
+ goto lineError;
+ char **command = ReadCommand(fp);
+ if( !command )
+ goto lineError;