#include "main.h" #include "readline.h" #include #include #include #include #include #include #include #include #include #include #include #include "wind.h" #include "sms.h" /* * Entry point of mesms and event loop */ #ifdef DEBUG #include #endif const int colors[] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE}; #define MAX_PATH 1024 #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) extern char* msg_win_str; extern conversation* currentConv; static bool visual_mode = false; WINDOW *cmd_win; WINDOW *sep_win; char status[10]; extern int firstSMSIndex; extern int canAugment; extern int showName; extern config_t config; void fail_exit(const char *msg) { if (visual_mode) endwin(); #ifdef DEBUG fprintf(stderr, "%s\n", msg); #endif exit(EXIT_FAILURE); } int main(int argc, char* argv[]){ #ifdef DEBUG freopen("/tmp/mesms.debug", "w", stderr); #endif setlocale(LC_ALL, ""); readConfigFile(); /* Gestion des paramètres */ while (1) { int c; int optIndex = 0; static struct option optlv[] = { {"help", no_argument, 0, 'h' }, {"version", no_argument, 0, 'v' }, {"contact", required_argument, 0, 'c' }, {NULL, 0, 0, 0 } }; c = getopt_long(argc, argv, "hvc:n:", optlv, &optIndex); if (c == -1) break; switch (c) { case 'v': if( !strcmp(optlv[optIndex].name, "version") ) { puts( VERSION_MESMS ); } break; case 'h': puts( HELP_STRING_MESMS ); return EXIT_SUCCESS; break; case 'c': if( optarg ) { int r = 0; if( r = fillContactList(config.CONTACT_FILENAME) ) { #ifdef DEBUG fprintf(stderr, "Error reading contact list\n"); #endif return r; } contact* contact = NULL; int nameOrNumber = 0; if( nameOrNumber = (*optarg == '+' ) ) r = findContact(optarg, &contact); else r = findContactFromName(optarg, &contact, NULL); if( r ) { #ifdef DEBUG fprintf(stderr, "Missing contact"); #endif printf("%s",optarg); return r; } if( nameOrNumber ) printf("%s", contact->display_name); else printf("%s", contact->number); return 0; } else { #ifdef DEBUG fprintf(stderr, "Missing phone number"); return EXIT_FAILURE; #endif } break; case '?': default: return EXIT_FAILURE; } } /* Initialisation */ int r = 0; if( *config.CONTACT_FILENAME && (r = fillContactList(config.CONTACT_FILENAME)) ) { #ifdef DEBUG fprintf(stderr, "Error reading contact list (%s)\n", config.CONTACT_FILENAME); #endif return r; } if( r = loadConv() ) { return r; } sortContacts(); /* Initialisation ncurses */ int c; int defaultBG = -1; initscr(); if (has_colors()) { if(use_default_colors() == ERR) defaultBG = COLOR_BLACK; CHECK(start_color); } CHECK(noecho); CHECK(nonl); CHECK(intrflush, stdscr, FALSE); CHECK(keypad, stdscr, TRUE); visual_mode = true; curs_set(0); cmd_win = newwin(1, COLS, LINES - 1, 0); sep_win = newwin(1, COLS, LINES - 2, 0); init_pair( 12, COLOR_WHITE, COLOR_BLUE); init_pair( 11, COLOR_RED, COLOR_RED); init_pair( 10, COLOR_GREEN, COLOR_GREEN); CHECK(wbkgd, sep_win, COLOR_PAIR(12)); CHECK(wrefresh, sep_win); init_readline(); const int nbColor = sizeof colors / sizeof *colors; for(int i = 1 ; i < nbColor ; i++) { init_pair( i, colors[i], defaultBG); } // inotify stuff int fd = inotify_init(), wd_in = -1, wd_out = -1; char buffer[EVENT_BUF_LEN]; char sms_filename[200]; /*checking for error*/ #ifdef DEBUG if ( fd < 0 ) { fprintf( stderr, "inotify_init init error"); } #endif if( fd >= 0 ) { fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK); if( *config.SMS_SENTBOX ) { wd_out = inotify_add_watch( fd, config.SMS_SENTBOX, IN_MOVED_TO); } if( *config.SMS_INBOX ) { wd_in = inotify_add_watch( fd, config.SMS_INBOX, IN_CREATE ); // From SMS_OUTBOX to SMS_SENTBOX } } /* Premier affichage */ resize(); int tabed = 0; /* Event loop */ while( c = getch() ) { int ret = read( fd, buffer, EVENT_BUF_LEN ); int i = 0; while( ret > 0 ) { struct inotify_event *event = (struct inotify_event*) (buffer+i); ret -= EVENT_SIZE + event->len; i += EVENT_SIZE + event->len; if ( event->len && (event->mask & IN_CREATE || event->mask & IN_MOVED_TO) && !( event->mask & IN_ISDIR ) ) { #ifdef DEBUG fprintf(stderr, "New SMS (%s)\n", event->name); #endif if( strncmp(event->name, "IN", 2) == 0 ) { sprintf(sms_filename, "%s%s", config.SMS_INBOX, event->name); readSMS(sms_filename, SMS_IN, SMS_UNREAD); } else { sprintf(sms_filename, "%s%s", config.SMS_SENTBOX, event->name); readSMS(sms_filename, SMS_OUT, SMS_UNREAD); } } } if( i > 0 ) { showContactListW(); } if (c == KEY_RESIZE) { resize(); refresh(); continue; } if ( c == 'q' ) { break; } switch( c ) { case KEY_DOWN: case KEY_RIGHT: case 'j': if( !tabed ) { selectNextContact(); showContactListW(); } else { if( canAugment ) firstSMSIndex++; clearWind(); showMessageWind(); } break; case KEY_UP: case KEY_LEFT: case 'k': if( !tabed ) { selectPreviousContact(); showContactListW(); } else { if( firstSMSIndex > 0 ) firstSMSIndex--; canAugment=1; clearWind(); showMessageWind(); } break; case '\t': if( currentConv ) tabed = !tabed; break; case '/': // Search by name if( !tabed ) { contact* found = NULL; move(LINES-1,0); readline_n("> ", ""); int r = findContactFromName(msg_win_str, &found, getContactSelected()); if( r == 0 ) { setContactSelection(found); } curs_set(0); showContactListW(); } else { move(LINES-1,0); readline_n("/ ", ""); if(!*msg_win_str) break; int res = searchSMS(msg_win_str); if( res >= 0 ) { canAugment = 1; firstSMSIndex = res; clearWind(); showMessageWind(); } } break; case 'n': showName = !showName; showContactListW(); break; case '\r': { contact* tmp = getContactSelected(); currentConv = tmp->conversation; toTheEnd(); resize(); } break; case 'd': { contact* selected = getContactSelected(); readline_n("Delete contact | Type 'yes' to confirm : ", ""); if( strcmp(msg_win_str, "yes") == 0) { deleteContact(selected); writeContactList(config.CONTACT_FILENAME); showContactListW(); } break; } case 'e': { contact* selected = getContactSelected(); readline_n("Edit contact | Name : ", selected->name); strcpy(selected->name, msg_win_str); readline_n("Edit contact | Display name : ", selected->display_name); strcpy(selected->display_name, msg_win_str); writeContactList(config.CONTACT_FILENAME); showContactListW(); } break; case 'a': if( !tabed ) { contact newContact = {"", "", "", 0, NULL}; readline_n("New contact | Name : ", ""); if( !*msg_win_str ) break; strcpy(newContact.name, msg_win_str); readline_n("New contact | Display name : ", ""); strcpy(newContact.display_name, msg_win_str); if( !*msg_win_str ) break; readline_n("New contact | Number : ", ""); strcpy(newContact.number, msg_win_str); addContact(&newContact); if( !*config.CONTACT_FILENAME ) { wordexp_t p; r = wordexp("~/.mesms_contacts.csv", &p, 0); if( r == 0 && p.we_wordc > 0 ) { strcpy(config.CONTACT_FILENAME, p.we_wordv[0]); } } writeContactList(config.CONTACT_FILENAME); showContactListW(); } break; case 'h': runtimeHelp(); resize(); break; case 'i': case 's': { char* number = NULL; contact* currentContact = getContactSelected(); char* contactName = "???"; sms* lastMessage = NULL; if( currentContact ) contactName = currentContact->display_name; if( currentConv ) { number = currentConv->number; int tmpLastIndex = currentConv->nbSMS - 1; while(tmpLastIndex >= 0 && currentConv->listSMS[tmpLastIndex].in_out) tmpLastIndex--; if( tmpLastIndex >= 0 ) lastMessage = ¤tConv->listSMS[tmpLastIndex]; } else { if( !contactName ) { // Should be a repported error break; } number = currentContact->number; } const char* defaultEditor = "vim", * const envEditor = getenv("EDITOR"), * const visEditor = getenv("VISUAL"); if( envEditor && envEditor[0] ) { defaultEditor = envEditor; } if( visEditor && visEditor[0] ) { defaultEditor = visEditor; } FILE* tmp = NULL; char fileName[] = "mesms_XXXXXX"; int fd = mkstemp(fileName); { FILE* infos = fdopen(fd, "w"); fputc('\n', infos); if( lastMessage && lastMessage->text) { fprintf(infos, "\n\n# >"); for(int i = 0; lastMessage->text[i]; ++i) { if(lastMessage->text[i] == '\n') fprintf(infos, "\n# >"); else fputc(lastMessage->text[i], infos); } } fprintf(infos, "\n#\n# %s", contactName); fclose(infos); } char* cmd = malloc(2 + strlen(defaultEditor) + strlen(fileName) ); sprintf( cmd, "%s %s", defaultEditor, fileName ); edit: system(cmd); free(cmd); { FILE* r = fopen(fileName,"r"); FILE* t = tmpfile(); int c = 0; int nb = 0; int lastCR = -1; fpos_t posLastCR = {}; while( (c = fgetc(r)) != EOF ) { if(c == '\n') { bool isEnd = 1; lastCR = nb; fgetpos(r, &posLastCR); int C = c; while( (C = fgetc(r)) != EOF) { if(C == '\n'); else if(C == '#') while( (C = fgetc(r)) != '\n' && C != EOF); else { isEnd = 0; break; } } if(isEnd) { break; } else { fsetpos(r, &posLastCR); } } nb++; fputc(c,t); } char* string = malloc( nb+1 ); fclose(r); unlink( fileName ); rewind(t); nb = 0; while( (c = fgetc(t)) != EOF ) { string[nb++] = c; } string[nb] = 0; contact* d = NULL; findContact(number, &d); int ret = 0; if( (ret = confirmSend(string, d->display_name)) == 1 ) { int toGammu[2]; pipe(toGammu); pid_t cpid = fork(); if(cpid == 0) { dup2(toGammu[0], 0); close(toGammu[1]); close(STDOUT_FILENO); execvp("gammu-smsd-inject", (char*[]){"gammu-smsd-inject", "TEXT", number, "-len", "400", "-unicode"}); } else if(cpid > 0) { close(toGammu[0]); FILE* gammuInput = fdopen(toGammu[1], "w"); if( gammuInput ) { fprintf(gammuInput, "%s", string); fclose(gammuInput); } } } else if( ret == 2 ) { goto edit; } } resize(); } case KEY_HOME: if ( tabed ) { firstSMSIndex = 0; clearWind(); showMessageWind(); } break; case KEY_END: if ( tabed ) { toTheEnd(); clearWind(); showMessageWind(); } } } // inotify stuff if( wd_in >= 0 ) { inotify_rm_watch( fd, wd_in ); } if( wd_out >= 0 ) { inotify_rm_watch( fd, wd_out ); } end: endwin(); return 0; }