/* $Id$ * * This file is part of pgets. * * pgets is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your * option) any later version. * * pgets 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 General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with pgets; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include "lock.h" #include "modem.h" #include "util.h" #include "db.h" #define ETS_RESET ('$') #define ETS_NEXT ('%') int verbose = 1; volatile int quit = 0; void sigint(int s) { const char *e = "\r*** Got SIGINT, exiting *** \n"; loop_write(2, e, strlen(e)); quit = 1; } int ets_reset(int fd) { char c = ETS_RESET; return (write(fd, &c, sizeof(c)) != sizeof(c)) ? -1 : 0; } int ets_next(int fd) { char c = ETS_NEXT; return (write(fd, &c, sizeof(c)) != sizeof(c)) ? -1 : 0; } int atoi_l(char *s, int l) { char *p = strndup(s, l); int r = atoi(p); free(p); return r; } int ets_parse(struct entry *entry, char *ln) { int i, t; memset(entry, 0, sizeof(struct entry)); if (ln[0] != '*') for (i = 0; i <= 20; i++) { if (ln[i] >= '0' && ln[i] <= '9') entry->remote_msn[i] = ln[i]; else break; } if (ln[25] >= '0' && ln[25] <= '9' && ln[26] >= '0' && ln[26] <= '9') { entry->local_mm = atoi_l(ln+25, 2); if (entry->local_mm <= 0) { fprintf(stderr, "Corrupt local MM column.\n"); return -1; } } if (ln[32] >= '0' && ln[32] <= '9' && ln[33] >= '0' && ln[33] <= '9') { entry->participant = atoi_l(ln+32, 2); if (!((entry->participant >= 31 && entry->participant <= 38) || (entry->participant >= 41 && entry->participant <= 48))) { fprintf(stderr, "Corrupt participant column.\n"); return -1; } } entry->incoming = ln[35] == 'K' ? 1 : 0; if (!(ln[39] >= '0' && ln[39] <= '9' && ln[40] >= '0' && ln[40] <= '9')) { fprintf(stderr, "Corrupt day column.\n"); return -1; } if (!(ln[42] >= '0' && ln[42] <= '9' && ln[43] >= '0' && ln[43] <= '9')) { fprintf(stderr, "Corrupt month column.\n"); return -1; } if (!(ln[45] >= '0' && ln[45] <= '9' && ln[46] >= '0' && ln[46] <= '9')) { fprintf(stderr, "Corrupt hour column.\n"); return -1; } if (!(ln[48] >= '0' && ln[48] <= '9' && ln[49] >= '0' && ln[49] <= '9')) { fprintf(stderr, "Corrupt minute column.\n"); return -1; } entry->day = atoi_l(ln+39, 2); entry->month = atoi_l(ln+42, 2); entry->hour = atoi_l(ln+45, 2); entry->minute = atoi_l(ln+48, 2); if (entry->day < 1 || entry->day > 31 || entry->month < 1 || entry->month > 12 || entry->hour < 0 || entry->hour > 24 || entry->minute < 0 || entry->minute >= 60) { fprintf(stderr, "Corrupt timespec column.\n"); return -1; } if (!((ln[51] == ' ' || (ln[51] >= '0' && ln[51] <= '9')) && (ln[52] == ' ' || (ln[52] >= '0' && ln[52] <= '9')) && ln[53] >= '0' && ln[53] <= '9')) { fprintf(stderr, "Corrupt minute (duration) column.\n"); return -1; } if (!(ln[55] >= '0' && ln[55] <= '9' && ln[56] >= '0' && ln[56] <= '9')) { fprintf(stderr, "Corrupt second (duration) column.\n"); return -1; } t = atoi_l(ln+55, 2); if (t < 0 || t >= 60) { fprintf(stderr, "Corrupt second (duration) column. (#2)\n"); return -1; } entry->duration = atoi_l(ln+51,3)*60 + t; if (entry->duration < 0) { fprintf(stderr, "Corrupt duration column.\n"); return -1; } return 0; } int ets_read_entry(int fd, struct entry *entry) { char ln[80]; int r; if ((r = read_line(fd, ln, sizeof(ln))) != 74) { if (r == 1 && ln[0] == '\n') return -2; fprintf(stderr, "Error while reading line (%i|%i).\n", r, (int) ln[0]); return -1; } if (ln[73] != '\n') { fprintf(stderr, "Corrupt line.\n"); return -1; } ln[73] = 0; if (ln[37] == 'V') return 0; if (ets_parse(entry, ln) == 0) return 1; fprintf(stderr, "Failure in line [%s]\n", ln); return -1; } void work(int fd, void *db) { int n = 0, v = 0, a = 0; if (ets_reset(fd) != 0) { fprintf(stderr, "Could not reset PBX.\n"); return; } // Accelerate a bit if (ets_next(fd) != 0) return; while (!quit) { struct entry entry; int r; if ((r = ets_read_entry(fd, &entry)) < 0) break; if (r > 0) { v++; if ((r = db_write_entry(db, &entry)) < 0) break; else if (r == 0) a++; } if (verbose) { fprintf(stderr, "%3.1f%% done; %i of %i valid entries added.\r", (float)(++n)/10, a, v); fflush(stdout); } if (ets_next(fd) != 0) break; } if (verbose) fprintf(stderr, "Finished; %i entries in PBX; %i of %i valid entries added.\n", n, a, v); } void help(const char *p) { fprintf(stderr, "%s [-h] [-q] [-d DEVICE] [-b DATABASE]\n" " -h Shows this help\n" " -q Disables verbose mode\n" " -d DEVICE specifies the serial device to use\n" " -b DATABASE specifies the database to use\n", p); exit(1); } int main(int argc, char *argv[]) { int fd = -1, r = 1, locked = 0; const char *dev = "/dev/ttyS1"; void *db = NULL; char* dbspec = NULL; int c; while ((c = getopt (argc, argv, "hqd:b:")) != -1) switch (c) { case 'q': verbose = 0; break; case 'b': dbspec = optarg; break; case 'd': dev = optarg; break; default: help(basename(argv[0])); break; } if (device_lock(dev, basename(argv[0])) != 0) goto finish; locked = 1; if ((fd = modem_open(dev)) < 0) goto finish; //"dbname=pgets user=pgets_fill password=mahatma" if (!(db = db_connect(dbspec))) goto finish; while (*dbspec) *(dbspec++) = 'X'; signal(SIGINT, sigint); siginterrupt(SIGINT, 0); flush_data(fd); work(fd, db); r = 0; finish: if (fd >= 0) modem_close(fd); if (db) db_disconnect(db); if (locked) device_unlock(dev); return r; }