Try this.  I wrote it while practicing with APUE.


/* 
 * FILE:   list-homepages.c
 * AUTHOR: Alan Shutko
 * DATE:   Wed Sep 18 1996
 *
 */

static char *rcsid = "$Header: /home/ats/Software/list-homepages.c,v 1.7.1.4 
1997/03/19 22:50:07 ats Exp $";

#define HTML_DIR "/public_html"
#define SORT_COMMAND "/bin/sort"
#define HEADER_FILE "su-header.html"
#define FOOTER_FILE "su-footer.html"
 
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

typedef enum err_status
{
    ERR_RETURN,
    ERR_QUIT,
    ERR_DUMP
} err_status ;

void error_system(err_status errflag, const char *fmt, ...);
void error_user(err_status errflag, const char *fmt, ...);
size_t copy_file(FILE* in, FILE* out);

#define MAXLINE 4096

int main()
{
    struct stat dir;
    int i;
    struct passwd *pwent;
    char path[PATH_MAX];
    char *fullname, *tmp;
    int fd[2];
    pid_t pid;
    FILE* fp;
    size_t count;

    fprintf(stdout, "Content-type: text/html\n\n");
 
    if ((fp = fopen(HEADER_FILE, "r")) != NULL)
        copy_file(fp, stdout);
    else
    {
        fprintf(stdout, "<HTML><HEAD>\n");
        fprintf(stdout, "<title>Group Home Pages</title>\n");
        fprintf(stdout, "<body>\n");
        fprintf(stdout, "<h1>Group Home Pages</h1>\n");
        fprintf(stdout, "<ul>\n");
    }
    
    fflush(NULL);
    
    if (pipe(fd) < 0)
        error_system(ERR_QUIT, "error creating pipe in line %d", __LINE__);
    
    if ( (pid = fork()) < 0)
        error_system(ERR_QUIT, "error in fork");
    else if (pid > 0)           /* parent */
    {
        FILE* pipep;
        if ((pipep = fdopen(fd[1], "w")) == NULL)
            error_system(ERR_QUIT, "error in fdopen");
        
        for (i = 1; (pwent = getpwent()); i++)
        {
            if (pwent->pw_gid != 2000) /* not student group */
                continue;
            
            strcpy(path, pwent->pw_dir);
            strcat(path, HTML_DIR);
            
            if ((strlen(pwent->pw_gecos)) > 0) /* Use GECOS.  Strip comma */
            {
                if ( (fullname = malloc(1+sizeof(char) *
                                        strlen(pwent->pw_gecos)))
                     == NULL)
                    error_system(ERR_DUMP, "could not get memory for fullname");
                /* Strip commas */
                strcpy(fullname, pwent->pw_gecos);
                if ((tmp = strpbrk(fullname, ",")) != NULL)
                    *tmp =  '\0';
            }
            else                /* Use pw_name */
            {
                if ((fullname = malloc(1+sizeof(char) *
                                       strlen(pwent->pw_name)))
                     == NULL)
                    error_system(ERR_DUMP,
                                 "could not get memory for fullname");
                strcpy(fullname, pwent->pw_name);
            }
            
            if (stat(path, &dir) < 0) /* doesn't exist */
            {
                free(fullname);
                continue;
            }
            
            fprintf(pipep, "<!--%s--><li><a href=\"/~%s/\">%s</a>\n",
                    fullname, pwent->pw_name, fullname);
            free(fullname);
        }
        fclose(pipep);
        close(fd[1]);
    }
    else
    {
        close(fd[1]);
        if (fd[0] != STDIN_FILENO)
        {
            if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
                error_system(ERR_QUIT, "error dup2 to stdin");
            close(fd[0]);
        }
        execlp(SORT_COMMAND, "sort", (char *)0);

        /* Error has occured if we get here */
        error_system(ERR_QUIT, "error in exec");
       
        exit(0);
    }
    wait(NULL);

    if ((fp = fopen(FOOTER_FILE, "r")) != NULL)
        copy_file(fp, stdout);
    else
        fprintf(stdout, "</body>\n");
    
    exit(0);
}


/*@@
   @routine    error_system
   @date       Thu Sep 12 14:27:20 1996
   @author     Alan Shutko
   @desc 

   This call signals an error in handling a system call to the user.
   It will print a error string (with standard printf handling), print
   the system error, then continue as specified in the abort
   parameter.

   If abort is RETURN, error_system will return to the caller.  If
   QUIT, it will call exit(EXIT_FAILURE).  If DUMP, it will call
   abort().
   
   @enddesc 
   @calls     
   @calledby   
   @var     abort
   @vdesc   Details what action to take after error is printed
   @vtype   err_status
   @vio     in
   @var     fmt
   @vdesc   format string
   @vtype   char*
   @vio     in
   @vcomment 
   Printf style handline
   @endvar 
@@*/


void error_system(err_status errflag, const char *fmt, ...)
{
    va_list args;
    int errno_save;             /* prevent errors from printf */
    char buf[MAXLINE];

    va_start(args, fmt);

    errno_save = errno;
    vsprintf(buf, fmt, args);
    sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
    strcat(buf, "\n");
    fputs(buf, stderr);
    fflush(NULL);

    va_end(args);
    switch (errflag)
    {
        case ERR_RETURN:
            return;
        case ERR_DUMP:
            abort();
        case ERR_QUIT:
            exit(EXIT_FAILURE);
        default:
            error_user(ERR_DUMP, "Bad call to error_system!");
    }
}

 /*@@
   @routine    error_user
   @date       Thu Sep 12 14:40:10 1996
   @author     Alan Shutko
   @desc 

   This call signals an error in userspace to the user.  It will print
   a error string (with standard printf handling).

   If abort is RETURN, error_system will return to the caller.  If
   QUIT, it will call exit(EXIT_FAILURE).  If DUMP, it will call
   abort().
   
   @enddesc 
   @calls     
   @calledby   
   @var     abort
   @vdesc   Details what action to take after error is printed
   @vtype   err_status
   @vio     in
   @var     fmt
   @vdesc   format string
   @vtype   char*
   @vio     in
   @vcomment 
   Printf style handline
   @endvar 
@@*/


void error_user(err_status errflag, const char *fmt, ...)
{
    va_list args;

    int errno_save;
    /* prevent errors from printf */
    char buf[MAXLINE];

    va_start(args, fmt);
    errno_save = errno;
    vsprintf(buf, fmt, args);
    strcat(buf, "\n");
    fputs(buf, stderr);
    fflush(NULL);

    va_end(args);
    switch (errflag)
    {
        case ERR_RETURN:
            return;
        case ERR_DUMP:
            abort();
        case ERR_QUIT:
            exit(EXIT_FAILURE);
        default:
            error_user(ERR_DUMP, "Bad call to error_system!");
    }
}

size_t copy_file(FILE* in, FILE* out)
{
    size_t count, total;
    char buf[BUFSIZ];
    
    while (!feof(in))
    {
        if (!(count = fread(buf, sizeof(char), BUFSIZ, in) ))
            error_system(ERR_QUIT, "fread failed");

        if ((fwrite(buf, sizeof(char), count, out)) != count)
            error_system(ERR_QUIT, "fwrite failed");
        total += count;
    }
    
    return(total);
}


/*
 * Local Variables:
 * compile-command: "gcc -Wall -o list-homepages list-homepages.c"
 * End:
 */


-- 
Alan Shutko <[EMAIL PROTECTED]> - By consent of the corrupted
I'm successful because I'm lucky.   The harder I work, the luckier I get.


-- 
  PLEASE read the Red Hat FAQ, Tips, Errata and the MAILING LIST ARCHIVES!
http://www.redhat.com/RedHat-FAQ /RedHat-Errata /RedHat-Tips /mailing-lists
         To unsubscribe: mail [EMAIL PROTECTED] with 
                       "unsubscribe" as the Subject.

Reply via email to