I'm trying to use gogo-shell to add some console commands
For example I'm create commands add and show
public void add(CommandSession commandSession, int i) {
List<Integer> il = commandSession.get("list");
if (il == null) {
il = new ArrayList<Integer>();
il.add(i);
commandSession.put("list",il)
} else {
il.add(i)
}
}
public void show(CommandSession commandSession) {
List<Integer> il = commandSession.get("list");
il.foreach(System.out::println);
}
and when i use them like
add 1 | add 2 | add 3 | add 4 | show
I'm geting something like
null pointer Exception
or
1
3
4
2
I think this happens because pipes (add) runs in parallel. So how can I write command where piping will be sequential.
Pipelines in gogo (like in bash) expect to consume data from standard input and produce data on standard output. Each element in the pipeline runs concurrently, as a separate thread.
The 'add' command in your example does not consume or produce data on standard in/out and is thus not suitable to run in a pipeline.
If you just want the commands to run sequentially, then use the ';' command separator:
g! add 1; add 2; add 3; add 4; show
Related
I'm calling CLIPS Eval() and other functions from my C code and need help understanding how to handle return values that are CLIPSValue or UDFValue. A simple example ...
...
CLIPSValue cv;
UDFValue uv;
EvalError ee;
LoadError le;
entry->env = CreateEnvironment();
le = Load(entry->env, filePathBuffer);
if (le != LE_NO_ERROR)
{
// report the load error ...
}
// Tried this but having trouble handling cv: GetDeftemplateList(entry->env, &cv, NULL);
// Trying with Eval ...
ee = Eval(entry->env, "(list-deftemplates)", &cv);
printf("%d -- %hi -- %ld -- %s", ee, cv.multifieldValue->header.type, cv.multifieldValue->length, cv.multifieldValue->lexemeValue->contents);
...
... the above printf is broken because I'm not correctly understanding cv structure/union.
Also looking into using DataObjectToString(...) but can't see how to convert CLIPSValue to UDFValue which DataObjectToString(...) needs as input.
Further processing of the result is needed, so using something like WriteCLIPSValue(...) isn't sufficient.
Would it be possible to use a router other than STDOUT with WriteCLIPSValue(...) and similar functions to only format response strings sort of like sprintf(...)?
I'm open to whatever approach is best but prefer simple/minimal C code.
This is the code fragment for iterating over the multifield value return by GetDeftemplateList and printing the string values contained in the multifield:
GetDeftemplateList(entry->env,&cv,NULL);
for (i = 0; i < cv.multifieldValue->length; i++)
{
WriteString(mainEnv,STDOUT,cv.multifieldValue->contents[i].lexemeValue->contents);
WriteString(mainEnv,STDOUT,"\n");
}
In the most general case, you'd want to verify that cv.header->type is actually a multifield and cv.multifieldValue->contents[i].header->type is a symbol or string before pulling values out of the multifieldValue or lexemeValue unions, but in this case we know that's what GetDeftemplateList is going to return.
Intro
I am integrating EndpointSecurity Framework and observing ES_EVENT_TYPE_AUTH_EXEC event.
I able to see the command arguments, but I am not able to read the command input.
Assuming that the command is as follow:
thirdPartyApp do something < ~/Desktop/file.txt
My code is: (msg is a value of type es_event_exec_t *)
for (int i = 0; i < es_exec_arg_count(&msg->event.exec); i++) {
es_string_token_t arg = es_exec_arg(&msg->event.exec, i);
print("arg: %s",arg.data);
}
Challenge is
The code output is only:
thirdPartyApp do something , without < ~/Desktop/file.txt
The thing is, < ~/Desktop/file.txt is not an argument, its a redirect as described here
What did I try?
I tried to read the env arguments too, but they were not helpful at all.
I tried to read the file descriptors, and then to read the file using NSFileHandle but they all were empty, 0 bytes.
Waiting to here from you
Redirects work by the shell open(2)ing the files you redirected and dup(2)ing them onto 0,1,2 (depending on redirect) before fork(2)ing or posix_spawn(2)ing, and allowing the child (spawned command). That means that EPS will not be able to see them as es_exec_args - because (as you correctly say) they're not arguments.
If you use
const es_fd_t * _Nonnull
es_exec_fd(const es_event_exec_t * _Nonnull event, uint32_t index);
you should be able to get back an es_fd_t - however the only relevant field will be the fdtype:
typedef struct {
int32_t fd;
uint32_t fdtype;
union {
struct {
uint64_t pipe_id;
} pipe;
};
} es_fd_t;
A better option is to thus leave the comfort of EPS and use proc_info(2) (via libproc.h) which can get you the full FD information for any process and fd (much like supraudit from http://newosxbook.com/tools/supraudit.html does).
Note, that STILL won't get you the input itself. That input is consumed by the process using read(2) (and output using write(2), of course), and neither EPS nor BSM (auditing) offers hooks for that.
I want to be able to do something like this:
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final". How might I still do something like the code above (if it is even possible)? If it can't be done, what should be done instead to get a similar result?
As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).
Simple workaround:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
Since you are using lambdas, you can benefit also from other features of Java 8, like streams.
For instance, IntStream:
A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations. This is the int primitive specialization of Stream.
can be used to replace the for loop:
IntStream.range(0,10).forEach(i->{...});
so now you have an index that can be used to your purpose:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Also you can generate a stream from an array:
Stream.of(button).forEach(btn->{...});
In this case you won't have an index, so as #shmosel suggests, you can use the source of the event:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
EDIT
As #James_D suggests, there's no need of downcasting here:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
In both cases, you can also benefit from parallel operations:
IntStream.range(0,10).parallel()
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Stream.of(button).parallel()
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
Use the Event to get the source Node.
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
Lambda expressions are effectively like an annonymous method which works on stream. In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.
In order to work around it,
final int index=button[i];
And use index instead of i inside your lambda expression.
You say If the button is pressed, but in your example all the buttons in the list will be disabled. Try to associate a listener to each button rather than just disable it.
For the logic, do you mean something like that :
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
I Also like Sedrick's answer but you have to add an action listener inside the loop .
I'm trying to establish an interactive session with another process using Mathematicas' StartProcess. It is basically the same scenario as in this question, only that I'm calling a D program instead of a Fortran one.
Take for instance a minimal D program that reads from Standard Input and writes to Standard Output interactively (notice the infinite loop):
// D
void main(string[] argv) {
while(true) {
auto name = readln().chomp;
writefln("Hello %s!", name);
}
}
When I run this program from the command prompt, it behaves as expected. If I would want to run it from Mathematica, this is supposed to work:
(* Mathematica *)
dhello = StartProcess["dhello.exe"];
WriteLine[dhello, "Wulfrick"];
ReadLine[dhello]
but it doesn't. The call to ReadLine[] blocks, as if waiting for the Process to finish. I initially thought it may be a problem in Mathematica, but I tried calling a C# program instead and it worked! Take for instance:
// C#
static void Main(string[] args) {
while (true) {
var name = Console.ReadLine();
Console.WriteLine($"Hello {name}!");
}
}
Now on the Mathematica side, doing:
(* Mathematica *)
cshello = StartProcess["cshello.exe"];
WriteLine[cshello, "Wulfrick"];
ReadLine[cshello]
Works as expected, printing the output as soon as I call ReadLine[] and maintaining interactivity. So it looks like the problem is in the D side really. Also that's why I decided to post here and not on mathematica.stackexchange.
I would really like to make this work with the D program. Any input is much appreciated.
System:
Windows 10 x64
Mathematica 11.2
DMD v2.078.2
Standard output may not have been flushed.
Try:
import std.stdio : stdout;
stdout.flush();
At the end of your while loop.
I have this code:
var obj;
if (!instance_exists(oTextbox)) {
obj=instance_create(0,0,oTextbox)
obj.textfont=argument0
obj.text[0]=argument1
obj.text[1]=argument2
obj.text[2]=argument3
obj.text[3]=""
}
Its a simple way to draw text, but when I call it with less arguments I get a compile error(expected 4 arguments provided 3),
I just want a way to be able to provide less arguments so the code will ignore if I provided less arguments and will just go to the last line
Well not very sure what you mean exactly, you can try varargs to pass variable number of arguments and check length when using them:
public void DrawText(Object... args)
{
var obj;
if (!instance_exists(oTextbox)) {
obj=instance_create(0,0,oTextbox);
int len=args.Length;
obj.textfont = args[0].toString();
obj.text[0] = args[1].toString();
if(len>2){
obj.text[1] = args[2].toString();
}
if(len>3){
obj.text[2] = args[3].toString();;
}
if(len>4){
obj.text[3] = args[4].toString();
}
}
}
Supposing you will always pass at least two values, one for textfont and one for text[0].