/* Copyright 2000, 2001, 2002 Laurent Wacrenier This file is part of libhome libhome is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. libhome is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with libhome; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" static char const rcsid[] UNUSED = "$Id: hmysql.c,v 1.36 2005/06/23 13:02:59 lwa Exp $"; #include #include #include #include #include #include #include #include "hparam.h" static MYSQL mysql; extern int home_stayopen; static char *openhost=NULL; static int inited=0; static time_t backuptime; static void hmysql_clean(void) { if (openhost || inited) { mysql_close(&mysql); } openhost=NULL; inited=0; backuptime=0; } static void *hmysql_error (char *context) { home_retry("MySQL %s error: %s", context, mysql_error(&mysql)); hmysql_clean(); return NULL; } static char *hmysql_open(void) { extern struct param home_param; char **hosts; int nhost=0; if (backuptime && home_param.backtime >0 && time(NULL) > backuptime + home_param.backtime) hmysql_clean(); if (openhost && mysql_ping(&mysql)!=0) { home_error("MySQL ping to %s error: %s", openhost, mysql_error(&mysql)); hmysql_clean(); } if (!inited) { hmysql_clean(); mysql_init(&mysql); inited=1; } if (openhost) return openhost; hosts=home_param.my_hosts; if (hosts==NULL) { home_retry("no auth server defined"); return NULL; } do { /* fuites de mémoire (??) mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, home_param.mygroup); mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, home_param.mycnf); */ char *host = NULL; char *unix_socket = NULL; unsigned int port = 0; if (*hosts && **hosts == '/') { unix_socket = *hosts; } else { host = *hosts; port = home_param.my_port; } #if HAVE_MYSQL_OPT_CONNECT_TIMEOUT /* API >= 3.23.29 */ if (home_param.my_connect_timeout > 0) { unsigned int timeout = home_param.my_connect_timeout; mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout); } #endif if (mysql_real_connect(&mysql, host, home_param.my_user, home_param.my_passwd, home_param.my_database, port, unix_socket, 0)) { openhost=*hosts; if (nhost) backuptime=time(NULL); return openhost; } else { home_error("MySQL unable to connect to %s: %s", *hosts, mysql_error(&mysql)); } nhost++; } while(*(++hosts)); hmysql_error("connect"); return NULL; } static struct passwd *hmysql_store(MYSQL_RES *res, char **alias) { MYSQL_ROW row; struct passwd *pwd; extern struct param home_param; row=mysql_fetch_row(res); if (row==NULL) { mysql_free_result(res); return NULL; } if (alias) { if (*alias==NULL && row[7] && *(row[7])) { *alias=strdup(row[7]); mysql_free_result(res); return NULL; } else { *alias=NULL; } } pwd = home_getpwd(); pwd->pw_name=strdup(row[0]); pwd->pw_passwd=strdup(row[1] ? row[1] : ""); pwd->pw_uid=row[2] ? (uid_t)home_calc(strtoul(row[2], NULL, 10), home_param.uid_calc): (uid_t)-1; pwd->pw_gid=row[3] ? (gid_t)strtoul(row[3], NULL, 10) : (gid_t)-1; #ifdef HAS_PW_CLASS pwd->pw_class=strdup(row[4] ? row[4] : ""); #endif pwd->pw_gecos=strdup(row[9] ? row[9] : ""); pwd->pw_dir=hexpand_home(row[0], row[5]); pwd->pw_shell=strdup(row[8] ? row[8] : ""); #ifdef HAS_PW_CHANGE pwd->pw_change=0; #endif #ifdef HAS_PW_EXPIRE pwd->pw_expire=home_expire(row[10]); #endif #ifdef HAS_PW_FIELDS /* internal FreeBSD */ #endif #ifdef HAS_PW_QUOTA pwd->pw_quota=row[6] ? (int)strtol(row[6], NULL, 10) : 0; pwd->pw_quota *= home_param.quota_unit; #endif mysql_free_result(res); return pwd; } static MYSQL_RES *hmysql_query(char *rentry) { char fquery[LINEMAX]; MYSQL_RES *res; int fquery_len; extern struct param home_param; if (hmysql_open()==NULL) { return NULL; } if (IS_UID(rentry)) { fquery_len=snprintf(fquery, LINEMAX, home_param.query, home_param.where_uid, GET_UID(rentry)); if (fquery_len >= LINEMAX) { home_error("query too long for uid %.20s...", GET_UID(rentry)); return NULL; } } else { char eentry[MAXUSERLEN*2+1]; mysql_escape_string(eentry, rentry, strlen(rentry)); fquery_len=snprintf(fquery, LINEMAX, home_param.query, home_param.where_nam, eentry); if (fquery_len >= LINEMAX) { home_error("query too long for user %.20s...", rentry); return NULL; } } if (mysql_real_query(&mysql, fquery, fquery_len)!=0) { return hmysql_error("query"); } if ((res=mysql_use_result(&mysql))==NULL) { return hmysql_error("use result"); } return res; } struct home_driver hmysql_driver = { (home_query_t) hmysql_query, (home_store_t) hmysql_store, (home_clean_t) hmysql_clean, };