Thread: Search through file and print an IP

  1. #16
    Registered User
    Join Date
    Dec 2017
    Posts
    958
    Code:
    void scan_ipconfig() {
        const char *terms[] = {
            "IPv4",
            "subred",
            "Puerta",
            "Servidores DNS",
            NULL
        };
        FILE *f = popen("ipconfig /allcompartments /all", "r");
        char line[256];
        while (fgets(line, sizeof line, f))
            for (const char **p = terms; *p; ++p)
                if (strstr(line, *p))
                    fputs(line, stdout);
        pclose(f);
    }
    If you want the truth to stand clear before you, never be for or against. - Sent-ts'an

  2. #17
    Registered User
    Join Date
    May 2020
    Posts
    39
    Quote Originally Posted by john.c View Post
    Code:
    void scan_ipconfig() {
        const char *terms[] = {
            "IPv4",
            "subred",
            "Puerta",
            "Servidores DNS",
            NULL
        };
        FILE *f = popen("ipconfig /allcompartments /all", "r");
        char line[256];
        while (fgets(line, sizeof line, f))
            for (const char **p = terms; *p; ++p)
                if (strstr(line, *p))
                    fputs(line, stdout);
        pclose(f);
    }
    Thanks! That works like a charm, much appreciated!

    Actually, for this very module I need to filter the adapters shown by ipconfig /allcompartments /all and offer some kind of menu to select one of them and show such properties. A friend suggested a constructor which accumulates the position of each one, but I don't really understand the approach - also, and the most trivial yet scary thing, I don't know which command I should use to extract and separate info from each adapter or how to do that - maybe stop reading after each \n\n? Honestly, I don't know...

  3. #18
    Registered User
    Join Date
    May 2020
    Posts
    39
    Quote Originally Posted by john.c View Post
    Maybe try something like this.
    Code:
    void ping(const char *ip) {
        char ping_cmd[256];
        sprintf(ping_cmd, "ping %s", ip);
        FILE *f = popen(ping_cmd, "r");  // popen is a posix function
        while (fgets(line, sizeof line, f))
            if (strstr(line, term))
                printf("\n\n   IP responde positivamente: %s", ip);
        pclose(f);
    }
    As for this part, I'm showing how it looks like in my implementation. I'm having a hard time at reading the whole external .txt (variable x), which consists on different lines of IP's, one above the other. I need to read them all and cast a printf whether they get a positive response or not:

    Code:
    void seleccionarArchivo()
    {
        FILE* fp, * fp2;
        char ch[500], x[500], str[500], line[BUFSIZ];
        char term[20] = "Media"; // Línea de caracteres de búsqueda para remarcar IP's que respondan positivamente
        char ping_cmd[256];
    
        printf("\n    Escribe la ruta del documento deseado\n\n");
        scanf("%s", x);
    
        fp = fopen(x, "r");
        if (fp == NULL)
        {
            printf("\n    El archivo no se ha podido encontrar\n\n");
            exit(0);
        }
        // Bloque que printa el contenido del archivo donde están las IP's
        while (fgets(ch, sizeof(ch), fp))
        {
            printf("%s", ch);
        }
        fclose(fp);
    
        // Bloque que analizará las IP's que responden positivamente
        sprintf(ping_cmd, "ping %s", ch);
        FILE* f = _popen(ping_cmd, "r");
        while (fgets(line, sizeof line, f))
            if (strstr(line, term))
                printf("\n\n   The IP responds: %s", ch);
            else("\n\n   The IP %s does not respond", ch);
        _pclose(f);
    }
    I don't know if that's possible without redirecting the results to an external file (as I did quite sloppily before), but this way you suggested looks neater. Only if I'd be able to fulfill the whole iteration..., it seems like it just skips the first line for some weird reason still. Nor even my teacher knows why (not that he seems much interested...).

  4. #19
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    Well as written, you're only going to ping the last line of the file.
    Code:
        while (fgets(ch, sizeof(ch), fp))
        {
            printf("%s", ch);
    
            sprintf(ping_cmd, "ping %s", ch);
            FILE* f = _popen(ping_cmd, "r");
            while (fgets(line, sizeof line, f)) {
                if (strstr(line, term)) {
                    printf("\n\n   The IP responds: %s", ch);
                } else {
                    printf("\n\n   The IP %s does not respond", ch);
                }
            }
            _pclose(f);
    
        }
        fclose(fp);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #20
    Registered User
    Join Date
    May 2020
    Posts
    39
    Quote Originally Posted by Salem View Post
    Well as written, you're only going to ping the last line of the file.
    Wow, much better, thanks a whole damn lot! Had to remove the "else {" part, since it printed the other string for each line read by the pointer and looked annoying. Would it be a clean way to print "The IP %s does not respond" AFTER the ping's concluded (i.e. the line's been read and the term variable doesn't appear)? Once again, THANKS a lot. I'm learning much more here than with my teacher's correspondence, that's for sure.

    P.D. Also, printing the contents of the external file refered to by variable x would be ace, just before launching the pings. But, to be honest, it's less important.

  6. #21
    Registered User
    Join Date
    May 2020
    Posts
    39
    Quote Originally Posted by john.c View Post
    Code:
    void scan_ipconfig() {
        const char *terms[] = {
            "IPv4",
            "subred",
            "Puerta",
            "Servidores DNS",
            NULL
        };
        FILE *f = popen("ipconfig /allcompartments /all", "r");
        char line[256];
        while (fgets(line, sizeof line, f))
            for (const char **p = terms; *p; ++p)
                if (strstr(line, *p))
                    fputs(line, stdout);
        pclose(f);
    }
    I'm back, sir.
    Now that I've got the other two modules straight, I'm having some more hard time for a switch menu that allows me selecting among my different network adapters and, once selected, display such detailed info. Your help is much appreciated but I've been toying with different options and I've found out this one is also useful:

    Code:
    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <stdio.h>
    #include <stdlib.h>
    #pragma comment(lib, "IPHLPAPI.lib")
    
    void main(void) {
    
        IP_ADAPTER_INFO* pAdapterInfo;
        ULONG            ulOutBufLen;
        DWORD            dwRetVal;
    
    
        pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
        ulOutBufLen = sizeof(IP_ADAPTER_INFO);
        int i;
    
        if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) {
            free(pAdapterInfo);
            pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
        }
        if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS) {
            printf("GetAdaptersInfo call failed with %d\n", dwRetVal);
        }
    
        PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
        printf("Los adaptadores de red disponibles son los siguientes:\n\n");
        while (pAdapter) {
            printf("%s\n", pAdapter->Description);
            printf("IP: %s\n", pAdapter->IpAddressList.IpAddress.String);
            printf("Mascara de subred: %s\n", pAdapter->IpAddressList.IpMask.String);
            printf("\Puerta de enlace: %s\n\n", pAdapter->GatewayList.IpAddress.String);
            pAdapter = pAdapter->Next;
        }
    
        if (pAdapterInfo)
            free(pAdapterInfo);
    }
    Now, my two questions/cries of help:

    1. With such approach, could I implement the DNS servers too? I'm trying to find out how to call them but it seems too advanced for my entry level, so I might end up following your previous way of work.
    2. How the hell do I invoke a menu that lets me list the adapters (i.e. pAdapter->Description), showing the remaining info (IpAddressList.IpAddress.String + IpMaskString + GatewayList.IpAddressString AND that DNS list) once I select the adapter via keyboard?

    My teacher recommends the leecad function (and there's almost no info out there about how to use it) instead of a scanf - no idea at all.
    A friend of mine worked his own way with a counter, accumulating the position of each adapter, but looks messy for me.

    Once again, many thanks for your time. I'm almost there.
    Last edited by JSteel; 05-10-2020 at 10:04 AM.

  7. #22
    Registered User
    Join Date
    May 2020
    Posts
    39
    Ha, sorry for my insistence. I've reworked my code, implementing john.c's instead of that of the previous post (which proved to be a bit problematic). So far:

    Code:
    #define _CRT_SECURE_NO_WARNINGS
    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #pragma comment(lib, "IPHLPAPI.lib")
    
    void main(void) {
    
        char termAdaptador[BUFSIZ] = "Adaptador";
        char* p, * p2;
        char str[100], line[256];
        const char* terms[] = {
        "IPv4",
        "subred",
        "Puerta",
        "Servidores DNS",
        NULL
        };
    
        // Redirection to ip.out.txt in order to gather the info I want
        strcpy(str, ">> ip.out.txt ");
        strcat(str, "ipconfig /allcompartments /all");
        system(str);
    
        // Listing the adapters
        FILE* f = _popen("ipconfig /allcompartments /all", "r");
        printf("\n    Available adapters:\n\n");
        while (fgets(line, sizeof line, f)) {
            if (strstr(line, termAdaptador) != NULL)
                printf(line);
        }
    
        // Scanf to choose my adapter and display its info
        printf("Write down the adapter: ");
        scanf("%s", line); // Is it right?
    
         // Here I want to print the detailed info I extracted off the adapter, i.e. IP, submask, gateway and DNS servers.
        while (fgets(line, sizeof line, f))
            for (const char** p = terms; *p; ++p)
                if (strstr(line, *p))
                    fputs(line, stdout);
      
    
    }
    Now I'm having trouble extracting such info off the file and printing it right. My ip.out.txt looks like this, to get an idea:

    Code:
    Adaptador de Ethernet Ethernet:
    
       Sufijo DNS espec¡fico para la conexi¢n. . : 
       Descripci¢n . . . . . . . . . . . . . . . : Realtek XXXXX
       Direcci¢n f¡sica. . . . . . . . . . . . . : XXXXXXXXXXXXXXXXXX
       DHCP habilitado . . . . . . . . . . . . . : s¡
       Configuraci¢n autom tica habilitada . . . : s¡
       V¡nculo: direcci¢n IPv6 local. . . : XXXXXXXXX(Preferido) 
       Direcci¢n IPv4. . . . . . . . . . . . . . : XX.XX.XX.XX(Preferido) 
       M scara de subred . . . . . . . . . . . . : XXXXXX
       Concesi¢n obtenida. . . . . . . . . . . . : lunes, 11 de mayo de 2020 7:46:16
       La concesi¢n expira . . . . . . . . . . . : martes, 12 de mayo de 2020 1:46:15
       Puerta de enlace predeterminada . . . . . : 192.168.1.1
       Servidor DHCP . . . . . . . . . . . . . . : 192.168.1.1
       IAID DHCPv6 . . . . . . . . . . . . . . . : XXXXXXXXX
       DUID de cliente DHCPv6. . . . . . . . . . : XXXXXXXXX
       Servidores DNS. . . . . . . . . . . . . . : XXXX
                                           XXXXXX
       NetBIOS sobre TCP/IP. . . . . . . . . . . : habilitado
    
    Adaptador de LAN inal mbrica Wi-Fi:
    
       Estado de los medios. . . . . . . . . . . : medios desconectados
       Sufijo DNS espec¡fico para la conexi¢n. . : 
       Descripci¢n . . . . . . . . . . . . . . . : Qualcomm Atheros XXXXXXXXX
       Direcci¢n f¡sica. . . . . . . . . . . . . : XXXXXXX
       DHCP habilitado . . . . . . . . . . . . . : s¡
       Configuraci¢n autom tica habilitada . . . : s¡

  8. #23
    Registered User
    Join Date
    May 2020
    Posts
    39
    Sorry for the annoyance, but after some time of struggle I think I'm almost there and it's annoying indeed not finding how...

    So now I have:

    Code:
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char extraer_info(const char* adaptador);
    
    void main(void) {
        FILE* fp;
        char termAdaptador[BUFSIZ] = "Adaptador";
        char* p, * p2;
        char str[100], line[256], adaptador[100];
        const char* terms[] = {
        "IPv4",
        "subred",
        "Puerta",
        "Servidores DNS",
        NULL
        };
    
        // Redirection to ip.out.txt in order to gather the info I want
        strcpy(str, "> ip.out.txt ");
        strcat(str, "ipconfig /allcompartments /all");
        system(str);
    
        // Listing the adapters
        fp = fopen("ip.out.txt", "r");
        printf("\n    Los adaptadores de red disponibles son los siguientes:\n\n");
        while (fgets(line, sizeof line, fp)) {
            if (strstr(line, termAdaptador) != NULL)
                printf(line);
    
        }
    
        // Scanf to choose my adapter and display its info
        printf("Escribe el adaptador deseado: ");
        scanf("%s", adaptador);
        printf("\n\n");
        char adapt_info = extraer_info(adaptador); // I've created the function to scanf the name of the adapter among those that've been listed
    }
    
    char extraer_info(const char* adaptador)
    {
        FILE* fp;
        const char* const Delim = "Adaptador"; // I want to find the string of letters that coincides with my variable "adaptador" to position my pointer there, don't know how to
        const char* terms[] = {
        "IPv4",
        "subred",
        "Puerta",
        "Servidores DNS",
        NULL
     };
    
        fp = fopen("ip.out.txt", "r");
        char line[256];
        while (fgets(line, sizeof line, fp))
            for (const char** p = terms; *p; ++p)
                if (strstr(line, *p))
                    fputs(line, stdout); // That's messy indeed. I want to scan through the opened file (that looks like the one I've pasted just before) and find the string referred by the variable "adaptador" to extract the paragraph that follows, until the next \n\n, and be able to print its specs properly.
    
        //exit(EXIT_FAILURE); // OK, some work needs to be done but not worried about that bit.
        return 0;
    }
    Sloppy, I know, but I think it would do the trick. So I need those final touches I'm unable to find out..., thanks in advance!

  9. #24
    Registered User
    Join Date
    May 2020
    Posts
    39
    Guess who's back...
    I need a slight modification of this piece for a different program.

    Quote Originally Posted by Salem View Post
    Well as written, you're only going to ping the last line of the file.
    Code:
        while (fgets(ch, sizeof(ch), fp))
        {
            printf("%s", ch);
    
            sprintf(ping_cmd, "ping %s", ch);
            FILE* f = _popen(ping_cmd, "r");
            while (fgets(line, sizeof line, f)) {
                if (strstr(line, term)) {
                    printf("\n\n   The IP responds: %s", ch);
                } else {
                    printf("\n\n   The IP %s does not respond", ch);
                }
            }
            _pclose(f);
    
        }
        fclose(fp);
    Instead of printing "The IP responds...", I should redirect the IP whose ping has shown success in returning "term" to a temporary file (for the time being I'm toying with a regular one in order to check if it works). Now, what I have so far:

    Code:
        fp = fopen(x, "r");
        while (fgets(ch, sizeof(ch), fp))
        {
            printf("Launching ping over %s", ch);
    
            sprintf(ping_cmd, "ping %s", ch);
            FILE* f = _popen(ping_cmd, "r");
            while (fgets(line, sizeof line, f)) {
                if (strstr(line, term)) {
                    sprintf(ping_cmd, "> ips_responden.txt", ch);
                }
            }
            _pclose(f);
        }
        fclose(fp);
    I guess my error dwells on the latter "sprintf", for the while loop pings successfully on the console but doesn't return any output file with such "working" IP's listed therein...

    As for the temporary file, would it be really messy to transform? I'm reading some info but I want to have my tasks straight before I'm even trying.

    Cheers!

  10. #25
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    > sprintf(ping_cmd, "> ips_responden.txt", ch);
    No, this isn't going to append anything to a file called ips_responden.txt

    Somewhere earlier on
    Code:
    FILE *responses = fopen("ips_responden.txt","w");
    Then where you have sprintf, try
    Code:
    fprintf(responses, "Got %s from %s\n", line, ch );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #26
    Registered User
    Join Date
    May 2020
    Posts
    39
    Thanks a lot once again, Salem. Worked perfectly. Now my code looks like this:

    Code:
        fp = fopen(x, "r");
        FILE* responses = fopen("ips_responden.txt", "w"); // FILE* tmp = tmpfile(); 
        while (fgets(ch, sizeof(ch), fp))
        {
            printf("Lanzando ping sobre %s", ch);
            sprintf(ping_cmd, "ping %s", ch);
            FILE* f = _popen(ping_cmd, "r");
            while (fgets(line, sizeof line, f)) {
                if (strstr(line, term)) {
                    fprintf(responses, "%s\n", ch); // fprintf(tmp, "%s\n", ch);
                }
            }
        }
        fclose(fp);
    I've commented the lines which I want to implement as a rather temporary file once I get the whole program straight and I'm able to see it's working right as a whole. From what I've gathered, it works like this, i.e. replacing those lines for the bold ones.

  12. #27
    Registered User
    Join Date
    May 2020
    Posts
    39
    Ha, the tmp conversion is troublesome, indeed. I'm following this route:

    Code:
    FILE* tmp = tmpfile(); 
        while (fgets(ch, sizeof(ch), fp))
        {
            printf("Lanzando ping a %s", ch);
            sprintf(ping_cmd, "ping %s", ch);
            FILE* f = _popen(ping_cmd, "r");
            while (fgets(line, sizeof line, f)) {
                if (strstr(line, term)) {
                    fprintf(tmp, "%s\n", ch);
                }
            }
            fclose(f);
        }
        fclose(tmp);
        fclose(fp);
    So far, so good, methinks. But then...:

    Code:
     // tmp = fopen(tmp, "r"); // How do I open the temporary file? Do I close it at all? It just crashes over and over...
         while (fgets(ipresp, sizeof(ipresp), tmp))
        {
            int response1 = velocidad_media(ipresp);
            printf("\n    Velocidad de respuesta media: %d ms.\n", ipresp, response1);
        }
    Here I want to recycle that comparison function I used before, to compare between ping results. This time I don't have a predefined number of IP's to compare, but it depends on the actual IP's that responded well during the previous ping procedure.

    Code:
    int velocidad_media(const char* ip)
    {
        const char* const Delim = "Media = ";
        printf("\n    Extrayendo velocidad media de %s", ip);
    
        char cmd[64];
        sprintf(cmd, "ping %s", ip);
        FILE* p = _popen(cmd, "r");
        char line[256];
        while (fgets(line, sizeof(line), p))
        {
            char* s = NULL;
            if ((s = strstr(line, Delim)) != NULL)
            {
                _pclose(p);
                return atoi(s + strlen(Delim));
            }
        }
        _pclose(p);
    
        return -1;
    }
    Except for the tmp conversion, it works almost fine. Only that I want to get the results for the IP's that got a good response and therefore got saved at the "ips_responden.txt" file (tmp file, this time), and this code includes some annoying line break (I think), so I get the extracted info for the IP AND a weird one that isn't at the .txt file. How do I prevent that?

  13. #28
    Registered User
    Join Date
    May 2020
    Posts
    39
    I've finally come across the solution by myself, due to an annoying \n out there. As for temporary files, no worries, I'll do well with normal redirection.

    Now, that I'm almost there, I need one final bit comparing the speed of DNS servers offered by a network interface (using netsh) and those that I had to read from the IP's listed from an output file.

    Following the previous help, I've worked with this:

    Code:
        responses = fopen("ips_responden.txt", "r");
        while (fgets(ipresp, sizeof(ipresp), responses))
        {
            int response1 = velocidad_media(ipresp);
            printf("\n    Velocidad de respuesta media: %d ms.\n", response1);
        }
    This would give me the average speed of my response to a ping, namely "ipresp". This time I've only received the answer from a single IP, but how would I store different speeds and compare between them? I'd need to store the lowest (i.e. fastest response) in order to compare it with the already operative network interface I've chosen.

    As for the network interface, the same can be said. Netsh can give me different DNS servers and I'd need to compare between them in order to store the lowest value and compare it with the previous block. I could launch this (adaptador is the variable storing the number of interface I've chosen):

    Code:
        strcpy(str, "netsh interface ipv4 show dnsservers ");
        strcat(str, adaptador);
        system(str);
    But how could I store the DNS servers I obtain as separate entities, preferably without printing them through console before deciding which one is faster?
    Last edited by JSteel; 05-14-2020 at 01:21 PM.

  14. #29
    Registered User
    Join Date
    May 2020
    Posts
    39
    Still stuck in a loop.
    I've asked my teacher and he gave me some guidelines, including a new line which includes a new variable, namely response2 here, but still unable to fix this part. Communication through email is as clumsy as my approach in C:

    Code:
            responses = fopen("ips_responden.txt", "r");
            while (fgets(ipresp, sizeof(ipresp), responses))
            {
                int response1 = velocidad_media(ipresp);
                while (fgets(ipresp2, sizeof(ipresp2), responses))
                {
                    int response2 = velocidad_media(ipresp2);
    
                    if (response1 < response2) { // If response1 < response 2 I must save the faster IP the best result
                        printf("\nVelocidad de respuesta media: %d ms.\n", response1);
                    }
                    else
                        printf("\nVelocidad de respuesta media: %d ms.\n", response2);
    
                }
            }
    In other words, I need to browse through the IP's in the .txt file and if one's average speed is faster than the other, replace it and compare with the remaining ones until I get the faster one and store it so I can manipulate it later on. This way I'm just able to save weird characters and the loop won't go the way I want, but I'm unable to find its logic somehow. I mean, sp. with the replacement thing within the loop - and also unable to find info/right parameters to look for through forums.

    I think it's well done and it works most of the times (I think). But sometimes the IP's just give me 0 ms of response which means it doesn't do that well...

    And, whereas I can print which one wins, how do I store it as the "winner" in order to compare with another set of IP's which will come later on?
    Last edited by JSteel; 05-15-2020 at 02:42 PM. Reason: Improved code

  15. #30
    Registered User
    Join Date
    May 2020
    Posts
    39
    Still trying to solve my loop but I feel I'm close to it.

    Code:
            int best_response = velocidad_media(fgets(ipresp, sizeof(ipresp), responses));
            char best_ip;
            responses = fopen("ips_responden.txt", "r");
            while (fgets(ipresp, sizeof(ipresp), responses))
            {
                int response1 = velocidad_media(ipresp);
                if (response1 < best_response) {
                    best_response = response1;
                    best_ip = response1;
                }
                printf("\n    Velocidad de respuesta media: %d ms.\n", best_response);
                printf("    IP seleccionada: %s", best_ip);
            }
    The implementation of "best_ip" seems the only troublesome issue here. I've already gotten the best_respone but don't know how to store the line that's read when getting such string. Please help and I thiink I'm done!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Cant print a file
    By Gainborought in forum C Programming
    Replies: 5
    Last Post: 02-07-2014, 11:45 PM
  2. Replies: 3
    Last Post: 02-01-2014, 06:50 PM
  3. Replies: 3
    Last Post: 03-13-2013, 07:10 PM
  4. Print to file
    By metaTron in forum C Programming
    Replies: 14
    Last Post: 01-19-2006, 04:10 PM
  5. how to print it to a file
    By xlordt in forum C Programming
    Replies: 4
    Last Post: 10-04-2002, 11:44 AM

Tags for this Thread