Author: baggins Date: Fri Oct 26 11:33:38 2007 GMT Module: SOURCES Tag: HEAD ---- Log message: - don't mess with syslog (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=434372)
---- Files affected: SOURCES: samba-pam_smbpass-syslog.patch (NONE -> 1.1) (NEW) ---- Diffs: ================================================================ Index: SOURCES/samba-pam_smbpass-syslog.patch diff -u /dev/null SOURCES/samba-pam_smbpass-syslog.patch:1.1 --- /dev/null Fri Oct 26 13:33:38 2007 +++ SOURCES/samba-pam_smbpass-syslog.patch Fri Oct 26 13:33:33 2007 @@ -0,0 +1,584 @@ +Goal: Don't call openlog() or closelog() from pam_smbpass + +Fixes: bug #434372 (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=434372) + +Upstream status: submitted as bugzilla bug #4831 + +Index: samba-3.0.25c/source/pam_smbpass/support.c +=================================================================== +--- samba-3.0.25c.orig/source/pam_smbpass/support.c 2007-08-26 12:07:14.098417404 +0200 ++++ samba-3.0.25c/source/pam_smbpass/support.c 2007-08-26 13:09:09.419359938 +0200 +@@ -15,6 +15,7 @@ + * Mass Ave, Cambridge, MA 02139, USA. + */ + ++ #include "config.h" + #include "includes.h" + #include "general.h" + +@@ -66,19 +67,44 @@ + + char *servicesf = dyn_CONFIGFILE; + +- /* syslogging function for errors and other information */ +- +- void _log_err( int err, const char *format, ... ) +- { +- va_list args; ++/* syslogging function for errors and other information */ ++#ifdef HAVE_PAM_VSYSLOG ++void _log_err( pam_handle_t *pamh, int err, const char *format, ... ) ++{ ++ va_list args; + +- va_start( args, format ); +- openlog( "PAM_smbpass", LOG_CONS | LOG_PID, LOG_AUTH ); +- vsyslog( err, format, args ); +- va_end( args ); +- closelog(); ++ va_start(args, format); ++ pam_vsyslog(pamh, err, format, args); ++ va_end(args); ++} ++#else ++void _log_err( pam_handle_t *pamh, int err, const char *format, ... ) ++{ ++ va_list args; ++ const char tag[] = "(pam_smbpass) "; ++ char *mod_format; ++ ++ mod_format = SMB_MALLOC_ARRAY(char, sizeof(tag) + strlen(format)); ++ /* try really, really hard to log something, since this may have ++ been a message about a malloc() failure... */ ++ if (mod_format == NULL) { ++ va_start(args, format); ++ vsyslog(err | LOG_AUTH, format, args); ++ va_end(args); ++ return; + } + ++ strncpy(mod_format, tag, strlen(tag)+1); ++ strncat(mod_format, format, strlen(format)); ++ ++ va_start(args, format); ++ vsyslog(err | LOG_AUTH, mod_format, args); ++ va_end(args); ++ ++ free(mod_format); ++} ++#endif ++ + /* this is a front-end for module-application conversations */ + + int converse( pam_handle_t * pamh, int ctrl, int nargs +@@ -95,12 +121,14 @@ + ,response, conv->appdata_ptr); + + if (retval != PAM_SUCCESS && on(SMB_DEBUG, ctrl)) { +- _log_err(LOG_DEBUG, "conversation failure [%s]" +- ,pam_strerror(pamh, retval)); ++ _log_err(pamh, LOG_DEBUG, ++ "conversation failure [%s]", ++ pam_strerror(pamh, retval)); + } + } else { +- _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" +- ,pam_strerror(pamh, retval)); ++ _log_err(pamh, LOG_ERR, ++ "couldn't obtain coversation function [%s]", ++ pam_strerror(pamh, retval)); + } + + return retval; /* propagate error status */ +@@ -126,7 +154,7 @@ + + /* set the control flags for the SMB module. */ + +-int set_ctrl( int flags, int argc, const char **argv ) ++int set_ctrl( pam_handle_t *pamh, int flags, int argc, const char **argv ) + { + int i = 0; + const char *service_file = dyn_CONFIGFILE; +@@ -168,7 +196,7 @@ + /* Read some options from the Samba config. Can be overridden by + the PAM config. */ + if(lp_load(service_file,True,False,False,True) == False) { +- _log_err( LOG_ERR, "Error loading service file %s", service_file ); ++ _log_err(pamh, LOG_ERR, "Error loading service file %s", service_file); + } + + secrets_init(); +@@ -191,7 +219,7 @@ + } + + if (j >= SMB_CTRLS_) { +- _log_err( LOG_ERR, "unrecognized option [%s]", *argv ); ++ _log_err(pamh, LOG_ERR, "unrecognized option [%s]", *argv); + } else { + ctrl &= smb_args[j].mask; /* for turning things off */ + ctrl |= smb_args[j].flag; /* for turning things on */ +@@ -230,7 +258,7 @@ + * evidence of old token around for later stack analysis. + * + */ +-char * smbpXstrDup( const char *x ) ++char * smbpXstrDup( pam_handle_t *pamh, const char *x ) + { + register char *newstr = NULL; + +@@ -240,7 +268,7 @@ + for (i = 0; x[i]; ++i); /* length of string */ + if ((newstr = SMB_MALLOC_ARRAY(char, ++i)) == NULL) { + i = 0; +- _log_err( LOG_CRIT, "out of memory in smbpXstrDup" ); ++ _log_err(pamh, LOG_CRIT, "out of memory in smbpXstrDup"); + } else { + while (i-- > 0) { + newstr[i] = x[i]; +@@ -282,7 +310,7 @@ + /* log the number of authentication failures */ + if (failure->count != 0) { + pam_get_item( pamh, PAM_SERVICE, (const void **) &service ); +- _log_err( LOG_NOTICE ++ _log_err(pamh, LOG_NOTICE + , "%d authentication %s " + "from %s for service %s as %s(%d)" + , failure->count +@@ -291,7 +319,7 @@ + , service == NULL ? "**unknown**" : service + , failure->user, failure->id ); + if (failure->count > SMB_MAX_RETRIES) { +- _log_err( LOG_ALERT ++ _log_err(pamh, LOG_ALERT + , "service(%s) ignoring max retries; %d > %d" + , service == NULL ? "**unknown**" : service + , failure->count +@@ -327,8 +355,7 @@ + + if (!pdb_get_lanman_passwd(sampass)) + { +- _log_err( LOG_DEBUG, "user %s has null SMB password" +- , name ); ++ _log_err(pamh, LOG_DEBUG, "user %s has null SMB password", name); + + if (off( SMB__NONULL, ctrl ) + && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) +@@ -338,15 +365,16 @@ + const char *service; + + pam_get_item( pamh, PAM_SERVICE, (const void **)&service ); +- _log_err( LOG_NOTICE, "failed auth request by %s for service %s as %s", +- uidtoname(getuid()), service ? service : "**unknown**", name); ++ _log_err(pamh, LOG_NOTICE, ++ "failed auth request by %s for service %s as %s", ++ uidtoname(getuid()), service ? service : "**unknown**", name); + return PAM_AUTH_ERR; + } + } + + data_name = SMB_MALLOC_ARRAY(char, sizeof(FAIL_PREFIX) + strlen( name )); + if (data_name == NULL) { +- _log_err( LOG_CRIT, "no memory for data-name" ); ++ _log_err(pamh, LOG_CRIT, "no memory for data-name"); + } + strncpy( data_name, FAIL_PREFIX, sizeof(FAIL_PREFIX) ); + strncpy( data_name + sizeof(FAIL_PREFIX) - 1, name, strlen( name ) + 1 ); +@@ -392,31 +420,31 @@ + retval = PAM_MAXTRIES; + } + } else { +- _log_err(LOG_NOTICE, ++ _log_err(pamh, LOG_NOTICE, + "failed auth request by %s for service %s as %s", + uidtoname(getuid()), + service ? service : "**unknown**", name); + newauth->count = 1; + } + if (!sid_to_uid(pdb_get_user_sid(sampass), &(newauth->id))) { +- _log_err(LOG_NOTICE, ++ _log_err(pamh, LOG_NOTICE, + "failed auth request by %s for service %s as %s", + uidtoname(getuid()), + service ? service : "**unknown**", name); + } +- newauth->user = smbpXstrDup( name ); +- newauth->agent = smbpXstrDup( uidtoname( getuid() ) ); ++ newauth->user = smbpXstrDup(pamh, name); ++ newauth->agent = smbpXstrDup(pamh, uidtoname( getuid() )); + pam_set_data( pamh, data_name, newauth, _cleanup_failures ); + + } else { +- _log_err( LOG_CRIT, "no memory for failure recorder" ); +- _log_err(LOG_NOTICE, ++ _log_err(pamh, LOG_CRIT, "no memory for failure recorder"); ++ _log_err(pamh, LOG_NOTICE, + "failed auth request by %s for service %s as %s(%d)", + uidtoname(getuid()), + service ? service : "**unknown**", name); + } + } else { +- _log_err(LOG_NOTICE, ++ _log_err(pamh, LOG_NOTICE, + "failed auth request by %s for service %s as %s(%d)", + uidtoname(getuid()), + service ? service : "**unknown**", name); +@@ -490,8 +518,8 @@ + retval = pam_get_item( pamh, authtok_flag, (const void **) &item ); + if (retval != PAM_SUCCESS) { + /* very strange. */ +- _log_err( LOG_ALERT +- , "pam_get_item returned error to smb_read_password" ); ++ _log_err(pamh, LOG_ALERT, ++ "pam_get_item returned error to smb_read_password"); + return retval; + } else if (item != NULL) { /* we have a password! */ + *pass = item; +@@ -543,7 +571,7 @@ + + if (retval == PAM_SUCCESS) { /* a good conversation */ + +- token = smbpXstrDup(resp[j++].resp); ++ token = smbpXstrDup(pamh, resp[j++].resp); + if (token != NULL) { + if (expect == 2) { + /* verify that password entered correctly */ +@@ -555,7 +583,8 @@ + } + } + } else { +- _log_err(LOG_NOTICE, "could not recover authentication token"); ++ _log_err(pamh, LOG_NOTICE, ++ "could not recover authentication token"); + } + } + +@@ -568,7 +597,7 @@ + + if (retval != PAM_SUCCESS) { + if (on( SMB_DEBUG, ctrl )) +- _log_err( LOG_DEBUG, "unable to obtain a password" ); ++ _log_err(pamh, LOG_DEBUG, "unable to obtain a password"); + return retval; + } + /* 'token' is the entered password */ +@@ -583,7 +612,7 @@ + || (retval = pam_get_item( pamh, authtok_flag + ,(const void **)&item )) != PAM_SUCCESS) + { +- _log_err( LOG_CRIT, "error manipulating password" ); ++ _log_err(pamh, LOG_CRIT, "error manipulating password"); + return retval; + } + } else { +@@ -597,8 +626,8 @@ + || (retval = pam_get_data( pamh, data_name, (const void **)&item )) + != PAM_SUCCESS) + { +- _log_err( LOG_CRIT, "error manipulating password data [%s]" +- , pam_strerror( pamh, retval )); ++ _log_err(pamh, LOG_CRIT, "error manipulating password data [%s]", ++ pam_strerror( pamh, retval )); + _pam_delete( token ); + item = NULL; + return retval; +@@ -622,8 +651,8 @@ + if (pass_new == NULL || (pass_old && !strcmp( pass_old, pass_new ))) + { + if (on(SMB_DEBUG, ctrl)) { +- _log_err( LOG_DEBUG, +- "passwd: bad authentication token (null or unchanged)" ); ++ _log_err(pamh, LOG_DEBUG, ++ "passwd: bad authentication token (null or unchanged)"); + } + make_remark( pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ? + "No password supplied" : "Password unchanged" ); +Index: samba-3.0.25c/source/pam_smbpass/pam_smb_auth.c +=================================================================== +--- samba-3.0.25c.orig/source/pam_smbpass/pam_smb_auth.c 2007-08-26 12:07:14.098417404 +0200 ++++ samba-3.0.25c/source/pam_smbpass/pam_smb_auth.c 2007-08-26 13:09:09.419359938 +0200 +@@ -75,10 +75,9 @@ + + /* Samba initialization. */ + load_case_tables(); +- setup_logging("pam_smbpass",False); + in_client = True; + +- ctrl = set_ctrl(flags, argc, argv); ++ ctrl = set_ctrl(pamh, flags, argc, argv); + + /* Get a few bytes so we can pass our return value to + pam_sm_setcred(). */ +@@ -93,23 +92,23 @@ + retval = pam_get_user( pamh, &name, "Username: " ); + if ( retval != PAM_SUCCESS ) { + if (on( SMB_DEBUG, ctrl )) { +- _log_err(LOG_DEBUG, "auth: could not identify user"); ++ _log_err(pamh, LOG_DEBUG, "auth: could not identify user"); + } + AUTH_RETURN; + } + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG, "username [%s] obtained", name ); ++ _log_err(pamh, LOG_DEBUG, "username [%s] obtained", name); + } + + if (!initialize_password_db(True)) { +- _log_err( LOG_ALERT, "Cannot access samba password database" ); ++ _log_err(pamh, LOG_ALERT, "Cannot access samba password database"); + retval = PAM_AUTHINFO_UNAVAIL; + AUTH_RETURN; + } + + sampass = samu_new( NULL ); + if (!sampass) { +- _log_err( LOG_ALERT, "Cannot talloc a samu struct" ); ++ _log_err(pamh, LOG_ALERT, "Cannot talloc a samu struct"); + retval = nt_status_to_pam(NT_STATUS_NO_MEMORY); + AUTH_RETURN; + } +@@ -123,7 +122,7 @@ + } + + if (!found) { +- _log_err(LOG_ALERT, "Failed to find entry for user %s.", name); ++ _log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", name); + retval = PAM_USER_UNKNOWN; + TALLOC_FREE(sampass); + sampass = NULL; +@@ -142,7 +141,7 @@ + + retval = _smb_read_password(pamh, ctrl, NULL, "Password: ", NULL, _SMB_AUTHTOK, &p); + if (retval != PAM_SUCCESS ) { +- _log_err(LOG_CRIT, "auth: no password provided for [%s]", name); ++ _log_err(pamh,LOG_CRIT, "auth: no password provided for [%s]", name); + TALLOC_FREE(sampass); + AUTH_RETURN; + } +@@ -194,8 +193,8 @@ + retval = pam_get_item( pamh, PAM_AUTHTOK, (const void **) &pass ); + + if (retval != PAM_SUCCESS) { +- _log_err( LOG_ALERT +- , "pam_get_item returned error to pam_sm_authenticate" ); ++ _log_err(pamh, LOG_ALERT, ++ "pam_get_item returned error to pam_sm_authenticate"); + return PAM_AUTHTOK_RECOVER_ERR; + } else if (pass == NULL) { + return PAM_AUTHTOK_RECOVER_ERR; +Index: samba-3.0.25c/source/pam_smbpass/pam_smb_acct.c +=================================================================== +--- samba-3.0.25c.orig/source/pam_smbpass/pam_smb_acct.c 2007-08-26 12:07:14.098417404 +0200 ++++ samba-3.0.25c/source/pam_smbpass/pam_smb_acct.c 2007-08-26 13:09:09.419359938 +0200 +@@ -52,29 +52,28 @@ + + /* Samba initialization. */ + load_case_tables(); +- setup_logging( "pam_smbpass", False ); + in_client = True; + +- ctrl = set_ctrl( flags, argc, argv ); ++ ctrl = set_ctrl(pamh, flags, argc, argv); + + /* get the username */ + + retval = pam_get_user( pamh, &name, "Username: " ); + if (retval != PAM_SUCCESS) { + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG, "acct: could not identify user" ); ++ _log_err(pamh, LOG_DEBUG, "acct: could not identify user"); + } + return retval; + } + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG, "acct: username [%s] obtained", name ); ++ _log_err(pamh, LOG_DEBUG, "acct: username [%s] obtained", name); + } + + /* Getting into places that might use LDAP -- protect the app + from a SIGPIPE it's not expecting */ + oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); + if (!initialize_password_db(True)) { +- _log_err( LOG_ALERT, "Cannot access samba password database" ); ++ _log_err(pamh, LOG_ALERT, "Cannot access samba password database"); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return PAM_AUTHINFO_UNAVAIL; + } +@@ -88,7 +87,7 @@ + } + + if (!pdb_getsampwnam(sampass, name )) { +- _log_err( LOG_DEBUG, "acct: could not identify user" ); ++ _log_err(pamh, LOG_DEBUG, "acct: could not identify user"); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return PAM_USER_UNKNOWN; + } +@@ -101,8 +100,8 @@ + + if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG +- , "acct: account %s is administratively disabled", name ); ++ _log_err(pamh, LOG_DEBUG, ++ "acct: account %s is administratively disabled", name); + } + make_remark( pamh, ctrl, PAM_ERROR_MSG + , "Your account has been disabled; " +Index: samba-3.0.25c/source/pam_smbpass/pam_smb_passwd.c +=================================================================== +--- samba-3.0.25c.orig/source/pam_smbpass/pam_smb_passwd.c 2007-08-26 12:07:14.098417404 +0200 ++++ samba-3.0.25c/source/pam_smbpass/pam_smb_passwd.c 2007-08-26 13:09:09.419359938 +0200 +@@ -104,10 +104,9 @@ + + /* Samba initialization. */ + load_case_tables(); +- setup_logging( "pam_smbpass", False ); + in_client = True; + +- ctrl = set_ctrl(flags, argc, argv); ++ ctrl = set_ctrl(pamh, flags, argc, argv); + + /* + * First get the name of a user. No need to do anything if we can't +@@ -117,12 +116,12 @@ + retval = pam_get_user( pamh, &user, "Username: " ); + if (retval != PAM_SUCCESS) { + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG, "password: could not identify user" ); ++ _log_err(pamh, LOG_DEBUG, "password: could not identify user"); + } + return retval; + } + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG, "username [%s] obtained", user ); ++ _log_err(pamh, LOG_DEBUG, "username [%s] obtained", user); + } + + /* Getting into places that might use LDAP -- protect the app +@@ -130,7 +129,7 @@ + oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); + + if (!initialize_password_db(False)) { +- _log_err( LOG_ALERT, "Cannot access samba password database" ); ++ _log_err(pamh, LOG_ALERT, "Cannot access samba password database"); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return PAM_AUTHINFO_UNAVAIL; + } +@@ -142,12 +141,12 @@ + } + + if (!pdb_getsampwnam(sampass,user)) { +- _log_err( LOG_ALERT, "Failed to find entry for user %s.", user ); ++ _log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", user); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return PAM_USER_UNKNOWN; + } + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_DEBUG, "Located account for %s", user ); ++ _log_err(pamh, LOG_DEBUG, "Located account for %s", user); + } + + if (flags & PAM_PRELIM_CHECK) { +@@ -173,7 +172,7 @@ + #define greeting "Changing password for " + Announce = SMB_MALLOC_ARRAY(char, sizeof(greeting)+strlen(user)); + if (Announce == NULL) { +- _log_err(LOG_CRIT, "password: out of memory"); ++ _log_err(pamh, LOG_CRIT, "password: out of memory"); + TALLOC_FREE(sampass); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return PAM_BUF_ERR; +@@ -188,8 +187,8 @@ + SAFE_FREE( Announce ); + + if (retval != PAM_SUCCESS) { +- _log_err( LOG_NOTICE +- , "password - (old) token not obtained" ); ++ _log_err(pamh, LOG_NOTICE, ++ "password - (old) token not obtained"); + TALLOC_FREE(sampass); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return retval; +@@ -234,7 +233,7 @@ + } + + if (retval != PAM_SUCCESS) { +- _log_err( LOG_NOTICE, "password: user not authenticated" ); ++ _log_err(pamh, LOG_NOTICE, "password: user not authenticated"); + TALLOC_FREE(sampass); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); + return retval; +@@ -259,8 +258,8 @@ + + if (retval != PAM_SUCCESS) { + if (on( SMB_DEBUG, ctrl )) { +- _log_err( LOG_ALERT +- , "password: new password not obtained" ); ++ _log_err(pamh, LOG_ALERT, ++ "password: new password not obtained"); + } + pass_old = NULL; /* tidy up */ + TALLOC_FREE(sampass); +@@ -281,7 +280,7 @@ + retval = _pam_smb_approve_pass(pamh, ctrl, pass_old, pass_new); + + if (retval != PAM_SUCCESS) { +- _log_err(LOG_NOTICE, "new password not acceptable"); ++ _log_err(pamh, LOG_NOTICE, "new password not acceptable"); + pass_new = pass_old = NULL; /* tidy up */ + TALLOC_FREE(sampass); + CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); +@@ -301,16 +300,17 @@ + + /* password updated */ + if (!sid_to_uid(pdb_get_user_sid(sampass), &uid)) { +- _log_err( LOG_NOTICE, "Unable to get uid for user %s", ++ _log_err(pamh, LOG_NOTICE, ++ "Unable to get uid for user %s", + pdb_get_username(sampass)); +- _log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)", ++ _log_err(pamh, LOG_NOTICE, "password for (%s) changed by (%s/%d)", + user, uidtoname(getuid()), getuid()); + } else { +- _log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)", ++ _log_err(pamh, LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)", + user, uid, uidtoname(getuid()), getuid()); + } + } else { +- _log_err( LOG_ERR, "password change failed for user %s", user); ++ _log_err(pamh, LOG_ERR, "password change failed for user %s", user); + } + + pass_old = pass_new = NULL; +@@ -321,7 +321,7 @@ + + } else { /* something has broken with the library */ + +- _log_err( LOG_ALERT, "password received unknown request" ); ++ _log_err(pamh, LOG_ALERT, "password received unknown request"); + retval = PAM_ABORT; + + } +Index: samba-3.0.25c/source/pam_smbpass/support.h +=================================================================== +--- samba-3.0.25c.orig/source/pam_smbpass/support.h 2007-08-26 12:07:14.098417404 +0200 ++++ samba-3.0.25c/source/pam_smbpass/support.h 2007-08-26 13:09:09.419359938 +0200 +@@ -1,8 +1,8 @@ + /* syslogging function for errors and other information */ +-extern void _log_err(int, const char *, ...); ++extern void _log_err(pam_handle_t *, int, const char *, ...); + + /* set the control flags for the UNIX module. */ +-extern int set_ctrl(int, int, const char **); ++extern int set_ctrl(pam_handle_t *, int, int, const char **); + + /* generic function for freeing pam data segments */ + extern void _cleanup(pam_handle_t *, void *, int); +@@ -12,7 +12,7 @@ + * evidence of old token around for later stack analysis. + */ + +-extern char *smbpXstrDup(const char *); ++extern char *smbpXstrDup(pam_handle_t *,const char *); + + /* ************************************************************** * + * Useful non-trivial functions * ================================================================ _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
