Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4504744
shell.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
shell.c
View Options
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<unistd.h>
#include
<sys/wait.h>
#include
"ant.h"
#include
"modules/symbol.h"
static
jsval_t
builtin_shell_text
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
);
static
jsval_t
builtin_shell_lines
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
);
static
jsval_t
shell_exec
(
struct
js
*
js
,
const
char
*
cmd
,
size_t
cmd_len
)
{
jsval_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
);
int
exit_code
=
WIFEXITED
(
status
)
?
WEXITSTATUS
(
status
)
:
-1
;
if
(
output_size
>
0
&&
output
[
output_size
-
1
]
==
'\n'
)
output_size
--
;
jsval_t
stdout_val
=
js_mkstr
(
js
,
output
,
output_size
);
free
(
output
);
js_set
(
js
,
result
,
"stdout"
,
stdout_val
);
js_set
(
js
,
result
,
"stderr"
,
js_mkstr
(
js
,
""
,
0
));
js_set
(
js
,
result
,
"exitCode"
,
js_mknum
(
exit_code
));
jsval_t
text_fn
=
js_mkfun
(
builtin_shell_text
);
js_set
(
js
,
result
,
"text"
,
text_fn
);
jsval_t
lines_fn
=
js_mkfun
(
builtin_shell_lines
);
js_set
(
js
,
result
,
"lines"
,
lines_fn
);
return
result
;
}
static
jsval_t
builtin_shell_text
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
(
void
)
args
;
(
void
)
nargs
;
jsval_t
this_val
=
js_getthis
(
js
);
if
(
js_type
(
this_val
)
!=
JS_OBJ
)
{
return
js_mkerr
(
js
,
"text() must be called on a shell result"
);
}
jsval_t
stdout_val
=
js_get
(
js
,
this_val
,
"stdout"
);
return
stdout_val
;
}
static
jsval_t
builtin_shell_lines
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
(
void
)
args
;
(
void
)
nargs
;
jsval_t
this_val
=
js_getthis
(
js
);
if
(
js_type
(
this_val
)
!=
JS_OBJ
)
return
js_mkerr
(
js
,
"lines() must be called on a shell result"
);
jsval_t
stdout_val
=
js_get
(
js
,
this_val
,
"stdout"
);
if
(
js_type
(
stdout_val
)
!=
JS_STR
)
return
js_mkerr
(
js
,
"No stdout available"
);
size_t
text_len
;
char
*
text
=
js_getstr
(
js
,
stdout_val
,
&
text_len
);
if
(
!
text
)
return
js_mkerr
(
js
,
"Failed to get stdout"
);
jsval_t
lines_array
=
js_mkobj
(
js
);
size_t
line_count
=
0
;
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
;
if
(
i
<
text_len
&&
text
[
i
]
==
'\n'
)
{}
char
idx_str
[
32
];
snprintf
(
idx_str
,
sizeof
(
idx_str
),
"%zu"
,
line_count
);
jsval_t
line_val
=
js_mkstr
(
js
,
text
+
line_start
,
line_len
);
js_set
(
js
,
lines_array
,
idx_str
,
line_val
);
line_count
++
;
line_start
=
i
+
1
;
}
}
js_set
(
js
,
lines_array
,
"length"
,
js_mknum
((
double
)
line_count
));
return
lines_array
;
}
static
jsval_t
builtin_shell_dollar
(
struct
js
*
js
,
jsval_t
*
args
,
int
nargs
)
{
if
(
nargs
<
1
)
return
js_mkerr
(
js
,
"$() requires at least one argument"
);
if
(
js_type
(
args
[
0
])
!=
JS_OBJ
)
{
if
(
js_type
(
args
[
0
])
==
JS_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"
);
jsval_t
result
=
shell_exec
(
js
,
cmd
,
cmd_len
);
jsval_t
promise
=
js_mkpromise
(
js
);
js_resolve_promise
(
js
,
promise
,
result
);
return
promise
;
}
return
js_mkerr
(
js
,
"$() requires a template string"
);
}
jsval_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
;
jsval_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
);
jsval_t
str_val
=
js_get
(
js
,
strings_array
,
idx_str
);
if
(
js_type
(
str_val
)
==
JS_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
)
{
jsval_t
val
=
args
[
i
+
1
];
char
val_str
[
256
];
size_t
val_len
=
0
;
if
(
js_type
(
val
)
==
JS_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
(
js_type
(
val
)
==
JS_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'
;
jsval_t
result
=
shell_exec
(
js
,
command
,
cmd_pos
);
free
(
command
);
jsval_t
promise
=
js_mkpromise
(
js
);
js_resolve_promise
(
js
,
promise
,
result
);
return
promise
;
}
jsval_t
shell_library
(
struct
js
*
js
)
{
jsval_t
lib
=
js_mkobj
(
js
);
js_set
(
js
,
lib
,
"$"
,
js_mkfun
(
builtin_shell_dollar
));
js_set
(
js
,
lib
,
get_toStringTag_sym_key
(),
js_mkstr
(
js
,
"shell"
,
5
));
return
lib
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sun, May 3, 9:58 AM (3 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
524467
Default Alt Text
shell.c (6 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment