Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4424231
shell.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
shell.c
View Options
#include
<compat.h>
// IWYU pragma: keep
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#ifdef _WIN32
#define popen _popen
#define pclose _pclose
#else
#include
<sys/wait.h>
#endif
#include
"ant.h"
#include
"errors.h"
#include
"internal.h"
#include
"modules/symbol.h"
static
ant_value_t
builtin_shell_text
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
);
static
ant_value_t
builtin_shell_lines
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
);
static
ant_value_t
shell_exec
(
ant_t
*
js
,
const
char
*
cmd
,
size_t
cmd_len
)
{
ant_value_t
result
=
js_mkobj
(
js
);
FILE
*
fp
=
popen
(
cmd
,
"r"
);
if
(
!
fp
)
{
js_set
(
js
,
result
,
"stdout"
,
js_mkstr
(
js
,
""
,
0
));
js_set
(
js
,
result
,
"stderr"
,
js_mkstr
(
js
,
"Failed to execute command"
,
25
));
js_set
(
js
,
result
,
"exitCode"
,
js_mknum
(
1
));
return
result
;
}
char
*
output
=
NULL
;
size_t
output_size
=
0
;
size_t
output_capacity
=
4096
;
output
=
malloc
(
output_capacity
);
if
(
!
output
)
{
pclose
(
fp
);
return
js_mkerr
(
js
,
"Out of memory"
);
}
char
buffer
[
4096
];
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
)
!=
NULL
)
{
size_t
len
=
strlen
(
buffer
);
if
(
output_size
+
len
>=
output_capacity
)
{
output_capacity
*=
2
;
char
*
new_output
=
realloc
(
output
,
output_capacity
);
if
(
!
new_output
)
{
free
(
output
);
pclose
(
fp
);
return
js_mkerr
(
js
,
"Out of memory"
);
}
output
=
new_output
;
}
memcpy
(
output
+
output_size
,
buffer
,
len
);
output_size
+=
len
;
}
int
status
=
pclose
(
fp
);
#ifdef _WIN32
int
exit_code
=
status
;
#else
int
exit_code
=
WIFEXITED
(
status
)
?
WEXITSTATUS
(
status
)
:
-1
;
#endif
if
(
output_size
>
0
&&
output
[
output_size
-
1
]
==
'\n'
)
output_size
--
;
ant_value_t
stdout_val
=
js_mkstr
(
js
,
output
,
output_size
);
free
(
output
);
js_set
(
js
,
result
,
"exitCode"
,
js_mknum
(
exit_code
));
js_set
(
js
,
result
,
"text"
,
js_heavy_mkfun
(
js
,
builtin_shell_text
,
stdout_val
));
js_set
(
js
,
result
,
"lines"
,
js_heavy_mkfun
(
js
,
builtin_shell_lines
,
stdout_val
));
return
result
;
}
static
ant_value_t
builtin_shell_text
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
(
void
)
args
;
(
void
)
nargs
;
ant_value_t
fn
=
js_getcurrentfunc
(
js
);
return
js_get_slot
(
fn
,
SLOT_DATA
);
}
static
ant_value_t
builtin_shell_lines
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
(
void
)
args
;
(
void
)
nargs
;
ant_value_t
fn
=
js_getcurrentfunc
(
js
);
ant_value_t
stdout_val
=
js_get_slot
(
fn
,
SLOT_DATA
);
size_t
text_len
;
char
*
text
=
js_getstr
(
js
,
stdout_val
,
&
text_len
);
if
(
!
text
)
return
js_mkarr
(
js
);
ant_value_t
lines_array
=
js_mkarr
(
js
);
size_t
line_start
=
0
;
for
(
size_t
i
=
0
;
i
<=
text_len
;
i
++
)
{
if
(
i
==
text_len
||
text
[
i
]
==
'\n'
)
{
size_t
line_len
=
i
-
line_start
;
ant_value_t
line_val
=
js_mkstr
(
js
,
text
+
line_start
,
line_len
);
js_arr_push
(
js
,
lines_array
,
line_val
);
line_start
=
i
+
1
;
}
}
return
lines_array
;
}
static
ant_value_t
builtin_shell_dollar
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"$() requires at least one argument"
);
if
(
!
is_special_object
(
args
[
0
]))
{
if
(
vtype
(
args
[
0
])
==
T_STR
)
{
size_t
cmd_len
;
char
*
cmd
=
js_getstr
(
js
,
args
[
0
],
&
cmd_len
);
if
(
!
cmd
)
return
js_mkerr
(
js
,
"Failed to get command string"
);
return
shell_exec
(
js
,
cmd
,
cmd_len
);
}
return
js_mkerr
(
js
,
"$() requires a template string"
);
}
ant_value_t
strings_array
=
args
[
0
];
char
*
command
=
malloc
(
4096
);
if
(
!
command
)
return
js_mkerr
(
js
,
"Out of memory"
);
size_t
cmd_pos
=
0
;
size_t
cmd_capacity
=
4096
;
ant_value_t
length_val
=
js_get
(
js
,
strings_array
,
"length"
);
int
length
=
(
int
)
js_getnum
(
length_val
);
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
char
idx_str
[
32
];
snprintf
(
idx_str
,
sizeof
(
idx_str
),
"%d"
,
i
);
ant_value_t
str_val
=
js_get
(
js
,
strings_array
,
idx_str
);
if
(
vtype
(
str_val
)
==
T_STR
)
{
size_t
str_len
;
char
*
str
=
js_getstr
(
js
,
str_val
,
&
str_len
);
if
(
cmd_pos
+
str_len
>=
cmd_capacity
)
{
cmd_capacity
*=
2
;
char
*
new_cmd
=
realloc
(
command
,
cmd_capacity
);
if
(
!
new_cmd
)
{
free
(
command
);
return
js_mkerr
(
js
,
"Out of memory"
);
}
command
=
new_cmd
;
}
memcpy
(
command
+
cmd_pos
,
str
,
str_len
);
cmd_pos
+=
str_len
;
}
if
(
i
+
1
<
nargs
)
{
ant_value_t
val
=
args
[
i
+
1
];
char
val_str
[
256
];
size_t
val_len
=
0
;
if
(
vtype
(
val
)
==
T_STR
)
{
size_t
len
;
char
*
s
=
js_getstr
(
js
,
val
,
&
len
);
val_len
=
len
<
sizeof
(
val_str
)
-
1
?
len
:
sizeof
(
val_str
)
-
1
;
memcpy
(
val_str
,
s
,
val_len
);
}
else
if
(
vtype
(
val
)
==
T_NUM
)
{
val_len
=
snprintf
(
val_str
,
sizeof
(
val_str
),
"%g"
,
js_getnum
(
val
));
}
if
(
cmd_pos
+
val_len
>=
cmd_capacity
)
{
cmd_capacity
*=
2
;
char
*
new_cmd
=
realloc
(
command
,
cmd_capacity
);
if
(
!
new_cmd
)
{
free
(
command
);
return
js_mkerr
(
js
,
"Out of memory"
);
}
command
=
new_cmd
;
}
memcpy
(
command
+
cmd_pos
,
val_str
,
val_len
);
cmd_pos
+=
val_len
;
}
}
command
[
cmd_pos
]
=
'\0'
;
ant_value_t
result
=
shell_exec
(
js
,
command
,
cmd_pos
);
free
(
command
);
return
result
;
}
ant_value_t
shell_library
(
ant_t
*
js
)
{
ant_value_t
lib
=
js_mkobj
(
js
);
js_set
(
js
,
lib
,
"$"
,
js_mkfun
(
builtin_shell_dollar
));
js_set_sym
(
js
,
lib
,
get_toStringTag_sym
(),
js_mkstr
(
js
,
"shell"
,
5
));
return
lib
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, May 2, 1:56 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
538822
Default Alt Text
shell.c (5 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment