Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/core/IronPython.Modules/fcntl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public static object ioctl(CodeContext context, int fd, int cmd, [NotNone] IBuff

#region Helper Methods

private static int GetFileDescriptor(CodeContext context, object? obj) {
internal static int GetFileDescriptor(CodeContext context, object? obj) {
if (!PythonOps.TryGetBoundAttr(context, obj, "fileno", out object? filenoMeth)) {
throw PythonOps.TypeError("argument must be an int, or have a fileno() method.");
}
Expand Down
101 changes: 93 additions & 8 deletions src/core/IronPython.Modules/termios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
using Microsoft.Scripting.Runtime;

using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;

using static IronPython.Modules.PythonIOModule;

Expand Down Expand Up @@ -323,8 +325,81 @@ public static void PerformModuleReload(PythonContext context, PythonDictionary d
public static int B230400 => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 230400 : 0x1003;
// higher baud rates are not defined on macOS

#endregion


#region Public Functions

[DllImport("libc", SetLastError = true, EntryPoint = "tcsendbreak")]
private static extern int _tcsendbreak(int fd, int duration);

[LightThrowing]
public static object? tcsendbreak(CodeContext context, int fd, int duration) {
CheckFileDescriptor(fd);
if (_tcsendbreak(fd, duration) == -1) {
return LightExceptions.Throw(GetLastTermiosError(context));
}
return null;
}

[LightThrowing]
public static object? tcsendbreak(CodeContext context, object? fd, int duration)
=> tcsendbreak(context, PythonFcntl.GetFileDescriptor(context, fd), duration);


[DllImport("libc", SetLastError = true, EntryPoint = "tcdrain")]
private static extern int _tcdrain(int fd);

[LightThrowing]
public static object? tcdrain(CodeContext context, int fd) {
CheckFileDescriptor(fd);
if (_tcdrain(fd) == -1) {
return LightExceptions.Throw(GetLastTermiosError(context));
}
return null;
}

[LightThrowing]
public static object? tcdrain(CodeContext context, object? fd)
=> tcdrain(context, PythonFcntl.GetFileDescriptor(context, fd));


[DllImport("libc", SetLastError = true, EntryPoint = "tcflush")]
private static extern int _tcflush(int fd, int queue);

[LightThrowing]
public static object? tcflush(CodeContext context, int fd, int queue) {
CheckFileDescriptor(fd);
if (_tcflush(fd, queue) == -1) {
return LightExceptions.Throw(GetLastTermiosError(context));
}
return null;
}

[LightThrowing]
public static object? tcflush(CodeContext context, object? fd, int queue)
=> tcflush(context, PythonFcntl.GetFileDescriptor(context, fd), queue);


[DllImport("libc", SetLastError = true, EntryPoint = "tcflow")]
private static extern int _tcflow(int fd, int action);

[LightThrowing]
public static object? tcflow(CodeContext context, int fd, int action) {
CheckFileDescriptor(fd);
if (_tcflow(fd, action) == -1) {
return LightExceptions.Throw(GetLastTermiosError(context));
}
return null;
}

[LightThrowing]
public static object? tcflow(CodeContext context, object? fd, int action)
=> tcflow(context, PythonFcntl.GetFileDescriptor(context, fd), action);


public static object tcgetattr(CodeContext context, int fd) {
if (fd < 0) throw PythonOps.ValueError("file descriptor cannot be a negative integer ({0})", fd);
CheckFileDescriptor(fd);
if (fd > 0) throw new NotImplementedException("termios support only for stdin");

if (context.LanguageContext.SystemStandardIn is not TextIOWrapper stdin) {
Expand Down Expand Up @@ -360,6 +435,7 @@ public static object tcgetattr(CodeContext context, object? file) {


public static void tcsetattr(CodeContext context, int fd, int when, object? attributes) {
CheckFileDescriptor(fd);
if (fd != 0) throw new NotImplementedException();

if (context.LanguageContext.SystemStandardIn is not TextIOWrapper stdin) {
Expand Down Expand Up @@ -528,11 +604,20 @@ public RawConsole(CodeContext context) : base(context) {
public override bool isatty(CodeContext context) => true;
}

private static int ToInt(this object? o)
=> o switch {
int i => i,
BigInteger bi => (int)bi,
Extensible<BigInteger> ebi => (int)ebi.Value,
_ => throw PythonOps.TypeErrorForBadInstance("an integer is required (got type {0})", o)
};

private static void CheckFileDescriptor(int fd) {
if (fd < 0) {
throw PythonOps.ValueError("file descriptor cannot be a negative integer ({0})", fd);
}
}


private static Exception GetLastTermiosError(CodeContext context) {
int errno = Marshal.GetLastWin32Error();
return PythonExceptions.CreateThrowable(termioserror(context), errno, PythonNT.strerror(errno));
}


private static PythonType termioserror(CodeContext context)
=> (PythonType)context.LanguageContext.GetModuleState("termioserror");
}