Path: utzoo!utgpu!attcan!uunet!husc6!mailrus!cornell!uw-beaver!fluke!ssc-vax!uvicctr!tholm From: tholm@uvicctr.UUCP (Terrence W. Holm) Newsgroups: comp.os.minix Subject: leave(1) Message-ID: <546@uvicctr.UUCP> Date: 8 Nov 88 22:38:47 GMT Reply-To: tholm@uvicctr.UUCP (Terrence W. Holm) Organization: University of Victoria, Victoria B.C. Canada Lines: 350 EFTH MINIX report #56 - November 1988 - leave(1) There follows an implementation of leave(1) for MINIX. ---------------------------------------------------------- echo x - leave.1 gres '^X' '' > leave.1 << '/' XCOMMANDS X leave(1) - informs user when it is time to leave X XINVOCATION X leave [ [+] hhmm ] X XEXPLANATION X The user tells leave(1) when there is something more X important than MINIX work to do. Leave(1) will inform X the user when the time approaches (five minutes before), X and up to ten minutes after the deadline. X X The time may be in a 12 or 24 hour format, for example X 730 or 1930. If preceded by a "+" then the deadline is X relative to the current time, for example +2400 means X 24 hours from now. A ':' may be inserted between the X hour and minute fields. X X The argument string may be empty, in which case leave(1) X will prompt for a [+]hhmm string. If only an ENTER is X typed then leave(1) terminates. One could use this in X a .profile. X X The signals sigint, sigquit and sigterm are all ignored X in the background process. Leave(1) will terminate after X the user logs out. / echo x - leave.c gres '^X' '' > leave.c << '/' X/* leave(1) X * X * Author: Terrence W. Holm Nov. 1988 X * X * Usage: leave [ [+] hhmm ] X */ X X#include X#include X#include X X#define Min(a,b) ((a Xlong timezone; X#else Xlong timezone = 0 * HOUR; /* Should be in ctime(3) */ X#endif X#endif X X Xlong time(); Xchar *ttyname(); Xchar *cuserid(); Xchar *ctime(); X X Xmain( argc, argv ) X int argc; X char *argv[]; X X { X char when[ STRING ]; X long now = time( 0 ); X long leave; X int hour, min; X int pid; X X X /* Get the argument string "when" either from stdin, or argv */ X X if ( argc <= 1 ) X { X printf( "When do you have to leave? " ); X X if ( fgets( when, STRING, stdin ) == NULL || when[0] == '\n' ) X exit( 0 ); X } X else X { X strcpy( when, argv[1] ); X X if ( argc > 2 ) X strcat( when, argv[2] ); X } X X X /* Determine the leave time from the current time and "when" */ X X X if ( when[0] == '+' ) X { X Get_Hour_Min( &when[1], &hour, &min ); X X leave = now + hour * HOUR + min * MIN; X } X else X { X /* User entered an absolute time. */ X X#ifdef BSD X timezone = - localtime(&now)->tm_gmtoff; X#endif X X Get_Hour_Min( &when[0], &hour, &min ); X X if ( hour >= 1 && hour <= 12 ) X { X /* 12-hour format: relative to previous midnight or noon. */ X X leave = now - (now - timezone) % HALF_DAY + hour % 12 * HOUR + min * MIN; X X if ( leave < now - HOUR ) X leave = leave + HALF_DAY; X else if ( leave < now ) X { X printf( "That time has already passed!\n" ); X exit( 1 ); X } X } X else if ( hour <= 24 ) X { X /* 24-hour format: relative to previous midnight. */ X X leave = now - (now - timezone) % DAY + hour * HOUR + min * MIN; X X if ( leave < now - HOUR ) X leave = leave + DAY; X else if ( leave < now ) X { X printf( "That time has already passed!\n" ); X exit( 1 ); X } X } X else X Usage(); X } X X X printf( "Alarm set for %s", ctime( &leave ) ); X X if ( (pid = fork()) == -1 ) X { X fprintf( stderr, "leave: can not fork\n" ); X exit( 1 ); X } X X if ( pid != 0 ) X exit( 0 ); X X X /* Only the child continues on */ X X { X char *user = cuserid( NULL ); X char *tty = ttyname( 0 ) + 5; X long delta; X int i; X X if ( user == NULL || tty == NULL ) X { X fprintf( stderr, "leave: Can not determine user and terminal name\n" ); X exit( 1 ); X } X X X signal( SIGINT, SIG_IGN ); X signal( SIGQUIT, SIG_IGN ); X signal( SIGTERM, SIG_IGN ); X X X for(;;) X { X if( ! Still_Logged_On( user, tty ) ) X exit( 0 ); X X /* How much longer until the leave time? */ X X delta = leave - time( 0 ); X X /* Which interval are we currently in? */ X X for ( i = 0; i < INTERVALS; ++i ) X if ( delta + intervals[i] > 0 ) X break; X X /* If we are within intervals[0] then print a warning. */ X /* If there are more intervals than messages, then use */ X /* warnings[WARNINGS-1] for all subsequent messages. */ X X if ( i > 0 ) X printf( "\007%s\n", warnings[ i > WARNINGS ? WARNINGS-1 : i-1 ] ); X X if ( i == INTERVALS ) X { X printf( "That was the last time I'll tell you. Bye.\n" ); X exit( 0 ); X } X X /* Sleep until the next interval. For long periods, wake */ X /* up every hour to check if the user is still on (also */ X /* required because 16 bit ints don't allow long waits). */ X X sleep( (int) Min( delta + intervals[i], HOUR ) ); X } X } X } X X X XGet_Hour_Min( when, hour, min ) X char *when; X int *hour; X int *min; X X { X int hour_min; X int just_min = 0; X X switch ( sscanf( when, "%d:%d", &hour_min, &just_min ) ) X { X case 1 : *hour = hour_min / 100; X *min = hour_min % 100; X break; X X case 2 : *hour = hour_min; X *min = just_min; X break; X X default: Usage(); X } X X X if ( hour_min < 0 || just_min < 0 || *min > 59 ) X Usage(); X } X X X XStill_Logged_On( user, tty ) X char *user; X char *tty; X X { X FILE *f; X long size; /* Number of wtmp records in the file */ X int wtmp_count; /* How many to read into wtmp_buffer */ X X X if( (f = fopen( WTMP, "r" )) == NULL ) X /* No login/logout records kept */ X return( 1 ); X X if ( fseek( f, 0L, 2 ) != 0 || (size = ftell(f)) % sizeof(struct utmp) != 0 ) X { X fprintf( stderr, "leave: invalid wtmp file\n" ); X exit( 1 ); X } X X X size /= sizeof(struct utmp); /* Number of records in wtmp */ X X X while( size > 0 ) X { X wtmp_count = (int) Min( size, MAX_WTMP_COUNT ); X X size -= (long) wtmp_count; X X fseek( f, size * sizeof(struct utmp), 0 ); X X if ( fread( &wtmp_buffer[ 0 ], sizeof(struct utmp), wtmp_count, f ) != wtmp_count ) X { X fprintf( stderr, "leave: read error on wtmp file\n" ); X exit( 1 ); X } X X X while ( --wtmp_count >= 0 ) X { X if ( strcmp( wtmp_buffer[ wtmp_count ].ut_line, "~" ) == 0 ) X return( 0 ); X X if ( strncmp( wtmp_buffer[ wtmp_count ].ut_line, tty, 8 ) == 0 ) X if ( strncmp( wtmp_buffer[ wtmp_count ].ut_name, user, 8 ) == 0 ) X return( 1 ); X else X return( 0 ); X } X X } /* end while( size > 0 ) */ X X return( 0 ); X } X X X XUsage() X { X fprintf( stderr, "Usage: leave [[+]hhmm]\n" ); X exit( 1 ); X } / ---------------------------------------------------------- Terrence W. Holm uw-beaver!uvicctr!tholm