Items overriden in list from keyboard thread - c

[1]I'm having a problem with my keyboard input thread. I'm currently using fgets to read input from the keyboard and then store it to a list using List_add. Problem is, my program seems to just print the last character that I inputted instead of the different strings of messages.
UPDATE:
Code in keyboardinput Thread
#define MAX_LEN 258
static pthread_t keyboardThread;
static pthread_mutex_t *psharedMutex;
static List* pList;
void* inputFunction(void* unused){
printf("Enter message:\n");
while (1) {
char* messageAllocated;
messageAllocated = malloc(MAX_LEN);
if(messageAllocated != NULL) {
//Wait for user input
fgets(messageAllocated, MAX_LEN, stdin); // This is how C read something from keyboard
pthread_mutex_lock(psharedMutex);
{
List_add(pList, messageAllocated); // Add message to list for FCFS
}
pthread_mutex_unlock(psharedMutex);
if (messageAllocated[0] == '!' && messageAllocated[2] == '\0') {
break;
}
memset(messageAllocated, 0, MAX_LEN);
}
else {
printf("Malloc Failed.\n");
}
};
return NULL;
}
void KeyboardInput_init(List* myList, pthread_mutex_t *sharedMutex) {
psharedMutex = sharedMutex;
pList = myList;
pthread_create(&keyboardThread, NULL, inputFunction, NULL);
}
void KeyboardInput_shutdown() {
pthread_join(keyboardThread, NULL);
}
Code in main.c
int main(int argc, char** args) {
// Create 2 Lists for transmit and receive
//List listPool;
List* outboundList; // Used in keyboard and UDP sendto threads
List* inboundList; // Used in screen and UDP recvfrom threads
outboundList = List_create();
inboundList = List_create();
// Receive information for s-talk transmission (ports, machine names)
setUpSTalkApplication();
Printer_init();
Signaller_init();
Printer_waitForShutdown();
Signaller_shutdown();
// Startup Modules
Receiver_init("Message received on Port ", &sharedMutex, remoteMachineName, hostPort); // goes before keyboard
KeyboardInput_init(outboundList, &sharedMutex);
Sender_init(outboundList, &sharedMutex, &condVar, remoteMachineName, targetPort);
//ScreenOutput_init(inboundList, &condVar, &sharedMutex);
// Shutdown Modules
//ScreenOutput_shutdown();
KeyboardInput_shutdown();
Receiver_shutdown();
Sender_shutdown();
printf("Done.\n");
while(List_count(outboundList) != 0) {
char* x = List_trim(outboundList);
printf("%s", x);
};
return 0;
}

Firstly, You should validate the pointer messageAllocated after malloc and the sizeof(messageAllocated) is only 4 or 8 bytes, you should use MAX_LEN instead of sizeof(messageAllocated)
while (1) {
char * messageAllocated;
messageAllocated = malloc(MAX_LEN);
if(messageAllocated != NULL)
{
fgets(messageAllocated, MAX_LEN, stdin);
List_add(pList, messageAllocated)
if (messageAllocated[0] == '!') {
break;
}
//hope you are doing this before reading another string, or else there will be memory leak
free(messageAllocated); messageAllocated = NULL;
}
else
{
printf("malloc failed\n");
}
}

Related

ncurses new_item() failure

I am quite new to ncurses and I have been trying to implement a scrolling menu by following the documentation here. My code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ncurses.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <menu.h>
int NUMBER_OF_TRACKS = 0;
struct Track {
char *title;
char *pathName;
}; typedef struct Track Track;
/*
* playSong is responsible for playing the selected track.
* This function utilizes fork and execvp to accomplish this.
* could maybe use popen again?
*/
void playSong(char *title) {
FILE *fp;
char cmdBuffer[1024];
sprintf(cmdBuffer, "cd ~/Music/iTunes/\"iTunes Media\"/Music/ && afplay %s", title);
fp = popen(cmdBuffer, "r");
if(fp == NULL) {
printf("Unable to play track.\n");
exit(1);
}
// close the pipe
if(pclose(fp) == -1) {
printf("Error while closing pipe.\n");
exit(1);
}
}
/*
* escapeString takes in a path name for a track, and adds escape characters
* to it so that it later be played by the system.
*/
char * escapeString(char *pathName) {
char * escape = (char *)malloc(1024 * sizeof(char));
int index = 0;
for(int i = 0; pathName[i] != '\n'; i++) {
if(pathName[i] == '/') {
if(i == 1) {
// we don't need to doubly pad the first '/' with quotes
escape[index++] = pathName[i];
escape[index++] = '\"';
}
else {
escape[index++] = '\"';
escape[index++] = pathName[i];
escape[index++] = '\"';
}
}
else {
escape[index++] = pathName[i];
}
}
// don't forget to add last quote to end the song
escape[index++] = '\"';
// don't forget null!
escape[index] = '\0';
return escape;
}
/*
* getTrackTitle parses the escaped pathame and returns only the name of the
* song.
*/
char * getTrackTitle(char *pathName) {
char *title = (char *)malloc(1024*sizeof(char));
int slashCount = 0;
int index = 0;
for(int i = 0; pathName[i] != '\0'; i++) {
if(slashCount == 3) {
title[index++] = pathName[i];
}
else if(pathName[i] == '/') {
slashCount++;
}
}
title[index] = '\0';
return title;
}
Track ** getUserTracks() {
FILE *fp;
char pathName[300]; // may need to be longer?
// use fp with popen
char *cmd = "cd ~/Music/iTunes/\"iTunes Media\"/Music/ && find . -name \"*.m4a\"";
fp = popen(cmd, "r");
if(fp == NULL) {
printf("Unable to find your tracks!\n");
exit(1);
}
// create our list
Track **trackList = (Track **)malloc(1024 * sizeof(Track *));
// read the output (i.e) the tracks
while(fgets(pathName, sizeof(pathName), fp) != NULL) {
// allocate memory for track
trackList[NUMBER_OF_TRACKS] = (Track *)malloc(sizeof(Track));
// get the escaped path name
char *escapedPath = escapeString(pathName);
// store values in struct
trackList[NUMBER_OF_TRACKS]->pathName = escapedPath;
trackList[NUMBER_OF_TRACKS]->title = getTrackTitle(escapedPath);
// update number of tracks
NUMBER_OF_TRACKS++;
}
// null terminate list
trackList[NUMBER_OF_TRACKS] = (Track *)NULL;
// close the pipe
if(pclose(fp) == -1) {
printf("Error while closing pipe.\n");
exit(1);
}
// return our list
return trackList;
}
int main(int argc, char **argv) {
/* START NCURSES */
initscr(); // create screen
curs_set(0); // hide cursor
noecho(); // don't show the characters the user is typing
cbreak(); // allow user to quit with ctrl-c; may want to remove this later
// get screen size
int yMax, xMax;
getmaxyx(stdscr, yMax, xMax);
ITEM **userTracks;
MENU *trackMenu;
WINDOW *trackMenuWindow;
// create items for our menu
Track **choices = getUserTracks();
userTracks = (ITEM **)calloc(NUMBER_OF_TRACKS+1, sizeof(ITEM *));
for(int i = 0; i < NUMBER_OF_TRACKS; i++) {
ITEM *trackItem = new_item(choices[i]->title, "");
userTracks[i] = trackItem;
}
userTracks[NUMBER_OF_TRACKS] = (ITEM *)NULL;
/* MENU STUFF */
// create the menu
trackMenu = new_menu((ITEM **)userTracks);
// printf("Item count: %d\n", item_count(trackMenu));
/* create the window associated with the menu */
trackMenuWindow = newwin(yMax, xMax, 0, 0);
box(trackMenuWindow, 0, 0); // adds border to window
keypad(trackMenuWindow, TRUE); // enables keypd use on menu
/* set main window and set sub windows */
set_menu_win(trackMenu, trackMenuWindow);
set_menu_sub(trackMenu, derwin(trackMenuWindow, yMax - 1, xMax - 1, 1, 1));
set_menu_format(trackMenu, 5, 1); // sets number of items to be displayed
/* Set menu mark to the string " * " */
set_menu_mark(trackMenu, NULL);
/* Post the menu */
post_menu(trackMenu);
wrefresh(trackMenuWindow);
int keyPressed;
while((keyPressed = wgetch(trackMenuWindow)) != 'q') {
switch(keyPressed) {
case KEY_DOWN:
menu_driver(trackMenu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(trackMenu, REQ_UP_ITEM);
break;
case KEY_NPAGE:
menu_driver(trackMenu, REQ_SCR_DPAGE);
break;
case KEY_PPAGE:
menu_driver(trackMenu, REQ_SCR_UPAGE);
break;
}
wrefresh(trackMenuWindow);
}
unpost_menu(trackMenu);
free_menu(trackMenu);
for(int i = 0; i < NUMBER_OF_TRACKS; i++) {
free_item(userTracks[i]);
}
endwin();
/* END NCURSES */
return 0;
}
Essentially, I am interested in getting a list of all the user's (iTunes) songs on their machine and displaying them in a (scrollable) menu.
I am able to retrieve all the songs and store them in my Track **choices array, however, I am not able to create any menu items from them. I have deduced that my issue lies within the followig snippet:
// create items for our menu
Track **choices = getUserTracks();
userTracks = (ITEM **)calloc(NUMBER_OF_TRACKS+1, sizeof(ITEM *));
for(int i = 0; i < NUMBER_OF_TRACKS; i++) {
ITEM *trackItem = new_item(choices[i]->title, "");
userTracks[i] = trackItem;
}
userTracks[NUMBER_OF_TRACKS] = (ITEM *)NULL;
Specifically the line ITEM *trackItem = new_item(choices[i]->title, "");
It appears as though new_item() is returning NULL in every iteration. Moreover, errno is being set to E_BAD_ARGUMENT implying that choices[i]->title is not a valid string, though I cannot imagine why this would be the case.
Any help would be immensely appreciated!
You may compile the code above as follows: gcc -I/usr/local/opt/ncurses/include -L/usr/local/opt/ncurses/lib <source_file>.c -lmenu -lncurses
You might be able to get away with excluding -I/usr/local/opt/ncurses/include -L/usr/local/opt/ncurses/lib but that unfortunately doesn't work for me.
Fair warning, this program might not work on Windows/Linux environments due to their file structure and iTunes requirement, but I have not tested it.
Turns out the strings in my structure were nonsense. I needed to allocate memory on the heap for them within my getUserTracks() function.

Copy TCHAR* string from other thread

I want to copy data from another thread to struct and print. _tpintf() doesnt show russian letters corret.
in concole I see this, but I expect to see "IN THREAD текст клиент1". Please explain why tchar doesnt work? Also I noticed that if I use _tcprintf, "клиент1" shows correct, but "текст" become wrong
Code of thread function which tries to copy data from another
static DWORD WINAPI StdinInfo(LPVOID param)
{
struct msg msg;
TCHAR buf[1280] = { 0 };
parameters* p = (parameters*)param;
while (TRUE)
{
_fgetts(buf, 1280, stdin);
while (_tcslen(buf) > 0 && buf[_tcslen(buf) - 1] == TEXT('\n'))
buf[_tcslen(buf) - 1] = TEXT('\0');
buf[128] = TEXT('\0');
if (!_tcscmp(buf, TEXT("stop")))
{
//printf("Terminating...\n");
msg.isEmpty = 0;
msg.type = STOP;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
SendMessage(p, &msg);
break;
}
else if (!_tcscmp(buf, TEXT("exit")))
{
msg.isEmpty = 0;
msg.type = DISCONNECT;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
SendMessage(p, &msg);
break;
}
msg.isEmpty = 0;
msg.type = MESSAGE;
_tcscpy(msg.message, buf);
_tcscpy(msg.nickName, p->nickName);
_tprintf(TEXT(" IN TREAD %s %s\n"), msg.message, p->nickName);
SendMessage(p, &msg);
}
return 0;
}

How to pass global user defined structures to each callbacks libwebsockets C

im not sure if this related to lws but i just can't find way to pass global structure which holds its values between the callbacks .
the simple story is that i have simple hashtable in C
https://github.com/cgjones/android-system-core/blob/master/libcutils/hashmap.c
i try to explain in the example :
i have the main :
//HERE I DEFINE IT AS GLOBAL
Hashmap *users_map;
static struct lws_protocols protocols[] = {
{
"wsapi",
callback_wsapi,
sizeof(struct per_session_data__apigataway),
128,
} ,
{ NULL, NULL, 0, 0 } /* terminator */
};
int main(int argc, char **argv)
{
struct lws_context_creation_info info;
//HERE i init the hash map
users_map = hashmapCreate(10, str_hash_fn, str_eq);
memset(&info, 0, sizeof info);
info.port = server_port;
info.protocols = protocols;
...
info.options = opts | LWS_SERVER_OPTION_LIBUV;
context = lws_create_context(&info);
if (lws_uv_initloop(context, NULL, 0)) {
lwsl_err("lws_uv_initloop failed\n");
goto bail;
}
uv_timer_init(lws_uv_getloop(context, 0), &timeout_watcher);
uv_timer_start(&timeout_watcher, main_loop_count_callback, 1000, 1000);
lws_libuv_run(context, 0);
return 0;
}
and this is the callback_wsapi C file i removed allot of code just to show the important stuff
//HERE I SET IT AS EXTERN SO IT WILL BE VISIBLE TO ALL
extern Hashmap *users_map;
int
callback_iogame(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
unsigned char out[LWS_PRE + 512];
struct per_session_data__apigataway *pss =
(struct per_session_data__apigataway *)user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
{
//HERE IT LOSSING SCOPE AND THE HASHMAP NOT INITIALIZED
int bfor2 = hashmapSize(users_map);
break;
}
case LWS_CALLBACK_RECEIVE:
{
char* client_req_str;
client_req_str = (char*)in;
if (strncmp((const char *)client_req_str, "player\n",6) == 0)
{
//ON THE FIRST REQUEST FROM THE CLINET IT WORKS
int bfor = hashmapSize(users_map);
hashmapPut(users_map, pss->id, pss);
int after = hashmapSize(users_map);
}
//Only invoke callback back to client when baby client is ready to eat
lws_callback_on_writable(wsi);
break;
}
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
break;
case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
break;
default:
break;
}
So i can get the hashmap only in the first request when it gets to : LWS_CALLBACK_RECEIVE
then it just losing scope .
Questions :
1. How can i make this hashmap global to the callbacks ? it supposed to hold the server total users .

How to create AT Commands Parser in C to get the incoming string from USART1?

I want to get the string from USART1 of STM32VLDiscovery (STM32F100X4) and write an AT Command Parser from the string received from USART1.
Below are the concept that I have developed but I am not sure whether it's correct or not.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dosomethinga.h"
void dosomethingB();
void GET_AT_COMMAND(char*);
void takecommand(char *, char *);
int quit;
int main()
{ char buff[15];
char command = '\0';
quit = 0;
while(!quit)
{
printf("Enter your command: ");
scanf("%s", &buff);
if (buff[0] == 'A' && buff[1] == 'T' && buff[2] == '+')
{
GET_AT_COMMAND(buff);
}
}
}
void dosomethingB()
{
printf("dosomethingB called \n");
}
void GET_AT_COMMAND(char *text)
{
int command;
char temp[10] = "";
/*if(text[3] == 'A')
command = 1;
else if(text[3] == 'B')
command = 2;
else if(text[3] == 'Z')
command = 3;
*/
takecommand(text,temp);
if (strcmp(temp, "CALLA") == 0)
command = 1;
if (strcmp(temp, "CALLB") == 0)
command = 2;
if (strcmp(temp, "Z") == 0)
command = 3;
switch(command)
{
case 1:
dosomethingA();
break;
case 2:
printf("herehere.... \n");
dosomethingB();
break;
case 3:
printf("Exiting program.... \n");
quit = 1;
break;
default:
printf("Nothing to do here \n");
}
}
void takecommand(char *mycmd, char *hold)
{
int i;
for(i = 0; i < 10 ; i++)
{
hold[i] = mycmd[i+3];
}
}
Can anyone explain on the steps that I should do? Thanks.
Basicly you should wait an attention "AT" from the input and ignore anything before it.
For example inputs "XYZATZ\r" and "AaatZ\r" should be both handled as a "ATZ" command.
There can also be short pause between 'A' and 'T' (and all other chars of commands too), because human may type those commands.
By the default all commands end to "\r" character.
See more about AT commands from ITU-T documentation. For example from V.250 standard.
There are probably many alternative ways to implement that. The best alternative depends on your needs. If you are going to implement all AT-commands of mobile-terminal, then you should spend more time for the parser. If you want make some test application for few commands, then your implementation could be simple as your provided one.
I have developed this AT command parser, this could be use for reference.
When you get data from UART1 just call this method at_wait_msg() to parse the AT message
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
static const char *AT_HEADER = "AT";
static const char *AT_DEVICE_PROFILE = "DR";
static const char *AT_SET_DEVICE = "SD";
static const char AT_EOF = '\r';
typedef enum {
DeviceProfile,
SetDevice,
Error
} AT_Msg_Type;
typedef struct {
char header[3];
char command[3];
char data[128];
} AT_Msg_Data;
static void at_wait_msg(char text);
static void at_wait_msg_complete(char *text);
static void at_parse_msg(AT_Msg_Data *data);
static AT_Msg_Type at_check_format(AT_Msg_Data *data);
static char _rx_data[512];
static uint16_t _rx_index = 0;
int main()
{
//example data getting from UART1
char text[] = "ATDR\rATSD123456abchelloworld\r1123ATssa\r";
for (int i = 0; i < strlen(text) + 1; i++) {
//to simulate getting data from UART1 byte per byte
at_wait_msg(text[i]);
}
return 0;
}
static void at_wait_msg(char text)
{
_rx_data[_rx_index++] = text;
if (text == AT_EOF) {
at_wait_msg_complete(_rx_data);
_rx_index = 0;
}
}
static void at_wait_msg_complete(char *text)
{
AT_Msg_Data data;
int result = sscanf_s(_rx_data, "%2s%2s%s\r",
data.header, sizeof(data.header),
data.command, sizeof(data.command),
data.data, sizeof(data.data));
if (result >= 2) {
at_parse_msg(&data);
}
}
static void at_parse_msg(AT_Msg_Data *data)
{
AT_Msg_Type type = at_check_format(data);
switch (type) {
case DeviceProfile:
printf("device profile\r\n");
break;
case SetDevice:
printf("settings %s\r\n", data->data);
break;
case Error:
default:
printf("Error\r\n");
break;
}
}
static AT_Msg_Type at_check_format(AT_Msg_Data *data)
{
if (strcmp(data->header, AT_HEADER) != 0) {
return Error;
}
if (strcmp(data->command, AT_DEVICE_PROFILE) == 0) {
return DeviceProfile;
}
if (strcmp(data->command, AT_SET_DEVICE) == 0) {
return SetDevice;
}
return Error;
}

FreeImage include in c

Is there any way to include http://freeimage.sourceforge.net/index.html in my c test program without first installing the library? It fails to compile because of some memset..
Here is my C code. Is there any way to make it work? Please try compiling it and tell me how to do it if it works?
#define NAZIV_DATOTEKE 50
#include <stdio.h>
#include "FreeImage.h"
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message);
FIBITMAP* GenericLoader(const char* lpszPathName, int flag);
int main(){
FreeImage_Initialise();
FIBITMAP *dib, *ptr;
char ulaz_slika[NAZIV_DATOTEKE] = "bmp_24.bmp";
char izlaz_slika[NAZIV_DATOTEKE] = "free.bmp"; //podrazumevana vrednost
dib = GenericLoader(ulaz_slika, 0);
//slika = FreeImage_Load(FIF_BMP, "bmp_24.bmp", BMP_DEFAULT);
FreeImage_SetOutputMessage(FreeImageErrorHandler);
if (dib) {
printf("Ucitan \"%s\".\n", ulaz_slika);
}
FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(ulaz_slika, 0);
if ((fif != FIF_BMP) && (fif != FIF_ICO) && (fif != FIF_JPEG) && (fif != FIF_PNG) && (fif != FIF_TIFF)){
printf("Format slike nije podrzan.\n");
return 1;
}
ptr = FreeImage_ConvertTo24Bits(dib);
FreeImage_SetOutputMessage(FreeImageErrorHandler);
FreeImage_Unload(dib);
FreeImage_SetOutputMessage(FreeImageErrorHandler);
dib = ptr;
if (dib) {
printf("Konvertovan u RGB.\n");
}
const char *slika = (const char*)FreeImage_GetBits(dib);
if (FreeImage_Save(fif, dib, izlaz_slika, BMP_DEFAULT)) {
printf("Snimljen \"%s\".\n", izlaz_slika);
}
if (dib) {
FreeImage_Unload(dib);
}
FreeImage_DeInitialise();
return 0;
}
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message){
printf("\n*** ");
if(fif != FIF_UNKNOWN) {
if (FreeImage_GetFormatFromFIF(fif))
printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
}
printf(message);
printf(" ***\n");
}
FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
// check the file signature and deduce its format
// (the second argument is currently not used by FreeImage)
fif = FreeImage_GetFileType(lpszPathName, 0);
if(fif == FIF_UNKNOWN) {
// no signature ?
// try to guess the file format from the file extension
fif = FreeImage_GetFIFFromFilename(lpszPathName);
}
// check that the plugin has reading capabilities ...
if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
// ok, let's load the file
FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
// unless a bad file format, we are done !
return dib;
}
return NULL;
}
No you cannot. To compile your source, the linker needs the library.

Resources