#include #include #include #include #include #include #include #include #include #if 0 static char *strip_end(char *str) { int len = strlen(str); for (str += len - 1 ; len > 0 && (isspace(*str) || *str == 26) ; len--, str--) *str = '\0'; return str+1; } #endif static int popauth_getip (char ip[20]) { int ret = -1; char lineip[PATH_MAX]; if (fgets(lineip,sizeof(lineip)-1,stdin)!=NULL){ char *paren = strchr(lineip,'('); if (paren != NULL){ paren++; char *endparen = strchr(paren,')'); if (endparen != NULL){ *endparen = '\0'; if (strlen(paren) < 20){ strcpy (ip,paren); ret = 0; } } } } return ret; } static void usage() { fprintf (stderr,"popauth --setip map_path map_format\n"); fprintf (stderr,"Normal usage: popauth --setip /etc/mail/popauth hash\n"); fprintf (stderr,"\n"); fprintf (stderr,"popauth --clean map_path format seconds\n"); fprintf (stderr,"\tRemove old entries from the table\n"); } static int popauth_makemap( const char *db, const char *format, const char *key, const char *val) { int ret = -1; char cmd[PATH_MAX]; if (key == NULL){ snprintf (cmd,sizeof(cmd)-1,"makemap -o %s %s <%s",format,db,db); ret = system (cmd); }else{ snprintf (cmd,sizeof(cmd)-1,"makemap -o %s %s",format,db); FILE *fout = popen (cmd,"w"); if (fout != NULL){ fprintf (fout,"%s\t%s\n",key,val); ret = pclose (fout); } } return ret; } static FILE *fopen_lock (const char *fname, const char *mode) { FILE *ret = fopen (fname,mode); if (ret != NULL){ flock (fileno(ret),LOCK_EX); } return ret; } int main (int argc, char *argv[]) { int ret = -1; if (argc < 2){ usage(); }else if (strcmp(argv[1],"--setip")==0){ if (argc != 4){ usage(); }else{ const char *db = argv[2]; const char *format = argv[3]; char ip[20]; while (popauth_getip(ip)!=-1){ char date[20]; snprintf (date,sizeof(date)-1,"%lu",time(NULL)); FILE *fin = fopen_lock (db,"r+"); if (fin == NULL){ if (errno == ENOENT){ FILE *fout = fopen (db,"w"); if (fout == NULL){ fprintf (stderr,"Can't open %s (%s)\n",db,strerror(errno)); }else{ fprintf (fout,"%s\t%s\n",ip,date); fclose (fout); ret = popauth_makemap (db,format,ip,date); } }else{ fprintf (stderr,"Can't open %s (%s)\n",db,strerror(errno)); } }else{ char line[1000]; bool found = false; while (fgets(line,sizeof(line)-1,fin)!=NULL){ char key[1000],tmp[1000]; if (sscanf (line,"%s %s",key,tmp)==2){ if (strcmp(key,ip)==0){ found = true; } } } if (!found){ if (fseek (fin,0,SEEK_END) != -1){ fprintf (fin,"%s\t%s\n",ip,date); fflush (fin); ret = popauth_makemap (db,format,ip,date); } }else{ ret = 0; } fclose (fin); } } } }else if (strcmp(argv[1],"--clean")==0){ if (argc != 5){ usage(); }else{ const char *db = argv[2]; char dbtmp[PATH_MAX]; snprintf (dbtmp,sizeof(dbtmp)-1,"%s.tmp",db); const char *format = argv[3]; time_t ti = time(NULL)-atoi(argv[4]); FILE *fin = fopen_lock (db,"r"); if (fin != NULL){ FILE *fout = fopen (dbtmp,"w"); if (fout != NULL){ char line[1000]; bool removed = false; while (fgets(line,sizeof(line)-1,fin)!=NULL){ time_t t; char ip[1000]; if (sscanf(line,"%s %lu",ip,&t)==2 && t >= ti){ fputs (line,fout); }else{ removed = true; } } fclose (fout); if (removed){ rename (dbtmp,db); ret = popauth_makemap (db,format,NULL,NULL); }else{ ret = 0; unlink (dbtmp); } } fclose (fin); } } } return ret; }