trying to a system call in an if statement

Discussion in 'Mac Programming' started by trey5498, Jul 11, 2008.

  1. trey5498 macrumors regular

    Joined:
    Jun 16, 2008
    #1
    Code:
    if ([system("lpstat -a Printer1 | grep -o "accepting"")] == accepting) 
    Here is what I got. The system call works, but it is not working in the if statement

    and when I make is


    Code:
    if (system("lpstat -a Printer1 | grep -o "accepting"") == accepting) 
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    Are you trying to run a system command and read in its output?

    If so, you need a file descriptor, and assign the value of popen:
    http://www.manpagez.com/man/3/popen/

    something like:

    Code:
    FILE *myFD = NULL;
    myFD = popen("lpstat -a Printer1 | grep -o "accepting","r");
    if(myFD == NULL) {
      //There was a problem
    }
    /*
    read from myFD using fgets, etc. into a character buffer
    */
    pclose(myFD);
    -Lee
     
  3. trey5498 thread starter macrumors regular

    Joined:
    Jun 16, 2008
    #3
    no what I am doing is calling a system command to display is a printer is already installed. No files involved. The line:

    Code:
    system("lpstat -a Printer1 | grep -o "accepting"")
    
    it will get the word grab accepting out of "Printer1 accepting requests since friday ......" Basically if the printer is there and i grep the accepting, I am trying to compare string to string. and the file descriptor is the way? ok I will take a look into that a little more
     
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    popen is the way to read the output of a system command into your program. In this case, after the popen you would read from the file descriptor and see what the line is. Grep might not do what you think it does. You could do something like:
    Code:
    myFD = popen("lpstat -a Printer1 | grep -o \"accepting\"" | wc -l,"r");
    Then when you read from there the output will be 0 if there is no line containing accepting or 1 if there is a line containing accepting. you will still read it as a character buffer, so you'd need to use something like:
    Code:
    strncmp(buffer,"1",1);
    In unix everything is a file. In this case the file descriptor is reading/writing to the pipes for stdin and stdout for your commands. The pipes are files, like everything else.

    -Lee
     
  5. trey5498 thread starter macrumors regular

    Joined:
    Jun 16, 2008
    #5
    Code:
    myFD = popen("lpstat -a CSE-211-DJQ | grep -o \"accepting\"","r");
    if (myFD == NULL) {
    	[cse211djq setToolTip:@"CSE Plotters"];		 
    } else {
    	[cse211djq setToolTip:@"Printer already Installed"];
    	[cse211djq setEnabled:false]; 
    }
    myFD = NULL;
    myFD = popen("lpstat -a ARC-118-DJQ | grep -o \"accepting\"","r");
    if (myFD == NULL) {
    	[arc118djq setToolTip:@"Architecture Plotters"];		 
    } else {
    	[arc118djq setToolTip:@"Printer already Installed"];
    	[arc118djq setEnabled:false]; 
    }
    Rest of the printers (total of 17)
    
    strncmp(buffer,"1",1);
    pclose(myFD);
    
    Yields:

    error: syntax error before string constant
    warning: data definition has no type or storage class

    to the strncmp command

    and:

    warning: parameter names (without types) in function declaration
    warning: data definition has no type or storage class

    to the pclose.

    Have no idea about the strncmp but I am sure I can find something while searching or does it need to be called after setting myFD? However do I need to set myFD to null before closing it?

    the grep command yeild ONLY the "accepting" if the printer is installed, that is tested and works ;)
     
  6. trey5498 thread starter macrumors regular

    Joined:
    Jun 16, 2008
    #6
    Update figured some of it out but I have another issue and moving pclose up a little bit in the entire .m file fixed its warnings:

    Code:
    myFD = popen("lpstat -a CSE-211-DJQ | grep -o \"accepting\"","r");
    if (strcmp (myFD,"accepting")) {
    		
    		[cse211djq setToolTip:@"Printer already Installed"];
    		[cse211djq setEnabled:false]; 
    
    } else {
    		[cse211djq setToolTip:@"CSE Plotters"];
    }
    
    yeilds a warning: passing argument 1 of 'strcmp' from incompatible pointer type after the use of strncmp even when i change the "accepting" to a "1"
     
  7. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #7
    I was more pointing out what system calls to make to accomplish this.

    You will need to use popen to run the command and get a file descriptor to it's stdout.

    You will need to use fgets or something similar to read in to a char buffer from the file descriptor you opened.

    You can then use strncmp to compare the char buffer you read to whatever. I didn't see the -o, so you could use strncmp to compare what you read to "accepting" as a string literal.

    Close the file descriptor with pclose.

    Repeat this process for each thing you need to examine.

    -Lee
     
  8. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #8
    This is no good. From terminal do "man strncmp" to see what arguments you need. It is two const char *s and 1 size_t. You are passing one FILE * and one const char * to strcmp. You need to read from the FILE * into a char *, then do the comparison. You need to compare the result of strcmp or strncmp to 0. If the result is equal to 0, the strings match. If it is not equal to 0, they do not match.

    -Lee
     
  9. trey5498 thread starter macrumors regular

    Joined:
    Jun 16, 2008
    #9
    ahhh kk, well I have looked a little close and have figured some of the problems going and have figured out some. I will continue to look. The other problem is more down the line of importing headers (simple I know) However when I try to import the variables from lets say tooltips.h to dvrchk.m it seems I have to redeclare them? is this true?
     
  10. trey5498 thread starter macrumors regular

    Joined:
    Jun 16, 2008
    #10
    Code:
    myFD = popen("lpstat -a CSE-211-DJQ | grep -o \"accepting\"","r");.
    fgets(buffer, 10, myFD);
    if (strncmp (buffer,"accepting",9) == 0) {
    		
    		[cse211djq setToolTip:@"Printer already Installed"];
    		[cse211djq setEnabled:false]; 
    
    } else {
    		[cse211djq setToolTip:@"CSE Plotters"];
    }
    

    WORKS!!!!!! Thank you for your patience ;) Also thank you for pointing me in the direction however making me figure it out myself ;)
     
  11. lazydog macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #11
    Congratulations on getting your code to work, but I noticed the above comment. Not sure how many code blocks your are copying for all 17 printers but it might be worth thinking about getting rid of all this duplication - in the short term you may only save some typing and cutting and pasting, but in the long run your code will be easier to debug and maintain.

    Best way is to create a printer class with members for the printer attributes, eg name etc, and methods for doing whatever it is you need to do to each printer. You would then maintain an array or set of printers. Adding or removing printers would be easy... well depending on how you've set up the UI part of your app. Ideally, your app, including the UI, should not be hard coded to any particular list of printers,.

    If you prefer not to use objects/classes you can use a c struct to represent a printer and functions to initialise and manipulate the printers (passing a printer struct as an argument).

    good luck

    b e n
     
  12. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #12
    You're welcome. I'm glad this is working, but I wanted to ensure that you are using pclose after each popen when you are done reading the associated file handle. If not, you are leaking file handles and this could lead to a "too many open files" error. This can be infuriating to track down.

    -Lee
     
  13. ElectricSheep macrumors 6502

    ElectricSheep

    Joined:
    Feb 18, 2004
    Location:
    Wilmington, DE
    #13
    I haven't played around with it too much, but I wonder if the clang static analyzer would catch bugs like leaked file descriptors. It's something I've been meaning to investigate.
     
  14. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #14
    I have not tried clang before. I wrote a test program for this, and I'm not sure if clang is failing for some reason or if it is running successfully and is failing to detect the bug. I'm pretty sure clang is failing, but if you have it set up and it is working for you, you can test this with the code I wrote:
    Code:
    #include <stdio.h>
    #include <string.h>
    char *get_output_line(char *);
    int main(int argc, char *argv[]) {
      char res[256];
      char *res_ptr = NULL;
      res_ptr=get_output_line("ls -l");
      if(res_ptr != NULL) {
        strncpy(res,res_ptr,(size_t)256);
        printf("Ls res: %s\n",res);
      } else {
        printf("Could not get result\n");
      }
      res_ptr=get_output_line("uname");
      if(res_ptr != NULL) {
        strncpy(res,res_ptr,(size_t)256);
        printf("uname res: %s\n",res);
      } else {
        printf("Could not get result\n");
      }
      res_ptr=get_output_line("uptime");
      if(res_ptr != NULL) {
        strncpy(res,res_ptr,(size_t)256);
        printf("uptime res: %s\n",res);
      } else {
        printf("Could not get result\n");
      }
      return 0;
    }
    
    char *get_output_line(char *command) {
      FILE *my_file = NULL;
      char result[256];
      if(command == NULL) return NULL;
      if(strlen(command) <= 0) return NULL;
      
      my_file = popen(command,"r");
      if(my_file == NULL) return NULL;
      fgets(result,(size_t)256,my_file);
      return result;
    }
    
    I don't think there are other bugs, so the only thing it should detect (if it can) is the failure in get_output_line to pclose my_file.

    -Lee
     

Share This Page