:: Re: [DNG] Pointer error in the back…
Etusivu
Poista viesti
Vastaa
Lähettäjä: Edward Bartolo
Päiväys:  
Vastaanottaja: aitor_czr, dng
Aihe: Re: [DNG] Pointer error in the backend of Netman
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;    
}