Matthias Scheler wrote:
> Oliver Fromme wrote:
> > [...]
> > > A usual problem with Solaris boxen is the stream limit at 256 for 32 bit
> > > applications. Is milter-greylist built as a 32 bit binary?
> >
> > You don't need to make a 64bit binary in order to
> > get around that limit. On recent Solaris versions
> > you can increase the current limit using ulimit on
> > the command line, or setrlimit() from within a
> > program (which is recommended if a program needs
> > that many).
>
> The problem is or at least was that "milter-greylist" want to use fdopen()
> to write the database file. And Solaris' standard I/O implementation only
> supports file descriptors < 256 for 32 bit programs.
That's true. I didn't realize that it was using stdio
functions (I only thought of the network sockets).
Well, there are three solutions:
- Do not use stdio functions (i.e. no functions that use
FILE*), but instead use open(2), write(2) etc. However,
that might be inconvenient and/or inefficient, depending
on the kind of use.
- Use SFIO from AT&T, which is a replacement for stdio and
does not have a restriction on the number of streams:
http://www.research.att.com/~gsf/download/ref/sfio/sfio.html
However, requiring such a third-party library for milter-
greylist is probably awkward, and I'm not sure about the
licensing issues.
- Best solution: Reserve a low-numbered file descriptor
at the start of the program. For example, you can call
low_fd = open("/dev/null", O_RDWR);
right at the start of the program, so it will probably
get FD 3 (because only FD 0, 1, and 2 are used for stdin,
stdout and stderr). After daemonifocation you might
even get FD 0, because stdin/out/err are usually closed
when you become a daemon.
Then just keep that FD ("low_fd" in the example above)
around for later use. Then, if you need a FILE* with
a low numbered FD (so you can use stdio functions), do
this:
+ Open the file normally with open(2). That will
give you a high-numbered FD:
high_fd = open("greylist.db", O_RDWR);
Of course, you can also use mkstemp() which calls
open() internally and returns such an FD as well:
high_fd = mkstemp("greylist.db.XXXXXX");
+ Use dup2() to duplicate the descriptor to the low-
numbered FD that you reserved at the beginning:
error = dup2(high_fd, low_fd)
If low_fd is still open, it is closed first, then
it is associated with the same file as high_fd.
You can close high_fd now; it's not needed anymore
so you can free the FD:
close(high_fd);
Now you can use fdopen() to retrieve a FILE*
pointer for low_fd, and use stdio functions with
that FILE* normally:
myfile = fdopen(low_fd, "r+");
+ When you're done with the file, do _not_ close()
or fclose() low_fd! That would free the descriptor,
so it might get re-used by somethign else (e.g. for
a network socket), so you lose your low-numbered FD.
Instead, fflush() the FILE*, then open /dev/null
again and dup2 it back to your low_fd, so the file
is closed but you still have the FD:
error = fflush(myfile);
high_fd = open("/dev/null", O_RDWR);
error = dup2(high_fd, low_fd); /* close db file */
No, I'm not going to submit a patch. I guess it's easy
enough for somebody else, given the above explanations.
:-)
Best regards
Oliver
--
Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606, Gesch\ufffdftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht M\ufffdn-
chen, HRB 125758, Gesch\ufffdftsf\ufffdhrer: Maik Bachmann, Olaf Erb, Ralf Gebhart
FreeBSD-Dienstleistungen, -Produkte und mehr: http://www.secnetix.de/bsd
"The scanf() function is a large and complex beast that often does
something almost but not quite entirely unlike what you desired."
-- Chris Torek