root/usr.sbin/cron/misc.c
/*      $OpenBSD: misc.c,v 1.72 2022/05/21 01:21:29 deraadt Exp $       */

/* Copyright 1988,1990,1993,1994 by Paul Vixie
 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
 * Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/wait.h>

#include <bitstring.h>          /* for structs.h */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>               /* for structs.h */

#include "macros.h"
#include "structs.h"
#include "funcs.h"
#include "globals.h"

int LineNumber;

/* get_char(file) : like getc() but increment LineNumber on newlines
 */
int
get_char(FILE *file)
{
        int ch;

        ch = getc(file);
        if (ch == '\n')
                Set_LineNum(LineNumber + 1)
        return (ch);
}

/* unget_char(ch, file) : like ungetc but do LineNumber processing
 */
void
unget_char(int ch, FILE *file)
{
        ungetc(ch, file);
        if (ch == '\n')
                Set_LineNum(LineNumber - 1)
}

/* get_string(str, max, file, termstr) : like fgets() but
 *              (1) has terminator string which should include \n
 *              (2) will always leave room for the null
 *              (3) uses get_char() so LineNumber will be accurate
 *              (4) returns EOF or terminating character, whichever
 */
int
get_string(char *string, int size, FILE *file, char *terms)
{
        int ch;

        while ((ch = get_char(file)) != EOF && !strchr(terms, ch)) {
                if (size > 1) {
                        *string++ = ch;
                        size--;
                }
        }

        if (size > 0)
                *string = '\0';

        return (ch);
}

/* skip_comments(file) : read past comment (if any)
 */
void
skip_comments(FILE *file)
{
        int ch;

        while ((ch = get_char(file)) != EOF) {
                /* ch is now the first character of a line.
                 */

                while (ch == ' ' || ch == '\t')
                        ch = get_char(file);

                if (ch == EOF)
                        break;

                /* ch is now the first non-blank character of a line.
                 */

                if (ch != '\n' && ch != '#')
                        break;

                /* ch must be a newline or comment as first non-blank
                 * character on a line.
                 */

                while (ch != '\n' && ch != EOF)
                        ch = get_char(file);

                /* ch is now the newline of a line which we're going to
                 * ignore.
                 */
        }
        if (ch != EOF)
                unget_char(ch, file);
}

/* char *first_word(char *s, char *t)
 *      return pointer to first word
 * parameters:
 *      s - string we want the first word of
 *      t - terminators, implicitly including \0
 * warnings:
 *      (1) this routine is fairly slow
 *      (2) it returns a pointer to static storage
 */
char *
first_word(char *s, char *t)
{
        static char retbuf[2][MAX_TEMPSTR + 1]; /* sure wish C had GC */
        static int retsel = 0;
        char *rb, *rp;

        /* select a return buffer */
        retsel = 1-retsel;
        rb = &retbuf[retsel][0];
        rp = rb;

        /* skip any leading terminators */
        while (*s && (NULL != strchr(t, *s))) {
                s++;
        }

        /* copy until next terminator or full buffer */
        while (*s && (NULL == strchr(t, *s)) && (rp < &rb[MAX_TEMPSTR])) {
                *rp++ = *s++;
        }

        /* finish the return-string and return it */
        *rp = '\0';
        return (rb);
}