+ }
+}
+
+int PTY_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ tPTY *pty = Node->ImplPtr;
+ struct ptymode *mode = Data;
+ struct ptydims *dims = Data;
+
+ int is_server = !pty || Node == pty->ServerNode;
+
+ switch(ID)
+ {
+ case DRV_IOCTL_TYPE: return DRV_TYPE_TERMINAL;
+ case DRV_IOCTL_IDENT: memcpy(Data, "PTY\0", 4); return 0;
+ case DRV_IOCTL_VERSION: return 0x100;
+ case DRV_IOCTL_LOOKUP: return 0;
+
+ case PTY_IOCTL_GETMODE:
+ if( !pty ) return 0;
+ if( !CheckMem(Data, sizeof(*mode)) ) { errno = EINVAL; return -1; }
+ *mode = pty->Mode;
+ // TODO: ACK client's SETMODE
+ return 0;
+ case PTY_IOCTL_SETMODE:
+ if( !pty ) return 0;
+ if( !CheckMem(Data, sizeof(*mode)) ) { errno = EINVAL; return -1; }
+ PTY_SetAttrib(pty, NULL, mode, !is_server);
+ return 0;
+ case PTY_IOCTL_GETDIMS:
+ if( !pty ) return 0;
+ if( !CheckMem(Data, sizeof(*dims)) ) { errno = EINVAL; return -1; }
+ *dims = pty->Dims;
+ return 0;
+ case PTY_IOCTL_SETDIMS:
+ if( !pty ) return 0;
+ if( !CheckMem(Data, sizeof(*dims)) ) { errno = EINVAL; return -1; }
+ PTY_SetAttrib(pty, dims, NULL, !is_server);
+ return 0;
+ case PTY_IOCTL_GETID:
+ if( pty )
+ {
+ size_t len = strlen(pty->Name)+1;
+ if( Data )
+ {
+ if( !CheckMem(Data, len) ) { errno = EINVAL; return -1; }
+ strcpy(Data, pty->Name);
+ }
+ return len;
+ }
+ return 0;
+ case PTY_IOCTL_SETID:
+ if( Data && !CheckString(Data) ) { errno = EINVAL; return -1; }
+ if( pty ) return EALREADY;
+ pty = PTY_Create(Data, NULL, NULL,NULL, NULL);
+ if(pty == NULL)
+ return 1;
+ Node->ImplPtr = pty;
+ pty->ServerNode = Node;
+ return 0;
+ }
+ errno = ENOSYS;
+ return -1;