19

For my OS class I'm supposed to implement Linux's cat using only system calls (no printf)

Reading this reference I found it being used to print to a file. I guess I should manipulate ofstream.

In the example appears: ofstream outfile ("new.txt",ofstream::binary);

How can I make it write to the screen?

EDIT: I realized this write() is part of iostream library, is this the same as the int write (int fd, char *buf , int size) system call?

jamessan
  • 41,569
  • 8
  • 85
  • 85
andandandand
  • 21,946
  • 60
  • 170
  • 271
  • 2
    And don't forget that Linux cat is GNU cat and sports 11 non-ignored command line options ;-).http://linux.die.net/man/1/cat – Peter G. Oct 05 '10 at 18:00
  • You've tagged this as `C` but you're talking about and have linked to `C++` classes. Is this supposed to be C, or C++? Re your edit - I wouldn't consider iostream to be allowed, given "only system calls", only things like `man 2 write` – Stephen P Oct 05 '10 at 18:13

5 Answers5

29

A system call is a service provided by Linux kernel. In C programming, functions are defined in libc which provide a wrapper for many system calls. The function call write() is one of these system calls.

The first argument passed to write() is the file descriptor to write to. The symbolic constants STDERR_FILENO, STDIN_FILENO, and STDOUT_FILENO are respectively defined to 2, 0, and 1 in unidtd.h. You want to write to either STDOUT_FILENO or STDERR_FILENO.

const char msg[] = "Hello World!";
write(STDOUT_FILENO, msg, sizeof(msg)-1);

You can alternatively use the syscall() function to perform an indirrect system call by specifying the function number defined in syscall.h or unistd.h. Using this method, you can guarantee that you are only using system calls. You may find The Linux System Call Quick Refernence (PDF Link) to be helpful.

/* 4 is the system call number for write() */
const char msg[] = "Hello World!";
syscall(4, STDOUT_FILENO, msg, sizeof(msg)-1);
jschmier
  • 15,458
  • 6
  • 54
  • 72
10

No, std::ostream::write is not the same as the write system call. It does (almost certainly) use the write system call, at least on a system like Linux that has such a thing, and it normally does pretty similar things, but it's still a separate thing of its own.

Linux will, however, pre-open standard input, standard output and standard error streams for your process. To write to the screen, you'd normally use write (i.e., the one that is a system call) to write to stream number 1 or stream number 2 (which are standard output and standard error respectively).

If you need to write to the screen even if those are re-directed, you'd normally open a stream to /dev/tty and (again) use write to write to it:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main() { 
    char msg[] = "hello\n";

    int fd = open("/dev/tty", O_WRONLY);
    write(fd, msg, sizeof(msg));
    return 0;
}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
4
#include <unistd.h>
/* ... */
const char msg[] = "Hello world";
write( STDOUT_FILENO, msg, sizeof( msg ) - 1 );

First argument is the file descriptor for STDOUT (usually 1), the second is the buffer to write from, third is the size of the text in the buffer (-1 is to not print zero terminator).

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
3
#define _GNU_SOURCE         /* See feature_test_macros(7) */    
#include <unistd.h> // For open, close, read, write, fsync
#include <sys/syscall.h>  //For SYSCALL id __NR_xxx

//Method 1 : API    
write(1,"Writing via API\n",\
        strlen("Writing via API\n") ); 
fsync(1);
//Method 2  : Via syscall id
const char msg[] = "Hello World! via Syscall\n";
syscall(__NR_write, STDOUT_FILENO, msg, sizeof(msg)-1);     
syscall(__NR_fsync, STDOUT_FILENO );    // fsync(STDOUT_FILENO);
-3

Your reference is incorrect. It's part of C++ and has nothing to do with your assignment. The correct reference is http://www.opengroup.org/onlinepubs/9699919799/functions/write.html

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711