summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/log.c
blob: e306db93759d93f29a97d25b915ab636244156dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/************************************************************************
* LOG.C - Creates a ASCII file with time and date stamps for logging    *
*         hours.                                                        *
*                                                                       *
*   usage: LOG [IN][OUT][CALC]                                          *
*               IN - Creates an opening entry from which a "time spent" *
*                    is calculated.                                     *
*              OUT - Creates a closing entry and calculates             *
*                    "time spent" for that entry.                       *
*             CALC - Calculates total overall "time spent" for the      *
*                    entire log.                                        *
*                                                                       *
*   NOTES:  I used seconds to do all the calculations. The other        *
*           time/date entries are for human readability. Some           *
*           enhancments can be done to this program.                    *
*           i.e. Wage/Pay calculation, closing the log after a CALC     *
*           to insure log is not reused, tracking hours for individual  *
*           people, tracking hours for individual projects, etc.        *
*                                                                       *
*  Public domain by Robert Sprawls.                                     *
************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <time.h>

/* Define time file constants   */

#define HOUR        3600        /* Number of seconds in an hour.        */
#define MINS        60          /* Number of seconds in a minute        */
#define IN_ENTRY    40          /* Size of an IN entry                  */
#define SEC_OFF     4           /* Offset of seconds in an IN entry     */
#define HOUR_OFF    64          /* Offset of seconds in an "time spent" */
                                /* calculated entry.                    */

/* Define values returned to DOS */

#define OK          0   /* Executed normally, nothing will be eched */
#define OPENLOG     1   /* Attempted to log in while open entry in log */
#define CLOSEDLOG   2   /* Attempted to log out while closed entry in log */
#define FILE_ERROR  3   /* File access error. Just in case. */
#define SEEK_ERROR  4   /* File positioning error */
#define NOPARMS     5   /* No parameters supplied to program */
#define INVALID     6   /* Invalid parameters */

void    usage( void );
long    get_in_entry( FILE * );
void    fastforw( FILE * );     /* Oppisite of rewind();        */
void    quit( int );

char    strbuf[ IN_ENTRY + 1 ];
FILE    *wrklog;

int main( int argc, char *argv[] )
{
    char    outline[ IN_ENTRY * 2 + 1 ];
    long    in_entry_time = 0, total_seconds = 0;
    double  hours, pay;
    time_t  current_time;
    div_t   hdiv, mdiv;

    if( argc < 2 )
    {
        usage();
        quit( NOPARMS );
    }

    /* Open log. Can be any directory.  */
    if(( wrklog = fopen( "WORK.LOG", "a+" )) == NULL )
        quit( FILE_ERROR );

    strupr( argv[ 1 ] );

    time( &current_time );

    /* Create an opening IN entry.  */
    if( strcmp( "IN", argv[ 1 ] ) == 0 )
    {
        /* Make sure there isn't a open entry already.  */
        if( get_in_entry( wrklog ) )
            quit( OPENLOG );

        /* Stamp it.    */
        fprintf( wrklog, "%3s %ld %s", argv[ 1 ], current_time,
            ctime( &current_time ));
    }
    /* Create a closinf OUT entry.  */
    else if( strcmp( "OUT", argv[ 1 ] ) == 0 )
    {
        /* Make sure there is a previous IN entry.  */
        if( ( in_entry_time = get_in_entry( wrklog )) == 0 )
            quit( CLOSEDLOG );

        total_seconds = current_time - in_entry_time;
        sprintf( outline, "%3s %ld %s", argv[ 1 ], current_time,
            ctime( &current_time ));

        /* Cut off the newline character that's normally put on.    */
        outline[ strlen( outline ) - 1 ] = '\0';
        hdiv = div( total_seconds, HOUR );
        mdiv = div( hdiv.rem, MINS );

        sprintf( strbuf, "     Time Spent: %02d:%02d:%02d/%ld\n\n",
            hdiv.quot, mdiv.quot, mdiv.rem, total_seconds );
        strcat( outline, strbuf );
        fprintf( wrklog, outline );
    }
    /* Calculate the overall "time spent"   */
    else if( strcmp( "CALC", argv[ 1 ] ) == 0 )
    {
        rewind( wrklog );
        while( !feof( wrklog ) )
        {
            /* This is to eliminate garbage or residual entries.    */
            outline[ 0 ] = '\0';

            fgets( outline, 80, wrklog );
            if( strstr( outline, "OUT" ) != NULL )
            {
                total_seconds += atol( &outline[ HOUR_OFF ] );
            }

        }

        /* goto to end of file and stamp total hours    */
        fastforw( wrklog );
        if( total_seconds )
        {
            hdiv = div( total_seconds, HOUR );
            mdiv = div( hdiv.rem, MINS );
            fprintf( wrklog, "\t\t\t\t\t\t\t\t\t\t  "
                "Total Hours: %02d:%02d:%02d/%ld\n",
                hdiv.quot, mdiv.quot, mdiv.rem, total_seconds );
        }
    }
    else
    {
        usage();
        quit( INVALID );
    }

    quit( OK );
}

void usage( void )
{
    printf( "\nusage: LOG [IN][OUT][CALC]\n");
}

/****************************************************************
* get_in_entry - gets a previous IN entry.                      *
*                                                               *
*  Params: FILES *fp - file pointer.                            *
* Returns: The entry's seconds if successful, else 0            *
*                                                               *
* NOTES: If fseek fails for any reason, function does not       *
*        return. Instead, quit is call with the error code.     *
****************************************************************/

long get_in_entry( FILE *fp )
{

    if( fseek( fp, -IN_ENTRY, SEEK_END ) != 0 )
        quit( SEEK_ERROR );

    fread( strbuf, 1, IN_ENTRY, fp );
    fastforw( fp );

    if( strstr( strbuf, "IN" ) == NULL )
        return( 0 );
    else
    {
        return( atol( &strbuf[ SEC_OFF ]));
    }
}

/****************************************************************
* quit() - Program exit function. Reports of any outstanding    *
*          errors.                                              *
*                                                               *
*  Params:  errcode - Error code as defined in beginning.       *
* Returns:  nothing.                                            *
****************************************************************/

void quit( int errcode )
{
    char *errmsg[] =
    {
        "",
        "Log has an open entry.",
        "No corresponding IN entry.",
        "File open error.",
        "Seek error",
        "No parameters specified.",
        "Invalid Parameters."
    };

    printf( "\n%s\n", errmsg[ errcode ] );

    fclose( wrklog );
    exit( errcode );
}

/****************************************************************
* fastforw() - Puts file pointer to end of file.                *
*                                                               *
*  Params: fp - File pointer.                                   *
* Returns: nothing.                                             *
****************************************************************/

void fastforw( FILE *fp )
{
    fseek( fp, 0, SEEK_END );
}