F'rinstance, I have a directory full of libao-0.8.3, libogg-1.0, libvorbis-1.0, and vorbis-tools-1.0, all of which compiled without
any obvious problems. But there don't seem to be any clues as to how I make the latest mozilla fire them up with it gets an ogg
file.
The sound situation is Linux ain't pretty at the moment, since there are about 4 or 5 competing standards none of which have won yet. Let me try and clear it up a little -
The original was/dev/dsp, but most original sound drivers would only let one process open that at a time (to match the sound card only having one DSP to play sounds with) so if you were say playing a game, and it had/dev/dsp open, nothing else could play sounds. This standard is called the Open Sound System, or OSS.
Similar is ALSA, the Advanced Linux Sound Architecture, which has a/dev/dsp-compatibility mode but whose main drivers implement a much more sophisticated framework, suitable for "3D" sound cards etc. ALSA was not actually packaged with Linux proper until very recently, but many vendors integrated and bundled it, so it is widely available.
Unhelpfully, ALSA became popular back when it was still in heavy development, so there are really two ALSA interfaces in use: version 0.5 and version 0.9. Presumably 0.5 will eventually spin off into irrelevance, now that 0.9 has basically stabilised.
To solve the one-process-at-a-time problem, several solutions have come out. The oldest (and little-used anymore) is NAS, the Network Audio System originally from hardware vendor NCD. Yes, "network" means you can upload noise in realtime to someone else's machine (assuming they don't lock you out). Fun stuff. NAS may not have been strictly the earliest - it had a couple of competitors, way back when, whose names I can no longer remember.
A slightly more recent development was ESD, the Enlightened Sound Daemon (or something like that), which sits on your machine holding/dev/dsp or ALSA open, accepts requests from multiple simultaneous programs, and mixes sound as needed. Used quite a bit, but the programming interface is rather baroque, so nobody really likes it much.
The KDE project, recognising the problems with ESD, created aRts, which I think is an acronym but I don't remember for what. aRts performs the same function as ESD but reportedly in a cleaner / more powerful / generally better way. Last I heard, GNOME was adopting aRts as well, so this is probably the wave (har har) of the future.
The sad thing is, whichever of the above your environment is using, it can't easily coexist with any of the others. So you have to know which you are using, and tell all your applications.
Now back to ogg vorbis. The `libao' - that is, "audio output library" - is an attempt to abstract away the actual sound output methods (the above, plus a few custom methods for other versions of Unix) into a single interface. So any libao-using application can use several if not all of the above schemes. In ogg123 see the man page under '-d' for how to specify the output driver. Alternately, you can put the correct driver in/etc/libao.conf (or wherever that file lives in your compile): "default_driver=oss", sez mine.
So you may just have to find the correct "-d" switch for the `ogg123' command. Read the FM. (:
As for launching from Mozilla, well, I don't know what to tell you, except go through Edit / Preferences / Helper Applications / New... and fill in the fields "Ogg Vorbis audio", "ogg", "application/x-ogg", and "/usr/local/bin/ogg123 -d esd" or whatever. Good luck. Suggest making sure you can play a local ogg file using that command before adding it to Mozilla.
I always thought the standard for false was zero and true was non-zero. Is if different for those two?
As p3d0 said, shells behave the opposite. (Although there once was an odd bug in - what was it, Ultrix? - where csh behaved the opposite, i.e. didn't behave the opposite, i.e. was buggy, with regards to the && and || short-circuit operators. But then, csh history is replete with odd bugs.)
But to expand on the point: in Unix, the exit status of a program is an integer (7 unsigned bits, anyway: trying to use more is not portable). Convention dictates that 0 is normal termination, non-zero is abnormal, and anything over 128 means it was killed by a signal rather than the exit() function. (Which signal? Subtract 128 to find out.) Furthermore, many programs document their various abnormal exit status numbers to mean various failure cases.
Note that even MS-DOS (and all of its misshapen get) uses the zero / greater-than-zero convention. In DOS, a process's return value is called the "errorlevel", which indeed more accurately describes its main purpose.
This convention also goes a little deeper in Unix. Most system calls and many C library functions (remember, the standard C library was first defined on Unix) return 0 for success (or similar concepts: "equality" in the string compare function strcmp()) and non-zero for failure ("inequality" in strcmp()). Even system calls which return other meaningful integers (open(), for example) generally use >=0 for success and -1 for failure.
So it may make no sense from a boolean logic point of view but zero==true is surprisingly widespread. Mostly because there is often only one way to succeed at a task but many ways to fail, and it's useful to be able to report specific failure modes.
Last I heard, China was a communist country?!? Did that suddenly change?
No, not suddenly, but yes, it changed. China is largely a market economy these days.
According to a friend of mine who has been there, China still has some of the socialist mindset - within their capitalist companies. Apparently a lot of industrialists have built companies practically the size of city-states, which wholly own such things as day care, education, entertainment, etc., for the employees and their families. That is, socialism stepped down a notch from the government to the corporation. My friend has a lot of respect for this approach, due to one of his pet theories: the usefulness of socialism is inversely proportional to the implementation unit size. (I.e. socialism presents a lot of problems for a national government, but is pretty much required for a nuclear family.)
Now, as far as political freedoms, they are still well behind the curve.
[Says the guy who is neither a Chinaman nor an Asian-American....]
Maybe this is parseing code that should be added to lspci, maybe witha -m option it could list devices detected and modules
associated with that particular hardware. hmmm, I've been needing a project lately.
Hey, go ahead - sounds potentially useful. However, note that this work has been done already, at least three times:
the kernel autoconfig work by Giacomo Catenazzi (sp? - well, in any case he's "cate % debian ^ org", which I can spell), which did a hardware scan of your system in order to customise a kernel build, as far as possible, for the current hardware. This was adopted by ESR for his (in)famous CML2 work, but I don't know if it has been maintained since that died. I don't remember whether or not he figured out how to use the embedded PCI tables, since those haven't been compiled yet by the time autoconfig runs.
libdetect, the hardware detection library used (I think) in kudzu for red hat.
Greg Kroah-Hartman's hotplug package (look around on sf.net) does pretty much the same thing as well, for hot-pluggable hardware - which these days includes PCI and PCI-like (CardBus) devices on a number of platforms.
Before reinventing the wheel, you might look at the existing wheels. Not that I have done so, mind... I'm even too lazy to google for links for you. (:
Yes, it was the wrong word to use. However the response was used only to be nit-picky
No, the response seems to have been posted to take advantage of an opportunity to make a point on the story itself. (We are still talking about the actual story "Reuters Accused Of Hacking For Typing In URL", right?) I thought it was quite appropriate and only incidentally aimed at you personally.
So this card has a Zorro edge and a PCI edge. Someone needs to get a Pentium motherboard and an Amiga motherboard together, plug the card into both, and get some shots of two nekkid computers boffing - biethnic pr0n, as it were. (Ewwwww!)
I should point out that the instructions I posted should work for kernel 2.4 - but I do not remember what kernel 2.2 has in the way of USB mouse support, or indeed any USB support - I seem to remember USB was pretty skeletal back then, but I could be wrong.
The bits where I referred to kernel 2.5, I haven't tested - I can't boot 2.5 on this box, but I did read through some of the input layer code, in order to understand mouse protocols for another project. (Found a gpm bug in the process - gpm and the kernel disagree about a small detail in the imps2 and exps2 protocols..)
Timezone - yes. Or get it to look for an NTP server.
Uh - are you sure NTP provides a timezone? I thought it just provided the One True Time.
You forgot the bit about arranging hard disks, partitions, and boot sequence. Unless you are IBM or Microsoft and believe that nobody would ever try to install your product as the second OS on a machine. (Well, Microsoft thinks you might, but only if the first OS is also from Microsoft.)
You also forgot the bit about choosing your install source / mirror. Again, if you are IBM or Microsoft, you just punt and assume the machine has a CD-ROM drive and the user wants to use an installation CD - as opposed to the department file server, or the Internet at large, or a USB ZIP drive you are carting around for the purpose.
just mostly the idea that adding a USB mouse is such a hassle that the author of the walk through omitted it. Even if manual
configuration is necessary, it should not be that long to explain.
It's not hard. In fact, Debian's stock XFree86 config file already includes the necessary support (I think - I'm running sarge, not woody) - you shouldn't have to touch it. Just make sure your kernel supports it. This consists of loading three modules: usb-uhci (or other host USB adapter driver - depends on your hardware), mousedev (general kernel support for mice) and hid (for any USB "human interface device" including mice).
Restart X - or possibly not even that - and you should be good to go. (And yes, once mousedev is loaded, you should be able to unplug / replug your USB mouse without X even noticing.)
I have never managed to get the full combination of GPM, XFree86, and USB Mouse working together.
Don't bother with GPM repeater stuff. Just load the modules listed in the parent post, then tell your gpm conf that you have/dev/input/mice as a 'exps2' mouse, and tell XFree86 that you have/dev/input/mice as a 'ExplorerPS/2' mouse. The kernel will funnel your USB mice through/dev/input/mice and you will be happy.
In kernel 2.5, the input layer has been extended to deal with most other mice as well. Same instructions as noted above, except that you may have to load different modules (psmouse.o for PS/2, sermouse.o for serial, etc) - the original mouse type doesn't matter, the kernel should auto-detect most mice and emulate the same Intellimouse Explorer PS/2 protocol for any of them. Good stuff - Vojtech Pavlik worked hard to pull Linux up to the Windows 95 level of mouse p-n-p and deserves a little recognition.
I really like 160x64 consoles; there really isn't anything else that's exactly like it
I used to do 160x60. No more - now I do 144x72. (What a GeForce 3 was meant to do.) Spent a couple hours hand-tuning TextConfig to get that last hertz of vertical refresh, too. That and my Model M keyboard are the two reasons There's No Place Like Home, even with ssh and gnuclient.
I wish that whoever was maintaining the pci data base the lspci used would add a field for what module driver is used for that
hardware. Make for great hardware detection, atleast on the pci bus.
The equivalent facility already exists. Look on your machine,/lib/modules/kernel-version/modules.pcimap . It is generated from tables compiled into your modules, and it gives enough information to identify the driver(s), if any, that believe they can handle any given PCI device. Parsing this information is an exercise for the reader, or for the distribution installer.
If you want to see where this data comes from, look in the kernel source tree. include/linux/pci_ids.h defines symbolic names for most supported (and some unsupported) PCI vendors and devices, in C symbol format. (A similar list, but in human-readable description format, is in drivers/pci/pci.ids, which is basically a copy of/usr/share/misc/pci.ids, which is used by lspci.) Then, in your individual driver files, look for a table starting with a line similar to
which flags it so that depmod, the module dependency calculator, can find it and add its contents to the modules.pcimap file.
Duplicating all this in pci.ids would IMHO be inappropriate - that file is not in any way specific to Linux. Since the driver itself has to know what devices it supports anyway, this list logically belongs in the driver source.
That's the one. I wish I could remember what it did to the machine - it was very subtle
Weird. That's just a helper module used by several other network modules, for cards based on the 8390 or similar chips. I didn't think 8390.o by itself did anything until other modules were loaded.
BTW: for new x86 machines, getting the right network module is mostly a matter of trying (a) 3c59x (b) eepro100 (c) 8139too (d) tulip (e) 8139cp. If it's gigabit, try (a) e1000. The NIC market has really consolidated over the years, just like the CD-ROM interface market did.
In any case, PCI autodetect is a long-solved problem. Kernel modules have embedded tables saying which PCI devices they support - you just have to extract that info and compare it with your/proc/bus/pci/. (This table is comparable to the one in the OEMSETUP.INF that comes with Windows drivers.) That is probably the one major deficiency I see in the stock Debian installer. (As an end-user. I know developers find a lot of faults with it from a maintainability standpoint, which is why they are replacing it for sarge.)
Neither do all EULAs; they can, in fact, grant rights above and beyond fair use rights. It sounds like you're observing (please
correct me if I'm wrong) that the typical big, bad EULA functions differently, in practical terms, from the GPL.
I think you're getting hung up on a matter of definition. I (and many people here, probably including jmd!) define "EULA" as a license that claims to impose restrictions on use of your software which didn't already exist in copyright law. "For distribution only with a new computer..." tells you that, for some reason, Microsoft can arbitrarily waive the first sale doctrine on your behalf. If a shrink-wrap license does not attempt to impose any such restrictions, I and most people here would not call it an EULA. I suppose you could call any commercial software license an EULA, but that would dilute the term to the point of no longer being useful.
Such non-restrictive licenses are not very common in any case. After all, if the vendor didn't want to add any restrictions to the protections they already enjoy under copyright law, why would they bother writing a license at all? It's not like they have to spell out the fact that you're not allowed to redistribute additional copies of the work, or combine it with your own software and sell derived works.
As to the validity of EULAs, I think it's ridiculous that a software vendor should have the power to tell me what I can and can't do with a copy I have purchased. Imagine an EULA for books. "This is the `airport bookstore license' for [insert novel title]. By opening to the first page, you agree to be bound to the following agreement: You may read and re-read the Book on any airplane or in any airport lounge, so long as you do not read it aloud. You may lend the Book to any member of your travelling party, but you may not lend, give or sell the Book to anyone else. You may not publish reviews of the Book, and you may not disclose `benchmark' comments to anyone comparing the Book to any other book. (If you liked the Book and wish to say positive things about it, contact the Publisher for a `benchmark license', which will allow positive comments.) If you take the Book outside an airport, you must ensure that it remains shut until you re-enter an airport; this is to prevent unauthorised reading. If you want to bring a copy of the Book home to read, ask about the (more expensive) `home reading EULA'."
It's a big bluff. Software vendors probably know very well they have no right to tell us what we can and can't do with our software within the bounds of copyright law except by negotiating individual contracts with us, but they figure we will assume their shrink-wrap licenses are legally binding. And this has gone on long enough now that I doubt the courts will ever set them straight, for fear of unleashing chaos to the entire COTS software industry.
There is another trick to do with no run-time checks from the software: the eXecutable page bit in the page descriptor(I don't
remember - is there such a bit ? I think that it is).
Yes indeed, see this post for a (one-sided) discourse on this approach.
As you see, there is no problem with segments, as long as you have 1 code segment, 1 data segment and 1 stack segment which are
static.
OK, but...
static int foo_global;/* in DS */
static int *foo (int *bar)
{
foo_global += *bar;
return &foo_global;
}
int main (void)
{
int x = 3;/* in SS */
int *y = foo(&x);
}
How does your compiler tell the "foo" function whether the passed-in pointer "bar" is in DS or SS? In the above example, it is in SS. Same with the assignment of "y" in main() - is that DS or SS? In this case, DS.
The obvious answer is: don't have separate data and stack segments. But then how would you make the stack segment non-executable? You can't just make the DS non-executable - there's code out there that relies on being able to compile code and run it straight from DS. (JIT compilers for LISP etc. being the obvious example.) Come to think of it, JIT compilers would break if CS != DS as well - malloced space for a new JIT function would be in DS, but later the program would try to execute it. Sure, JIT-compilers are not 100% portable C - by their very nature they are non-portable - but you can't just shut them out.
as far as I know, each ring has its own version of the SP register, and the stack data are
implicitely stored in the segment defined by the SS selector.
OK, but we're talking ring 3 only - these overflows are happening in pure user code.
I don't know how the Linux kernel works, but this is a problem only if CS = SS. If such is the case, then a patch that makes SS a
different memory space would be sufficient to catch any stack problems.
Linux basically refuses to do segments - so segment registers are all equal (oh, except there's one - is it GS? - used for thread-local storage, but only since about 2-3 months ago). One big headache with separate segments for text, data and stack is C pointers, specifically void*. void*, you see, has to be a superset of all other pointers - code pointers or data pointers. So if you can't count on CS==DS, a void* must include the segment register, making it larger than 32 bits. Certain other pointers may need to include segment information, too - in fact, if SS != DS, or if either SS or DS were expected to be changed within the program, then just about all pointers would have to.
MS-DOS did this, although of course that was 16/20-bit real-mode 8086, not protected-mode 386. You could compile with about five different "memory models", which made different assumptions about segment layout. There were keywords FAR and NEAR to override the default for your memory model when declaring functions and globals, and woe to him who used them inconsistently. And if you used a precompiled library, its header files had better have the correct NEAR and FAR sprinkled throughout, in case it was compiled with a different memory model than what you are using.
...So are you seriously suggesting Linux adopt that sorry mess? No thanks. (: One segment to rule them all is just fine with me.
If there
was proper segmentation, there would be no such problem like attacks from buffer overflows, because it would be impossible at the
CPU level to execute code within data.
Totally flat mode was the best thing to happen to x86 processors since the built-in math coprocessor. (Oh, wait, protected mode came first, wasn't it? Oh well.) Segments are just too evil to program for.
If you really want to make C safe from buffer overflows, it is actually quite simple, conceptually: add runtime memory region checking. I used to think this impossible in C, but it's actually not that hard. All you have to do is turn every pointer into a (pointer,start,end) or (start,offset,maxoffset) tuple, and pass them around that way. Things like malloc() would be the only functions that dig in and change the (start,end) bits. Every time a pointer was passed to or from a function call, the boilerplate that builds the stack frame would perform bounds checking, as would all pointer arithmetic.
There's at least one gcc patch out there that does this, or something like it. A few problems with this approach: (a) that you are defining a new ABI, so you can't use any library code without recompiling it; (b) by making pointers longer than 32 bits, you lose a lot of space and speed efficiency; and (c) with 64- or 96-bit pointers, many programs will break because they assume a pointer will fit in, say, a 'long int'.
"Critical Kerberos Flaw Revealed" is not exactly an appropriate headline for a fscking buffer overflow. Getting a bit
sensational now, aren't we?
Hey, it worked - at least, it sure got me to read the blurb in a hurry. (While hyperventilating, but whatever.) Maybe they did it on purpose. At least the panic attack only lasted a couple sentences. If they'd made me actually read the article to find this out....
I cant comment on the presence or absense of stack instructions.
However, thats really a non-issue because no matter how the stack is implemented the stack still exists:)
Ah, ok - and thanks for the link. I was responding to your thought that it was a BIOS setting, which turns out not to be the case. If it were indeed a BIOS setting, it would have to depend on any SPARC OS reading this setting and making the change explicitly. Not likely, since it's easier to configure the OS in other ways (in this case, a variable in/etc/system if you run Solaris, or sorry-out-of-luck if you run Linux).
Because it is too hard to set up and roll out. It is great for large implementations, but for small stuff - secure access by a few people between a few servers - ssh and ssh tunneling are a heckuva lot easier and have basically eaten its lunch.
I wonder how much you could do before you got noticed, but even if you managed to copy over the encrypted password files, I'm sure
you could find some that fell to cracking software.
Just copy the Kerberos secrets database and you can grant yourself tickets to impersonate anyone you want. I am not a Kerberos admin, but I believe in general changing said secret is far from trivial, because every single service provider on the network must be updated.
(This is by design - the whole K architecture is designed around an ultimately trusted KDC which is known to the services via some sort of shared secret.)
I'm pretty sure sun/sparcs
can keep track of stack space as well if you supply some weird option in the bios. I would imagine other cpus are capable of this
as well.
If I'm not mistaken, the SPARC doesn't even have a stack. The stack is emulated entirely in software - "push X" becomes something like "store to address [reg1+reg2], then decrement reg2 by sizeof(X)" - where reg1 and reg2 are two registers handed down from on high by the ABI spec.
Matter of fact, as I recall, the PowerPC doesn't have a stack either. (I just skimmed certain sections of my Green Book (IBM, The PPC Arch) and didn't find anything, but then again IBM have really odd conventions for their mnemonics so I could easily have missed it.) Traditional RISC instruction sets [is that redundant?] tend to have such rich register indexing semantics that emulating a stack in software is trivial.
There is something else that I would like to know. Since a buffer overflow attack overwrites with data memory addresses filled with
instructions, why not designing an operative system that isolates the executable memory from the data memory?
This is theoretically a good idea - and in fact it has been done as a Linux patch, more than once. Google for "solar designer" linux non-executable stack. There are a couple of problems:
Some code needs to be able to write a stream of instructions that it will then jump to. This is called a "trampoline" and can accomplish tricks which are otherwise difficult to do within the confines of a compiled language. I think GCC emits trampolines for certain C++ constructs on certain architectures, but I seem to remember there was some noise made awhile back about migrating to other methods so as to work with non-exec stacks.
Just-in-time (JIT) compilers for languages such as LISP and Java have to be able to write executable code at runtime, though it's not really called a trampoline in that case.
It is possible to exploit a buffer overflow without actually executing code directly. Hard to explain, but the gist is that you overwrite bits of the stack which represent the function return address, so that the function "returns" to somewhere other than where it came from - say for example into the C library's system() function. Craft the rest of your overflow properly and you can dictate the arguments to said function - say system("/bin/sh").
I believe it has been demonstrated that any buffer overflow which can be exploited to execute code directly can also be exploited to execute code via the indirect method outlined above. At least on certain architectures. RTFG.
So, if Linus (for example) were to incorporate Solar Designer's non-exec stack patch into the Linux kernel, the exploit writers of the world would spend a week or so re-learning how to build buffer exploits to use nonexecutable means.
This is the main reason people oppose the non-executable stack patches. If widely used, we would in the long run be no better off than before. The added complexity in the Linux kernel would buy nothing. Naturally, those who have to battle kernel complexity generally oppose it. But - note that as long as only a few people use Solar's patch, they are better off, because the exploit writers do not focus on them. (Same reason there are more viruses for Windows than for MacOS 9, which had little significant virus resistance.)
Ahem. I also feel compelled to mention (since someone else will if I don't) that in combination with other techniques, such as relinking libraries with random load addresses on each machine, the non-exec stack patch may actually be effective. I am nowhere near enough of an expert to say for sure. (Jakub Jelinek's ELF prelinker sounds rather interesting in that context....) Also, architectures (like the HP PA-RISC) whose stacks grow upward instead of downward are probably resistant to most common buffer overflow techniques, but again I don't have the skillz to say whether such techniques could be adapted.
Are you claiming
that (a) the model in question is flawed,
I would be inclined to think so. If you consider certain fatal genetic diseases or mortality vectors as equivalent to homosexuality
(they both prevent the passing of genetic material to the next generation), a 1% less likelihood of passing offspring would not
weed out any specific gene.
Mutations happen all the time - "defective" genes can reappear in any generation. The occasional mutation can sustain low percentages of an undesirable trait. Consider the famous European royal family gene pool trait of haemophilia - I once read (yes, another specific cite from yours truly) that they traced down which queen was born with the mutation responsible. Might've been Elizabeth I of England, but it's been awhile. In any case, I believe the hypothetical "gay gene", going by the percentage of homosexuals in our population, has a much higher representation than can be explained by periodic mutations.
If my "feeling" about this is mistaken, feel free to trot out a specific genetic disorder that (a) would measurably affect reproductive rates (so pattern baldness probably doesn't count) and (b) has a prevalence anywhere near that of homosexuality (0.7% - 10%, depending on whom you ask).
No, I don't believe that homosexuals produce as much offspring as heterosexuals. But I am starting to question your critical
thinking skills.
You should have questioned them from the start. I am posting to a semi-off-topic thread on slashdot, and have been doing so for two days now, even though I have other things in life to occupy my time. Insofar as critical thinking requires common sense, mine is probably deficient.
For what it's worth, I'm questioning your critical thinking skills too. Just to be fair, y'know.
(The other choices: (c) there is at least one other factor at work, cf. the shaman theory, or (d) homosexuality does not have a
significant genetic factor after all.)
(c) is plausible, (d) is not as plausible, and you forget (e) you made a distinct error in either listening, understanding, or
representing what the biologist was trying to say.
You know, it doesn't matter all that much whether or not I faithfully conveyed the theory. Points (a) through (d) are still pretty much your only options. (Well, you can amend (a) to say "the model in question is flawed, or you didn't describe it correctly".) So really your (e) is not a separate option so much as a clarification of (a).
Awwwwrite, screw it, I'll just dig up the original email message. Keep in mind that this was written in April 1995, so the various details I got wrong just might have more to do with my crippled, atrophied rote recall skills than my crippled, atrophied critical thinking skills. And you'll have to take my word for it that my cut-n-paste skills are sufficiently advanced to produce a reasonably accurate facimile.
Apologies to Dr. S, the copyright holder, who probably doesn't mind, since he did post it semi-publicly.
[begin quote]
It's a bit of an overstatement to say there are "genes for
homosexuality," but it's a term of convenience. It's also an obvious
overstatement to say homosexuals do not reproduce. However, it's probably
fair to say they have fewer children than heterosexuals. Even if
homosexuals have 99 children for every 100 children that heterosexuals have
(probably a liberal estimate), computer/evolutionary modeling shows the
genes causing this slight reduction in reproductive rate would be
eliminated by natural selection fairly quickly -- not within recorded human
cultural history, but certainly within the time span of human biological
evolution since the oldest Australopithecus (ca. 3.6 million years).
Alright then, if we accept the premises (albeit simplistically stated) that
(1) there are "genes for homosexuality," (2) homosexuals reproduce less
than heterosexuals, and (3) natural selection eliminates genes that reduce
reproductive success, then why hasn't natural selection eliminated these
genes for homosexuality? -- A seeming paradox and problem for genetic
theories of homosexuality, but not so.
One hypothesis is simply that since homosexuals do have children (EVEN IF
fewer than others), this would still propagate the genes. But this isn't
very convincing in view of the aforementioned computer simulations of
evolution.
(Aside: it appears the Good Doctor disagrees with you. Perhaps his critical thinking skills are crippled and atrophied as well?)
Another is a little more complex. I'm just reflecting some common
speculation here; I'm not an anthropologist and I don't even play one in [email forum], so feel free to correct me where necessary. But picture this
scenario for one of our ancestors, Cro-Magnon (early Homo sapiens):
The Cro-Magnon people lived in little tribes of maybe 20-40 people. Their
culture was well enough developed that they could have had a shaman as many
tribes do today. This shaman could have a powerful influence on the
success and solidarity of the tribe. He was a religious leader, and we
know the unifying power of religious belief, even primitive animistic
beliefs. He was also a healer, both through his knowledge of nature (what
to eat, what to avoid, medicinal plants, natural enemies, sanitation, etc.)
and through the purely psychosomatic effects of people's belief in his
powers (like the ability of Voodoo to heal or kill). So a shaman has a
very important influence on the reproductive success of the tribe.
From what I have read, anthropologists today find the shamans of extant
tribes are often homosexual. Their homosexuality and disinterest in the
opposite sex may indeed predispose them to select, or be selected for, the
shamanistic role. Being free of paternal responsibilities, they are also
free to focus their lives on the knowledge and practices of shamanism.
Homosexuality may therefore be a device that enables the shaman to benefit
the tribe as a whole, and enhance overall tribal survival and fertility.
In a tribe of such size, most members of a given sex are relatives.
(Typically, one sex or the other must marry outside of the tribe -- in
ground squirrels and lions, for example, the adolescent males are forced to
leave, and the more stationary or "philopatric" group consists of closely
related females; in chimpanzees the females are forced to leave and the
males remain. This behavior evolved because it minimizes inbreeding.) So
who is the shaman benefitting? Let's say in human cultures it's usually
the men who remain in the territory of their birth and the women who
outbreed (marry into other tribes). In this case he is benefitting men who
are his brothers, cousins, nephews, and so forth.
If (again, simplistically speaking) there is a single gene (technically,
allele) "h" that "causes" homosexuality, there is a 50% chance that his
brother also carries "h," a 25% chance that his brother's son also carries
"h," a 12.5% (1/8) chance that a first cousin carries it, etc. The shaman
could be homozygous recessive (hh) and behaviorally homosexual, while his
relatives could be heterozygous (Hh) or homozygous dominant (HH) and
behaviorally heterosexual; but the Hh individuals are carriers of the
allele h. Homosexuality could continue to appear in a small percentage
(2-5%?) of their descendents who happen to get the genotype hh.
So if the shaman's role increases the chances that his brothers, nephews,
cousins, etc. have children, then he is indirectly contributing to the
propagation of this allele "h." A tribe with a weak shaman may perish
through disease, tribal warfare, loss of territory, etc. A tribe with a
strong shaman may be prosperous and fertile. A strong shaman could
actually get more of his genes perpetuated, through close relatives, than
an ordinary heterosexual male who, say, raises 2-3 offspring to maturity (a
liberal estimate for hunter-gatherer societies).
This is called "kin selection theory." It's a modification of traditional
Darwinian natural selection, and was developed since about 1962. It has
now been demonstrated in many animal species -- animals achieve
reproductive success not only through their own offspring, but through
their contributions to the reproduction of relatives. Even if the latter
is ALL an animal does, it can still get some of its genes propagated.
That's the hypothesis. Proving it would be pretty tough because we can't
do breeding experiments with people the way we can with animals. But at
least it's an idea consistent with biological and evolutionary knowledge
based on other species.
[end quote]
*Sigh*. I could have used the extra hour of sleep I skipped up in order to dig up and post that message... further proof that whatever my critical thinking skills, I really don't have much common sense. And, dangit, it took me long enough to come up with this post, so I'm gonna use that +1 bonus even though I'm offtopic. (:
I used to be similarly confused as to how genetic homosexuality could exist with natural selection, but the answer is quite
obvious. Answer: You don't have to lust over the act of procreation in order to procreate. Many homosexuals have the desire to have
offspring. Boffing the hetero is nothing more than a 30 minute task.
How do you make it last 30 minutes? (:
Seriously - to repeat my earlier post: the biologist I talked to claimed that even if homosexuals had 99% as many children as heterosexuals did, it would not be enough to save the 'gay gene', in the long run, according to computer models. Are you claiming that (a) the model in question is flawed, or (b) on average, homosexuals have (or had, historically) at least as many children as heterosexuals do? I find (b) more than a little hard to believe. Maybe "its" [sic] just my "crippled, atropied [sic] critical thinking skills".
(The other choices: (c) there is at least one other factor at work, cf. the shaman theory, or (d) homosexuality does not have a significant genetic factor after all.)
Its the our
crippled, atropied critical thinking skills, unable to perceive things outside of our cultural context, that prevents us from
making obvious conclusions.
Did anyone ever tell you intellectual snobbery is unattractive?
The sound situation is Linux ain't pretty at the moment, since there are about 4 or 5 competing standards none of which have won yet. Let me try and clear it up a little -
The sad thing is, whichever of the above your environment is using, it can't easily coexist with any of the others. So you have to know which you are using, and tell all your applications.
Now back to ogg vorbis. The `libao' - that is, "audio output library" - is an attempt to abstract away the actual sound output methods (the above, plus a few custom methods for other versions of Unix) into a single interface. So any libao-using application can use several if not all of the above schemes. In ogg123 see the man page under '-d' for how to specify the output driver. Alternately, you can put the correct driver in /etc/libao.conf (or wherever that file lives in your compile): "default_driver=oss", sez mine.
So you may just have to find the correct "-d" switch for the `ogg123' command. Read the FM. (:
As for launching from Mozilla, well, I don't know what to tell you, except go through Edit / Preferences / Helper Applications / New... and fill in the fields "Ogg Vorbis audio", "ogg", "application/x-ogg", and "/usr/local/bin/ogg123 -d esd" or whatever. Good luck. Suggest making sure you can play a local ogg file using that command before adding it to Mozilla.
As p3d0 said, shells behave the opposite. (Although there once was an odd bug in - what was it, Ultrix? - where csh behaved the opposite, i.e. didn't behave the opposite, i.e. was buggy, with regards to the && and || short-circuit operators. But then, csh history is replete with odd bugs.)
But to expand on the point: in Unix, the exit status of a program is an integer (7 unsigned bits, anyway: trying to use more is not portable). Convention dictates that 0 is normal termination, non-zero is abnormal, and anything over 128 means it was killed by a signal rather than the exit() function. (Which signal? Subtract 128 to find out.) Furthermore, many programs document their various abnormal exit status numbers to mean various failure cases.
Note that even MS-DOS (and all of its misshapen get) uses the zero / greater-than-zero convention. In DOS, a process's return value is called the "errorlevel", which indeed more accurately describes its main purpose.
This convention also goes a little deeper in Unix. Most system calls and many C library functions (remember, the standard C library was first defined on Unix) return 0 for success (or similar concepts: "equality" in the string compare function strcmp()) and non-zero for failure ("inequality" in strcmp()). Even system calls which return other meaningful integers (open(), for example) generally use >=0 for success and -1 for failure.
So it may make no sense from a boolean logic point of view but zero==true is surprisingly widespread. Mostly because there is often only one way to succeed at a task but many ways to fail, and it's useful to be able to report specific failure modes.
Dang it, I hate having to choose between two responses...
No, not suddenly, but yes, it changed. China is largely a market economy these days.
According to a friend of mine who has been there, China still has some of the socialist mindset - within their capitalist companies. Apparently a lot of industrialists have built companies practically the size of city-states, which wholly own such things as day care, education, entertainment, etc., for the employees and their families. That is, socialism stepped down a notch from the government to the corporation. My friend has a lot of respect for this approach, due to one of his pet theories: the usefulness of socialism is inversely proportional to the implementation unit size. (I.e. socialism presents a lot of problems for a national government, but is pretty much required for a nuclear family.)
Now, as far as political freedoms, they are still well behind the curve.
[Says the guy who is neither a Chinaman nor an Asian-American....]
Which individuals are being inconsistent? I want to join in on the public flogging.
Hey, go ahead - sounds potentially useful. However, note that this work has been done already, at least three times:
Before reinventing the wheel, you might look at the existing wheels. Not that I have done so, mind ... I'm even too lazy to google for links for you. (:
No, the response seems to have been posted to take advantage of an opportunity to make a point on the story itself. (We are still talking about the actual story "Reuters Accused Of Hacking For Typing In URL", right?) I thought it was quite appropriate and only incidentally aimed at you personally.
So this card has a Zorro edge and a PCI edge. Someone needs to get a Pentium motherboard and an Amiga motherboard together, plug the card into both, and get some shots of two nekkid computers boffing - biethnic pr0n, as it were. (Ewwwww!)
I should point out that the instructions I posted should work for kernel 2.4 - but I do not remember what kernel 2.2 has in the way of USB mouse support, or indeed any USB support - I seem to remember USB was pretty skeletal back then, but I could be wrong.
The bits where I referred to kernel 2.5, I haven't tested - I can't boot 2.5 on this box, but I did read through some of the input layer code, in order to understand mouse protocols for another project. (Found a gpm bug in the process - gpm and the kernel disagree about a small detail in the imps2 and exps2 protocols..)
Emailed, for lack of any <aol/>s. (:
Uh - are you sure NTP provides a timezone? I thought it just provided the One True Time.
You forgot the bit about arranging hard disks, partitions, and boot sequence. Unless you are IBM or Microsoft and believe that nobody would ever try to install your product as the second OS on a machine. (Well, Microsoft thinks you might, but only if the first OS is also from Microsoft.)
You also forgot the bit about choosing your install source / mirror. Again, if you are IBM or Microsoft, you just punt and assume the machine has a CD-ROM drive and the user wants to use an installation CD - as opposed to the department file server, or the Internet at large, or a USB ZIP drive you are carting around for the purpose.
It's not hard. In fact, Debian's stock XFree86 config file already includes the necessary support (I think - I'm running sarge, not woody) - you shouldn't have to touch it. Just make sure your kernel supports it. This consists of loading three modules: usb-uhci (or other host USB adapter driver - depends on your hardware), mousedev (general kernel support for mice) and hid (for any USB "human interface device" including mice).
Restart X - or possibly not even that - and you should be good to go. (And yes, once mousedev is loaded, you should be able to unplug / replug your USB mouse without X even noticing.)
Don't bother with GPM repeater stuff. Just load the modules listed in the parent post, then tell your gpm conf that you have /dev/input/mice as a 'exps2' mouse, and tell XFree86 that you have /dev/input/mice as a 'ExplorerPS/2' mouse. The kernel will funnel your USB mice through /dev/input/mice and you will be happy.
In kernel 2.5, the input layer has been extended to deal with most other mice as well. Same instructions as noted above, except that you may have to load different modules (psmouse.o for PS/2, sermouse.o for serial, etc) - the original mouse type doesn't matter, the kernel should auto-detect most mice and emulate the same Intellimouse Explorer PS/2 protocol for any of them. Good stuff - Vojtech Pavlik worked hard to pull Linux up to the Windows 95 level of mouse p-n-p and deserves a little recognition.
I used to do 160x60. No more - now I do 144x72. (What a GeForce 3 was meant to do.) Spent a couple hours hand-tuning TextConfig to get that last hertz of vertical refresh, too. That and my Model M keyboard are the two reasons There's No Place Like Home, even with ssh and gnuclient.
The equivalent facility already exists. Look on your machine, /lib/modules/kernel-version/modules.pcimap . It is generated from tables compiled into your modules, and it gives enough information to identify the driver(s), if any, that believe they can handle any given PCI device. Parsing this information is an exercise for the reader, or for the distribution installer.
If you want to see where this data comes from, look in the kernel source tree. include/linux/pci_ids.h defines symbolic names for most supported (and some unsupported) PCI vendors and devices, in C symbol format. (A similar list, but in human-readable description format, is in drivers/pci/pci.ids, which is basically a copy of /usr/share/misc/pci.ids, which is used by lspci.) Then, in your individual driver files, look for a table starting with a line similar to
This table should be followed by a declaration which flags it so that depmod, the module dependency calculator, can find it and add its contents to the modules.pcimap file.Duplicating all this in pci.ids would IMHO be inappropriate - that file is not in any way specific to Linux. Since the driver itself has to know what devices it supports anyway, this list logically belongs in the driver source.
Weird. That's just a helper module used by several other network modules, for cards based on the 8390 or similar chips. I didn't think 8390.o by itself did anything until other modules were loaded.
BTW: for new x86 machines, getting the right network module is mostly a matter of trying (a) 3c59x (b) eepro100 (c) 8139too (d) tulip (e) 8139cp. If it's gigabit, try (a) e1000. The NIC market has really consolidated over the years, just like the CD-ROM interface market did.
In any case, PCI autodetect is a long-solved problem. Kernel modules have embedded tables saying which PCI devices they support - you just have to extract that info and compare it with your /proc/bus/pci/. (This table is comparable to the one in the OEMSETUP.INF that comes with Windows drivers.) That is probably the one major deficiency I see in the stock Debian installer. (As an end-user. I know developers find a lot of faults with it from a maintainability standpoint, which is why they are replacing it for sarge.)
I think you're getting hung up on a matter of definition. I (and many people here, probably including jmd!) define "EULA" as a license that claims to impose restrictions on use of your software which didn't already exist in copyright law. "For distribution only with a new computer..." tells you that, for some reason, Microsoft can arbitrarily waive the first sale doctrine on your behalf. If a shrink-wrap license does not attempt to impose any such restrictions, I and most people here would not call it an EULA. I suppose you could call any commercial software license an EULA, but that would dilute the term to the point of no longer being useful.
Such non-restrictive licenses are not very common in any case. After all, if the vendor didn't want to add any restrictions to the protections they already enjoy under copyright law, why would they bother writing a license at all? It's not like they have to spell out the fact that you're not allowed to redistribute additional copies of the work, or combine it with your own software and sell derived works.
As to the validity of EULAs, I think it's ridiculous that a software vendor should have the power to tell me what I can and can't do with a copy I have purchased. Imagine an EULA for books. "This is the `airport bookstore license' for [insert novel title]. By opening to the first page, you agree to be bound to the following agreement: You may read and re-read the Book on any airplane or in any airport lounge, so long as you do not read it aloud. You may lend the Book to any member of your travelling party, but you may not lend, give or sell the Book to anyone else. You may not publish reviews of the Book, and you may not disclose `benchmark' comments to anyone comparing the Book to any other book. (If you liked the Book and wish to say positive things about it, contact the Publisher for a `benchmark license', which will allow positive comments.) If you take the Book outside an airport, you must ensure that it remains shut until you re-enter an airport; this is to prevent unauthorised reading. If you want to bring a copy of the Book home to read, ask about the (more expensive) `home reading EULA'."
It's a big bluff. Software vendors probably know very well they have no right to tell us what we can and can't do with our software within the bounds of copyright law except by negotiating individual contracts with us, but they figure we will assume their shrink-wrap licenses are legally binding. And this has gone on long enough now that I doubt the courts will ever set them straight, for fear of unleashing chaos to the entire COTS software industry.
Yes indeed, see this post for a (one-sided) discourse on this approach.
OK, but...
static int foo_global; /* in DS */
/* in SS */
static int *foo (int *bar)
{
foo_global += *bar;
return &foo_global;
}
int main (void)
{
int x = 3;
int *y = foo(&x);
}
How does your compiler tell the "foo" function whether the passed-in pointer "bar" is in DS or SS? In the above example, it is in SS. Same with the assignment of "y" in main() - is that DS or SS? In this case, DS.
The obvious answer is: don't have separate data and stack segments. But then how would you make the stack segment non-executable? You can't just make the DS non-executable - there's code out there that relies on being able to compile code and run it straight from DS. (JIT compilers for LISP etc. being the obvious example.) Come to think of it, JIT compilers would break if CS != DS as well - malloced space for a new JIT function would be in DS, but later the program would try to execute it. Sure, JIT-compilers are not 100% portable C - by their very nature they are non-portable - but you can't just shut them out.
OK, but we're talking ring 3 only - these overflows are happening in pure user code.
Linux basically refuses to do segments - so segment registers are all equal (oh, except there's one - is it GS? - used for thread-local storage, but only since about 2-3 months ago). One big headache with separate segments for text, data and stack is C pointers, specifically void*. void*, you see, has to be a superset of all other pointers - code pointers or data pointers. So if you can't count on CS==DS, a void* must include the segment register, making it larger than 32 bits. Certain other pointers may need to include segment information, too - in fact, if SS != DS, or if either SS or DS were expected to be changed within the program, then just about all pointers would have to.
MS-DOS did this, although of course that was 16/20-bit real-mode 8086, not protected-mode 386. You could compile with about five different "memory models", which made different assumptions about segment layout. There were keywords FAR and NEAR to override the default for your memory model when declaring functions and globals, and woe to him who used them inconsistently. And if you used a precompiled library, its header files had better have the correct NEAR and FAR sprinkled throughout, in case it was compiled with a different memory model than what you are using.
...So are you seriously suggesting Linux adopt that sorry mess? No thanks. (: One segment to rule them all is just fine with me.
Totally flat mode was the best thing to happen to x86 processors since the built-in math coprocessor. (Oh, wait, protected mode came first, wasn't it? Oh well.) Segments are just too evil to program for.
If you really want to make C safe from buffer overflows, it is actually quite simple, conceptually: add runtime memory region checking. I used to think this impossible in C, but it's actually not that hard. All you have to do is turn every pointer into a (pointer,start,end) or (start,offset,maxoffset) tuple, and pass them around that way. Things like malloc() would be the only functions that dig in and change the (start,end) bits. Every time a pointer was passed to or from a function call, the boilerplate that builds the stack frame would perform bounds checking, as would all pointer arithmetic.
There's at least one gcc patch out there that does this, or something like it. A few problems with this approach: (a) that you are defining a new ABI, so you can't use any library code without recompiling it; (b) by making pointers longer than 32 bits, you lose a lot of space and speed efficiency; and (c) with 64- or 96-bit pointers, many programs will break because they assume a pointer will fit in, say, a 'long int'.
Hey, it worked - at least, it sure got me to read the blurb in a hurry. (While hyperventilating, but whatever.) Maybe they did it on purpose. At least the panic attack only lasted a couple sentences. If they'd made me actually read the article to find this out....
Ah, ok - and thanks for the link. I was responding to your thought that it was a BIOS setting, which turns out not to be the case. If it were indeed a BIOS setting, it would have to depend on any SPARC OS reading this setting and making the change explicitly. Not likely, since it's easier to configure the OS in other ways (in this case, a variable in /etc/system if you run Solaris, or sorry-out-of-luck if you run Linux).
(You shouldn't have been modded down, btw.)
Because it is too hard to set up and roll out. It is great for large implementations, but for small stuff - secure access by a few people between a few servers - ssh and ssh tunneling are a heckuva lot easier and have basically eaten its lunch.
Just copy the Kerberos secrets database and you can grant yourself tickets to impersonate anyone you want. I am not a Kerberos admin, but I believe in general changing said secret is far from trivial, because every single service provider on the network must be updated.
(This is by design - the whole K architecture is designed around an ultimately trusted KDC which is known to the services via some sort of shared secret.)
If I'm not mistaken, the SPARC doesn't even have a stack. The stack is emulated entirely in software - "push X" becomes something like "store to address [reg1+reg2], then decrement reg2 by sizeof(X)" - where reg1 and reg2 are two registers handed down from on high by the ABI spec.
Matter of fact, as I recall, the PowerPC doesn't have a stack either. (I just skimmed certain sections of my Green Book (IBM, The PPC Arch) and didn't find anything, but then again IBM have really odd conventions for their mnemonics so I could easily have missed it.) Traditional RISC instruction sets [is that redundant?] tend to have such rich register indexing semantics that emulating a stack in software is trivial.
This is theoretically a good idea - and in fact it has been done as a Linux patch, more than once. Google for "solar designer" linux non-executable stack. There are a couple of problems:
Some code needs to be able to write a stream of instructions that it will then jump to. This is called a "trampoline" and can accomplish tricks which are otherwise difficult to do within the confines of a compiled language. I think GCC emits trampolines for certain C++ constructs on certain architectures, but I seem to remember there was some noise made awhile back about migrating to other methods so as to work with non-exec stacks.
Just-in-time (JIT) compilers for languages such as LISP and Java have to be able to write executable code at runtime, though it's not really called a trampoline in that case.
It is possible to exploit a buffer overflow without actually executing code directly. Hard to explain, but the gist is that you overwrite bits of the stack which represent the function return address, so that the function "returns" to somewhere other than where it came from - say for example into the C library's system() function. Craft the rest of your overflow properly and you can dictate the arguments to said function - say system("/bin/sh").
I believe it has been demonstrated that any buffer overflow which can be exploited to execute code directly can also be exploited to execute code via the indirect method outlined above. At least on certain architectures. RTFG.
So, if Linus (for example) were to incorporate Solar Designer's non-exec stack patch into the Linux kernel, the exploit writers of the world would spend a week or so re-learning how to build buffer exploits to use nonexecutable means.
This is the main reason people oppose the non-executable stack patches. If widely used, we would in the long run be no better off than before. The added complexity in the Linux kernel would buy nothing. Naturally, those who have to battle kernel complexity generally oppose it. But - note that as long as only a few people use Solar's patch, they are better off, because the exploit writers do not focus on them. (Same reason there are more viruses for Windows than for MacOS 9, which had little significant virus resistance.)
Ahem. I also feel compelled to mention (since someone else will if I don't) that in combination with other techniques, such as relinking libraries with random load addresses on each machine, the non-exec stack patch may actually be effective. I am nowhere near enough of an expert to say for sure. (Jakub Jelinek's ELF prelinker sounds rather interesting in that context....) Also, architectures (like the HP PA-RISC) whose stacks grow upward instead of downward are probably resistant to most common buffer overflow techniques, but again I don't have the skillz to say whether such techniques could be adapted.
Mutations happen all the time - "defective" genes can reappear in any generation. The occasional mutation can sustain low percentages of an undesirable trait. Consider the famous European royal family gene pool trait of haemophilia - I once read (yes, another specific cite from yours truly) that they traced down which queen was born with the mutation responsible. Might've been Elizabeth I of England, but it's been awhile. In any case, I believe the hypothetical "gay gene", going by the percentage of homosexuals in our population, has a much higher representation than can be explained by periodic mutations.
If my "feeling" about this is mistaken, feel free to trot out a specific genetic disorder that (a) would measurably affect reproductive rates (so pattern baldness probably doesn't count) and (b) has a prevalence anywhere near that of homosexuality (0.7% - 10%, depending on whom you ask).
You should have questioned them from the start. I am posting to a semi-off-topic thread on slashdot, and have been doing so for two days now, even though I have other things in life to occupy my time. Insofar as critical thinking requires common sense, mine is probably deficient.
For what it's worth, I'm questioning your critical thinking skills too. Just to be fair, y'know.
You know, it doesn't matter all that much whether or not I faithfully conveyed the theory. Points (a) through (d) are still pretty much your only options. (Well, you can amend (a) to say "the model in question is flawed, or you didn't describe it correctly".) So really your (e) is not a separate option so much as a clarification of (a).
Awwwwrite, screw it, I'll just dig up the original email message. Keep in mind that this was written in April 1995, so the various details I got wrong just might have more to do with my crippled, atrophied rote recall skills than my crippled, atrophied critical thinking skills. And you'll have to take my word for it that my cut-n-paste skills are sufficiently advanced to produce a reasonably accurate facimile.
Apologies to Dr. S, the copyright holder, who probably doesn't mind, since he did post it semi-publicly.
[begin quote]
(Aside: it appears the Good Doctor disagrees with you. Perhaps his critical thinking skills are crippled and atrophied as well?)
[end quote]
*Sigh*. I could have used the extra hour of sleep I skipped up in order to dig up and post that message ... further proof that whatever my critical thinking skills, I really don't have much common sense. And, dangit, it took me long enough to come up with this post, so I'm gonna use that +1 bonus even though I'm offtopic. (:
How do you make it last 30 minutes? (:
Seriously - to repeat my earlier post: the biologist I talked to claimed that even if homosexuals had 99% as many children as heterosexuals did, it would not be enough to save the 'gay gene', in the long run, according to computer models. Are you claiming that (a) the model in question is flawed, or (b) on average, homosexuals have (or had, historically) at least as many children as heterosexuals do? I find (b) more than a little hard to believe. Maybe "its" [sic] just my "crippled, atropied [sic] critical thinking skills".
(The other choices: (c) there is at least one other factor at work, cf. the shaman theory, or (d) homosexuality does not have a significant genetic factor after all.)
Did anyone ever tell you intellectual snobbery is unattractive?