Ruby where is etc module file and can it be customized? - ruby

Etc module is great, but if I used NIS or LDAP where passwd, group, and shadow are not from /etc/{passwd, group, shadow}, then Etc module is not going to help.
Is it possible to edit the Etc module path's /etc/{passwd,group,shadow}?
On my Linux box, I have gone into /usr/lib/ruby/1.8, there are modules but couldn't fine etc.rb or related modules.
Many thanks

In general, you can use
SomeClass.method(:foo).source_location
to find out where (on disk) a method is defined. I don't think this was available in ruby 1.8, but even it is the result is nil, because these methods are implemented in C. The ruby 1.9 implementation is here for example. Somewhere in /usr/lib/ruby/1.8 there should be an etc.so (on linux or etc.bundle on os x and so on)
This doesn't mean that you can't overwrite the method, but it does mean that you can't just edit the source as you would with a plain .rb file (you'd have to recompile the extension afterwards and move it to the correct location, which is system dependant)

Related

How does require 'digest/md5' works?

require 'digest/md5' # => true
Digest::Md5.hexdigest('') # => "d41d8cd98f00b204e9800998ecf8427e"
Which file does this require use? Is an actual file being required? Or is it required programmatically?
This is (sorta) explained in the documentation for Kernel#require:
require(name) → true or false
Loads the given name, returning true if successful and false if
the feature is already loaded.
If the filename does not resolve to an absolute path, it will be
searched for in the directories listed in $LOAD_PATH ($:).
If the filename has the extension “.rb”, it is loaded as a source file; if
the extension is “.so”, “.o”, or “.dll”, or the default shared library
extension on the current platform, Ruby loads the shared library as a Ruby
extension. Otherwise, Ruby tries adding “.rb”, “.so”, and so on to the
name until found. If the file named cannot be found, a LoadError will be raised.
By default $LOAD_PATH will include the directories where Ruby's standard library lives. Directories, plural, because native (compiled binary) modules in the standard library live in a different directory than pure-Ruby modules.
Digest is actually a great example because some of its files are native and others are Ruby.
On my Mac $LOAD_PATH includes (among others) these two directories (truncated for readability):
.../usr/lib/ruby/2.0.0
.../usr/lib/ruby/2.0.0/universal-darwin15
The former is where pure-Ruby modules live and the latter is where native modules live.
So when I do require 'digest/md5' Ruby first looks in .../usr/lib/ruby/2.0.0/ for a directory named digest/, and upon finding it, for a file in it named md5.rb. It doesn't find it, so it looks for md5.bundle. Why .bundle and not .so or .o? Because that's the "default shared library extension" that Ruby was configured with when it was compiled for OS X. Go figure.
Ruby doesn't find it there, so next it looks in .../usr/lib/ruby/2.0.0/universal-darwin15/digest/. There's no md5.rb there, but there is an md5.bundle, so Ruby loads it.
It loads a C-extension that can be found in Ruby's source dir - ruby/ext/digest/md5/
It's one of Ruby's standard libraries (stdlib), which means that it's available in pretty much every implementation of Ruby. It does, in fact, load a file. But it's a file that was copied to your computer when you installed Ruby and is pretty much always going to be available to you. Another good example of a standard library is DateTime.
One thing that confused me a lot when I started learning Ruby and Rails was that Rails requires a fair number of Ruby's standard libraries for you. So it's good to be aware of what's actually going on under the hood.

Is there any way to simulate LD_LIBRARY_PATH in Windows?

I have a program do so some graphics. When I run it interactively, I want it to use OpenGL from the system to provide hardware accelerated graphics. When I run it in batch, I want to be able to redirect it to use the Mesa GL library so that I can use OSMesa functionality to render to an offscreen buffer. The OSMesa functionality is enabled by doing a LoadLibrary/GetProcAddress if the batch start up option is selected.
On Linux, its fairly easy to make this work. By using a wrapper script to invoke the program, I can do something like this:
if [ "$OPTION" = "batch" ]; then
export LD_LIBRARY_PATH=$PATHTO/mesalibs:$LD_LIBRARY_PATH
fi
It is possible to do something this in Windows?
When I try adding a directory to the PATH variable, the program continues to go to the system opengl32.dll. The only way I can get the program to use the Mesa GL/OSMesa shared libraries is to have them reside in the same directory as my program. However, when I do that, the program will never use the system opengl32.dll.
If I've understood what you're saying correctly, the wrong version of opengl32.dll is being loaded when your process starts up, i.e., load-time dynamic linking. There is probably no good way to solve your problem without changing this.
You say you can't use conveniently use run-time dynamic linking (LoadLibrary/GetProcAddress) for opengl32.dll because the calls to it are coming from the Qt library. I presume that the Qt library is itself dynamically linked, however, so you should be able to solve your problem by using run-time linking for it. In this scenario, provided you load opengl32.dll before you load the Qt library, you should be able to explicitly choose which version of opengl32.dll you want to load.
You might want to consider using delayed loading in order to simplify the process of moving from load-time to run-time linking. In this scenario, the first call into the Qt library causes it to be loaded automatically, and you'll just need to explicitly load opengl32.dll first.
There are a few ways you could handle this, depending on the libraries and their names/locations:
If both have the same name (opengl32.dll), then you need to add the Mesa DLL location to the search path such that it is searched before the system directory. The order directories are checked in is detailed here. As you can see, $PATH comes last, after system, so you can't just add the directory to that. However, you can make use of the second step ("The current directory") by setting the working directory to a path containing the mesa files. Generally this means starting the application using an absolute path while in the directory containing the files.
That's still not particularly pleasant, though. If you can, you should use LoadLibrary and check for an environment variable (OPENGL_LIBRARY_PATH) when your app starts up. Assuming the exports from opengl32.dll and Mesa's DLL are the same, you can do something like:
void LoadExports()
{
char location[MAX_PATH];
getenv("OPENGL_LIBRARY_PATH", location);
HMODULE oglLib = LoadLibrary(location);
function1 = GetProcAddress(oglLib, "glVertex2f");
...
}
This will work perfectly fine, doing almost exactly what you want.
However, if you want to do that, you can't import opengl32.dll, which you're probably doing, you have to dynamically link throughout. Make sure not to link against opengl32.lib and you should be fine. Depending on how many functions you use, it may be a pain to set up, but the code can easily be scripted and only needs done once, you can also use static variables to cache the results for the lifetime of the program. It's also possible to use different function names for different libraries, although that takes a bit more logic, so I'll leave the details to you.
Though this should be possible in the cmd window, it seems you're having no luck.
Try: set a variable in your script (RUNNING_IN_SCRIPT=Y) and then parse for that variable in your executable and LoadLibrary from the absolute path of installation - be sure to clear the variable when you exit.
Windows used to search different paths for dynamic libraries, but due to security consideration, the system path is searched first.
You could, however use Delay Load Imports to get a workaround:
If you're using MSVC, you could single-out the DLLs you're interested in loading on your own with /DELAYIMPORT flag to the linker.
Then, override the delay load helper function and use LoadLibrary to find the proper DLL (and not trust it to the system).
After loading the correct DLL, have your helper function just call the original one that will do all the GetProcAddress business by itself.

Make emacs autocomplete Ruby methods

Is there a way to make emacs pull autocompletions of ruby methods the way Eclipse and NetBeans do? That is if I type File. and press CTRL-space in Eclipse I will get a list of File methods. Same with variables. I have installed autocomplete plugin, ruby-mode, rinari and cedet, but so far it will complete local variable and method names, but will not native ones.
I think you need something like RSense. You might also like the more general auto complete mode.
I'm not familiar with ruby, but if by "native methods" you mean stuff in some system library, there are a couple options for extending CEDET to do the work.
If there are ruby files somewhere that have all that code in them, and if ruby supports some sort of "include" or "import" statement, then you need to add that location to the include path for ruby. This probably requires a change the the ruby source code to add a new system include path. You can see examples in semantic-c.el. You may also need to override the function semantic-tag-include-filename to convert the include into a findable filename.
If there are no includes, and there is just some ruby interpreter that knows all this stuff, then you will instead need to code up a full ruby "omniscient" database, similar to semanticdb-el.el. It will need a way to query ruby for various things and return them as answers.
Any such enhancements would be welcome back in the ruby support in CEDET's contrib area.
Ruby is an interpreted language, making it difficult to do certain things, such as autocompletion. How would you know what the object type is, if it's not defined? Therefore, premade solutions are limited or nonexistent. Even the autocompletion in Netbean/Eclipse will only work on class methods (if I'm not mistaken).

Ruby: targeting multiple platforms in one project

I am creating an [Iron]Ruby project that needs to support several environments (more specifically, WPF, Silverlight, and WinForms - but that's not as important). The following is an actual, concrete example of where I'm stuck:
I have to implement a Bitmap class as part of a library, and this class will need to be implemented differently depending on what environment it's running in (e.g. if I'm running this in the browser as a silverlight app, I won't have access to methods that would be available on the desktop). And here's the catch - I don't control the instantiation of Bitmap, nor any of the other classes within the library. Why? Because it's a port of another application; and, while I do have the code for the application, I don't want to break compatibility by changing that code. I do, however, control the entry point to the application, so I can require whatever I need, perform setup, configure global variables, etc.
Edit: If you're curious, this is the project I'm working on:
http://github.com/cstrahan/open-rpg-maker
Here's what I want to know:
How should I set the configuration at startup, such that Bitmap will behave appropriately?
How should I structure this in my git repo / source tree?
Here are some of my thoughts, but I'm sure you'll have better ideas:
How should I set the configuration at startup?
When distributing the app, place a require at the top depending on the targeted environment, like so: require silverlight/bitmap. In this case, lib/bitmap.rb would be empty, while lib/silverlight/bitmap.rb would contain the implementation. Or...
Stuff all implementations in lib/bitmap.rb, and conditionally execute based on a class instance variable or constant: Bitmap.impl = "silverlight". Or...
Maintain a separate branch for each distro - despite the library being almost exactly the same.
How should I structure this in my git repo / source tree?
Separate branches per distribution. Or...
Separate implementation-specific subfolders (e.g. lib/silverlight/bitmap.rb).
Being very new to Ruby, I'm not very familiar with such best practices (I'm coming from C#). Any advice would be greatly appreciated!
-Charles

In Ruby, what's the equivalent of Java's technique of limiting access to source in a cowork situation?

In Java when you compile a .java file which defines a class, it creates a .class file. If you provide these class files to your coworkers then they cannot modify your source. You can also bundle all of these class files into a jar file to package it up more neatly and distribute it as a single library.
Does Ruby have any features like these when you want to share your functionality with your coworkers but you don't want them to be able to modify the source (unless they ask you for the actual .rb source file and tell you that they want to change it)?
I believe the feature you are looking for is called "trust" (and a source code control repository). Ruby isn't compiled in the same way that Java is, so no you can't do this.
I have to say your are in a rough position, not wanting to share code with a coworker. However, given that this is an unassailable constraint perhaps you could change the nature of the problem.
If you have a coworker that needs access to some service provided by a library of yours, perhaps you could expose it by providing a web/rest service instead of as a .rb file.
This way you can hide your code behind a web server, and if there is a network architecture that allows for low latency making these service calls, you can effectively achive the same goal.
Trust is a lot easier though.
edit:
Just saw this on HN: http://blog.astrails.com/2009/5/12/ruby-http-require, allows a ruby file to include another file through http instead of the filesystem.
Ruby is
A dynamic, interpreted, open source programming language with a focus on simplicity and productivity.
So like all interpreted languages, you need to give the source code to anyone who want's to execute your program/script.
By the way searching "compiled ruby" on google returned quiet a few results.
I don't think there is one. Ruby is purely an interpreted language, which means ruby interprets your source code directly in order to run it. Java is compiled, so there's an intermediate bytecode (the .class). You can obfuscate your ruby if you really wish, but it's probably more trouble than it's worth.
Just to make sure you realize, however, upwards of 95% of Java can be decompiled back into source using various free utilities, so in reality, Java's compilation isn't much better than distributing Ruby source.
This is not a language specific problem and one that can be managed more effectively through source control software.
There is a library called ruby2c that compiles a subset of Ruby into C code (which you can then compile into native code, if you want).
It was actually originally written as a Ruby code obfuscator (but has since been used for lots of other stuff, including Ruby Arduino development).

Resources