/* Copyright 2004 Laurent Wacrenier & Olivier Fredj 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: hpgsql.c,v 1.4 2005/09/14 08:57:00 lwa Exp $"; #include #include #include #include #include #include #include #include "hparam.h" static PGconn *pgsql ; extern int home_stayopen; static time_t backuptime; static char *openhost=NULL; void hpgsql_clean(void) { if (PQstatus(pgsql) != CONNECTION_BAD) PQfinish(pgsql); backuptime=0; } static void *hpgsql_error (char *context) { home_retry("PgSQL %s error: %s", context, PQerrorMessage(pgsql)); hpgsql_clean(); return NULL; } static char *hpgsql_open(void) { extern struct param home_param; char **hosts; int nhost=0; if (backuptime && home_param.backtime >0 && time(NULL) > backuptime + home_param.backtime) hpgsql_clean(); if (openhost && PQstatus(pgsql) == CONNECTION_OK) return openhost; hosts = home_param.pg_hosts; if (hosts == NULL) { home_retry("no auth server defined"); return NULL; } do { pgsql = PQsetdbLogin( *hosts, NULL /* port */, NULL /* options */, NULL /* tty */, home_param.pg_database, home_param.pg_user, home_param.pg_passwd) ; if (PQstatus(pgsql) != CONNECTION_OK) home_error("PgSQL unable to connect to %s: %s", *hosts, PQerrorMessage(pgsql)); else { openhost = *hosts; if (nhost) backuptime = time(NULL); return openhost; } nhost++; } while(*(++hosts)); hpgsql_error("connect"); return NULL; } static struct passwd *hpgsql_store(PGresult *res, char **alias) { struct passwd *pwd; extern struct param home_param; if (PQntuples(res) <= 0) { PQclear(res); return(NULL); } if (alias) { if (*alias==NULL && !(PQgetisnull(res,0,7))) { *alias=strdup(PQgetvalue(res,0,7)); PQclear(res); return NULL; } else *alias=NULL; } pwd = home_getpwd(); pwd->pw_name = strdup(PQgetvalue(res,0,0)); pwd->pw_passwd = strdup(!(PQgetisnull(res,0,1)) ? PQgetvalue(res,0,1) : ""); pwd->pw_uid = !(PQgetisnull(res,0,2)) ? (uid_t) home_calc(strtoul(PQgetvalue(res,0,2), NULL, 10), home_param.uid_calc) : (uid_t)-1; pwd->pw_gid = !(PQgetisnull(res,0,3)) ? (gid_t)strtoul(PQgetvalue(res,0,3), NULL, 10) : (gid_t)-1; #ifdef HAS_PW_CLASS pwd->pw_class = strdup(!(PQgetisnull(res,0,4)) ? PQgetvalue(res,0,4) : ""); #endif pwd->pw_gecos = strdup(!(PQgetisnull(res,0,9)) ? PQgetvalue(res,0,9) : ""); pwd->pw_dir = hexpand_home(PQgetvalue(res,0,0), PQgetvalue(res,0,5)); pwd->pw_shell = strdup(!(PQgetisnull(res,0,8)) ? PQgetvalue(res,0,8) : ""); #ifdef HAS_PW_CHANGE pwd->pw_change = 0; #endif #ifdef HAS_PW_EXPIRE pwd->pw_expire = home_expire(PQgetvalue(res,0,10)); #endif #ifdef HAS_PW_FIELDS /* internal FreeBSD */ #endif #ifdef HAS_PW_QUOTA pwd->pw_quota = !(PQgetisnull)(res,0,6) ? (int)strtol(PQgetvalue(res,0,6), NULL, 10) : 0; pwd->pw_quota *= home_param.quota_unit; #endif PQclear(res); return(pwd); } static PGresult *hpgsql_query(char *rentry) { char fquery[LINEMAX]; PGresult *res; extern struct param home_param; int fquery_len; if (hpgsql_open()==NULL) return NULL; if (IS_UID(rentry)) { fquery_len = snprintf(fquery, LINEMAX, home_param.query, home_param.where_nam, GET_UID(rentry)); if (fquery_len >= LINEMAX) { home_error("query too long for UID %.20s...", rentry); return NULL; } } else { char eentry[MAXUSERLEN*2+1]; PQescapeString(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; } } res = PQexec(pgsql, fquery); if (PQresultStatus(res) != PGRES_TUPLES_OK) { PQclear(res); return(NULL); } return(res); } struct home_driver hpgsql_driver = { (home_query_t) hpgsql_query, (home_store_t) hpgsql_store, (home_clean_t) hpgsql_clean, };