Comments (10)
Resources
- how to call bash commands from c
- some examples of how to use bash history
- the bash man page for history
- how to get the last 10 lines of code from history:
fc -ln 10 | sed 's/[0-9]*//' | awk '{$1=$1};1'
from myaliases.
Proposed Interface
We can use alias with a new -h
option: alias -h [num_history_lines] alias_name
An argument to -h
can be optionally provided to specify how many of the previous lines from history to use. If it isn't specified, we could load all of the lines from the beginning of the current session's history. We can use unalias to delete an already existing alias.
problems that might arise:
- what if the alias_name includes an equal sign or other characters that aren't allowed? what if there are commands included after the equal sign? would we just ignore them?
- what if the alias_name already exists? will we just replace it? but then what if one of the commands in history is the command that we're replacing? (how does regular alias deal with this? is this just undefined behavior?)
- how will we merge history lines together into a single line for alias? we can't just put semicolons at the end of each command because sometimes that doesn't work. (ex: if the line ends with
&
) - also what does bash history do with multi-line commands (ie those separated by
\
)? will this cause any trouble for us?
Perhaps we might also want to add functionality for editing the alias using the user's default editor? This might be useful, especially since I can imagine some of these aliases becoming really long. In this case, would it be better to store these aliases as bash scripts so that they can be easily edited without having to re-parse the alias as a single line? Might this also allow for advanced functionality whereupon the user can specify their own custom arguments and options?
@GiselleSerate what are your thoughts on all of this?
from myaliases.
@aryam7 are you working on myaliases on your lunch break? xD
EDIT: I realized it's Saturday, never mind me
from myaliases.
- Maybe we should only read legal characters for the alias name, and then we will ignore any illegal characters and anything that follows.
- I think if alias_name already exists, we would replace it, as that's what normal alias does. If one of the commands in history is one we're replacing, it would do a recursive thing, so that's really bad and it would get stuck in an infinite loop, so I think we should check for that before we start aliasing.
- If we write this into a bash script, multiple lines wouldn't be an issue.
- I briefly investigated multiline commands and it basically just smashes them into one line all together, eliminating the slash and the enter. So I think that's totally okay and we can treat them like any other command.
I think we can use altalias in .bash_alias
because I've already got decent option handling in that (and it passes directly to alias if the option handling doesn't fly on my end . . . maybe I should pre-handle the error messages to warn if it's not an s
, h
, or p
option.)
I think writing these as bash scripts would be most optimal, because then our aliases could just call the applicable script. Then we'd have to figure out where the scripts are stored globally . . . likely we would want to put something in a folder elsewhere (like bin or something) that wouldn't get moved or installed in a different place relative to root. Also then we don't have to worry about multiple lines. I don't know what you're suggesting about editing the alias using the default editor (honestly giving them the filepath might be the best thing, unless you want to have a certain command that will be aliased to look in the folder and open it using their default editor).
from myaliases.
Cool, I agree with all of the bullet points. But I think recursive aliasing probably falls under the category of undefined behavior, along with referencing variables/functions/files that aren't loaded into the global environment on startup and all of the other crap that the user could throw at us. The original alias
command just treats this as undefined behavior too, I believe.
Yeah, I think using bash scripts would be pretty neat. That route would also really maximize the flexibility of this command (ie the user could pass arguments to their scripts and do all of the complicated stuff that a script has the power to do).
I also like the idea of creating aliases that call the scripts; we could use this to add the scripts to the global environment and it wouldn't require us messing with $PATH
or anything. Also unaliasing the script would literally be as easy as just unaliasing the command that calls the script -- we wouldn't have to write any extra code, since we could just leverage the unalias code you've already written. Also, if users want to see which scripts they've created, they can just use the already existing alias -p
infrastructure; we wouldn't have to write extra code for that either.
Yes, I was thinking we could store these bash scripts in a folder inside .myaliases
and create another option (maybe -e
for "edit") for alias that would allow us to automatically edit those scripts using the default editor. That way, the user doesn't have to know the path to the scripts (and also doesn't have to type it out).
One downside of this interface is that it kinda implies the user can edit non-script aliases, as well. Unless we want to write code that also edits regular aliases, we might want to require that both the -h
and -e
options are provided together. I guess we would just ignore the num_history_lines
parameter if it's provided in this case? I'm not exactly sure how best to approach this.
Let me know what you think!
from myaliases.
Cool, I'm always down for leaving it as undefined behavior. I guess it could fail pretty badly if people really wanted to give us bad input.
We probably want to delete the script itself when we unalias, because I don't want to be littering the system with garbage files.
I think editing should happen in post. I think it's reasonable to have a -h
flag and have that only save the file and then have a -e
flag that you can do on a subsequent run to edit the applicable file. At that point, you'd only need to provide the name of the alias, which I suppose would be the filename. The downside being what if the file provided does not exist . . . I don't know if we want to error out at that point or set the alias and give them a new file . . . I'd lean towards erroring out because if it's a typo, that's kinda hard to undo.
Do we have a path to the my_aliases
folder? I can't remember but we must, to get .usr_aliases
. . .
Also, I've been looking into stuff and probably it's better to use execve
than system
(maybe cause I skimmed and it said "security concern"). We could have scripts in files that execve
calls, and I will use my handy dandy fork
knowledge from 105 if necessary.
from myaliases.
I found a utility that turns shell script into C code, but I'm not sure that's really what we want.
from myaliases.
Ok. sounds good!
so use of the -e
flag to edit an alias that doesn't have a bash script is undefined behavior? or an error or something?
yeah, we should have a path to it. I think it's in the $ABSPATH
variable?
Ok! I'm all for using execve
. I'm also not sure I know enough to say whether that utility is what we need
from myaliases.
Yeah, we can probably error out, that shouldn't be too much of a problem. I think we should probably do it explicitly, because if we leave it as undefined behavior then what we'll get is a usage error.
The only problem with execve
is that we have to pass a script . . . haven't figured out if we can necessarily call stuff like ls
and so forth or if we need to delegate that to a script. (I need to figure out how to call normal scripts before figuring out system-type calls.)
EDIT: I used the code from this link with slight modifications (i.e. only initializing the 0th element of myArray) and it was able to call ls properly.
from myaliases.
About execve
Here's a summary of what I've figured out about execve
. @aryam7, if you have questions about things, lmk, I know I definitely underexplained forking but it's something we went over in 105 so I can definitely explain better/more if things are unclear.
Calling a local script
int main(int argc, char *argv[], char **env)
{
char *exePath = strcat(getenv("ABSPATH"), "/.testscript");
char *myArray[] = {"dontcare", "arg1", "arg2", NULL}; // Pass in single argument, array is null terminated.
execve(exePath, myArray, env); // On success, will not return to function.
}
This calls a bash script called .testscript
in the myaliases directory. Takes in two arguments. Argument 0 is replaced by the program name.
Calling a builtin function
int main(int argc, char *argv[], char **env)
{
char *exePath = "/bin/ls");
char *myArray[] = {"dontcare", NULL}; // Pass in single argument, array is null terminated.
execve(exePath, myArray, env); // On success, will not return to function.
}
Calls ls
.
Note about forks
I didn't add the fork code above for brevity, but execve
will not return control to your function (part of why main
isn't returning in my examples). If you'd like to do multiple tasks with no dependencies, you can:
if(fork()==0)
{
// Child thread; do a thing
}
else
{
// Parent thread; do another thing
}
Either may be done first, since they're now on separate threads, so you don't have control over that.
So normally if you want the parent to wait for the child to be done, you can put a waitpid
before the task you want to wait (takes the child pid, which gets spit out of the fork()
function, so you'll have to save it). I'm really not sure if that will work in this case with the execve
because it isn't actually returning to the function . . . but maybe once execve
is finished with the script it'll register as finished. Will test.
Caveats for your own C files
You gotta chmod
your executables or else bash scripts will not be able to call them. You'll be able to call them, but since no one else has permission to execute, you'll probably have to . . . pass chmod
711? That would give you all privileges but leave only execute for everyone else. (I don't know if a script counts as a group member, or another user, or what . . . maybe something to investigate.)
Also, you have to run make or the executables won't exist in the first place. I've written the Makefile such that running make all
should be sufficient, and once we figure out the proper chmod
settings I can have it chmod the executable as soon as it's made as well, but that requires that the user run make in the directory. Which maybe my setup script can do eventually.
In conclusion
We don't want to use C files for everything, because they seem to be bad at handling sequential bash commands, but using them as a framework for calling bash scripts that execute certain commands might not be the worst thing in the world.
If we are only calling these certain bash scripts from C, we can pass in parameters by index rather than option handling, if that seems easier.
I'm not sure about overhead, but none of this seems to be working too slowly. Maybe we should watch the bloat; we're currently using a function to call a C script that calls a bash script. So unless we have a good reason, we might want to stick to bash? This seems an unsatisfying and duct-tapey answer, so maybe I'll keep looking. I think the problem is that our stuff links directly back into the system, and we mostly know how to do that with bash commands, so everything gets filtered through an extremely small bottleneck of execve
. Maybe there's a better way to do this.
For history specifically
We can read straight from $HISTFILE
with C, that's not a problem. Possibly a pain to read "last X lines from file" but that's okay. Calling still has to happen through bash, though. Unless we add $ABSPATH
to $PATH
? (Note: PATH=$PATH:$ABSPATH
, but will append even if $ABSPATH
already is in $PATH
.) Or we . . . put our executables in bin. (I don't know if I want to do that.)
from myaliases.
Related Issues (20)
- options HOT 6
- Reran install script and .included gave me this HOT 2
- cds - too many file descriptors? HOT 3
- wiki better m8 HOT 1
- cds tab complete shell conditional agh HOT 2
- add guidance about setup/install to wiki
- document git and hg and grep
- prepending .included line into .bash_aliases HOT 7
- comments in cds command
- unalias for altalias? HOT 1
- double slashes in cds tab completion HOT 3
- alias in alias command
- test suite HOT 3
- Setup script's jank on an RPI HOT 6
- Setup script should finish off by sourcing HOT 1
- Somehow enforce make
- some ideas
- cds - is not portable
- wsl open cmd overrides default open cmd HOT 2
- WSL 2 alternative to SFTP Net Drive using SSHFS HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from myaliases.