Gary Winiger wrote: > > I think the Sun guys didn't think when they implemented this. I actually > > asked the Sun guys about it when I was writing this part of libpam_misc > > (5 years ago?) and they never gave any response. The first I heard that > > they had implemented it wrongly was actually about a year ago, when a > > commercial module developer emailed me to say that they'd run into this > > problem with their module and had opted to support both meanings of > > 'pam_message **' in what they passed to the conversation function. > > Slightly sick, but quite doable. > > I'm probably being dense, I read the documentation as: > > "int conv(int num_msg, const struct pam_message **msg, > struct pam_response **resp, void *appdata_ptr); > > > The num_msg parameter is the number of messages associated with the > call. The parameter msg is a pointer to an array of length num_msg of > the pam_message structure." > > Not an array of pam_message structure pointers. > > The code implements it as: > msg = (struct pam_message *)calloc(num_msg, > sizeof (struct pam_message)); > retcode = (pam_convp->conv)(num_msg, &msg, ret_respp, > conv_apdp); > > That seems the same to me as const struct pam_message *msg[]. Though No, (..., const struct pam_message *msg[], ...) implies [like the main(..., argv) case] that you are passing an array of pointers. In point of fact, K&Rv2 is quite careful to use the following prototype for their main(...) functions: main(int argc, char *argv[]) which, given the current topic, is less ambiguous than main(int argc, char **argv). Common usage of the latter (which I believe was what K&R used in their first C book - but that's my memory as opposed to actually based on having the book in front of me - refers to the same data structure). > I agree *msg[] might be clearer. I believe whomever did the prototype > at X/Open followed the main(int argc, char **argv, char **envp) > prototype that was popular at one time. IMO, the X/Open spec has a > number of typos that should be corrected some day. This could be one > of them. The prototype is also present in the original RFC from SunSoft. There is a cached copy of that here: http://www.kernel.org/pub/linux/libs/pam/pre/doc/rfc86.0.txt.gz Now that I read it again, its actually curious that the example login_conv() function that this document contains doesn't work as written(! No definition of 'm'), but its spirit seems a great deal more in line with the Linux implementation than the Solaris one. If the prototype had been written differently then it could have been: int conv(int num_msg, const struct pam_message *msg, struct pam_response **resp, void *appdata_ptr); which is not ambiguous, and quite sufficient for the way the conversation function is used. Unfortunately, we've all implemented an interpretation of **msg - which is incompatible with this more clear definition. History and backward compatibility - its a real pain. Cheers Andrew