From: jcb@frisbee.Eng.Sun.COM (Jim Becker) Newsgroups: alt.sources Subject: Baff -- But Another Folder Flasher (Sun only) Message-ID: <137509@sun.Eng.Sun.COM> Date: 19 Jun 90 17:27:00 GMT `Baff' is a utility which can be run in the background to watch for incoming mail. When it detects unread mail in the spool file it parses it and outputs the sender and subject lines to the FRAME BUFFER. It then leaves the lines for a brief period before erasing them. Baff is the cousin of Biff, but it tells you a bit more directly what is awaiting your eyes in the mail input basket. It's possible that the screen will get a little messed up if there are changes for the message duration, but this is infrequent (for me) and harmless. Baff currently runs only on Suns, although the principle could be used elsewhere. Although it compiles with the Sun pixrect lib, I use it on OpenWindows (aka X11/NeWS). This amazes people when they try to figure out how I'm doing this in X.. (It's possible, but would be slower). Most of the varients have been made user-specifiable, there is a usage message to give all the details. Just one file, so no Makefile logic. -Jim Becker -- Jim Becker / jcb%frisbee@sun.com / Sun Microsystems ---cut here--- /* * * baff.c -- But Another Folder Flasher * * This program runs in the background looking at the user's * mail spool file. When it detects that there has been a change * to the file, or at periodical intervals when there is outstanding * mail for the user, it blits the author/subject onto the frame * buffer directly. these lines are left up for a period then erased, * via the magic of Xor. * * This depends on using the pixrect library, and there is a hardcoded * default font/fontpath within also. Suns only at this point. * * Since the application writes to the frame buffer directly it can be * used under either SunView or X11/News servers, as well as at the console * level. This will baff*le people that don't know how it's done! * * To build: cc -o baff baff.c -lpixrect * * Jim Becker jcb%frisbee@sun.com -- released Spring 1990 * */ #include #include #include #include #include #include #include #define DELAY_TIME 10 /* time between checks */ #define THRESHHOLD 6 /* #times before show it*/ #define WAIT_TIME 3 /* how long on screen */ #define FONT_DIR "/usr/lib/fonts/fixedwidthfonts"; #define FONT_NAME "cour.r.16"; #define STR_MAX 128 #define MAX_LETTERS 50 #define TRUE 1 #define FALSE 0 #define EQUALN(a,b) (strncmp((char*)a,(char*)b,strlen(a))==0) typedef struct { char user[80]; char subject[80]; } letter; /* the following can be changed by the user */ static int delay_time = DELAY_TIME; static int threshhold = THRESHHOLD; static int wait_time = WAIT_TIME; static char font_dir[STR_MAX] = FONT_DIR; static char font_name[STR_MAX] = FONT_NAME; static char font_path[STR_MAX]; static letter letter_stack[MAX_LETTERS]; static int letter_count; static char file_name[STR_MAX]; static int last_file_time, current_file_time; static short user_active; static short subject_active; static struct pixrect *screen; struct pixfont *font_info; struct pr_prpos location; static char message[STR_MAX]; static int ypos = 30, xpos = 30; static int ysize; static char *usage_msg[] = { "\n\t\tBaff - \"But Another Folder Flasher\"\n\n", "This program runs in the background looking at the user's mail spool\n", "file. When it detects that there has been a change to the file, or at\n", "periodical intervals when there is outstanding mail for the user, it\n", "blits the author/subject onto the frame buffer directly. These lines\n", "are left up for a period then erased, Minor visual damage is possible,\n", "but harmless. This can also `baff'le those that think it's done in X..\n\n", "There are tweakable things, of course, with command line options:\n\n", " -d (delay_time) delay for seconds between mail checks\n", " -t (threshhold) every times checked display old info\n", " -w (wait_for) wait for seconds before erasing info\n\n", "The font can be changed with:\n\n", " -font name of a valid SunView style font\n", " -fdir where the fonts live in system\n\n", NULL}; mail_file_time() { struct stat file_stat; if( stat( file_name, &file_stat) != 0 ) return -1; else return (int)file_stat.st_mtime; } add_current_record() { letter_count++; user_active = FALSE; subject_active = FALSE; } clear_current_record() { user_active = FALSE; subject_active = FALSE; if( letter_count > 0 ) letter_count--; } set_current_user( user ) char *user; { strcpy( letter_stack[letter_count].user, user ); user_active = TRUE; } set_current_subject( subject ) char *subject; { strcpy( letter_stack[letter_count].subject, subject ); subject_active = TRUE; } open_parse_file() { FILE *mail; char line[STR_MAX]; mail = fopen( file_name, "r" ); letter_count = 0; clear_current_record(); if( mail == NULL ) return letter_count; while( fgets( line, sizeof(line), mail ) != NULL ) { line[strlen(line)-1] = '\0'; if( user_active && subject_active ) add_current_record(); if( EQUALN( "From:", line ) ) set_current_user( &line[6] ); else if( EQUALN( "Subject:", line ) ) set_current_subject( &line[9] ); else if( EQUALN( "Status:", line ) ) clear_current_record(); } if( user_active && subject_active ) add_current_record(); fclose(mail); return letter_count; } /* * write a single line to the display */ update_line( lineno ) int lineno; { sprintf(message, "%-36s \"%s\"\n", letter_stack[lineno].user, letter_stack[lineno].subject ); location.pos.x = xpos; location.pos.y = lineno * ysize + ypos; pf_ttext( location, PIX_NOT(PIX_DST) | PIX_COLOR( 1 ), font_info, message ); } /* * update entire display, first on with the lines then off */ update_display() { int i; location.pr = screen; /* two loops, cause it looks better to take 'em off in reverse */ for( i = 0; i < letter_count; i++ ) update_line( i ); /* let the user see the messages */ sleep(wait_time); for( i = letter_count-1; i >= 0; i-- ) update_line( i ); } /* * this spits out the message on how to use the demo program. */ static void usage() { char **string = usage_msg; while( *string != NULL ) printf( *string++ ); } parse_args( argc, argv ) int argc; char **argv; { char *arg; int i, j; short error = FALSE; for( i = 1; i < argc; i++ ) { arg = argv[i]; if( arg[0] == '-' ) { switch( arg[1] ) { case 't': if( i < (argc-1) ) { arg = argv[++i]; threshhold = atoi(arg); } break; case 'w': if( i < (argc-1) ) { arg = argv[++i]; wait_time = atoi(arg); } break; case 'd': if( i < (argc-1) ) { arg = argv[++i]; delay_time = atoi(arg); } break; case 'f': if( i < (argc-1) ) { if( arg[2] == 'o' ) { arg = argv[++i]; strcpy( font_name, arg ); } else if( arg[2] == 'd' ) { arg = argv[++i]; strcpy( font_dir, arg ); /* trim trailing / if there */ j = strlen(font_dir)-1; if( font_dir[j] == '/' ) font_dir[j] = '\0'; } } break; default: printf("don't understand argument `%s'\n", arg); case '-': case 'h': usage(); error = TRUE; } } } return !error; } main( argc, argv ) int argc; char **argv; { int refresh_count = 0; /* a little hardcoding for the hacker in me.. */ sprintf( file_name, "/usr/spool/mail/%s", getenv("USER") ); screen = pr_open( "/dev/fb" ); if( screen == NULL ) { printf("No frame buffer access to /dev/fb..\n"); exit(1); } if( argc > 1 ) { if( !parse_args( argc, argv ) ) exit(1); } /* construct the default fontname */ sprintf( font_path, "%s/%s", font_dir, font_name ); font_info = pf_open( font_path ); if( font_info == NULL ){ printf("Font `%s' not available..\n", font_path ); exit(1); } /* this is the space between lines */ ysize = font_info->pf_defaultsize.y; ysize += ysize / 3; /* spacing */ while(TRUE) { current_file_time = mail_file_time(); if( current_file_time > last_file_time || ++refresh_count > threshhold ) { /* get new letter stack */ if( open_parse_file() ) update_display(); last_file_time = current_file_time; refresh_count = 0; } sleep(delay_time); } } -- -- Jim Becker / jcb%frisbee@sun.com / Sun Microsystems