linuxvcs.pp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. unit linuxvcs;
  2. {*****************************************************************************}
  3. interface
  4. {*****************************************************************************}
  5. const vcs_device:shortint=-1;
  6. function try_grab_vcsa:boolean;
  7. {*****************************************************************************}
  8. implementation
  9. {*****************************************************************************}
  10. uses baseunix,strings;
  11. function try_grab_vcsa_in_path(path:Pchar;len:cardinal):boolean;
  12. const grab_vcsa='/grab_vcsa';
  13. grab_vcsa_s:array[1..length(grab_vcsa)] of char=grab_vcsa;
  14. var p:Pchar;
  15. child:Tpid;
  16. status:cint;
  17. pstat:stat;
  18. begin
  19. getmem(p,len+length(grab_vcsa)+1);
  20. move(path^,p^,len);
  21. move(grab_vcsa_s,(p+len)^,length(grab_vcsa));
  22. (p+len+length(grab_vcsa))^:=#0;
  23. {Check if file exists.}
  24. if fpstat(p,pstat)<>0 then
  25. begin
  26. try_grab_vcsa_in_path:=false;
  27. exit;
  28. end;
  29. child:=fpfork;
  30. if child=0 then
  31. begin
  32. fpexecve(p,nil,nil);
  33. halt(255); {fpexec must have failed...}
  34. end;
  35. fpwaitpid(child,status,0);
  36. try_grab_vcsa_in_path:=status=0; {Return true if success.}
  37. freemem(p);
  38. end;
  39. function try_grab_vcsa:boolean;
  40. {If we cannot open /dev/vcsa0-31 it usually because we do not have
  41. permission. At login the owner of the tty you login is set to yourself.
  42. This is not done for vcsa, which is kinda strange as vcsa is revoke from
  43. you when you log out. We try to call a setuid root helper which chowns
  44. the vcsa device so we can get access to the screen buffer...}
  45. var path,p:Pchar;
  46. begin
  47. try_grab_vcsa:=false;
  48. path:=fpgetenv('PATH');
  49. if path=nil then
  50. exit;
  51. p:=strscan(path,':');
  52. while p<>nil do
  53. begin
  54. if try_grab_vcsa_in_path(path,p-path) then
  55. begin
  56. try_grab_vcsa:=true;
  57. exit;
  58. end;
  59. path:=p+1;
  60. p:=strscan(path,':');
  61. end;
  62. if try_grab_vcsa_in_path(path,strlen(path)) then
  63. exit;
  64. end;
  65. procedure detect_linuxvcs;
  66. var f:text;
  67. fields:array [0..60] of int64;
  68. fieldct,i:integer;
  69. pid,ppid:longint;
  70. magnitude:int64;
  71. s:string[15];
  72. statln:ansistring;
  73. begin
  74. {Extremely aggressive VCSA detection. Works even through Midnight
  75. Commander. Idea from the C++ Turbo Vision project, credits go
  76. to Martynas Kunigelis <[email protected]>.}
  77. pid:=fpgetpid;
  78. repeat
  79. str(pid,s);
  80. assign(f, '/proc/'+s+'/stat');
  81. {$I-}
  82. reset(f);
  83. {$I+}
  84. if ioresult<>0 then
  85. break;
  86. readln(f, statln);
  87. close(f);
  88. magnitude := 1;
  89. fieldct := 0;
  90. fields[fieldct] := 0;
  91. for i := high(statln) downto low(statln) do
  92. begin
  93. case statln[i] of
  94. '-': magnitude := -1;
  95. '0'..'9': begin
  96. fields[fieldct] := fields[fieldct]
  97. + (magnitude * (ord(statln[i]) - ord('0')));
  98. magnitude := magnitude * 10;
  99. end;
  100. ' ': begin
  101. magnitude := 1;
  102. fieldct := fieldct + 1;
  103. fields[fieldct] := 0;
  104. end;
  105. else
  106. break;
  107. end;
  108. end;
  109. ppid := pid;
  110. pid := fields[fieldct - 1];
  111. if (fields[fieldct - 4] and $ffffffc0) = $00000400 then {/dev/tty*}
  112. begin
  113. vcs_device:=fields[fieldct - 4] and $3f;
  114. break;
  115. end;
  116. until (fields[fieldct - 4]=0) {Not attached to a terminal, i.e. an xterm.}
  117. or (pid=-1)
  118. or (ppid=pid);
  119. end;
  120. begin
  121. {Put in procedure because there are quite a bit of variables which are made
  122. temporary this way.}
  123. detect_linuxvcs;
  124. end.