/* * Topscreen * * Copyright (c) 1998, 2003, John T. Criswell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the author nor the contributors may be used to * endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * RCS_ID: $Header: /u/jcriswel/src/topscreen/RCS/topscreen.c,v 1.4 2003/03/23 02:58:20 jcriswel Exp $ */ #include #include #include #include #include int main (int argc, char * argv[]) { /* Window for the rest of the screen */ WINDOW * Rest; /* * Check the command line arguments first. */ if (argc < 4) { usage (argv[0]); exit (1); } /* * Initialize the curses library */ initscr (); /* * Create the header at the top which will never scroll away. */ create_top (atoi (argv[1]), argv[2]); /* * Now launch the command that will be displayed in the rest * of the screen. */ do_cmd (atoi (argv[1]), &(argv[3])); /* * Shutdown the curses library for this program. */ endwin (); exit (0); } /* * Function: create_top() * * Description: * This function reserves at the top of the screen the number of lines * specified. Then, it reads the given file and prints the contents at * the top of the screen. * * Inputs: * lines - The number of lines to reserve. * filename - The anem of the file containing the contents. * * Outputs: * None. * * Return value: * -1 : An error occurred. * 0 : Success * */ int create_top (int lines, char * filename) { /* The Window representing the first few lines on the screen */ WINDOW * Top; /* The file descriptor for this file */ int fd; /* The buffer to read the data into */ char buffer[1024]; /* The number of bytes read in */ int size; /* Index variable */ int index; /* The size of the screen */ int maxlength; int maxwidth; /* * Get the maximum size of the screen. */ getmaxyx (stdscr, maxlength, maxwidth); /* * Create a window at the top of the screen for the header * Four lines, eighty columns, beginy=0, beginx = 0 */ Top = newwin (lines, maxwidth, 0, 0); wrefresh (Top); idlok (Top,TRUE); scrollok (Top,TRUE); fd = open (filename,O_RDONLY); if (fd == -1) { printf ("Unable to open %s\n",filename); return -1; } /* * Next, read the file and print it's contents */ while ((size=read (fd, buffer, 1024)) > 0) { for (index=0; index < size; index++) { wprintw (Top, "%c", buffer[index]); } /* * Refresh the buffer after every read. */ wrefresh (Top); } return 0; } /* * Function: do_cmd() * * Description: * This function will create a window in the bottom section of the screen. * It will then launch the commmand and get its output and put it in this * bottom window. * * Inputs: * lines - The number of lines reserved at the top of the screen. * args - The vector of arguments to the command to execute. * * Outputs: * None. * * Return value: * -1 : An error occurred. * 0 : Success. */ int do_cmd (int lines, char ** args) { /* The Window representing the rest of the screen */ WINDOW * Screen; /* Process ID of child process that will execute the command */ int child; /* The pipe file descriptors that we'll use */ int filedes[2]; /* The buffer to read data into */ char buffer [1024]; /* The number of bytes read */ int size; /* Index variable for loops */ int index; /* The size of the screen */ int maxlength; int maxwidth; /* * Get the maximum size of the screen. */ getmaxyx (stdscr, maxlength, maxwidth); /* * Create a window representing the rest of the screen. * Four lines, eighty columns, beginy=0, beginx = 0 */ Screen = newwin (maxlength - lines, maxwidth, lines, 0); wrefresh (Screen); idlok (Screen,TRUE); scrollok (Screen,TRUE); /* * Create a pipe. */ if ((pipe (filedes)) == -1) { fprintf (stderr, "Can't create a pipe.\n"); return -1; } /* * Next, create a child process. */ if ((child=fork()) == -1) { fprintf (stderr, "Can't fork child process.\n"); return -1; } if (child) { /* Parent process */ close (filedes[1]); /* * Now, the parent will continually read * from the child until it gets on EOF. */ while ((size=read (filedes[0],buffer,1024)) != 0) { for (index=0; index < size; index++) { wprintw (Screen, "%c", buffer[index]); } /* * Refresh the buffer after every read. */ wrefresh (Screen); } } else { /* Child process */ /* * The first thing we need to do is to duplicate * our STDOUT and STDERR file descriptors to be the pipe * write descriptor. */ if ((dup2 (filedes[1], STDOUT_FILENO)) != STDOUT_FILENO) { fprintf (stderr, "Child can't dup!\n"); exit (1); } if ((dup2 (filedes[1], STDERR_FILENO)) != STDERR_FILENO) { fprintf (stderr, "Child can't dup!\n"); exit (1); } /* * Close the extra file descriptor. */ close (filedes[1]); close (filedes[0]); /* * Finally, exec the command. */ execvp (args[0], args); fprintf (stderr, "Child couldn't exec.\n"); exit (-1); } return 0; } /* * Function: usage() * * Description: * Prints out a usage statement. */ int usage (char * name) { printf ("%s: [args|args...}\n", name); return 0; }