root/usr/src/cmd/bnu/account.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/*        All Rights Reserved   */


#ident  "%Z%%M% %I%     %E% SMI"        /* from SVR4 bnu:account.c 1.3 */
/*
*/

#include        "uucp.h"
#include        "log.h"
#include <pwd.h>

/*
*               SYMBOL DEFINITIONS
*/

#define FS              ' '     /* Field seperator for output records. */
#define STD             'S'     /* standard service. */
#define LOGCHECK        { if (Collecting == FALSE) return; }

/*
*               STRUCTURE DEFINITIONS
*/

struct acData                   /* Data for construction of account record. */
                {
                        char    uid[MODSTR]; /* user id */
                        char    jobID[MODSTR]; /* C. file */
                        off_t   jobsize;        /* Bytes transferred in a job.*/
                        char    status; /* transaction status */
                        char    service; /* service grade */
                        char    jobgrade[MODSTR]; /* job grade */
                        char    time[MODSTR]; /* date and time the job execed */
                        char    origSystem[MODSTR]; /* originating system's                                                        name */
                        char    origUser[MODSTR]; /* originator's login
                                                           name */
                        char    rmtSystem[MODSTR]; /* system's name of
                                                           first hop */
                        char    rmtUser[MODSTR]; /* user's name of first
                                                           hop */
                        char    device[MODSTR]; /* network medium */
                        char    netid[MODSTR]; /* Network ID in use */
                        char    type[MODSTR]; /* type of transaction */
                        char    path[BUFSIZ]; /* path of the rest of the hops */

                };

/*
*               LOCAL DATA
*/

static int              Collecting = FALSE; /* True if we are collecting
                                             *   data. */
static int              LogFile = CLOSED; /* Log file file destriptor. */
static char             LogName[] = ACCOUNT; /* Name of our log file. */
static char             Record[LOGSIZE]; /* Place to build log records. */

static struct acData    Acct;   /* Accounting data. */

/*
*               LOCAL FUNCTIONS
*/

/* Declarations of functions: */

STATIC_FUNC void        reportJob();

/*
* Local Function:       reportJob - Write Job accounting information to Log
*
* This function writes accounting information about the current job to the log
* file.
*
* Parameters:
*
*       none.
*/

STATIC_FUNC void
reportJob ()

{
        static char     format[] = "%s%c%s%c%ld%c%c%c%c%c%s%c%s%c%s%c(%s)%c%s%c%s%c%s%c%s%c%s%c%s%c";

        register struct acData *        acptr;

        acptr = &Acct;                  /* Point to Acct data. */
        sprintf(Record, format,
                acptr->uid, FS,
                acptr->jobID, FS,
                acptr->jobsize, FS,
                acptr->status, FS,
                acptr->service, FS,
                acptr->jobgrade, FS,
                acptr->origSystem, FS,
                acptr->origUser, FS,
                acptr->time, FS,
                acptr->rmtSystem, FS,
                acptr->rmtUser, FS,
                acptr->device, FS,
                acptr->netid, FS,
                acptr->type, FS,
                acptr->path, FS);

        /* Terminate the record and write it out. */

        (void) strcat(Record, EOR);
        writeLog(Record,&LogFile,LogName,&Collecting);
}


/*
*               EXTERNAL FUNCTIONS
*/

/*
* Function:     acConnected - Report Connection Completion
*
* Parameters:
*
*       remote -        name of the remote system.
*
*       device -        the type of device being used for communicaitons.
*/

void
acConnected (remote, device)

char *  remote;
char *  device;

{
        register struct acData *        acptr = &Acct;

        LOGCHECK;
        copyText(acptr->rmtSystem, sizeof(acptr->rmtSystem), remote);
        copyText(acptr->device, sizeof(acptr->device), device);
        acptr->service = 'S'; /* default to standard service */
}

/* Function:    acDojob - Found Another Job
*
* acDojob  is called when a new job has been found.
*
* Parameters:
*
*       jobid -         The name of the job that was found.
*
*       system -        Originating system's name.
*
*       user -          Originator's login name.
*/

void
acDojob(jobid, system, user)

char *  jobid;
char *  system;
char *  user;

{
        register struct acData *        acptr = &Acct;

struct passwd *passent;
        LOGCHECK;
        if (strcmp(acptr->jobID,jobid) == 0)
                return;
        if ((*acptr->jobID != NULLCHAR) && (acptr->jobsize != 0)){
                reportJob();
        }
        copyText(acptr->jobID, sizeof(acptr->jobID), jobid);
        copyText(acptr->origSystem, sizeof(acptr->origSystem), system);
        copyText(acptr->origUser, sizeof(acptr->origUser), user);
        copyText(acptr->time, sizeof(acptr->time), timeStamp());
        acptr->jobgrade[0] = jobid[strlen(jobid)-5];
        acptr->jobgrade[1] = NULLCHAR;/* get job grade from jobid */
        acptr->jobsize = 0;
        while ((passent = getpwent()) != NULL){
          if (strcmp(passent->pw_name,user) == 0){
                sprintf(acptr->uid,"%ld",(long) passent->pw_uid);
                break;
          }
        }
}

/* End recording the accounting log */

void
acEnd(status)
char status;
{
        register struct acData *        acptr = &Acct;

        LOGCHECK;
        if (((*acptr->jobID != NULLCHAR) && (acptr->jobsize != 0))
                        || (status == PARTIAL)){
                acptr->status = status;
                reportJob();
        }

}

/* increment job size */

void
acInc()
{
        register struct acData *        acptr = &Acct;

        LOGCHECK;
        acptr->jobsize += getfilesize();
}

/*
* Function:     acInit - Initialize Accounting Package
*
* This function allows the accounting package to initialize its internal
* data structures.  It should be called when uucico starts running on master
* or changes the role from slave to master, or uuxqt is invoked.
*
* Parameters:
*
*       type: file transfer or remote exec.
*/

void
acInit (type)
char * type;

{
        register struct acData *        acptr = &Acct;

        /*
        * Attempt to open the log file.  If we can't do it, then we
        * won't collect statistics.
        */

        if (openLog(&LogFile,LogName) == SUCCESS){
                Collecting = TRUE;
                acptr->service = STD; /* default to standard service */
                acptr->status = COMPLETE; /* default to completed transfer */
                copyText(acptr->jobgrade, sizeof(acptr->jobgrade), NOTAVAIL);
                copyText(acptr->uid, sizeof(acptr->uid), NOTAVAIL);
                copyText(acptr->origSystem, sizeof(acptr->origSystem), NOTAVAIL);
                copyText(acptr->origUser, sizeof(acptr->origUser), NOTAVAIL);
                copyText(acptr->rmtSystem, sizeof(acptr->rmtSystem), NOTAVAIL);
                copyText(acptr->rmtUser, sizeof(acptr->rmtUser), NOTAVAIL);
                copyText(acptr->device, sizeof(acptr->device), NOTAVAIL);
                copyText(acptr->netid, sizeof(acptr->netid), NOTAVAIL);
                copyText(acptr->path, sizeof(acptr->path), NOTAVAIL);
                copyText(acptr->type, sizeof(acptr->type), type);
        }
        else
                Collecting = FALSE;
}

/*
* It is called when uuxqt is running
*
*       jobid - jobid after X. prefix
*       origsys - Originating system's name.
*       origuser - Originator's login name.
*       connsys - local system
*       connuser - login user
*       cmd - command to be execed by uuxqt
*/
void
acRexe(jobid,origsys,origuser,connsys,connuser,cmd)
char * jobid;
char * origsys;
char * origuser;
char * connsys;
char * connuser;
char * cmd;
{
        register struct acData *        acptr = &Acct;

        LOGCHECK;
        copyText(acptr->jobID, sizeof(acptr->jobID), jobid);
        copyText(acptr->origSystem, sizeof(acptr->origSystem), origsys);
        copyText(acptr->origUser, sizeof(acptr->origUser), origuser);
        copyText(acptr->rmtSystem, sizeof(acptr->rmtSystem), connsys);
        copyText(acptr->rmtUser, sizeof(acptr->rmtUser), connuser);
        copyText(acptr->path, sizeof(acptr->path), cmd);
        copyText(acptr->time, sizeof(acptr->time), timeStamp());
}
/*
* It is called when the command to be execed is finished
*
*       cpucycle: cpu time the command is consumed
*/
void
acEndexe(cycle,status)
time_t  cycle;
char status;
{

        register struct acData *        acptr = &Acct;

        LOGCHECK;
        acptr->jobsize = cycle;
        acptr->status = status;
        reportJob();
}
/*
 *      cpucycle()
 *
 *      return cputime(utime+stime) since last time called
 */
time_t
cpucycle()
{
        struct tms      tbuf;
        time_t  rval;
        static time_t   utime,stime;    /* guaranteed 0 first time called */

        times(&tbuf);
        rval = ((tbuf.tms_utime-utime) + (tbuf.tms_stime-stime))*1000/HZ;
        utime = tbuf.tms_utime;
        stime = tbuf.tms_stime;
        return(rval);
}