1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 | -- Copyright (C) 2022-2024 A.J. Ianozi <aj@ianozi.com>
--
-- This file is part of GetAda: the Unofficial Alire Installer
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Characters.Handling; use Ada.Characters.Handling;
with Platform; use Platform;
with Ada.Environment_Variables;
with Ada.Directories;
package body Shells is
-- Get the resulting configuration file to edit, based on the shell.
function Get_Shell_Config (Shell_Name : Supported_Shells) return String is
begin
case Shell_Name is
when sh | bash =>
return ".profile";
when zsh =>
return ".zshenv";
when others =>
raise Unsupported_Shell with Shell_Name'Image & " not supported";
end case;
end Get_Shell_Config;
-- I'm doing it this way in case I want to add support for fish, e.g.
-- "env.fish" etc.
function Get_Shell_Env (Shell_Name : Supported_Shells) return String is
begin
case Shell_Name is
when sh | bash | zsh =>
return "env.sh";
when others =>
raise Unsupported_Shell with Shell_Name'Image & " not supported";
end case;
end Get_Shell_Env;
procedure Write_Env_File
(Shell_Name : Supported_Shells; File : File_Type; Dir : String)
is
begin
case Shell_Name is
when sh | bash | zsh =>
Put_Line (File, "#!/bin/sh");
Put_Line (File, "# Add alire's dir to path");
Put_Line (File, "case "":$PATH:"" in");
Put_Line (File, "*"":" & Dir & ":""*)");
Put_Line (File, " : ;; # already exists, do nothing.");
Put_Line (File, "* )");
Put_Line (File, " # Add to path");
Put_Line (File, " export PATH=""$PATH:" & Dir & """");
Put_Line (File, "esac");
when others =>
raise Unsupported_Shell with Shell_Name'Image & " not supported";
end case;
end Write_Env_File;
function Get_Env_Command
(Shell_Name : Supported_Shells; Env_File : String) return String
is
begin
case Shell_Name is
when sh | bash | zsh =>
return ". """ & Env_File & """";
when null_shell =>
raise Unsupported_Shell with Shell_Name'Image & " not supported";
end case;
end Get_Env_Command;
-- Checks if this shell is compatible with the bourne shell
function Sh_Compatible (Shell_Name : Supported_Shells) return Boolean is
begin
case Shell_Name is
when sh | bash =>
return True;
when others =>
return False;
end case;
end Sh_Compatible;
function Available_Shells return Shell_Array
is
-- Env variable for current Shell
Shell_Env : constant String := "SHELL";
-- General location of available shells.
Shell_Path : constant String := "/etc/shells";
-- Truth table of avalaible shells
Shell_Amount : Natural := 0; -- Amount of shells discovered
Shell_List : array (Supported_Shells'Range) of Boolean :=
(others => False);
-- This processes each shell using the established variables above
procedure Process_Shell (Shell_Str : String) is
Prefix : constant String := "/bin/"; -- All lines start with this?
begin
-- If this line is /bin/something
if Shell_Str'Length > Prefix'Length
and then Index (Shell_Str, Prefix) = 1
then
declare
Check_Shell : constant String :=
To_Upper
(Shell_Str
(Shell_Str'First - 1 + Prefix'Length + 1 ..
Shell_Str'Last));
begin
for S in Shell_List'Range loop
if not Shell_List (S) -- the current item is false
and then S'Image = Check_Shell
then
if not Sh_Compatible (S) then
Shell_List (S) := True;
Shell_Amount := Shell_Amount + 1;
elsif not Shell_List (sh) then
Shell_List (sh) := True;
Shell_Amount := Shell_Amount + 1;
end if;
end if;
end loop;
end;
end if;
end Process_Shell;
begin
-- TODO: a better way to do this.
if OS = Windows then
declare
Result : constant Shell_Array (1 .. 1) :=
(1 => (Null_Unbounded_String, null_shell));
begin
return Result;
end;
end if;
-- First log current shell.
if Ada.Environment_Variables.Exists (Shell_Env) then
Process_Shell (Ada.Environment_Variables.Value (Shell_Env));
end if;
-- Next, check the available shells
if Ada.Directories.Exists (Shell_Path) then
declare
Shell_File : File_Type; -- To store the file
begin
Open (Shell_File, In_File, Shell_Path);
-- Iterate through the file, indexing which shells we support.
while not End_Of_File (Shell_File) loop
declare
Next_Line : constant String := Get_Line (Shell_File);
begin
Process_Shell (Next_Line);
end;
end loop;
Close (Shell_File);
end;
end if;
-- Verify that we have at least 1 found shell.
if Shell_Amount = 0 then
raise No_Shells_Found
with "Cannot locate /etc/shells or $SHELL does not exist." &
" Please pass ""--no-path""";
end if;
-- Create the array, fill it with resulting shells, return the result.
declare
Result : Shell_Array (1 .. Shell_Amount);
Counter : Positive := 1;
begin
for S in Shell_List'Range loop
if Shell_List (S) then
Result (Counter).Config_File :=
To_Unbounded_String (Get_Shell_Config (S));
Result (Counter).Shell := S;
Counter := Counter + 1;
end if;
end loop;
return Result;
end;
end Available_Shells;
end Shells;
|