unit Utmp; interface uses Linux; const Device_name_length = 12; Host_name_length = 245; User_name_length = 32; type tTime = Longint; tPid = Longint; tIP_Address = array[1..4] of Byte; tDevice_name = String[Device_name_length]; tUser_name = String[User_name_length]; tHost_name = String[Host_name_length]; tLogin_type = (Unkown, Run_level, Boot_time, New_time, Old_time, Init_process, Login_process, User_process, Dead_process); tLogin_types = set of tLogin_type; tParameter_type = (Include, Exclude); {$PACKRECORD 1} tUser = record Type_of_login : tLogin_type; Pid : tPid; Device : tDevice_name; Tty_name : String[4]; Login_time : tTime; User_name : tUser_name; Host_name : tHost_name; IP_Address : tIP_Address; end; pUser = ^tUser; Const DefaultLoginType : TLogin_Types = [User_Process]; Login_type_names : array [TLogin_type] of string[20] = ('Unkown', 'Run level', 'Boot time','New time', 'Old time', 'Init process', 'Login process', 'User process', 'Dead process'); All_Login_types : TLogin_types = [Unkown, Run_level, Boot_time, New_time, Old_time, Init_process, Login_process, User_process, Dead_process]; procedure Read_logged_users; function Get_next_user : tUser; function Get_next_user(var Last : Boolean) : tUser; procedure Set_search_parameters( const Parameter_type : tParameter_type; Login_types : tLogin_types); procedure Reset_user_search; function More_users : Boolean; function Number_of_logged_users : Word; {Low level rutines} function Number_of_utmp_entries : Word; procedure Set_utmp_file(const File_name : String); type texitstatus = record e_termination, e_exit : integer; end; tLL_Utmp = record ut_type : integer; ut_pid : longint; ut_line : tdevice_name; ut_id : array[1..4] of char; ut_user : tuser_name; ut_host : thost_name; ut_exit : texitstatus; ut_session : longint; ut_tv : Array [1..2] of longint; ut_addr : Array[1..4] of longint; pad : array [1..48] of char end; pUser_list = ^tUser_list; tUser_list = record User : tUser; Next : pUser_list; end; implementation Type tSearch_parameters = record Type_of_login_types : tParameter_type; Login_types : tLogin_types; end; var User_list : pUser_list; Current_user : pUser_list; Utmp_file : String; Search_parameters : tSearch_parameters; procedure Set_search_parameters( const Parameter_type : tParameter_type; Login_types : tLogin_types); begin Search_parameters.Type_of_login_types := Parameter_type; Search_parameters.Login_types := Login_types; end; function More_users : Boolean; var UL : pUser_list; Last : Boolean; begin UL := Current_user; Last := True; while (UL <> nil) and Last do begin if Search_parameters.Type_of_login_types = Exclude then begin Last := (UL^.User.Type_of_login in Search_parameters.Login_types); end else begin Last := not (UL^.User.Type_of_login in Search_parameters.Login_types); end; UL := UL^.Next; end; More_users := not Last; end; function Number_of_logged_users : Word; var I : Word; UL: pUser_list; begin I := 0; UL := User_list; while UL <> nil do begin if UL^.User.Type_of_login = User_process then begin I := I + 1; end; UL := UL^.Next; end; Number_of_logged_users := I; end; function Get_next_user : tUser; var Found : Boolean; User : pUser; begin if Current_user <> nil then begin Found := False; while (Current_user <> nil) and not Found do begin User := @Current_user^.User; if Search_parameters.Type_of_login_types = Exclude then begin Found := not (User^.Type_of_login in Search_parameters.Login_types); end else begin Found := (User^.Type_of_login in Search_parameters.Login_types); end; Current_user := Current_user^.Next; end; if Found then begin Get_next_user := User^; end else begin New(User); FillChar(User^, SizeOf(tUser), 0); Get_next_user := User^; Dispose(User); end; end else begin New(User); FillChar(User^, SizeOf(tUser), 0); Get_next_user := User^; Dispose(User); end; end; function Get_next_user(var Last : Boolean) : tUser; var Found : Boolean; User : pUser; UL : pUser_list; begin if Current_user <> nil then begin Found := False; while (Current_user <> nil) and not Found do begin User := @Current_user^.User; if Search_parameters.Type_of_login_types = Exclude then begin Found := not (User^.Type_of_login in Search_parameters.Login_types); end else begin Found := (User^.Type_of_login in Search_parameters.Login_types); end; Current_user := Current_user^.Next; end; if Found then begin Get_next_user := User^; UL := Current_user; Last := True; while (UL <> nil) and Last do begin if Search_parameters.Type_of_login_types = Exclude then begin Last := (UL^.User.Type_of_login in Search_parameters.Login_types); end else begin Last := not (UL^.User.Type_of_login in Search_parameters.Login_types); end; UL := UL^.Next; end; end else begin New(User); FillChar(User^, SizeOf(tUser), 0); Get_next_user := User^; Dispose(User); end; end else begin New(User); FillChar(User^, SizeOf(tUser), 0); Get_next_user := User^; Dispose(User); end; end; procedure Reset_user_search; begin Current_user := User_list; end; procedure Set_utmp_file(const File_name : String); begin Utmp_file := File_name; end; function Number_of_utmp_entries : Word; var S : Stat; begin Linux.FStat(Utmp_file, S); Number_of_utmp_entries := S.Size div System.SizeOf(tLL_Utmp); end; procedure Read_logged_users; procedure Read_entry(var F : File; var Entry : tUser; var User : Boolean); var LL_Entry : tLL_Utmp; I : Byte; begin BlockRead(F, LL_Entry, SizeOf(tLL_Utmp)); Byte(Entry.Type_of_login) := LL_Entry.ut_type; Entry.Pid := Longint(LL_Entry.ut_id); Entry.Device:=LL_entry.ut_line; Entry.TTy_Name:=LL_Entry.ut_id; Entry.Login_time := LL_Entry.ut_tv[1]; Entry.User_name:=LL_entry.ut_user; Entry.Host_name:=LL_entry.ut_host; For I:=1 to 4 do Entry.Ip_Address[I] := LL_Entry.ut_addr[i]; end; var F : File; I : Longint; UL: pUser_list; U : Boolean; begin System.Assign(F, Utmp_file); {$IFOPT I+} {$DEFINE I_was_on} {$ENDIF} {$I-} System.Reset(F,1); {$IFDEF I_was_on} {$UNDEF I_was_on} {$I+} {$ENDIF} UL := User_list; while UL <> nil do begin User_list := UL; UL := UL^.Next; Dispose(User_list); end; User_list := nil; if System.IOResult = 0 then begin for I := 1 to Number_of_utmp_entries do begin if User_list = nil then begin New(User_list); UL := User_list; UL^.Next := nil; end else begin New(UL^.Next); UL := UL^.Next; UL^.Next := nil; end; Read_entry(F, UL^.User, U); end; UL^.Next := nil; end else begin User_list := nil; end; System.Close(F); Current_user := User_list; end; begin User_list := nil; Current_user := nil; Utmp_file := '/var/run/utmp'; Set_search_parameters(Include,DefaultLoginType); end.