diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | lor | 416 | ||||
-rw-r--r-- | src/api.c | 89 | ||||
-rw-r--r-- | src/main.c | 63 | ||||
-rw-r--r-- | src/ui.c | 84 |
7 files changed, 218 insertions, 444 deletions
@@ -1,6 +1,4 @@ lib/cJSON.h lib/cJSON.c -lib/linenoise.c -lib/linenoise.h # the following is the binary discord.c @@ -1,9 +1,7 @@ default: - gcc -g -Ilib -Isrc -I. -pthread src/api.c -lcurl -odiscord.c + gcc -Wall -pedantic -g -Ilib -Isrc -I. -pthread src/api.c -lcurl -lncurses -lform -odiscord.c prepare: wget https://raw.githubusercontent.com/DaveGamble/cJSON/master/cJSON.c -O lib/cJSON.c wget https://raw.githubusercontent.com/DaveGamble/cJSON/master/cJSON.h -O lib/cJSON.h - wget https://raw.githubusercontent.com/antirez/linenoise/master/linenoise.h -O lib/linenoise.h - wget https://raw.githubusercontent.com/antirez/linenoise/master/linenoise.c -O lib/linenoise.c clean: - rm lib/cJSON.c lib/cJSON.h lib/linenoise.h lib/linenoise.c + rm lib/cJSON.c lib/cJSON.h @@ -9,7 +9,7 @@ an alternative client for the discord messaging platform, written in the C progr * GNU compiler collection * GNU Make * libcurl 7.17.0 or newer with HTTPS support -* [linenoise](//github.com/antirez/linenoise) library +* ncursesw ## instructions @@ -1,416 +0,0 @@ -gcc -g -Ilib -Isrc -I. -pthread src/api.c -lcurl -odiscord.c -src/api.c: In function ‘dc_client_init’: -src/api.c:167:64: error: pasting "->" and "c" does not give a valid preprocessing token - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:168:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->authorization); - ^~~~~~~ -src/api.c:167:64: error: ‘struct dc_client’ has no member named ‘c’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:168:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->authorization); - ^~~~~~~ -src/api.c:167:40: error: too many arguments to function ‘pthread_rwlock_destroy’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:168:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->authorization); - ^~~~~~~ -In file included from src/api.c:16: -/usr/include/pthread.h:894:12: note: declared here - extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:167:64: error: pasting "->" and "c" does not give a valid preprocessing token - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:169:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->username); - ^~~~~~~ -src/api.c:167:64: error: ‘struct dc_client’ has no member named ‘c’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:169:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->username); - ^~~~~~~ -src/api.c:167:40: error: too many arguments to function ‘pthread_rwlock_destroy’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:169:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->username); - ^~~~~~~ -In file included from src/api.c:16: -/usr/include/pthread.h:894:12: note: declared here - extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:167:64: error: pasting "->" and "c" does not give a valid preprocessing token - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:170:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->guilds); - ^~~~~~~ -src/api.c:167:64: error: ‘struct dc_client’ has no member named ‘c’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:170:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->guilds); - ^~~~~~~ -src/api.c:167:40: error: too many arguments to function ‘pthread_rwlock_destroy’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:170:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->guilds); - ^~~~~~~ -In file included from src/api.c:16: -/usr/include/pthread.h:894:12: note: declared here - extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:167:64: error: pasting "->" and "c" does not give a valid preprocessing token - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:171:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->errors); - ^~~~~~~ -src/api.c:167:64: error: ‘struct dc_client’ has no member named ‘c’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:171:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->errors); - ^~~~~~~ -src/api.c:167:40: error: too many arguments to function ‘pthread_rwlock_destroy’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:171:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->errors); - ^~~~~~~ -In file included from src/api.c:16: -/usr/include/pthread.h:894:12: note: declared here - extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:167:64: error: pasting "->" and "c" does not give a valid preprocessing token - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:172:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->sent_messages); - ^~~~~~~ -src/api.c:167:64: error: ‘struct dc_client’ has no member named ‘c’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~ -src/api.c:172:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->sent_messages); - ^~~~~~~ -src/api.c:167:40: error: too many arguments to function ‘pthread_rwlock_destroy’ - #define DC_CILD(name) if (name##_lock) pthread_rwlock_destroy(c->##name##_lock, NULL) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c:172:2: note: in expansion of macro ‘DC_CILD’ - DC_CILD(c->sent_messages); - ^~~~~~~ -In file included from src/api.c:16: -/usr/include/pthread.h:894:12: note: declared here - extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) - ^~~~~~~~~~~~~~~~~~~~~~ -src/api.c: In function ‘dc_fetch_guilds’: -src/api.c:403:29: error: expected ‘;’ before ‘{’ token - DC_CWLE(c, c->guilds_lock) {rs = -5; goto rc;} - ^ -In file included from src/api.c:11: -src/api.c:405:21: error: ‘guild’ undeclared (first use in this function); did you mean ‘dc_guild’? - cJSON_ArrayForEach(guild, json) { - ^~~~~ -lib/cJSON.h:283:48: note: in definition of macro ‘cJSON_ArrayForEach’ - #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - ^~~~~~~ -src/api.c:405:21: note: each undeclared identifier is reported only once for each function it appears in - cJSON_ArrayForEach(guild, json) { - ^~~~~ -lib/cJSON.h:283:48: note: in definition of macro ‘cJSON_ArrayForEach’ - #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - ^~~~~~~ -src/api.c:424:28: error: expected ‘;’ before ‘{’ token - DC_CUE(c, c->guilds_lock) {rs = -6; goto rc;} - ^ -src/api.c:401:3: error: label ‘rc’ used but not defined - goto rc; - ^~~~ -src/api.c: In function ‘dc_fetch_channels’: -src/api.c:435:26: warning: initialization of ‘struct dc_channel *’ from incompatible pointer type ‘struct dc_client *’ [-Wincompatible-pointer-types] - struct dc_channel * c = g->client; - ^ -src/api.c:438:7: error: ‘struct dc_channel’ has no member named ‘discriminator’ - if (c->discriminator < 0) - ^~ -src/api.c:439:22: warning: passing argument 1 of ‘dc_login’ from incompatible pointer type [-Wincompatible-pointer-types] - if ((rs = dc_login(c)) < 0) { - ^ -src/api.c:262:34: note: expected ‘struct dc_client *’ but argument is of type ‘struct dc_channel *’ - int dc_login (struct dc_client * c) { /* noui */ - ~~~~~~~~~~~~~~~~~~~^ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:440:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); - ^~~~~~~~~~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:440:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); - ^~~~~~~~~~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:440:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); - ^~~~~~~~~~~~~~~ -In file included from /usr/include/x86_64-linux-gnu/curl/curl.h:2826, - from src/api.c:6: -src/api.c:449:20: error: ‘struct dc_channel’ has no member named ‘curl’ - curl_easy_setopt(c->curl, CURLOPT_URL, url); - ^~ -src/api.c:450:20: error: ‘struct dc_channel’ has no member named ‘curl’ - curl_easy_setopt(c->curl, CURLOPT_HTTPGET, 1L); - ^~ -src/api.c:451:20: error: ‘struct dc_channel’ has no member named ‘curl’ - curl_easy_setopt(c->curl, CURLOPT_WRITEDATA, &s); - ^~ -src/api.c:452:27: error: ‘struct dc_channel’ has no member named ‘curl’ - res = curl_easy_perform(c->curl); - ^~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:454:3: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "curl_easy_perform(c->curl) " DC_I18N_FAILED ": %s", curl_easy_strerror(res)); - ^~~~~~~~~~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:454:3: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "curl_easy_perform(c->curl) " DC_I18N_FAILED ": %s", curl_easy_strerror(res)); - ^~~~~~~~~~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:454:3: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "curl_easy_perform(c->curl) " DC_I18N_FAILED ": %s", curl_easy_strerror(res)); - ^~~~~~~~~~~~~~~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:462:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %s", error_ptr); - ^~~~~~~~~~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:462:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %s", error_ptr); - ^~~~~~~~~~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:462:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED ": " DC_I18N_JSON_ERROR_BEFORE ": %s", error_ptr); - ^~~~~~~~~~~~~~~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:464:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED); - ^~~~~~~~~~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:464:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED); - ^~~~~~~~~~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:464:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "cJSON_Parse " DC_I18N_FAILED); - ^~~~~~~~~~~~~~~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:470:3: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "!cJSON_IsArray(json), s.ptr = %s", s.ptr); - ^~~~~~~~~~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:470:3: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "!cJSON_IsArray(json), s.ptr = %s", s.ptr); - ^~~~~~~~~~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:470:3: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "!cJSON_IsArray(json), s.ptr = %s", s.ptr); - ^~~~~~~~~~~~~~~ -src/api.c:475:18: error: ‘struct dc_channel’ has no member named ‘guilds_lock’ - if (DC_CWLE(c, c->guilds_lock)) {rs = -7; goto rc;} - ^~ -src/api.c:26:49: note: in definition of macro ‘DC_CWLE’ - #define DC_CWLE(c, name) (pthread_rwlock_wrlock(name) ? (DC_CLIENT_ERROR(c, DC_I18N_LOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:26:58: note: in expansion of macro ‘DC_CLIENT_ERROR’ - #define DC_CWLE(c, name) (pthread_rwlock_wrlock(name) ? (DC_CLIENT_ERROR(c, DC_I18N_LOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~~~~~~~~~~~~ -src/api.c:475:6: note: in expansion of macro ‘DC_CWLE’ - if (DC_CWLE(c, c->guilds_lock)) {rs = -7; goto rc;} - ^~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:26:58: note: in expansion of macro ‘DC_CLIENT_ERROR’ - #define DC_CWLE(c, name) (pthread_rwlock_wrlock(name) ? (DC_CLIENT_ERROR(c, DC_I18N_LOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~~~~~~~~~~~~ -src/api.c:475:6: note: in expansion of macro ‘DC_CWLE’ - if (DC_CWLE(c, c->guilds_lock)) {rs = -7; goto rc;} - ^~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:26:58: note: in expansion of macro ‘DC_CLIENT_ERROR’ - #define DC_CWLE(c, name) (pthread_rwlock_wrlock(name) ? (DC_CLIENT_ERROR(c, DC_I18N_LOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~~~~~~~~~~~~ -src/api.c:475:6: note: in expansion of macro ‘DC_CWLE’ - if (DC_CWLE(c, c->guilds_lock)) {rs = -7; goto rc;} - ^~~~~~~ -In file included from src/api.c:11: -src/api.c:476:21: error: ‘channel’ undeclared (first use in this function); did you mean ‘dc_channel’? - cJSON_ArrayForEach(channel, json) { - ^~~~~~~ -lib/cJSON.h:283:48: note: in definition of macro ‘cJSON_ArrayForEach’ - #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - ^~~~~~~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:482:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "!id || !name || type == NAN"); - ^~~~~~~~~~~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:482:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "!id || !name || type == NAN"); - ^~~~~~~~~~~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:482:4: note: in expansion of macro ‘DC_CLIENT_ERROR’ - DC_CLIENT_ERROR(c, "!id || !name || type == NAN"); - ^~~~~~~~~~~~~~~ -src/api.c:503:17: error: ‘struct dc_channel’ has no member named ‘guilds_lock’ - if (DC_CUE(c, c->guilds_lock)) {rs = -8; goto rc;} - ^~ -src/api.c:28:48: note: in definition of macro ‘DC_CUE’ - #define DC_CUE(c, name) (pthread_rwlock_unlock(name) ?(DC_CLIENT_ERROR(c, DC_I18N_UNLOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~ -src/api.c:22:46: error: ‘struct dc_channel’ has no member named ‘errors’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:49: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:28:56: note: in expansion of macro ‘DC_CLIENT_ERROR’ - #define DC_CUE(c, name) (pthread_rwlock_unlock(name) ?(DC_CLIENT_ERROR(c, DC_I18N_UNLOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~~~~~~~~~~~~ -src/api.c:503:6: note: in expansion of macro ‘DC_CUE’ - if (DC_CUE(c, c->guilds_lock)) {rs = -8; goto rc;} - ^~~~~~ -src/api.c:22:60: error: ‘struct dc_channel’ has no member named ‘errors_sizeof’; did you mean ‘messages_sizeof’? - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~~~~~~~~~~~~ -src/api.c:21:52: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:28:56: note: in expansion of macro ‘DC_CLIENT_ERROR’ - #define DC_CUE(c, name) (pthread_rwlock_unlock(name) ?(DC_CLIENT_ERROR(c, DC_I18N_UNLOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~~~~~~~~~~~~ -src/api.c:503:6: note: in expansion of macro ‘DC_CUE’ - if (DC_CUE(c, c->guilds_lock)) {rs = -8; goto rc;} - ^~~~~~ -src/api.c:22:76: error: ‘struct dc_channel’ has no member named ‘errors_lock’ - #define DC_CLIENT_ERROR(c, m, ...) DC_ERROR(c->errors, &c->errors_sizeof, c->errors_lock, m __VA_OPT__(,) __VA_ARGS__) /* yeah, that m is not a typo */ - ^~ -src/api.c:21:55: note: in definition of macro ‘DC_ERROR’ - #define DC_ERROR(e, s, l, m, ...) dc_push_error(e, s, l, __func__, __FILE__, __LINE__, 0##__VA_OPT__(1), m __VA_OPT__(,) __VA_ARGS__) - ^ -src/api.c:28:56: note: in expansion of macro ‘DC_CLIENT_ERROR’ - #define DC_CUE(c, name) (pthread_rwlock_unlock(name) ?(DC_CLIENT_ERROR(c, DC_I18N_UNLOCKING " " #name " " DC_I18N_FAILED) || 1) : 0) - ^~~~~~~~~~~~~~~ -src/api.c:503:6: note: in expansion of macro ‘DC_CUE’ - if (DC_CUE(c, c->guilds_lock)) {rs = -8; goto rc;} - ^~~~~~ -make: *** [Makefile:2: default] Error 1 @@ -1,3 +1,6 @@ +#if __INCLUDE_LEVEL__ != 0 +#pragma once +#endif #define _XOPEN_SOURCE 600 #define _POSIX_C_SOURCE 200809L #include <sys/types.h> @@ -63,14 +66,14 @@ struct dc_error { time_t time; short unsigned int reported /* 0: error was not yet shown to the user, 1: error was already shown to the user */; }; -int dc_error_free(struct dc_error * e) { /* noui, noapi, nolock - only called by dc_client_free */ +void dc_error_free(struct dc_error * e) { /* noui, noapi, nolock - only called by dc_client_free */ free(e->message); e->message = NULL; /* other strings are static */ e->line = 0; e->function = NULL; e->file = NULL; e->reported = 0; free(e); -}; +} struct dc_message { char * username; /* yesfree */ int discriminator; @@ -81,7 +84,7 @@ struct dc_message { unsigned long long int id; /* nouiw */ unsigned short int status; /* noapiw - 0 if it was not yet printed on the display, 1 if it was */ }; -int dc_message_free (struct dc_message * m) { /* noui, noapi, nolock - only called by dc_channel_free */ +void dc_message_free (struct dc_message * m) { /* noui, noapi, nolock - only called by dc_channel_free */ free(m->username); m->username = NULL; free(m->content); m->content = NULL; m->channel = NULL; @@ -105,7 +108,7 @@ struct dc_channel { struct dc_message ** messages; /* yesfree, nouiw */ _Atomic(size_t) messages_sizeof; /* nouiw */ }; -int dc_channel_free (struct dc_channel * ch) { /* noui, noapi, nolock - only called by dc_guild_free */ +void dc_channel_free (struct dc_channel * ch) { /* noui, noapi, nolock - only called by dc_guild_free */ free(ch->name); ch->name = NULL; free(ch->topic); ch->topic = NULL; ch->guild = NULL; @@ -123,7 +126,7 @@ struct dc_guild { struct dc_channel ** channels; /* yesfree, nouiw */ _Atomic(struct dc_client *) client; /* nofree - obviously */ }; -int dc_guild_free (struct dc_guild * g) { /* noui, noapi, nolock - only called by dc_client_free */ +void dc_guild_free (struct dc_guild * g) { /* noui, noapi, nolock - only called by dc_client_free */ free(g->name); g->name = NULL; g->id = 0; for (int i = 0; i < g->channels_sizeof; i++) @@ -141,7 +144,7 @@ struct dc_client { char * password; /* yesfree, noapiw, nolock */ char * username; /* yesfree, nouiw */ pthread_rwlock_t * username_lock; - _Atomic(int) discriminator; /* nouiw - < 0 indicates that the user is not logged in - set last in login procedure */ + _Atomic(int) discriminator; /* nouiw - -1: the user is not logged in, -2: user login failed and will not be retried, < 0: the user is not logged in */ struct dc_guild ** guilds; /* yesfree, nouiw */ _Atomic(size_t) guilds_sizeof; /* nouiw */ pthread_rwlock_t * guilds_lock; @@ -173,7 +176,7 @@ struct dc_client * dc_client_init () { /* gives you a prepared dc_client */ free(c); return NULL; /* don't even check for this, if pthread_rwlock_init fails we'll segfault */ } -int dc_client_free (struct dc_client * c) { /* noui, noapi, nolock - only called by main on exit */ +void dc_client_free (struct dc_client * c) { /* noui, noapi, nolock - only called by main on exit */ curl_easy_cleanup(c->curl); curl_slist_free_all(c->curl_headers); free(c->authorization); c->authorization = NULL; @@ -241,7 +244,7 @@ cJSON * dc_api (CURL * curl, char * body, int isfmt, char * endpoint, ...) { /* va_copy(ap2, ap); size_t strlenm = vsnprintf(NULL, 0, endpoint, ap); endpoint_formatted = malloc(sizeof(char)*strlenm+1); - vsnprintf(endpoint_formatted, strlenm, endpoint_formatted, ap2); /* sn instead of s because double evaulation may produce */ + vsnprintf(endpoint_formatted, strlenm, endpoint, ap2); /* sn instead of s because double evaulation may produce */ va_end(ap); /* larger output the next time and lead to overflow */ va_end(ap2); } @@ -280,6 +283,7 @@ int dc_login (struct dc_client * c) { /* noui */ data = malloc(strlen(DC_LOGIN_FORMAT)+strlen(c->email)+strlen(c->password)+1); CURLcode res; sprintf(data, DC_LOGIN_FORMAT, c->email, c->password); + curl_slist_free_all(c->curl_headers); c->curl_headers = curl_slist_append(c->curl_headers, "Content-Type: application/json"); c->curl_headers = curl_slist_append(c->curl_headers, "User-Agent: " DC_USER_AGENT); curl_easy_setopt(c->curl, CURLOPT_URL, DC_API_PREFIX "auth/login"); @@ -369,11 +373,12 @@ int dc_fetch_guilds (struct dc_client * c) { char * value2 = NULL; CURLcode res; cJSON * json = NULL; - if (c->discriminator < 0) + if (c->discriminator < 0) { if ((rs = dc_login(c)) < 0) { DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); return -1; } else rs = 1; + } curl_easy_setopt(c->curl, CURLOPT_URL, DC_API_PREFIX "users/@me/guilds"); curl_easy_setopt(c->curl, CURLOPT_HTTPGET, 1L); curl_easy_setopt(c->curl, CURLOPT_WRITEDATA, &s); @@ -413,7 +418,7 @@ int dc_fetch_guilds (struct dc_client * c) { for (int i = 0; i < c->guilds_sizeof; i++) if (idull == c->guilds[i]->id) continue; /* remove duplicates */ - c->guilds = realloc(c->guilds, ++c->guilds_sizeof); + c->guilds = realloc(c->guilds, sizeof(struct dc_guild *)*++c->guilds_sizeof); c->guilds[c->guilds_sizeof-1]->name = malloc(strlen(value)+1); strcpy(c->guilds[c->guilds_sizeof-1]->name, value); c->guilds[c->guilds_sizeof-1]->id = idull; @@ -435,11 +440,12 @@ int dc_fetch_channels (struct dc_guild * g) { struct dc_client * c = g->client; if (!c) return -2; - if (c->discriminator < 0) + if (c->discriminator < 0) { if ((rs = dc_login(c)) < 0) { DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); return -3; } else rs = 1; + } CURLcode res; struct writefunc_string s; init_writefunc_string(&s); @@ -491,7 +497,7 @@ int dc_fetch_channels (struct dc_guild * g) { for (int i = 0; i < g->channels_sizeof; i++) if (idull == g->channels[i]->id) continue; /* remove duplicates */ - g->channels = realloc(g->channels, ++g->channels_sizeof); + g->channels = realloc(g->channels, sizeof(struct dc_channel *)*++g->channels_sizeof); g->channels[g->channels_sizeof-1]->name = malloc(strlen(name)+1); strcpy(g->channels[g->channels_sizeof-1]->name, name); g->channels[g->channels_sizeof-1]->topic = malloc(strlen(topic)+1); @@ -515,11 +521,12 @@ int dc_send_message (struct dc_message * m) { /* nolock - once message is append struct dc_client * c = m->channel->guild->client; /* segfault senpai */ if (!c) return -2; - if (!c->username || !c->username[0]) + if (c->discriminator < 0) { if ((rs = dc_login(c)) < 0) { DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); return -3; } else rs = 1; + } cJSON * json = cJSON_CreateObject(); cJSON * nons = cJSON_CreateNumber(rand()); cJSON_AddItemToObject(json, "nonce", nons); @@ -577,11 +584,12 @@ int dc_fetch_messages (struct dc_channel * ch) { struct dc_client * c = g->client; if (!c) return -3; - if (c->discriminator < 0) + if (c->discriminator < 0) { if ((rs = dc_login(c)) < 0) { DC_CLIENT_ERROR(c, "dc_login(c) " DC_I18N_FAILED " (%d)", rs); return -4; } else rs = 1; + } cJSON * json = DC_API(c->curl, NULL, DC_API_PREFIX "channels/%llu/messages?limit=100&_=%d", ch->id, rand()); if (!json) { const char *error_ptr = cJSON_GetErrorPtr(); @@ -615,7 +623,7 @@ int dc_fetch_messages (struct dc_channel * ch) { continue; } for (int i = 20; i <= 25; i++) - timestamp[i] == 'X'; /* because strptime does not have wildcard support and those numbers are sub-second fractions */ + timestamp[i] = 'X'; /* because strptime does not have wildcard support and those numbers are sub-second fractions */ if (!strptime(timestamp, DC_TIMESTAMP_FORMAT, &tm)) { DC_CLIENT_ERROR(c, "strptime(timestamp, DC_TIMESTAMP_FORMAT, &tm) " DC_I18N_FAILED); continue; @@ -624,7 +632,7 @@ int dc_fetch_messages (struct dc_channel * ch) { for (int i = 0; i < ch->messages_sizeof; i++) if (idull == ch->messages[i]->id) continue; /* remove duplicates */ - ch->messages = realloc(ch->messages, ++ch->messages_sizeof); + ch->messages = realloc(ch->messages, sizeof(struct dc_message *)**+ch->messages_sizeof); #define DC_FMTM /* fetch messages this message */ ch->messages[ch->messages_sizeof-1] DC_FMTM->time = mktime(&tm); DC_FMTM->content = malloc(strlen(content)+1); @@ -641,12 +649,51 @@ int dc_fetch_messages (struct dc_channel * ch) { cJSON_Delete(json); json = NULL; return rs; } -struct dc_api_thread_control { - unsigned short int power; /* 1 if the thread should run, set it to 0 for the thread to return at the end of the loop */ +struct dc_thread_control { + unsigned short int power_api; /* 1 if the thread should run, set it to 0 for the thread to return at the end of the loop */ + unsigned short int power_ui; /* so same struct can be used for both api and ui thread, they have individual power switches */ struct dc_client ** clients; /* "array" of pointers to clients the thread should manage, ONLY ONE dc_api_thread PER PROCESS! */ - _Atomic(size_t) dc_clients_sizeof; - pthread_rwlock_t * clients_lock; + _Atomic(size_t) clients_sizeof; /* noapiw */ + pthread_rwlock_t * clients_lock; /* do not lock yet. you can use safe-appending from the ui thread by never reallocing the pointers and only incrementing _sizeof - don't even init&destroy*/ + FILE * cout; /* file descriptor of the terminal for the ui thread to write to */ + FILE * cin; /* file descriptor of the terminal for the ui thread to read from */ + FILE * cerr; /* file descriptor of the terminal for the ui thread to write error messages to */ }; -int dc_api_thread (struct dc_api_thread_control * t) { /* updates messages and sends messages when they are in the outbox */ +int dc_api_thread (struct dc_thread_control * t) { /* updates messages and sends messages when they are in the outbox */ + /* if (pthread_rwlock_wrlock(t->clients_lock)) + return -1; */ /* clients are not locked yet */ + for (int i = 0; i < t->clients_sizeof; i++) + dc_login(t->clients[i]); + while (t->power_api == 1) { /* as there's only one api thread and only it modifies things that need a guilds_lock, it's okay to */ + for (int i = 0; i < t->clients_sizeof; i++) { /* perform such unsafe loops without read-locking. note that you will deadlock */ + if (t->clients[i]->discriminator < -1) /* should you attempt to read-lock guilds_lock. */ + continue; /* the only exception is sent_messages that is write-locked */ + if (!t->clients[i]->guilds_sizeof || !(rand() % 1000)) /* roughly every 1000 cycles we'll update guilds */ + dc_fetch_guilds(t->clients[i]); + for (int j = 0; j < t->clients[i]->guilds_sizeof; j++) { + if (!t->clients[i]->guilds[j]->channels_sizeof || !(rand() % 100)) /* roughly every 100 cycles we'll update channels */ + dc_fetch_channels(t->clients[i]->guilds[j]); + for (int k = 0; k < t->clients[i]->guilds[j]->channels_sizeof; k++) + if (!(rand() % 10)) /* roughly every 10 cycles we'll update messages */ + dc_fetch_messages(t->clients[i]->guilds[j]->channels[k]); + } + if (DC_CWLE(t->clients[i], t->clients[i]->sent_messages_lock)) continue; + if (t->clients[i]->sent_messages_sizeof > 0) {/* no need to lock as only one thread does this */ + struct dc_message * msg2send = t->clients[i]->sent_messages[0]; + if (dc_send_message(msg2send) > 0) { + DC_CWLE(t->clients[i], t->clients[i]->guilds_lock); + msg2send->channel->messages = realloc(msg2send->channel->messages, sizeof(struct dc_message *)*++msg2send->channel->messages_sizeof); + msg2send->channel->messages[msg2send->channel->messages_sizeof-1] = msg2send; + DC_CUE(t->clients[i], t->clients[i]->guilds_lock); + for (int j = 0; j <= t->clients[i]->sent_messages_sizeof; j++) /* shift, we removed one from the start */ + t->clients[i]->sent_messages[j] = t->clients[i]->sent_messages[j+1]; + t->clients[i]->sent_messages_sizeof--; + } + } + while (DC_CUE(t->clients[i], t->clients[i]->sent_messages_lock)); + } + } + /* if (pthread_rwlock_unlock(t->clients_lock)) + return -2; */ return 1; } /* the thread shall use mutexes when doing things with shared memory - client structs */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..28b1449 --- /dev/null +++ b/src/main.c @@ -0,0 +1,63 @@ +#include <ui.h> +int main (int argc, char ** argv) { + srand(time(NULL)); + int rs = 0; + int opt; + pthread_t api_thread, ui_thread; + int api_ret ui_ret; + struct dc_client * c = dc_client_init(); + struct dc_thread_control = { + .power_api = 1; + .power_ui = 1; + .clients = &c; + .clients_sizeof = 1; + .cout = stdout; + .cin = stdin; + .cerr = stderr; + }; + while ((opt = getopt(argc, argv, "e:p:h")) != -1) { + switch (opt) { + case 'h': + fprintf(stdout, DC_I18N_USAGE); + dc_client_free(c); + return 0; + break; + case 'e': + c->email = malloc(strlen(optarg)+1); + strcpy(c->email, optarg); + break; + case 'p': + c->password = malloc(strlen(optarg)+1); + strcpy(c->password, optarg); + break; + default: + fprintf(stderr, DC_I18N_UNREC_ARG "\n", opt); + dc_client_free(c); + return 1; + } + } + if (!c->email) { + if (!getenv("DC_E")) { + fprintf(stderr, DC_I18N_MISSING_EP "\n"); + dc_client_free(c); + return 2; + } + c->email = malloc(strlen(getenv("DC_E"))+1); + strcpy(c->email, getenv("DC_E")); + } + if (!c->password) { + if (!getenv("DC_P")) { + fprintf(stderr, DC_I18N_MISSING_EP "\n"); + dc_client_free(c); + return 3; + } + c->password = malloc(strlen(getenv("DC_P"))+1); + strcpy(c->password, getenv("DC_P")); + } + api_ret = pthread_create(&api_thread NULL, dc_api_thread, dc_thread_control); + ui_ret = pthread_create(&ui_thread, NULL, dc_ui_thread, dc_thread_control); + pthread_join(api_thread, NULL); + pthread_join(ui_thread, NULL); + rc: + return rs; +} diff --git a/src/ui.c b/src/ui.c new file mode 100644 index 0000000..3f8dbaf --- /dev/null +++ b/src/ui.c @@ -0,0 +1,84 @@ +#define _XOPEN_SOURCE 600 +#define _POSIX_C_SOURCE 200809L +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +/* #include <api.c> */ +#include <ncursesw/ncurses.h> +#include <ncursesw/form.h> +#include <unistd.h> +#include <locale.h> +/* link with -lncursesw and -lformw */ +/* int dc_ui_thread (struct * dc_thread_control t) { */ +int main () { + FIELD * field[2]; /* field[0] je polje z besedilom */ + field[1] = NULL; + FORM * form; + int ret, x, y; + wint_t ch; + initscr(); + cbreak(); + noecho(); + nodelay(stdscr, TRUE); + setlocale(LC_ALL, "sl_SI.UTF-8"); + start_color(); + init_pair(0, COLOR_WHITE, COLOR_BLACK); + init_pair(1, COLOR_RED, COLOR_BLACK); + attron(COLOR_PAIR(1)); + keypad(stdscr, TRUE); + getmaxyx(stdscr, y, x); /* to je macro, zato y in x nista kazalca (;: */ + WINDOW * textwin = newwin(y-3, x, 0, 0); + WINDOW * formwin = newwin(2, x, y-2, 0); + scrollok(textwin, TRUE); + field[0] = new_field(2, x, y-2, 0, 5 /* offscreen rows */, 0); + set_field_back(field[0], A_UNDERLINE); + field_opts_off(field[0], O_AUTOSKIP); + form = new_form(field); + set_form_win(form, formwin); + post_form(form); + int i = 0; + wmove(textwin, 0, 0); + time_t last_time = 0; + refresh(); + while (1) { + if (last_time < time(NULL)) { + last_time = time(NULL); + attron(COLOR_PAIR(0)); + wprintw(textwin, "\nvrstica stevilka %d", i); + attron(COLOR_PAIR(1)); + mvprintw(y-3, 0, "#piš-ti-kurc-2 | discord.c | šijanec 2021"); + } + ret = get_wch(&ch); + if (ret != ERR) { + switch (ch) { + case KEY_LEFT: + form_driver(form, REQ_PREV_CHAR); + break; + case KEY_RIGHT: + form_driver(form, REQ_NEXT_CHAR); + break; + case KEY_BACKSPACE: + form_driver(form, REQ_DEL_PREV); + break; + case KEY_DOWN: + form_driver(form, REQ_SCR_FLINE); + break; + case KEY_UP: + form_driver(form, REQ_SCR_BLINE); + break; + default: + form_driver_w(form, ret, ch); + break; + } + } + wnoutrefresh(stdscr); + wnoutrefresh(textwin); + doupdate(); + i++; + } + unpost_form(form); + free_form(form); + free_field(field[0]); + endwin(); + return 1; +} |