From 78f4d7185530ac0991ecd5d59a7e2681e8a365ca Mon Sep 17 00:00:00 2001 From: vysheng Date: Thu, 3 Oct 2013 16:38:25 +0400 Subject: [PATCH] Added some files --- Makefile | 17 +++++ include.h | 6 ++ interface.c | 156 +++++++++++++++++++++++++++++++++++++++++ interface.h | 7 ++ loop.c | 44 ++++++++++++ loop.h | 4 ++ main.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++ telegram.h | 0 8 files changed, 432 insertions(+) create mode 100644 Makefile create mode 100644 include.h create mode 100644 interface.c create mode 100644 interface.h create mode 100644 loop.c create mode 100644 loop.h create mode 100644 main.c create mode 100644 telegram.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6b83182 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC=cc +CFLAGS=-c -Wall -Wextra -fPIC +LDFLAGS=-lreadline +LD=cc + +SRC=main.c loop.c interface.c +OBJ=$(SRC:.c=.o) +EXE=telegram + +all: $(SRC) $(EXE) + +$(EXE): $(OBJ) + $(LD) $(LDFLAGS) $(OBJ) -o $@ + +.c.o: + $(CC) $(CFLAGS) $< -o $@ + diff --git a/include.h b/include.h new file mode 100644 index 0000000..03f271d --- /dev/null +++ b/include.h @@ -0,0 +1,6 @@ +#ifndef __INCLUDE_H__ +#define __INCLUDE_H__ + +#define UU __attribute__ ((unused)) + +#endif diff --git a/interface.c b/interface.c new file mode 100644 index 0000000..61f6931 --- /dev/null +++ b/interface.c @@ -0,0 +1,156 @@ +#define _GNU_SOURCE +#include +#include + +#include +#include + +#include +#include +#include "include.h" +char *default_prompt = ">"; + +char *get_default_prompt (void) { + return default_prompt; +} + +char *complete_none (const char *text UU, int state UU) { + return 0; +} + +char *commands[] = { + "help", + "msg", + 0 }; + +int commands_flags[] = { + 070, + 072, +}; + +char *a = 0; +char **user_list = &a; +char **chat_list = &a; + +int init_token (char **q) { + char *r = *q; + while (*r == ' ') { r ++; } + if (!*r) { return 0; } + q = &r; + return 1; +} + +char *get_token (char **q, int *l) { + char *r = *q; + while (*r == ' ') { r ++; } + if (!*r) { + q = &r; + *l = 0; + return 0; + } + int neg = 0; + char *s = r; + while (*r && (*r != ' ' || neg)) { + if (*r == '\\') { + neg = 1 - neg; + } else { + neg = 0; + } + } + q = &r; + *l = r - s; + return s; +} + + +int get_complete_mode (void) { + char *q = rl_line_buffer; + if (!init_token (&q)) { return 0; } + int l = 0; + char *r = get_token (&q, &l); + if (!*q) { return 0; } + + char **command = commands; + int n = 0; + int flags = -1; + while (*command) { + if ((int)strlen (*command) == l && !memcmp (r, *command, l)) { + flags = commands_flags[n]; + break; + } + n ++; + command ++; + } + if (flags == -1) { + return -1; + } + int s = 0; + while (1) { + get_token (&q, &l); + if (!*q) { return flags & 7; } + s ++; + if (s <= 4) { flags >>= 3; } + } +} + +int complete_string_list (char **list, int index, const char *text, int len, char **R) { + index ++; + int cc = 0; + while (cc <= 1 && list[index] && strncmp (list[index], text, len)) { + index ++; + if (!list[index]) { index = 0; cc ++; } + } + if (list[index] && cc <= 1) { + *R = strdup (list[index]); + return index; + } else { + *R = 0; + return -1; + } +} +char *command_generator (const char *text, int state) { + static int len, index, mode; + + if (!state) { + len = strlen (text); + index = -1; + + rl_line_buffer[rl_point] = '\0'; /* the effect should be such + * that the cursor position + * is at the end of line for + * the auto completion regex + * above (note the $ at end) + */ + + mode = get_complete_mode (); + } else { + if (index == -1) { return 0; } + } + + if (mode == -1) { return 0; } + + char *R = 0; + switch (mode & 7) { + case 0: + index = complete_string_list (commands, index, text, len, &R); + return R; + case 1: + index = complete_string_list (user_list, index, text, len, &R); + return R; + case 2: + index = complete_string_list (chat_list, index, text, len, &R); + return R; + case 3: + return rl_filename_completion_function(text,state); + default: + return 0; + } +} + +char **complete_text (char *text, int start UU, int end UU) { + return (char **) rl_completion_matches (text, command_generator); +} + +void interpreter (char *line UU) { + assert (0); +} diff --git a/interface.h b/interface.h new file mode 100644 index 0000000..763dde8 --- /dev/null +++ b/interface.h @@ -0,0 +1,7 @@ +#ifndef __INTERFACE_H__ +#define __INTERFACE_H__ +char *get_default_prompt (void); +char *complete_none (const char *text, int state); +char **complete_text (char *text, int start, int end); +void interpreter (char *line); +#endif diff --git a/loop.c b/loop.c new file mode 100644 index 0000000..49be9ab --- /dev/null +++ b/loop.c @@ -0,0 +1,44 @@ +#define READLINE_CALLBACKS + +#include +#include + +#include +#include +#include +#include + +#include "interface.h" +extern char *default_username; +extern char *auth_token; +void set_default_username (const char *s); + + + +int main_loop (void) { + assert (0); +} + +int loop (void) { + size_t size = 0; + char *user = default_username; + + if (!user && !auth_token) { + printf ("Telephone number (with '+' sign): "); + if (getline (&user, &size, stdin) == -1) { + perror ("getline()"); + exit (EXIT_FAILURE); + } + user[strlen (user) - 1] = '\0'; + set_default_username (user); + } + + fflush (stdin); + + rl_callback_handler_install (get_default_prompt (), interpreter); + rl_attempted_completion_function = (CPPFunction *) complete_text; + rl_completion_entry_function = complete_none; + + return main_loop (); +} + diff --git a/loop.h b/loop.h new file mode 100644 index 0000000..d70a3e6 --- /dev/null +++ b/loop.h @@ -0,0 +1,4 @@ +#ifndef __LOOP_H__ +#define __LOOP_H__ +int loop (void); +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..cd3b7af --- /dev/null +++ b/main.c @@ -0,0 +1,198 @@ +/* + main.c: main initialization file + + This program 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, or (at + your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "loop.h" + +#define PROGNAME "telegram-client" +#define VERSION "0.01" + +#define CONFIG_DIRECTORY ".telegram/" +#define CONFIG_FILE CONFIG_DIRECTORY "config" +#define DOWNLOADS_DIRECTORY "downloads/" + +#define CONFIG_DIRECTORY_MODE 0700 + +#define DEFAULT_CONFIG_CONTENTS \ + "# This is an empty config file\n" \ + "# Feel free to put something here\n" + +char *default_username; +int setup_mode; +char *auth_token; + +void set_default_username (const char *s) { + if (default_username) { + free (default_username); + } + default_username = strdup (s); +} + +void set_setup_mode (void) { + setup_mode = 1; +} + + +/* {{{ TERMINAL */ +tcflag_t old_lflag; +cc_t old_vtime; +struct termios term; + +void get_terminal_attributes (void) { + if (tcgetattr (STDIN_FILENO, &term) < 0) { + perror ("tcgetattr()"); + exit (EXIT_FAILURE); + } + old_lflag = term.c_lflag; + old_vtime = term.c_cc[VTIME]; +} +/* }}} */ + +char *get_home_directory (void) { + struct passwd *current_passwd; + uid_t user_id; + setpwent (); + user_id = getuid (); + while ((current_passwd = getpwent ())) { + if (current_passwd->pw_uid == user_id) { + return current_passwd->pw_dir; + } + } + return 0; +} + +char *get_config_directory (void) { + char *config_directory; + int length = strlen (get_home_directory ()) + strlen (CONFIG_DIRECTORY) + 2; + + config_directory = (char *) calloc (length, sizeof (char)); + sprintf (config_directory, "%s/" CONFIG_DIRECTORY, + get_home_directory ()); + + return config_directory; +} + +char *get_config_filename (void) { + char *config_filename; + int length = strlen (get_home_directory ()) + strlen (CONFIG_FILE) + 2; + + config_filename = (char *) calloc (length, sizeof (char)); + sprintf (config_filename, "%s/" CONFIG_FILE, get_home_directory ()); + return config_filename; +} + +char *get_downloads_directory (void) +{ + char *downloads_directory; + int length = strlen (get_config_directory ()) + strlen (DOWNLOADS_DIRECTORY) + 2; + + downloads_directory = (char *) calloc (length, sizeof (char)); + sprintf (downloads_directory, "%s/" DOWNLOADS_DIRECTORY, get_config_directory ()); + + return downloads_directory; +} + +void running_for_first_time (void) { + struct stat *config_file_stat = NULL; + int config_file_fd; + char *config_directory = get_config_directory (); + char *config_filename = get_config_filename (); + char *downloads_directory = get_downloads_directory (); + + if (mkdir (config_directory, CONFIG_DIRECTORY_MODE) != 0) { + return; + } else { + printf ("\nRunning " PROGNAME " for first time!!\n"); + printf ("[%s] created\n", config_directory); + } + + // see if config file is there + if (stat (config_filename, config_file_stat) != 0) { + // config file missing, so touch it + config_file_fd = open (config_filename, O_CREAT | O_RDWR, S_IRWXU); + if (config_file_fd == -1) { + perror ("open[config_file]"); + exit (EXIT_FAILURE); + } + if (fchmod (config_file_fd, CONFIG_DIRECTORY_MODE) != 0) { + perror ("fchmod[" CONFIG_FILE "]"); + exit (EXIT_FAILURE); + } + if (write (config_file_fd, DEFAULT_CONFIG_CONTENTS, strlen (DEFAULT_CONFIG_CONTENTS)) <= 0) { + perror ("write[config_file]"); + exit (EXIT_FAILURE); + } + close (config_file_fd); + printf ("[%s] created\n", config_filename); + + /* create downloads directory */ + if (mkdir (downloads_directory, 0755) !=0) { + perror ("creating download directory"); + exit (EXIT_FAILURE); + } + } + + set_setup_mode (); +} + +void inner_main (void) { + loop (); +} + +void usage (void) { + printf ("%s [-u username]\n", PROGNAME); + exit (1); +} + +void args_parse (int argc, char **argv) { + int opt = 0; + while ((opt = getopt (argc, argv, "u:h")) != -1) { + switch (opt) { + case 'u': + set_default_username (optarg); + break; + case 'h': + default: + usage (); + break; + } + } +} + +int main (int argc, char **argv) { + running_for_first_time (); + + get_terminal_attributes (); + + args_parse (argc, argv); + + inner_main (); + + return 0; +} diff --git a/telegram.h b/telegram.h new file mode 100644 index 0000000..e69de29