Hi Aitor et al,
This is the working code. At least it worked with an initial
allocation of 1 structure instead of 10. I am using it with an initial
allocation of 10 structures. On this machine the code works and it
should also work in your case:
The code is attached.
Conside lines 236 - 240.
Line 238 calls calloc(list_delta, sizeof(void*)); list_delta is set to
10 but I also used 1 to force to loop use realloc with every
successive odd numbered iteration. Line 238 allocates an array of 10
void* pointers.
Realloc uses two parameters: the first is a pointer whose allocation
is to be modified/reallocated. The second is the NEW number of bytes
required. In the function line 240 is:
active_wifi_list = realloc(active_wifi_list, (((z - 1)/2) +
list_delta)*sizeof(void*));
I should assume that the assignment is unnecessary although it works.
Edward
On 10/12/2015, KatolaZ <katolaz@???> wrote:
> On Thu, Dec 10, 2015 at 04:11:27PM +0000, KatolaZ wrote:
>
> [cut]
>
>>
>> with
>>
>> $ gcc -std=c99 reference.c
>>
>> this is what I obtain:
>>
>> reference.c:3:16: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
>> void myfun(int &a){
>> ^
>> reference.c: In function ‘main’:
>> reference.c:13:4: warning: implicit declaration of function ‘myfun’
>> [-Wimplicit-function-declaration]
>> myfun(a);
>> ^
>>
>> So my version of gcc apparently does not know about this feature
>> included in the ANSI C99 standard....
>>
>
> And apparently they haven't fixed the "bug" while implementing the C11
> standard, either...
>
> katolaz@%%%%%%:~/test$ gcc -std=c11 reference.c
> reference.c:3:16: error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token
> void myfun(int &a){
> ^
> reference.c: In function ‘main’:
> reference.c:13:4: warning: implicit declaration of function ‘myfun’
> [-Wimplicit-function-declaration]
> myfun(a);
> ^
>
> Very strange, ain't it?
>
> HND
>
> KatolaZ
>
> --
> [ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
> [ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
> [ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
> [ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]
> _______________________________________________
> Dng mailing list
> Dng@???
> https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng
>
/*
netman - A Network Connection Manager
Copyright (C) 2015 Edward Bartolo
"netman" 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 3 of the License, or
(at your option) any later version.
"netman" 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 "netman". If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <alloca.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <math.h>
#include "paths.h"
#include "core_functions.h"
#include "essid_encoder.h"
#include "file_functions.h"
#include "automated_scanner.h"
/*
Note: Essid files under /etc/network/wifi are first copied to
/run/netman and wlan0 replaced by the system's own wifi network
interface. This means that under /etc/network/wifi wlan0 is only
a placeholder for the actual device name.
Looks in /etc/network/wifi or /run/netman for installed essid files.
If etc_network_path is true /etc/network/wifi is used, otherwise /run/netman is used.
The return value is a list of strings containing the encoded essid file names.
count returns the number of strings in the list and error returns a non-zero error code
in the event of an error with a value of zero when no error is generated.
*/
char** getInstalledEssidList(int etc_network_path, int* count, int* error)
{
char** essid_list;
DIR * dir;
struct dirent * ent;
int el_size = 0; // stands for essid_list size
essid_list = NULL;
// At first set *error to 0
*error = 0;
// First get a list of installed wireless "interfaces" files
if (etc_network_path )
dir = opendir(IFACES_PATH);
else dir = opendir(RUN_IFACES_PATH);
if (dir != NULL) {
while ((ent = readdir (dir)) != 0)
if(
strcmp(".", ent->d_name) != 0 &&
strcmp("..", ent->d_name) != 0
) {
(*count)++;
char* encoded_essid;
int err;
encoded_essid = ent->d_name;
if (el_size < *count) {
el_size =+ 10;
if (el_size == 10)
essid_list = calloc(*count + 9, sizeof(char*));
else essid_list = realloc(essid_list, (*count + 9)*sizeof(char*));
if (essid_list == NULL || errno == ENOMEM) {
fprintf(
stderr,
"ERROR: getInstalledEssidList(): "
"could not expand essid_list list. (Error: %s)\n",
strerror(errno)
);
el_size =- 10;
(*count)--;
*error = 1;
return essid_list;
}
}
char* essid;
err = decode_essid_alloc(encoded_essid, &essid);
if(err) {
fprintf(
stderr, "ERROR: "
"getInstalledEssidList(): decode_essid_alloc(encoded_essid=%s) failed; err=%d\n",
encoded_essid, err
);
(*count)--;
*error = 1;
return essid_list;
//continue;
}
err = decode_encoded_essid(encoded_essid, &essid);
if(err) {
fprintf(
stderr, "ERROR: "
"getInstalledEssidList(): decode_encoded_essid(encoded_essid=%s) failed; err=%d\n",
encoded_essid, err
);
*error = -1;
return essid_list;
}
essid_list[*count - 1] = essid;
//essid_list[*count - 1] = calloc(strlen(encoded_essid) + 1, sizeof(char));
//strcpy(essid_list[*count - 1], encoded_essid);
}
closedir(dir);
}
else {
if (etc_network_path) {
fprintf(
stderr, "Error: "
"getInstalledEssidList(): opendir(%s) failed (Error: %s)\n",
IFACES_PATH, strerror(errno)
);
} else {
fprintf(
stderr, "Error: "
"getInstalledEssidList(): opendir(%s) failed (Error: %s)\n",
RUN_IFACES_PATH, strerror(errno)
);
};
//return old_errno;
*error = 1;
return essid_list;
}
//return 0;
return essid_list;
}
/*
Runs "iwlist wlanx or equivalent scan" to get a list of active wifi transceivers in
the vicinity. The return value is a list of strings of type void** implying type casting
must be used to access the strings.
active_wifis returns the number of active wifi transceivers found and error contains a non zero
error code in the event of an error, otherwise zero is returned.
*/
void** getRadiatingWifiList(int* active_wifis, int* error)
{
// Hopefully, here we have a list of installed essid interfaces files
void** active_wifi_list = NULL;
char command[1024];
FILE * shell_reader;
char * scan_buffer;
int err;
*error = 0;
scan_buffer = calloc(1024, 1);
if (scan_buffer == NULL) {
fprintf(
stderr,
"ERROR: getRadiatingWifiList(): "
"calloc() failed to allocate memory for scan_buffer. (Error: %s)\n",
strerror(errno)
);
*error = 2;
return NULL;
}
err = snprintf(
command,
1024,
"/sbin/iwlist %s scan | grep \"Quality=\\|ESSID:\"",
wlanx
);
if(err<0) {
fprintf(stderr, "ERROR: snprintf(filename) failed; err=%d\n", err);
free(scan_buffer);
}
// read output lines containing 'Quality=' and 'ESSID:'
shell_reader = popen(command, "r");
if(!shell_reader) {
fprintf(
stderr,
"ERROR: getRadiatingWifiList(): "
"popen() failed (Error: %s)\n",
strerror(errno)
);
free(scan_buffer);
*error = 2;
return NULL;
}
wifi_quality* tmp_wifi_quality;
int z = 0;
*active_wifis = -1;
char* tmp_buffer = scan_buffer;
const int list_delta = 10;
while((scan_buffer = fgets(scan_buffer, 1024, shell_reader)))
{
z++;
if (z == 1)
active_wifi_list = calloc(list_delta, sizeof(void*));
else if ((z - 1) % (list_delta * 2) == 0)
active_wifi_list = realloc(active_wifi_list, (((z - 1)/2) + list_delta)*sizeof(void*));
if (active_wifi_list == NULL || errno == ENOMEM) {
fprintf(
stderr,
"ERROR: getRadiatingWifiList(): "
"could not expand active_wifi_list. (Error: %s)\n",
strerror(errno)
);
free(tmp_buffer);
*error = 2;
return active_wifi_list;
}
if (z % 2 == 1) {
(*active_wifis)++;
tmp_wifi_quality = calloc(1, sizeof(wifi_quality));
if (tmp_wifi_quality == NULL) {
fprintf(
stderr,
"ERROR: getRadiatingWifiList(): "
"could not allocate tmp_wifi_quality. (Error: %s)\n",
strerror(errno)
);
(*active_wifis)++;
free(tmp_buffer);
*error = 2;
return active_wifi_list;
}
active_wifi_list[*active_wifis] = tmp_wifi_quality;
char* substr = strstr((char *) scan_buffer, "Signal level=");
substr = strstr(substr, "=");
char* endstr = strstr(substr + 1, " ");
char tmpstr[MAX_ESSID_LENGTH];
strncpy(tmpstr, substr + 1, endstr - substr - 1);
tmpstr[endstr - substr - 1] = '\0';
tmp_wifi_quality->quality = strtod(tmpstr, NULL);
// P(dBm) = 10 · log10( P(mW) / 1mW)
// we want the absolute power
// P(mW) / 1mW = P*
// P* = antilog(P/10)
double log_quality = (tmp_wifi_quality->quality)/10;
tmp_wifi_quality->quality = pow(10, log_quality);
}
else {
char* tmpstr = strtok((char*) scan_buffer, "\"");
tmpstr = strtok(NULL, "\"");
strncpy(tmp_wifi_quality->name, tmpstr, strlen(tmpstr));
}
//printf("%s", scan_buffer);
}
free(tmp_buffer);
pclose(shell_reader);
return active_wifi_list;
}
// sort radiating wifis according to signal strength
int sortRadiatingWifisList(const int active_wifis, void** active_wifi_list)
{
int i, j = 0;
while (j < active_wifis) {
for (i = active_wifis - j - 1; i > -1; i--) {
if (
((wifi_quality*) active_wifi_list[i])->quality <
((wifi_quality*) active_wifi_list[i + 1])->quality
) {
wifi_quality* awifi_quality = (wifi_quality*) active_wifi_list[i];
active_wifi_list[i] = active_wifi_list[i + 1];
active_wifi_list[i + 1] = awifi_quality;
}
}
j++;
}
return 0;
}
/*
Checks whether essid is listed in installed_wifi_list. Return index of essid in list or -1
if essid is not found.
*/
int wifiEssidInstalled(const int installed_count, char** installed_wifi_list, char* essid)
{
int i;
for (i = 0; i < installed_count; i++) {
if (strcmp(installed_wifi_list[i], essid) == 0) {
return i;
}
}
return -1; // ie not found
}
int autoWirelessScanPlus()
{
char** essid_list;
int count = 0;
int error = 0;
int active_wifis;
void** active_wifi_list;
char scan_buffer[1025];
// pull up the network to enable scanning
char command_up[1024];
int err = snprintf(
command_up,
1024,
"/sbin/ifconfig %s up",
wlanx
);
if(err < 0) {
fprintf(stderr, "ERROR: snprintf(command_up) failed; err=%d\n", err);
return err;
}
int ret = system(command_up);
if (ret != 0) {
fprintf(
stderr,
"ERROR: autoWirelessScanPlus(): "
"/sbin/ifconfig() failed (Error: %s)\n",
strerror(errno)
);
return ret;
}
// get a list of currently installed wifi essids
essid_list = getInstalledEssidList(0, &count, &error);
if (error) {
int w;
if (essid_list != NULL) {
for (w = 0; w < count; w++)
free(essid_list[w]);
free(essid_list);
}
return 1;
}
// get a list of irradiating wifis
active_wifi_list = getRadiatingWifiList(&active_wifis, &error);
if (error) {
int w;
for (w = 0; w < count; w++)
free(essid_list[w]);
free(essid_list);
if (active_wifi_list != NULL) {
for (w = 0; w < active_wifis; w++)
free(active_wifi_list[w]);
free(active_wifi_list);
}
return 2;
}
// sort the radiating wifis in descending order according to strength
sortRadiatingWifisList(active_wifis, active_wifi_list);
/*
int ww;
for (ww = 0; ww <= active_wifis; ww++)
fprintf(stdout, "quality for %s is %g\n",
((wifi_quality*) active_wifi_list[ww])->name,
((wifi_quality*) active_wifi_list[ww])->quality);
*/
int wireless = 0;
int counter;
for (counter = 0; counter < active_wifis; counter++) {
char* tmp_essid_list_item = ((wifi_quality*) active_wifi_list[counter])->name;
if (wifiEssidInstalled(count, essid_list, tmp_essid_list_item) > -1) {
FILE * shell_reader;
// required command for popen: /sbin/ifup wlanx -i RUN_IFACES_PATH"/"essid_list[counter]
;
char ifup_cmd[40 + MAX_ESSID_LENGTH];
char** tmp_enc_essid;
tmp_enc_essid = malloc(sizeof(void*));
encodeString(tmp_essid_list_item, tmp_enc_essid);
//printf(encoded_essid);
err = snprintf(
ifup_cmd,
1024,
"/sbin/ifup %s -i \""RUN_IFACES_PATH"/%s\"",
wlanx,
*tmp_enc_essid
//tmp_essid_list_item
);
free(tmp_enc_essid[0]);
free(tmp_enc_essid);
if(err<0) {
fprintf(stderr, "ERROR: snprintf(filename) failed; err=%d\n", err);
error = 5;
break;
}
shell_reader = popen(ifup_cmd, "r");
if(!shell_reader) {
fprintf(
stderr,
"ERROR: autoWirelessScanPlus(): "
"popen() failed (Error: %s)\n",
strerror(errno)
);
error = 3;
break;
}
pclose(shell_reader);
shell_reader = popen(
"/bin/ip a | grep \"state UP\"", "r"
);
if(!shell_reader) {
fprintf(
stderr,
"ERROR: autoWirelessScanPlus(): "
"popen() failed (Error: %s)\n",
strerror(errno)
);
error = 4;
break;
}
while((fgets(scan_buffer, 1024, shell_reader))) {
if (strstr((char *) scan_buffer, wlanx) != NULL)
wireless++;
//else if (strstr((char *) scan_buffer, "eth0") != NULL)
// wired++;
}
pclose(shell_reader);
if (wireless) break; // if connected to wireless stop iterating
}
}
// free the essid string list
int u;
for (u = 0; u < count; u++)
free(essid_list[u]);
free(essid_list);
// free the radiating wifis list
for (u = 0; u <= active_wifis; u++)
free((wifi_quality*) active_wifi_list[u]);
free((void*) active_wifi_list);
return error;
}
int autoWirelessScanPlus_RN()
{
DIR * dir;
struct dirent * ent;
char* encoded_essid;
int error;
if ( (dir = opendir(IFACES_PATH)) != NULL ) {
while ( (ent = readdir (dir)) != 0)
if(
strcmp(".", ent->d_name) != 0 &&
strcmp("..", ent->d_name) != 0
) {
encoded_essid = ent->d_name;
error = moveEditEssidFile(wlanx, encoded_essid);
if (error) break;
}
closedir(dir);
}
if(!dir) {
fprintf(
stderr,
"ERROR: autoWirelessScanPlus_RN(): "
"opendir() failed (Error: %s)\n",
strerror(errno)
);
return errno;
}
if (!error)
error = autoWirelessScanPlus();
return error;
}