Skip to content

Commit 368df74

Browse files
authored
Implement tcgetwinsize, tcsetwinsize in termios (#1909)
1 parent 962b6dc commit 368df74

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

src/core/IronPython.Modules/termios.cs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,64 @@ public static void PerformModuleReload(PythonContext context, PythonDictionary d
396396
=> tcflow(context, PythonFcntl.GetFileDescriptor(context, fd), action);
397397

398398

399+
// Python 3.11: tcgetwinsize, tcsetwinsize
400+
401+
[LightThrowing]
402+
public static object tcgetwinsize(CodeContext context, int fd) {
403+
var ws = new ushort[4];
404+
var buf = new MemoryBufferProtocolWrapper<ushort>(ws.AsMemory());
405+
406+
object result = PythonFcntl.ioctl(fd, TIOCGWINSZ, buf, mutate_flag: true);
407+
408+
if (ToTermiosError(context, result) is not null and var ex) {
409+
return ex;
410+
}
411+
return PythonTuple.MakeTuple((int)ws[0], (int)ws[1]);
412+
}
413+
414+
[LightThrowing]
415+
public static object? tcgetwinsize(CodeContext context, object? fd)
416+
=> tcgetwinsize(context, PythonFcntl.GetFileDescriptor(context, fd));
417+
418+
419+
[LightThrowing]
420+
public static object? tcsetwinsize(CodeContext context, int fd, object? winsize) {
421+
CheckFileDescriptor(fd);
422+
423+
if (winsize is not IList wsList || wsList.Count != 2) {
424+
throw PythonOps.TypeError("tcsetwinsize, arg 2: must be a two-item sequence");
425+
}
426+
427+
long winsize_0 = (long)PythonOps.ToIndex(wsList[0]);
428+
long winsize_1 = (long)PythonOps.ToIndex(wsList[1]);
429+
430+
var ws = new ushort[4];
431+
var buf = new MemoryBufferProtocolWrapper<ushort>(ws.AsMemory());
432+
433+
object result = PythonFcntl.ioctl(fd, TIOCGWINSZ, buf, mutate_flag: true);
434+
if (ToTermiosError(context, result) is not null and var ex) {
435+
return ex;
436+
}
437+
438+
ws[0] = unchecked((ushort)winsize_0);
439+
ws[1] = unchecked((ushort)winsize_1);
440+
if (ws[0] != winsize_0 || ws[1] != winsize_1) {
441+
throw PythonOps.OverflowError("winsize value(s) out of range");
442+
}
443+
444+
result = PythonFcntl.ioctl(fd, TIOCSWINSZ, buf);
445+
if (ToTermiosError(context, result) is not null and var ex2) {
446+
return ex2;
447+
}
448+
449+
return null;
450+
}
451+
452+
[LightThrowing]
453+
public static object? tcsetwinsize(CodeContext context, object? fd, object? winsize)
454+
=> tcsetwinsize(context, PythonFcntl.GetFileDescriptor(context, fd), winsize);
455+
456+
399457
public static object tcgetattr(CodeContext context, int fd) {
400458
CheckFileDescriptor(fd);
401459
if (fd > 0) throw new NotImplementedException("termios support only for stdin");
@@ -609,13 +667,28 @@ private static void CheckFileDescriptor(int fd) {
609667
}
610668
}
611669

670+
private static object? ToTermiosError(CodeContext context, object? error) {
671+
if (LightExceptions.GetLightException(error) is Exception ex) {
672+
var pex = ex.GetPythonException();
673+
if (pex is PythonExceptions._OSError oserr) {
674+
return LightExceptions.Throw(GetTermiosError(context, oserr.errno, oserr.strerror));
675+
} else {
676+
return error;
677+
}
678+
}
679+
return null;
680+
}
612681

613682
private static Exception GetLastTermiosError(CodeContext context) {
614683
int errno = Marshal.GetLastWin32Error();
615-
return PythonExceptions.CreateThrowable(termioserror(context), errno, PythonNT.strerror(errno));
684+
return GetTermiosError(context, errno, PythonNT.strerror(errno));
616685
}
617686

618687

688+
private static Exception GetTermiosError(CodeContext context, object errno, object message)
689+
=> PythonExceptions.CreateThrowable(termioserror(context), errno, message);
690+
691+
619692
private static PythonType termioserror(CodeContext context)
620693
=> (PythonType)context.LanguageContext.GetModuleState("termioserror");
621694
}

src/core/IronPython/Runtime/Operations/PythonOps.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,11 @@ public static object Index(object? o) {
821821
throw TypeErrorForUnIndexableObject(o);
822822
}
823823

824+
internal static BigInteger ToIndex(object? o) {
825+
if (TryToIndex(o, out BigInteger index)) return index;
826+
throw TypeErrorForUnIndexableObject(o);
827+
}
828+
824829
internal static bool TryToIndex(object? o, [NotNullWhen(true)] out object? index) {
825830
var context = DefaultContext.Default;
826831

0 commit comments

Comments
 (0)