0

I want to use the above command in a c program in linux.

I have searched so far that there are system calls and exec calls that one may make in a code. Is there any other way using exec or system commands? Using the system command isn't an ideal command for a multi-threaded server ,what do you suggest?

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
Goldriver
  • 35
  • 11

3 Answers3

2

First make sure you have lp installed in this path. (Using which lp in the terminal).

You may want to understand the lp command. It's a classic unix command to send data to the "line printer", but it works with e.g. .pdf files too nowadays, depending on your printer system. However, it isn't necessarily installed. Sometimes, lpr may work better, too.

See also: http://en.wikipedia.org/wiki/Lp_%28Unix%29

The second part is about executing unix commands. system is the easiest (also the easiest to introduce a security issue into your program!), using fork and execve is one of a number of alternatives (have a look at man execve).

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
  • i actually tested the lp command from my linux terminal and i was successfully getting prints but i wanted to know how i can use this command in my c program. Yeah,it seems that system is the easiest but someone mentioned that it would slow down my program or hang my code in the above my comments. – Goldriver Jan 13 '15 at 21:19
  • To understand the two, have a look at http://stackoverflow.com/questions/27461936/system-vs-execve – Has QUIT--Anony-Mousse Jan 13 '15 at 22:22
1

Yes, this code is ok. It will print the file named filename provided that the lp is found at /usr/bin and the filename file exists. You can add checks for that if you want your program to report if something went wrong, other than that it will do exactly what you expect.

Doing system("lp filename"); would work if you don't mind your program blocking after that system() call and until lp finishes.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • It wouldn't be ideal for a multi-threaded server right? I don't want my program to go in block state after getting the system command. I want it to go back in listening state after it sends out the system command as i am implementing a multi-threaded server. – Goldriver Jan 13 '15 at 21:34
  • I want to ask one more thing. Can i pass a char array to a system call in my C program? like the following: char filename[1024]:"/home/user/Desktop/texts/hello1.txt" system("lp filename") – Goldriver Jan 13 '15 at 23:46
  • no, you need `snprintf` for that, something like `char command[SOME_LARGE_ENOUGH_VALUE]; snprintf(command, sizeof(command), "lp %s", filename); system(command);`. – Iharob Al Asimi Jan 14 '15 at 00:06
  • i see, great! .There is another thing pertaining to the fork+exec thing ,such a statement is only necessary when you have multiple clients accessing the printer right?. I mean to say without fork execve will still work fine? – Goldriver Jan 14 '15 at 00:19
  • No, it has nothing to do with that, you use it if you want your program to execute the `lp` command, and continue executing, `fork()` creates a new process which is then replaced by `execv()`, so the original process continues execution normally, there is also `popen()` wich also allows communication with the child process. – Iharob Al Asimi Jan 14 '15 at 00:22
1

You could also use popen(3) (instead of system(3)). But you always need to fork a process (both system and popen are calling fork(2)). BTW, if you have a CUPS server you might use some HTTP client protocol library like libcurl but that is probably inconvenient. Better popen or system an lp (or lpr) command.

BTW, printing is a relatively slow and complex operation, so the overhead of forking a process is negligible (I believe you could do that in a server; after all people usually don't print millions of pages). Some libraries might give you some API (e.g. QPrinter in Qt).

Notice that the lp (or lpr) command is not actually doing the printing, it is simply interacting with some print daemon (cupsd, lpd ...) and its spooling system. See e.g. CUPS. So running the lp or lpr command is reasonably fast (much faster than the printing itself), generally a few milliseconds (certainly compatible with a multi-threaded or server application).

Quite often, the command passed to popen or system is constructed (e.g. with snprintf(3) etc...), e.g.

  char cmdbuf[128];
  snprintf (cmdbuf, sizeof(cmdbuf), "lp %s", filename);

but beware of code injection (think about filename containing foo; rm -rf $HOME) and of buffer overflow

Of course, notice that library functions like system, popen, fopen are generally built above existing syscalls(2). Read Advanced Linux Programming

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Great Answer Basile! I couldn't up-vote you because of the damn no for reasons down-votes which took down my user rating as i am a relatively new user so i can't vote. – Goldriver Jan 13 '15 at 21:49
  • I want to ask one more thing. Can i pass a char array to a system call in my C program? like the following: char filename[1024]:"/home/user/Desktop/texts/hello1.txt" system("lp filename"); – Goldriver Jan 13 '15 at 23:44
  • @goldriver No, you have to form the whole command in the char array. eg: using `sprintf` and trhen "system" the char array. – Jasen Jan 14 '15 at 07:14
  • @Jasen: never suggest `sprintf` but only `snprintf` (or `asprintf` if available) – Basile Starynkevitch Jan 14 '15 at 08:29