LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 09-12-2012, 03:01 AM   #1
suttiwit
Member
 
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 192
Blog Entries: 2

Rep: Reputation: 22
Question [!] How to combine values in variable, text, int and other data in system(); (C).


Hello, I am a newbie to C. The system(); command is very useful for me. I used it so much in python. Now, i am learning C....

I was able to do this in python:
Code:
import os
editor = "nano"
file = "myfile.txt"
os.system(editor + " " + file) # This runs "nano myfile.txt".
But when i do something similar in C:
Code:
#include <stdio.h>
#include <stdlib.h>
#define EDITOR "nano"

int main()
{
char filename[9999] = "myfile.txt";
system("%s %s", EDITOR, filename);
return 0;
}
it gives me an error about "system(); can only take an argument" or something.

How do i do like in python in C? Help would be apreciated.
 
Old 09-12-2012, 03:10 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,618

Rep: Reputation: 484Reputation: 484Reputation: 484Reputation: 484Reputation: 484
sg like this:

Code:
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#define EDITOR "nano"

int systemf (const char *fmt, ...)
{
    char *cmdbuff= NULL;
    va_list ap;
    int rc;

    va_start (ap, fmt);
    rc= vasprintf (&cmdbuff, fmt, ap);
    va_end (ap);

    if (rc<0) {
        fprintf (stderr, "systemf: *** vasprintf error\n");
        goto RETURN;
    }

    rc= system (cmdbuff);

RETURN:
    if (cmdbuff) free (cmdbuff);
    return rc;
}

int main (void)
{
static const char filename[] = "myfile.txt";

    systemf ("%s %s", EDITOR, filename);
    return 0;
}

PS: you shouldn't hardcode "nano" into your program, instead ask environment variable $EDITOR to get the name of the user's preferred text-editor.
 
Old 09-12-2012, 03:13 AM   #3
suttiwit
Member
 
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 192
Blog Entries: 2

Original Poster
Rep: Reputation: 22
Hi, NevemTeve. Thanks for reply.. But, I don't understand much of it. Please give a more simpler code that only focuses on the system(); thanks.
 
1 members found this post helpful.
Old 09-12-2012, 03:15 AM   #4
414N
Member
 
Registered: Sep 2011
Location: Italy
Distribution: Slackware
Posts: 608

Rep: Reputation: 179Reputation: 179
man system
And this settles the RTFM part
system accepts only a char* as its only argument. What you've put in, however, is a format string followed by a list of variables in a printf/scanf fashion.
If you really want to use those variables you need to put them first inside a "buffer" string using sprintf, like:
Code:
char arg[9999];
sprintf(arg, "%s %s", EDITOR, filename);
system(arg);
Pay attention to the return values of those functions, especially the system calls like system().
EDIT: whoops, beaten on time!
 
2 members found this post helpful.
Old 09-12-2012, 03:18 AM   #5
suttiwit
Member
 
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 192
Blog Entries: 2

Original Poster
Rep: Reputation: 22
414N, hi, thank you so much. also, i didn't know it has a man page
 
Old 09-12-2012, 03:19 AM   #6
Celyr
Member
 
Registered: Mar 2012
Location: Italy
Distribution: Slackware+Debian
Posts: 314

Rep: Reputation: 77
Code:
#include <stdio.h>
#include <stdlib.h>
#define EDITOR "nano"

int main()
{
  char *buf[256];
  char *filename[128] = "myfile.txt";
  
  sprintf(buf, "%s %s", EDITOR, filename);

  return system(buf);
}
Please don't learn spaghetti code, every time you use a goto god kills a kitten.

EDIT: double beated on time -_-
Attached Images
File Type: jpg kitten.jpg (24.4 KB, 3 views)

Last edited by Celyr; 09-12-2012 at 09:08 AM.
 
1 members found this post helpful.
Old 09-12-2012, 03:21 AM   #7
suttiwit
Member
 
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 192
Blog Entries: 2

Original Poster
Rep: Reputation: 22
what's sprintf(); ?
 
Old 09-12-2012, 03:23 AM   #8
Celyr
Member
 
Registered: Mar 2012
Location: Italy
Distribution: Slackware+Debian
Posts: 314

Rep: Reputation: 77
Well, it's like printf but to a string instead of stdout.
Code:
man sprintf
 
Old 09-12-2012, 03:34 AM   #9
suttiwit
Member
 
Registered: Aug 2012
Location: Chiang Mai, Thailand
Distribution: Kubuntu 12.10 x86_64
Posts: 192
Blog Entries: 2

Original Poster
Rep: Reputation: 22
Exclamation

Quote:
Originally Posted by Celyr View Post
Code:
#include <stdio.h>
#include <stdlib.h>
#define EDITOR "nano"

int main()
{
  string buf[256];
  string filename[128] = "myfile.txt";
  
  sprintf(buf, "%s %s", EDITOR, filename);

  return system(buf);
}
Please don't learn spaghetti code, every time you use a goto god kills a kitten.

EDIT: double beated on time -_-
Eh? What did u mean?
 
Old 09-12-2012, 04:19 AM   #10
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,618

Rep: Reputation: 484Reputation: 484Reputation: 484Reputation: 484Reputation: 484
Quote:
Originally Posted by suttiwit View Post
But, I don't understand much of it. Please give a more simpler code that only focuses on the system(); thanks.
Either use the manual, or simply settle for the fact that now you have a 'systemf' function that works like 'sprintf' and 'system' combined. If you don't known what sprintf does, then... well, then get a basic textbook.
 
1 members found this post helpful.
Old 09-12-2012, 07:20 AM   #11
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,396

Rep: Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814
Quote:
Originally Posted by NevemTeve
Code:
int systemf (const char *fmt, ...)
{
    char *cmdbuff= NULL;
...
    if (rc<0) {
        fprintf (stderr, "systemf: *** vasprintf error\n");
        goto RETURN;
    }
...
RETURN:
    if (cmdbuff) free (cmdbuff);
    return rc;
}
Quote:
Originally Posted by Celyr
Please don't learn spaghetti code, every time you use a goto god kills a kitten.
That is a perfectly reasonable non-spaghetti use of goto, don't be a fanatic. The "if (cmdbuff)" is not needed though:
Code:
$ man 3 free
...
       The free() function frees the memory space pointed to by ptr...
       If ptr is NULL, no operation is performed.
I'd say the real problems here would be passing computed strings (which I guess will eventually be coming from user input) to system() which leads to possible security bugs. Also @Celyr: you should be using snprintf in that situation.
 
Old 09-12-2012, 07:29 AM   #12
Celyr
Member
 
Registered: Mar 2012
Location: Italy
Distribution: Slackware+Debian
Posts: 314

Rep: Reputation: 77
I don't think so, it's perfectly safe even this way without snprintf. But well you can use it if you like.
I don't get why use goto when you can use else and make the code more readable. There is no need to use goto and it should not be used.

Last edited by Celyr; 09-12-2012 at 07:32 AM.
 
Old 09-12-2012, 08:27 AM   #13
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,054

Rep: Reputation: 1104Reputation: 1104Reputation: 1104Reputation: 1104Reputation: 1104Reputation: 1104Reputation: 1104Reputation: 1104Reputation: 1104
Quote:
Originally Posted by suttiwit View Post
I am a newbie to C.
Something important to learn in any programming language, but even more important in C:

Figure out what basic functions you will need and write them, then use them.
Quote:
Code:
system("%s %s", EDITOR, filename);
You obviously want a function that is a combination of system and sprintf. The actual system function in C is not that.

Quote:
Originally Posted by Celyr View Post
Code:
int main()
{
...
  sprintf(buf, "%s %s", EDITOR, filename);

  return system(buf);
}
That is the beginner approach to such problems. A combination of sprintf and system is needed, with clear evidence that it will be needed multiple times. The beginner answer is to use sprintf and system where the combination is needed. That grows into using sprintf and system each time the combination is needed.

NevemTeve gave the better answer earlier. Write a general purpose function (once) that combines sprintf and system. Then use that function in each place where you want the combination.

We aren't just talking about sprintf+system here. We are talking about the difference between real programming and slapping stuff together in a programming language.

Quote:
Please don't learn spaghetti code, every time you use a goto god kills a kitten.
I'm with NevemTeve on that one as well. Highly improbable exceptions in a language without exception handling are much cleaner using goto rather than nesting else.

Quote:
Originally Posted by suttiwit View Post
Hi, NevemTeve. Thanks for reply.. But, I don't understand much of it. Please give a more simpler code that only focuses on the system(); thanks.
I'm writing this big reply because you are apparently rejecting the very good answer you got.

There are some complications in writing a general purpose sprintf+system function, because variable arg lists are tricky in C and because C traditionally didn't have good solutions to the risk of buffer overrun when using char buffers (because of the lack of a built in string type).

So NevemTeve used a GNU extension to C (be aware of that if you will be using a non GNU C compiler) and used C features too advanced for a beginner.

So

Quote:
Originally Posted by NevemTeve View Post
Either use the manual
A short function that is too advanced for a C beginner to write is simple enough for a C beginner to understand by reading the man pages of the constructs used.

Quote:
or simply settle for the fact that now you have a 'systemf' function that works like 'sprintf' and 'system' combined.
You don't need to understand the function he gave you. It does exactly what you seemed to want the system function to do. So you can include that in your code and then use it and not worry about why it works.

Last edited by johnsfine; 09-12-2012 at 08:48 AM.
 
1 members found this post helpful.
Old 09-12-2012, 08:29 AM   #14
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,618

Rep: Reputation: 484Reputation: 484Reputation: 484Reputation: 484Reputation: 484
1. sprintf (unlike snprintf and asprintf) may lead to buffer-overflow
2. free (NULL) might be problematic on some old/exotic platforms, so it is wise to make a habit of checking
3. goto's often can be eliminated with nested if's or other hard-to-read constructions, but that's not my cup of tea
 
Old 09-12-2012, 08:53 AM   #15
Celyr
Member
 
Registered: Mar 2012
Location: Italy
Distribution: Slackware+Debian
Posts: 314

Rep: Reputation: 77
Quote:
Originally Posted by NevemTeve View Post
1. sprintf (unlike snprintf and asprintf) may lead to buffer-overflow
2. free (NULL) might be problematic on some old/exotic platforms, so it is wise to make a habit of checking
3. goto's often can be eliminated with nested if's or other hard-to-read constructions, but that's not my cup of tea
You can freely make an example on how that source can produce a buffer overflow. How can 128+6 add up more that 256 will be a miracle I suppose?
Then again show me the proof that it will be needed more times, come on you are discussing on nothing and that goto still be awful

Last edited by Celyr; 09-12-2012 at 08:56 AM.
 
  


Reply

Tags
gcc, linux, script, shell, unix


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Combine multiple text files into one text file? dirtydog7655 Linux - Newbie 6 05-16-2013 10:47 PM
[SOLVED] Variables in text file, how to get their values when printing out the text? idaham Linux - General 2 04-14-2010 03:28 AM
Trying to combine lookahead and variable substitution djeepp Programming 1 09-03-2008 04:32 PM
int values from function main shifter Programming 6 05-07-2007 04:54 PM
how to send shell variable data to a text file ginda Programming 7 06-23-2006 05:49 AM


All times are GMT -5. The time now is 10:58 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration