Hi, I mentioned this awhile back, but didn't have the cycles to create a diff file. I finally had the time so here it is... I've been using this in version 5.2 and even back in 4.9.6.
I've attached a diff file to add the functions int vget_limits( char *domain, struct vlimits *limits ) int vset_limits( char *domain, struct vlimits *limits ) int vdel_limits( char *domain ) to the vpopmail library. These maintain either the raw file .qmailadmin-limits or will maintain the limits in a MySQL database. The items supported are: struct vlimits { int maxpopaccounts; int maxaliases; int maxforwards; int maxautoresponders; int maxmailinglists; int diskquota; int defaultquota; short disablepop; short disableimap; short disabledialup; short disablepasswordchanging; short disablewebmail; short disablerelay; }; I haven't included the changes to qmailadmin that I use, nor the changes to vdelivermail (for domain quota). diskquota is the current quota for a domain. defaultquota is the default quota for new users of this domain. The other items I believe are self explanatory. The config is updated so you would call --enable-mysql-limits as an option to configure. Hopefully you'll find this useful. Thanks, Brian
diff -c vpopmail-5.3.8.orig/Makefile.am vpopmail-5.3.8/Makefile.am *** vpopmail-5.3.8.orig/Makefile.am Thu Jun 20 19:04:23 2002 --- vpopmail-5.3.8/Makefile.am Thu Oct 17 10:54:42 2002 *************** *** 4,10 **** noinst_LIBRARIES=libvpopmail.a ! COMMONSOURCES=vpopmail.c md5.c bigdir.c vauth.c file_lock.c vpalias.c seek.c CONFIG_CLEAN_FILES=vauth.c libvpopmail_a_SOURCES=$(COMMONSOURCES) --- 4,10 ---- noinst_LIBRARIES=libvpopmail.a ! COMMONSOURCES=vpopmail.c md5.c bigdir.c vauth.c file_lock.c vpalias.c seek.c vlimits.c CONFIG_CLEAN_FILES=vauth.c libvpopmail_a_SOURCES=$(COMMONSOURCES) *************** *** 99,104 **** --- 99,105 ---- cp config.h $(DESTDIR)@vpopmaildir@/include cp config.h $(DESTDIR)@vpopmaildir@/include/vpopmail_config.h cp vauth.h $(DESTDIR)@vpopmaildir@/include + cp vlimits.h $(DESTDIR)@vpopmaildir@/include cp doc/man_html/* $(DESTDIR)@vpopmaildir@/doc/man_html cp doc/doc_html/* $(DESTDIR)@vpopmaildir@/doc/doc_html diff -c vpopmail-5.3.8.orig/Makefile.in vpopmail-5.3.8/Makefile.in *** vpopmail-5.3.8.orig/Makefile.in Tue Jul 16 16:58:40 2002 --- vpopmail-5.3.8/Makefile.in Thu Oct 17 10:57:21 2002 *************** *** 76,82 **** noinst_LIBRARIES = libvpopmail.a ! COMMONSOURCES = vpopmail.c md5.c bigdir.c vauth.c file_lock.c vpalias.c seek.c CONFIG_CLEAN_FILES = vauth.c libvpopmail_a_SOURCES = $(COMMONSOURCES) --- 76,82 ---- noinst_LIBRARIES = libvpopmail.a ! COMMONSOURCES = vpopmail.c md5.c bigdir.c vauth.c file_lock.c vpalias.c seek.c vlimits.c CONFIG_CLEAN_FILES = vauth.c libvpopmail_a_SOURCES = $(COMMONSOURCES) *************** *** 162,168 **** LIBS = @LIBS@ libvpopmail_a_DEPENDENCIES = cdb/*.o libvpopmail_a_OBJECTS = vpopmail.o md5.o bigdir.o vauth.o file_lock.o \ ! vpalias.o seek.o AR = ar PROGRAMS = $(vpopmailbin_PROGRAMS) --- 162,168 ---- LIBS = @LIBS@ libvpopmail_a_DEPENDENCIES = cdb/*.o libvpopmail_a_OBJECTS = vpopmail.o md5.o bigdir.o vauth.o file_lock.o \ ! vpalias.o seek.o vlimits.o AR = ar PROGRAMS = $(vpopmailbin_PROGRAMS) *************** *** 693,698 **** --- 693,699 ---- cp config.h $(DESTDIR)@vpopmaildir@/include cp config.h $(DESTDIR)@vpopmaildir@/include/vpopmail_config.h cp vauth.h $(DESTDIR)@vpopmaildir@/include + cp vlimits.h $(DESTDIR)@vpopmaildir@/include cp doc/man_html/* $(DESTDIR)@vpopmaildir@/doc/man_html cp doc/doc_html/* $(DESTDIR)@vpopmaildir@/doc/doc_html diff -c vpopmail-5.3.8.orig/acconfig.h vpopmail-5.3.8/acconfig.h *** vpopmail-5.3.8.orig/acconfig.h Thu Jun 20 23:12:35 2002 --- vpopmail-5.3.8/acconfig.h Thu Oct 17 10:47:57 2002 *************** *** 38,43 **** --- 38,45 ---- #undef ENABLE_MYSQL_LOGGING + #undef ENABLE_MYSQL_LIMITS + #undef CLEAR_PASS #undef VALIAS Common subdirectories: vpopmail-5.3.8.orig/attic and vpopmail-5.3.8/attic Common subdirectories: vpopmail-5.3.8.orig/cdb and vpopmail-5.3.8/cdb diff -c vpopmail-5.3.8.orig/configure vpopmail-5.3.8/configure *** vpopmail-5.3.8.orig/configure Tue Jul 16 16:58:40 2002 --- vpopmail-5.3.8/configure Thu Oct 17 10:51:39 2002 *************** *** 40,45 **** --- 40,47 ---- ac_help="$ac_help --enable-mysql-logging=y|n Turn on (y) or off (n, default) logging detailed authentication attempts, only valid for mysql" ac_help="$ac_help + --enable-mysql-limits=y|n Turn on (y) or off (n, default) mysql handling of +.qmailadmin-limits" + ac_help="$ac_help --enable-clear-passwd=n|y Turn on (y) or off (y, default) storing clear text passwords" ac_help="$ac_help --enable-users-big-dir=n|y Turn on (y) or off (y, default) using big dirs for users" *************** *** 1778,1783 **** --- 1780,1807 ---- ;; esac + # Check whether --enable-mysql-limits or --disable-mysql-limits was given. + if test "${enable_mysql_limits+set}" = set; then + enableval="$enable_mysql_limits" + ENABLE_MYSQL_LIMITS=$enableval + else + + ENABLE_MYSQL_LIMITS=n + + fi; + + case $ENABLE_MYSQL_LIMITS in + 1*|y*|Y*) + ENABLE_MYSQL_LIMITS=1 + cat >>confdefs.h <<EOF + #define ENABLE_MYSQL_LIMITS $ENABLE_MYSQL_LIMITS + EOF + + ;; + *) + ;; + esac + # Check whether --enable-clear-passwd or --disable-clear-passwd was given. if test "${enable_clear_passwd+set}" = set; then enableval="$enable_clear_passwd" *************** *** 3873,3878 **** --- 3897,3912 ---- echo " mysql logging = OFF --enable-mysql-logging=n default" ;; esac + + case $ENABLE_MYSQL_LIMITS in + 1*|y*|Y*) + echo " mysql limits = ON --enable-mysql-limits=y" + echo " --enable-mysql-limits=y \\" >> vpopmail.config.sh + ;; + *) + echo " mysql limits = OFF --enable-mysql-limits=n default" + ;; + esac case $CLEAR_PASS in 1*|y*|Y*) diff -c vpopmail-5.3.8.orig/configure.in vpopmail-5.3.8/configure.in *** vpopmail-5.3.8.orig/configure.in Tue Jul 16 16:57:44 2002 --- vpopmail-5.3.8/configure.in Thu Oct 17 10:50:29 2002 *************** *** 388,393 **** --- 388,409 ---- ;; esac + AC_ARG_ENABLE(mysql-limits, + [ --enable-mysql-limits=y|n Turn on (y) or off (n, default) mysql +handling of .qmailadmin-limits ], + ENABLE_MYSQL_LIMITS=$enableval, + [ + ENABLE_MYSQL_LIMITS=n + ]) + + case $ENABLE_MYSQL_LIMITS in + 1*|y*|Y*) + ENABLE_MYSQL_LIMITS=1 + AC_DEFINE_UNQUOTED(ENABLE_MYSQL_LIMITS,$ENABLE_MYSQL_LIMITS) + ;; + *) + ;; + esac + AC_ARG_ENABLE(clear-passwd, [ --enable-clear-passwd=n|y Turn on (y) or off (y, default) storing clear text passwords], CLEAR_PASS=$enableval, Common subdirectories: vpopmail-5.3.8.orig/contrib and vpopmail-5.3.8/contrib Common subdirectories: vpopmail-5.3.8.orig/convert and vpopmail-5.3.8/convert Common subdirectories: vpopmail-5.3.8.orig/doc and vpopmail-5.3.8/doc Common subdirectories: vpopmail-5.3.8.orig/ldap and vpopmail-5.3.8/ldap Common subdirectories: vpopmail-5.3.8.orig/oracle and vpopmail-5.3.8/oracle diff -c vpopmail-5.3.8.orig/vlimits.c vpopmail-5.3.8/vlimits.c *** vpopmail-5.3.8.orig/vlimits.c Thu Oct 17 12:54:30 2002 --- vpopmail-5.3.8/vlimits.c Thu Oct 17 12:54:03 2002 *************** *** 0 **** --- 1,189 ---- + /* + * vlimits.c + * handle domain limits in both file format + * Brian Kolaci <[EMAIL PROTECTED]> + */ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + #include <errno.h> + #include <unistd.h> + #include <sys/types.h> + #include "config.h" + #include "vlimits.h" + #include "vpopmail.h" + + + #ifndef ENABLE_MYSQL_LIMITS + + #define TOKENS " :\t\n\r" + + /* find/read the .qmailadmin-limits file */ + int vget_limits( char *domain, struct vlimits *limits ) + { + char buf[256]; + char dir[MAXPATHLEN]; + uid_t uid; + gid_t gid; + char * s1; + char * s2; + FILE * fs; + + /* initialize structure */ + memset(limits, 0, sizeof(*limits)); + limits->maxpopaccounts = -1; + limits->maxaliases = -1; + limits->maxforwards = -1; + limits->maxautoresponders = -1; + limits->maxmailinglists = -1; + limits->diskquota = 0; + limits->defaultquota =0; + limits->disablepop = 0; + limits->disableimap = 0; + limits->disabledialup = 0; + limits->disablepasswordchanging = 0; + limits->disablerelay = 0; + limits->disablewebmail = 0; + x + /* get filename */ + vget_assign(domain, dir, sizeof(dir), &uid, &gid); + strncat(dir, "/.qmailadmin-limits", sizeof(dir)); + + /* open file */ + if ((fs = fopen(dir, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fs) != NULL) { + if ((s1 = strtok(buf, TOKENS)) == NULL) + continue; + + if (!strcmp(s1, "maxpopaccounts")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->maxpopaccounts = atoi(s2); + } + + if (!strcmp(s1, "maxaliases")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->maxaliases = atoi(s2); + } + + if (!strcmp(s1, "maxforwards")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->maxforwards = atoi(s2); + } + + if (!strcmp(s1, "maxautoresponders")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->maxautoresponders = atoi(s2); + } + + if (!strcmp(s1, "maxmailinglists")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->maxmailinglists = atoi(s2); + } + + if (!strcmp(s1, "quota")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->diskquota = atoi(s2); + } + + if (!strcmp(s1, "default_quota")) { + if ((s2 = strtok(buf, TOKENS)) == NULL) + continue; + limits->defaultquota = atoi(s2); + } + + if (!strcmp(s1, "disable_pop")) { + limits->disablepop = 1; + } + + if (!strcmp(s1, "disable_imap")) { + limits->disableimap = 1; + } + + if (!strcmp(s1, "disable_dialup")) { + limits->disabledialup = 1; + } + + if (!strcmp(s1, "disable_password_changing")) { + limits->disablepasswordchanging = 1; + } + + if (!strcmp(s1, "disable_external_relay")) { + limits->disablerelay = 1; + } + + if (!strcmp(s1, "disable_webmail")) { + limits->disablewebmail = 1; + } + } + fclose(fs); + chown(dir,uid,gid); + chmod(dir, S_IRUSR|S_IWUSR); + } else { + fprintf(stderr, "vlimits: failed to open limits file (%d): %s\n", errno, dir); + return -1; + } + + return 0; + } + + int vset_limits( char *domain, struct vlimits *limits ) + { + char dir[256]; + uid_t uid; + gid_t gid; + FILE * fs; + + /* get filename */ + vget_assign(domain, dir, sizeof(dir), &uid, &gid); + strncat(dir, "/.qmailadmin-limits", sizeof(dir)); + + /* open file */ + if ((fs = fopen(dir, "w+")) != NULL) { + fprintf(fs, "maxpopaccounts: %d\n", limits->maxpopaccounts); + fprintf(fs, "maxaliases: %d\n", limits->maxaliases); + fprintf(fs, "maxforwards: %d\n", limits->maxforwards); + fprintf(fs, "maxautoresponders: %d\n", limits->maxautoresponders); + fprintf(fs, "maxmailinglists: %d\n", limits->maxmailinglists); + fprintf(fs, "quota: %d\n", limits->diskquota); + fprintf(fs, "default_quota: %d\n", limits->defaultquota); + if (limits->disablepop) + fprintf(fs, "disable_pop\n"); + if (limits->disableimap) + fprintf(fs, "disable_imap\n"); + if (limits->disabledialup) + fprintf(fs, "disable_dialup\n"); + if (limits->disablepasswordchanging) + fprintf(fs, "disable_password_changing\n"); + if (limits->disablewebmail) + fprintf(fs, "disable_webmail\n"); + if (limits->disablerelay) + fprintf(fs, "disable_external_relay\n"); + fclose(fs); + } else { + fprintf(stderr, "vlimits: failed to open limits file (%d): %s\n", errno, dir); + return -1; + } + + return 0; + } + + int vdel_limits( char *domain ) + { + char dir[256]; + uid_t uid; + gid_t gid; + + /* get filename */ + vget_assign(domain, dir, sizeof(dir), &uid, &gid); + strncat(dir, "/.qmailadmin-limits", sizeof(dir)); + return unlink(dir); + } + + #endif + diff -c vpopmail-5.3.8.orig/vlimits.h vpopmail-5.3.8/vlimits.h *** vpopmail-5.3.8.orig/vlimits.h Thu Oct 17 12:54:31 2002 --- vpopmail-5.3.8/vlimits.h Thu Oct 17 12:54:02 2002 *************** *** 0 **** --- 1,30 ---- + /* + * vlimits.h + * handle domain limits in both file and mysql tables + * Brian Kolaci <[EMAIL PROTECTED]> + */ + + #ifndef VPOPMAIL_VLIMITS_H + #define VPOPMAIL_VLIMITS_H + + struct vlimits { + int maxpopaccounts; + int maxaliases; + int maxforwards; + int maxautoresponders; + int maxmailinglists; + int diskquota; + int defaultquota; + short disablepop; + short disableimap; + short disabledialup; + short disablepasswordchanging; + short disablewebmail; + short disablerelay; + }; + + int vget_limits(char * domain, struct vlimits * limits); + int vset_limits(char * domain, struct vlimits * limits); + int vdel_limits(char * domain); + + #endif diff -c vpopmail-5.3.8.orig/vmysql.c vpopmail-5.3.8/vmysql.c *** vpopmail-5.3.8.orig/vmysql.c Thu Jun 20 23:11:42 2002 --- vpopmail-5.3.8/vmysql.c Thu Oct 17 10:42:27 2002 *************** *** 26,31 **** --- 26,32 ---- #include "config.h" #include "vpopmail.h" #include "vauth.h" + #include "vlimits.h" #include "vmysql.h" *************** *** 446,451 **** --- 447,454 ---- mysql_free_result(res_update); #endif + vdel_limits(domain); + return(0); } *************** *** 939,958 **** int found = 0; if ( vauth_open_read() != 0 ) return(-1); ! snprintf(SqlBufUpdate, SQL_BUF_SIZE, "select %s from dir_control where domain = \"%s\"", DIR_CONTROL_SELECT, domain ); ! if (mysql_query(&mysql_read,SqlBufUpdate)) { vcreate_dir_control(domain); ! snprintf(SqlBufUpdate, SQL_BUF_SIZE, "select %s from dir_control where domain = \"%s\"", DIR_CONTROL_SELECT, domain ); ! if (mysql_query(&mysql_read,SqlBufUpdate)) { return(-1); } } if (!(res_read = mysql_store_result(&mysql_read))) { ! printf("vsql_getpw: store result failed 6\n"); return(0); } --- 942,961 ---- int found = 0; if ( vauth_open_read() != 0 ) return(-1); ! snprintf(SqlBufRead, SQL_BUF_SIZE, "select %s from dir_control where domain = \"%s\"", DIR_CONTROL_SELECT, domain ); ! if (mysql_query(&mysql_read,SqlBufRead)) { vcreate_dir_control(domain); ! snprintf(SqlBufRead, SQL_BUF_SIZE, "select %s from dir_control where domain = \"%s\"", DIR_CONTROL_SELECT, domain ); ! if (mysql_query(&mysql_read,SqlBufRead)) { return(-1); } } if (!(res_read = mysql_store_result(&mysql_read))) { ! printf("vread_dir_control: store result failed 6\n"); return(0); } *************** *** 1353,1359 **** vcreate_vlog_table(); if (mysql_query(&mysql_update,SqlBufUpdate)) { fprintf(stderr, ! "error inserting into lastauth table\n"); } } res_update = mysql_store_result(&mysql_update); --- 1356,1362 ---- vcreate_vlog_table(); if (mysql_query(&mysql_update,SqlBufUpdate)) { fprintf(stderr, ! "error inserting into vlog table\n"); } } res_update = mysql_store_result(&mysql_update); *************** *** 1370,1376 **** snprintf( SqlBufCreate, SQL_BUF_SIZE, "CREATE TABLE vlog ( %s )", VLOG_TABLE_LAYOUT); if (mysql_query(&mysql_update,SqlBufCreate)) { ! fprintf(stderr, "could not create lastauth table %s\n", SqlBufCreate); return; } res_update = mysql_store_result(&mysql_update); --- 1373,1379 ---- snprintf( SqlBufCreate, SQL_BUF_SIZE, "CREATE TABLE vlog ( %s )", VLOG_TABLE_LAYOUT); if (mysql_query(&mysql_update,SqlBufCreate)) { ! fprintf(stderr, "could not create vlog table %s\n", SqlBufCreate); return; } res_update = mysql_store_result(&mysql_update); *************** *** 1391,1393 **** --- 1394,1526 ---- /* make sure the terminating NULL char is included */ *outstr++ = *instr++; } + + #ifdef ENABLE_MYSQL_LIMITS + void vcreate_limits_table() + { + if ( vauth_open_update() != 0 ) return; + + snprintf( SqlBufCreate, SQL_BUF_SIZE, "CREATE TABLE limits ( %s )", + LIMITS_TABLE_LAYOUT); + if (mysql_query(&mysql_update,SqlBufCreate)) { + fprintf(stderr, "could not create limits table %s\n", SqlBufCreate); + return; + } + res_update = mysql_store_result(&mysql_update); + mysql_free_result(res_update); + } + + int vget_limits( char *domain, struct vlimits *limits ) + { + int err; + + /* if we can not connect, set the verrori value */ + if ( (err=vauth_open_read()) != 0 ) { + return(-1); + } + + snprintf( SqlBufRead, SQL_BUF_SIZE, "SELECT maxpopaccounts, maxaliases, " + "maxforwards, maxautoresponders, maxmailinglists, diskquota, " + "defaultquota, disablepop, disableimap, disabledialup, " + "disablepasswordchanging, disablewebmail, disablerelay \n" + "FROM limits \n" + "WHERE domain = '%s'", domain); + + if (mysql_query(&mysql_read,SqlBufRead)) { + vcreate_limits_table(); + if (mysql_query(&mysql_read,SqlBufRead)) { + fprintf(stderr, "vmysql: sql error[j]: %s\n", mysql_error(&mysql_read)); + return(-1); + } + } + if (!(res_read = mysql_store_result(&mysql_read))) { + fprintf(stderr, "vmysql: store result failed\n"); + return -1; + } + + if (mysql_num_rows(res_read) == 0) { + fprintf(stderr, "vnysql: can't find limits for domain '%s'\n", domain); + return -1; + } + + if ((row = mysql_fetch_row(res_read)) != NULL) { + limits->maxpopaccounts = atoi(row[0]); + limits->maxaliases = atoi(row[1]); + limits->maxforwards = atoi(row[2]); + limits->maxautoresponders = atoi(row[3]); + limits->maxmailinglists = atoi(row[4]); + limits->diskquota = atoi(row[5]); + limits->defaultquota = atoi(row[6]); + limits->disablepop = atoi(row[7]); + limits->disableimap = atoi(row[8]); + limits->disabledialup = atoi(row[9]); + limits->disablepasswordchanging = atoi(row[10]); + limits->disablewebmail = atoi(row[11]); + limits->disablerelay = atoi(row[12]); + } + mysql_free_result(res_read); + + return 0; + } + + int vdel_limits( char *domain ) + { + snprintf( SqlBufUpdate, SQL_BUF_SIZE, "DELETE FROM limits WHERE domain = \"%s\"", + domain); + + if (mysql_query(&mysql_update,SqlBufUpdate)) { + return(-1); + } + res_update = mysql_store_result(&mysql_update); + mysql_free_result(res_update); + return 0; + } + + int vset_limits( char *domain, struct vlimits *limits ) + { + int err; + + /* if we can not connect, set the verrori value */ + if ( (err=vauth_open_update()) != 0 ) { + return(-1); + } + + snprintf( SqlBufUpdate, SQL_BUF_SIZE, "REPLACE INTO limits ( " + "domain, maxpopaccounts, maxaliases, " + "maxforwards, maxautoresponders, maxmailinglists, diskquota, " + "defaultquota, disablepop, disableimap, disabledialup, " + "disablepasswordchanging, disablewebmail, disablerelay ) \n" + "VALUES \n" + "('%s', %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", + domain, + limits->maxpopaccounts, + limits->maxaliases, + limits->maxforwards, + limits->maxautoresponders, + limits->maxmailinglists, + limits->diskquota, + limits->defaultquota, + limits->disablepop, + limits->disableimap, + limits->disabledialup, + limits->disablepasswordchanging, + limits->disablewebmail, + limits->disablerelay); + + if (mysql_query(&mysql_update,SqlBufUpdate)) { + vcreate_limits_table(); + if (mysql_query(&mysql_update,SqlBufUpdate)) { + fprintf(stderr, "vmysql: sql error[j]: %s\n", +mysql_error(&mysql_update)); + return(-1); + } + } + if (!(res_update = mysql_store_result(&mysql_update))) { + fprintf(stderr, "vmysql: store result failed\n"); + return -1; + } + mysql_free_result(res_update); + + return 0; + } + #endif +