Logo Search packages:      
Sourcecode: casu version File versions  Download package

init.c

/*
 *  CaSU - communications & status utilities.
 *  Copyright (C) 1992, 1993, 1994 Luke Mewburn <lm@rmit.edu.au>
 *    incorporating:
 *       flon - lists your friends who are logged on.
 *       to - send a short message to a friend
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "casu.h"

/* 
 *    getenvopts
 *
 *    argcp - pointer to original argc
 *    argvp - pointer to original argv
 *    env   - name of env var to check.
 *
 * This function is partially derived from code in gzip 1.0.6,
 * Copyright (C) 1992-1993 Jean-loup Gailly, (which itself was
 * derived from a function that I donated to Jean-loup :)
 */

      /* to assist in compatibility with previous versions */
static int dodgy_env = 0;

void add_envopt(argcp, argvp, name)
    int           *argcp;           /* pointer to argc */
    char    ***argvp;   /* pointer to argv */
    char    *name;            /* name of environment variable */
{
    char    *p, *env, **oargv, **nargv;
    int           oargc = *argcp;   /* old argc */
    int           nargc = 0;  /* number of arguments in env variable */
    int           op, tp;           /* pos in origenv, pos in tmp buf */
    int           quote;            /* # of single quotes in var. */

    env = getenv(name);
    if (env == NULL)
      return;
    p = (char *) malloc(strlen(env)+1);
    if (!p)
      errexit(strerror(errno), NULL);

    if (!strchr(env, '-'))    /* no `-' options in environment variable */
      dodgy_env++;
    for (op = tp = 0; env[op]; nargc++ )
    {                               /* move through env */
      quote = 0;
      while (env[op] == ' ' || env[op] == '\t')
          op++;                     /* skip leading whitespace */
      if (!env[op])
          break;
      
      while (env[op])
      {
          if (env[op] == '\'')
          {
            quote++;                /* single quote */
            op++;
            continue;
          }
          if ( !(quote % 2) && (env[op] == ' ' || env[op] == '\t') )
            break;                        /* nonquoted whitespace */
          if (env[op] == '\\')
          {
            op++;                   /* backslashed char */
            if (!env[op])
                errexit("Unterminated \\", name);
          }
          p[tp++] = env[op++];
      }
      if (quote % 2)                      /* uneven # of 's */
          errexit("Unmatched '", name);
      p[tp++] = '\0';
    }
    if (nargc == 0)
      return;
    *argcp += nargc;
    /*
     * Allocate the new argv array, with an extra element just in case
     * the original arg list did not end with a NULL.
     */
    nargv = (char**) calloc(*argcp+1, sizeof(char *));
    if (nargv == NULL)
      errexit(strerror(errno), NULL);
    oargv  = *argvp;
    *argvp = nargv;

                              /* Copy the program name first */
    if (oargc-- < 0)
      errexit("Argc<=0", NULL);
    *(nargv++) = *(oargv++);

                              /* Then copy the environment args */
    for (tp = 0; nargc > 0; nargc--)
    {
      *(nargv++) = &p[tp];          /* store start */
      while (p[tp++])
          ;                   /* skip over word */
    }

                              /* Finally copy the old args */
    while (oargc--)
      *(nargv++) = *(oargv++);
    return;
} /* add_envopt */


/*
 *    parse_options
 *
 * get all the options parsed...
 */

void
parse_options(origargc, myArgc, myArgv, frfile, format, yes_str, no_str)
    int  origargc, myArgc;
    char *myArgv[], **frfile, **format, **yes_str, **no_str;
{
    int           ch;

    opterr=1;
    while ((ch= getopt(myArgc, myArgv, "aAbBeEhHiIp:P:tTdDf:o:Oy:Yn:NvVU:w")) != -1)
      switch (ch)
      {
      case 'a':
            flags |= ALL_ON;
            break;
      case 'A':
            flags &= ~ALL_ON;
            break;
      case 'b':
            flags |= BEST_NAME;
            break;
      case 'B':
            flags &= ~BEST_NAME;
            break;
      case 'e':
            flags |= NO_MATES;
            break;
      case 'E':
            flags &= ~NO_MATES;
            break;
      case 'h':
            flags |= NO_HEADER;
            break;
      case 'H':
            flags &= ~NO_HEADER;
            break;
      case 'i':
            flags |= NO_IDLE;
            break;
      case 'I':
            flags &= ~NO_IDLE;
            break;
      case 'p':
      case 'P':
            {
                int p=0, v=0;
                  /* loop whilst this is a number < MAXIDLE */
                while (optarg[p] && (v <= MAXIDLE) && isdigit(optarg[p]))
                {
                  v *= 10;
                  v += optarg[p] - '0';
                  p++;
                }
                if (   (!optarg[p])
                  || ((strchr("sSmM", optarg[p]) && !optarg[p+1])))
                {
                  if (strchr("mM", optarg[p]))  /* not in seconds */
                      v *= IDLE_MULTIPLY;
                  if (ch == 'P')
                      min_idle = v;
                  else
                      max_idle = v;
                }
                else
                {
                  flags |= ERROR_OPT;     /* not a full number */
                  errmesg("illegal idle limit", optarg);
                }
            }
            break;
      case 't':
            flags |= NO_TAILER;
            break;
      case 'T':
            flags &= ~NO_TAILER;
            break;
      case 'd':
            flags |= ONE_ONLY;
            break;
      case 'D':
            flags &= ~ONE_ONLY;
            break;
      case 'f':
            *frfile=optarg;
            break;
      case 'o':
            *format=optarg;
            break;
      case 'O':
            *format = STRformat;
            break;
      case 'y':
            *yes_str=optarg;
            break;
      case 'Y':
            *yes_str=STRyes;
            break;
      case 'n':
            *no_str=optarg;
            break;
      case 'N':
            *no_str=STRno;
            break;
      case 'U':
            utmp_file=optarg;
            break;
      case 'w':
            progname = WHO_PROG;
            optind--;
            who_main(myArgc - optind, &myArgv[optind]);
            exit(0);
                  /* NOT REACHED */
      case 'v':
      case 'V':
            flags |= COPYLEFT;
      case '?':
            flags |= ERROR_OPT;
            break;
      }
    if (optind != myArgc)
      flags |= ERROR_OPT;

    if (flags & (ERROR_OPT + COPYLEFT))
    {
      if (dodgy_env || origargc == 1)
          fprintf(stderr, "\
Warning: Your $%s environment variable is of, or has, an older, incorrect,\n\
format. Please check this, referring to the manual for further help.\n",
STRflon);
      fprintf(stderr, "\
Usage: %s [-aAbBeEhHiItTdD] [-f friendsfile] [-o format] [-O] [-U utmpfile]\n\
\t\t[-y ys] [-Y] [-n ns] [-N] [-p max] [-P min] [-vV]\n", progname);

      if (flags & COPYLEFT)
      {
          fprintf(stderr, "\
\n\
%s version %s, %s.\n\
Copyright (C) 1992, 1993, 1994 Luke Mewburn.\n\
Email: <lm@rmit.edu.au>\n\
This is free software, and you are welcome to redistribute it under certain\n\
conditions. See version 2 of the GNU Public License for more details.\n\
", progname, VERSION, RELDATE);
            exit(0);
      }
      exit(1);
    }
    if (*format == NULL)
      *format = STRformat;
    if (*yes_str == NULL)
      *yes_str = STRyes;
    if (*no_str == NULL)
      *no_str = STRno;
} /* parse_options */


/*
 *    parse_format
 *
 * parse the format string, and generate the outbuffer, template buffer,
 * and command buffer.
 * The following structures are created inside printdat:
 * buf -    has the template copied to each for each line output
 *          (used in print.c, but allocated here).
 * form -   contains the text which is static in each output line.
 * cmds -   contains 16bit entries of the form:
 *            | RA | VW | 13..8 CMD | 7..0 WIDTH |
 *          RA - right align
 *          VW - variant width
 *          CMD - 6 bit command
 *          WIDTH - 8 bit width (unsigned) 255 maxwidth limit
 *
 * note that these strings are all one continuous chunk of memory, in
 * this format:
 *    cmds  x ints long
 *    form  x chars long, starts at command + x
 *    buf   x chars long, starts at template + y
 */

void
parse_format(format)
    char    *format;
{
    char    *clp;
    int           cpos, fpos;
    int           width, lp;

    static struct
    {
      char  spec [NUM_SPECIFIERS];
      int   wid  [NUM_SPECIFIERS];
      int   cmd  [NUM_SPECIFIERS];
      int   flags[NUM_SPECIFIERS];
    } defwids =
    {
      { 'u',            'p',        'r',        'c',        'x',
        'l',            'i',        't',        'm',        'h',
        'b',            'a' },
      {  8,       20,         20,         2,          1,
         15,            5,          8,          3,          16,
         18,            3 },
      {  C_USER,  C_PSEUDO,   C_REAL,           C_COUNT,    C_X,
         C_LOGIN, C_IDLE,           C_TTY,            C_MESG,           C_HOST,
         C_HOSTBRK,     C_AVAIL },
      {  0,       NEED_FFILE, NEED_PASSWD,      BLANKF,           BLANKF,
         0,       NEED_STAT,  0,          NEED_STAT,  0,
         0,       NEED_STAT | BLANKF }
    };

    if (flags & NO_IDLE)      /* stat is needed to remove idle entries */
      flags |= NEED_STAT;
    if (!(flags & ALL_ON))    /* don't need friends file with -a */
      flags |= NEED_FFILE;
    if (flags & NO_MATES)     /* need .friends & all people for no mates */
      flags |= (ALL_ON + NEED_FFILE);

    width = 0;
    for (clp=format; *clp; clp++)
    {
      int newwid = 0;
      while (*clp)
      {
          if (*clp == '%')
            if (clp[1] == '\0')
                errexit("No specifier after %", NULL);
            else
                if (clp[1] == '%')
                  clp++;
                else
                  break;
          newwid++;
          clp++;
      }
      width += newwid;
      if (! *clp)
          break;
      clp++;
      if (*clp == '-' || *clp == '.')
          clp++;
      if (! *clp)
          errexit("No specifier after %", NULL);

      newwid=0;
      while ((*clp) && isdigit(*clp) && (newwid <= MAX_WIDTH))
      {
          newwid = newwid*10 + *clp - '0';
          clp++;
      }
      if (! *clp)
          errexit("No specifier after %", NULL);
      if (newwid > MAX_WIDTH)
      {
          clp[1] = '\0';      /* so the fprintf in errexit doesn't die */
          errexit("Field width is too large", clp);
      }
      width += newwid;
      if (isupper(*clp))
          *clp = tolower(*clp);
      for ( lp = 0; lp < NUM_SPECIFIERS; lp++ )
          if ( defwids.spec[lp] == *clp )
            break;
      if (lp == NUM_SPECIFIERS)
      {
          clp[1] = '\0';      /* so printf in errexit doesn't die */
          errexit("Invalid format char", clp);
      }
      if (!newwid)
          width += defwids.wid[lp];
    } /* for */

    printdat.cmds = (int *) malloc((width + 1) * sizeof(int));
    if (printdat.cmds == NULL)
      errexit(strerror(errno), NULL);
    printdat.form = (char *) malloc((width + 1) * 2 * sizeof(char));
    if (printdat.form == NULL)
      errexit(strerror(errno), NULL);
    printdat.buf = &printdat.form[width+1];

    for (lp=0; lp<width;lp++)
      printdat.form[lp]=' ';
    
    cpos = fpos = 0;
    for (clp=format; *clp; clp++)
    {
      width = 0;
      while (*clp)
      {
          if (*clp == '%')
            if (clp[1] == '%')
                clp++;
            else
                break;
          printdat.form[fpos++] = *clp;
          width++;
          clp++;
      }
      while (width > MAX_WIDTH)     /* mark in 'static' slots */
      {
          printdat.cmds[cpos++] = C_NULL + MAX_WIDTH;
          width -= MAX_WIDTH;
      }
      if (width > 0)
          printdat.cmds[cpos++] = C_NULL + (width & C_WIDMASK);
      if (!*clp)
          break;
      clp++;
      printdat.cmds[cpos] = 0;
      if (*clp == '-')
      {
          clp++;
          printdat.cmds[cpos] |= C_RIGHT;
      }
      if (*clp == '.')
      {
          clp++;
          printdat.cmds[cpos] |= C_VARIENT;
      }
      width=0;
      while ((*clp) && isdigit(*clp))
      {
          width = width*10 + *clp - '0';
          clp++;
      }
      if (isupper(*clp))
          *clp = tolower(*clp);
      for (lp = 0; lp < NUM_SPECIFIERS; lp++)
          if (defwids.spec[lp] == *clp)
            break;
      flags |= defwids.flags[lp];
      if (!width)
          width = defwids.wid[lp];
      printdat.cmds[cpos] |= width + defwids.cmd[lp];
      if (flags & BLANKF)
      {
          if (!(flags & ONE_ONLY))
          {
                  /* don't print this field if not using -d */
            printdat.cmds[cpos] &= C_WIDMASK;
            printdat.cmds[cpos] |= C_NULL;
          }
          flags &= ~BLANKF;
      }
      cpos++;
      fpos += width;
    }
    printdat.form[fpos] = '\0';
    printdat.cmds[cpos] = 0;
#if 0 /* debugging... */
    {
      int l = -1;
      while (printdat.cmds[++l])
      printf("%.3d  %4.4x  %d\n", l, printdat.cmds[l],
                printdat.cmds[l] & C_WIDMASK);
      l = -1;
      while (printdat.form[++l])
          printf("%c", printdat.form[l] == ' '? '_' : printdat.form[l]);
      printf("\n");
    }
#endif
} /* parse_format */

Generated by  Doxygen 1.6.0   Back to index