drblez
drblez

Reputation: 11

ioctl TIOCGWINSZ in GNAT Ada returns errno 25, but C program work fine

On Mac OS X 10.9.5...

I'm tryng to get screen size using ioctl C-function

#include <sys/ioctl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
  struct winsize sz;

  ioctl(0, TIOCGWINSZ, &sz);
  printf("Screen width: %i  Screen height: %i\n", sz.ws_col, sz.ws_row);
  return 0;
}

it's work fine,

bash-3.2$ cc screen_size.c
bash-3.2$ ./a.out
Screen width: 167  Screen height: 40

But when I try to do the same in Ada I get errno=25

with Interfaces; use Interfaces;
with Interfaces.C; use Interfaces.C;
with Ada.Text_IO; use Ada.Text_IO;

procedure Screen_Size is

   TIOCGWINSZ : unsigned_long := 16#5413#;

   type winsize is
      record
         ws_row : unsigned_short;
         ws_col : unsigned_short;
         unused1 : unsigned_short;
         unused2 : unsigned_short;
      end record;
   pragma Pack(winsize);

   function ioctl (Fildes : in int; Request : in unsigned_long; ws : in out winsize) return int;
   pragma import(C, ioctl, "ioctl");

   Err_No : Integer;
   pragma Import (C, Err_No, "errno");

   ws : winsize;
   result : int;
   begin
   result := ioctl(0, TIOCGWINSZ, ws);
   if result = 0 then
      Put_Line ("Screen width: " & ws.ws_row'Img & " Screen height: " & ws.ws_col'Img);
   else
      Put_Line ("Err_No: " & Err_No'Img);
   end if;
end Screen_Size;

result:

bash-3.2$ gnatmake screen_size.adb
gcc -c screen_size.adb
gnatbind -x screen_size.ali
gnatlink screen_size.ali
bash-3.2$ ./screen_size
Err_No:  25

As described, errno 25 (ENOTTY) means "Inappropriate ioctl for device". What am I doing wrong?

Upvotes: 0

Views: 537

Answers (3)

drblez
drblez

Reputation: 11

i resolve problem. i found bad TIOCGWINSZ value. Right value is 1074295912

Upvotes: 1

Jacob Sparre Andersen
Jacob Sparre Andersen

Reputation: 6601

If I recall correctly, you can't call C functions with an undetermined number of arguments directly from Ada.

The usual procedure is to create a C wrapper which takes a fixed number of arguments, and then bind to that. An alternative may be to look up how C determines the actual number of arguments in a call, and emulate that in your binding. (I suspect that the last argument you pass has to be a null pointer/System.Null_Address.)

Upvotes: 0

egilhh
egilhh

Reputation: 6430

On my computer, man ioctl says the parameter profile of ioctl is int ioctl(int d, int request, ...); That is, request should be int, not unsigned_long as in your binding.

Upvotes: 0

Related Questions