* It seems like lager_syslog must require that either: 1) syslog:start/0 or syslog:start_link/0 was called 2) syslog_drv.so is in the PATH environment variable for erlang:open_port/2 to find as a port driver Both of these options have nothing to do currently with starting syslog as an application. This all seems odd, so I just added a load/0 function and an unload/0 function to make it easier to use the port driver without relying on an extra Erlang process that sits idle or the PATH environment variable's extra entry.
With R16B changes related to locking within the area of port drivers seemed to result in the syslog driver hanging on the driver_create_port call. To avoid this, move port creation and closing from C into Erlang. Rework the driver control interface to simplify the open call to just the setting of the logopt and facility on a new port. Remove the opening and closing of a port in the gen_server init and terminate as that port is no longer needed to communicate with the driver. Move the open call out of the gen_server and do it in the caller's process instead.
Use port_control and port_call instead of just port_command to communicate with the port driver. The port_control and port_call functions include a command integer argument that makes it easy to send specific commands to the driver, rather than encoding the commands as atoms in external format. They also allow for the easy return of simple terms in their preallocated return buffers. They also allow simple constants to be returned from the driver for badarg and other general errors. The log function still uses port_command, but sends an iolist for priority and message data rather than encoding to external format. Change open to return a new port, and change the log functions to take the log port returned from open as its first argument. Add a new variant of the log function that takes a format string and a list of format arguments. Drop the timeout argument to log, since it no longer is meaningful. Add a close/1 function to close the log. Modify the determination of the path to the driver shared library, making it match idiomatic code used for NIFs and drivers in other components. Add checking of the return values from the ei encoding and decoding functions in the driver code. Use driver_alloc and driver_free in the driver code rather than malloc and free. Also add checks for memory allocation failures. Use static initialization for the ErlDrvEntry struct. Remove the creation of driver atom constants that were no longer used. Add a test to verify that logging on a log that's already been closed returns an error.