home *** CD-ROM | disk | FTP | other *** search
-
- /*
- ** ACTIV -- keep an activioty typescript.
- ** whenever the user types, will prepend the time if the typein has been
- ** quiet for more than Interval, which defaults to 20 secs, but may be
- ** overridden with -i flag. If over two hours, pust the entire time and
- ** date out. Copies to a file.
- **
- ** Useage:
- ** activ [-i interval] file
- **
- ** History:
- ** 6/23/88 -- (marc) documented
- **
- */
-
- # include <stdio.h>
- # include <sgtty.h>
- # include <signal.h>
- # include <time.h>
- # include <errno.h>
- # include <ctype.h>
-
- # define MAXLINE 350
-
- struct sgttyb Ogttyb;
- char Erasec, Eofc, Killc, Wordc;
- char *Outfile;
- FILE *Outf;
-
- main(argc, argv)
- {
- args(argc, argv);
- openFile();
- setty();
- setend();
- dialog();
- }
-
- openFile()
- {
- if (!Outfile)
- {
- fprintf(stderr, "usage: activ file\n");
- exit (-1);
- }
- if (!(Outf = fopen(Outfile, "a+")))
- {
- perror(Outfile);
- exit (-1);
- }
- setlinebuf(Outfile);
- }
- setty()
- {
- struct sgttyb ngttyb;
- struct tchars tchars;
- struct ltchars lchars;
-
- /* set cbreak mode */
- ioctl(0, TIOCGETP, &Ogttyb);
- ngttyb = Ogttyb;
- ngttyb.sg_flags |= CBREAK;
- ngttyb.sg_flags &= ~ECHO;
-
- ioctl(0, TIOCSETP, &ngttyb);
- /* set editting characters */
- ioctl(0, TIOCGETC, &tchars);
- Eofc = tchars.t_eofc;
- ioctl(0, TIOCGLTC, &lchars);
- Wordc = lchars.t_werasc;
-
- Erasec = Ogttyb.sg_erase;
- Killc = Ogttyb.sg_kill;
- }
- setend()
- {
- int endIt();
-
- /* ensure that upon SIGINT, we dump things, and close the
- * file
- */
- signal(SIGINT, endIt);
- }
- endIt()
- {
- /* close file, reset tty mode to original mode */
- fclose(Outf);
- ioctl(0, TIOCSETP, &Ogttyb);
- exit (0);
- }
- dialog()
- {
- for (;;)
- {
- await_inp();
- fill_line();
- }
- }
- await_inp()
- {
- int fdt;
- int err;
- extern errno;
-
- for (;;)
- {
- fdt = 1 << 0;
- err = select(32, &fdt, NULL, NULL, NULL);
- if (err != -1)
- return;
- if (errno != EINTR)
- perror("select");
- }
- }
-
- # define INTERVAL 20
-
- char EntireLine[MAXLINE];
- int LineBegin;
- int OutCol;
- int EdittedLine;
- int ShownTill = 0;
- int FirstCharOnLine = 1;
- char Line[MAXLINE];
- long LastTime;
- long ThisTime;
- int Interval = INTERVAL;
- int EofIn;
-
- fill_line()
- {
- gettime();
- get_any(Line, sizeof Line);
- if (gt_interval())
- FirstCharOnLine = 1;
- if (FirstCharOnLine)
- {
- dumpline();
- newline();
- }
- add_to_line(Line);
- line_edit(); /* edit and echo. */
- if (completeline())
- {
- dumpline();
- }
- if (eof_reached())
- {
- endIt();
- /*NOTREACHED*/
- }
- }
- gettime()
- {
- ThisTime = time(NULL);
- }
- gt_interval()
- {
- long t = time(0);
-
- return (t - LastTime > Interval);
- }
- dumpline()
- {
- int n = strlen(EntireLine);
-
- fputs(EntireLine, Outf);
- if (n != 0 && EntireLine[n-1] != '\n')
- {
- putc('\n', stdout);
- putc('\n', Outf);
- }
- EntireLine[0] = 0;
- EdittedLine = 0;
- LineBegin = 0;
- OutCol = 0;
- fflush(Outf);
- }
- add_to_line(s)
- char *s;
- {
- strcat(EntireLine, s);
- }
- newline()
- {
- struct tm *tm;
- char data[40];
- char *timestring;
- char *ctime();
- struct tm *localtime();
- char *s;
-
- if (ThisTime - LastTime >= 2 * 60 * 60)
- {
- s = ctime(&ThisTime);
- s[strlen(s) - 1] = 0; /* get rid of final newline */
- sprintf(data, "[%s] ", s);
- }
- else
- {
- tm = localtime(&ThisTime);
- sprintf(data, "[%02d:%02d:%02d] ", tm->tm_hour, tm->tm_min,
- tm->tm_sec);
- s = data;
- }
- add_to_line(data);
- LineBegin = strlen(EntireLine);
- EdittedLine = LineBegin;
- OutCol = 0;
- LastTime = ThisTime;
- fputs(data, stdout);
- fflush(stdout);
- }
- line_edit()
- {
- char *i, *o;
-
- for (i = &EntireLine[EdittedLine], o = i;
- *i; i++)
- {
- if (*i == Killc)
- {
- o = &EntireLine[LineBegin];
- EdittedLine = LineBegin;
- erase_col(OutCol);
- OutCol = 0;
- }
- else if (*i == Erasec)
- {
- --o;
- if (OutCol > 0)
- {
- OutCol--;
- EdittedLine--;
- erase_col(1);
- }
- } else if (*i == Wordc)
- {
- if (OutCol <= 0)
- continue;
- /* skip initial spaces */
- if (isspace(o[-1]))
- {
- while (OutCol > 0 && isspace(*--o))
- {
- OutCol--;
- EdittedLine--;
- erase_col(1);
- }
- if (OutCol != 0)
- o++;
- }
- /* skip word */
- while (OutCol > 0 && !isspace(*--o))
- {
- OutCol--;
- EdittedLine--;
- erase_col(1);
- }
- if (OutCol != 0)
- o++;
- }
- else if (*i == Eofc)
- {
- EofIn++;
- break;
- }
- else if (isgraph(*i) || isspace(*i))
- {
- *o++ = *i;
- EdittedLine++;
- OutCol++;
- if (*i == '\n')
- {
- *i = 0;
- *--o = 0;
- dumpline();
- /* continue till end */
- line_edit();
- }
- else
- putchar(*i);
- }
- else
- {
- /* can't map the file output because doing it in place,
- * but can map the tty output, though i'll be confused
- * backspaceing!
- */
- EdittedLine += 1;
- OutCol += 2;
- putchar('^');
- putchar(*i | 0100);
- *o++ = *i;
- }
- }
- *o = 0;
- fflush(stdout);
- LastTime = ThisTime;
- FirstCharOnLine = 0;
- }
- completeline()
- {
- return (EntireLine[strlen(EntireLine) - 1] == '\n');
- }
- eof_reached()
- {
- return (EofIn);
- }
- erase_col(i)
- {
- while (--i >= 0)
- fputs("\b \b", stdout);
- fflush(stdout);
- }
- get_any(buf, size)
- char *buf;
- int size;
- {
- int n;
-
- n = read(0, buf, size);
- if (n > 0)
- buf[n] = 0;
- }
- args(argc, argv)
- int argc;
- char **argv;
- {
- int i;
-
- for (argv++; *argv; argv++)
- {
- if (**argv != '-')
- Outfile = *argv;
- else switch ((*argv)[1])
- {
- case 'i': /* set interval */
- if (!argv[1])
- break;
- i = atoi(*++argv);
- if (i > 0)
- Interval = i;
- break;
-
- case '?':
- fprintf(stderr, "usage: activ [-i interval] file\n");
- break;
-
- default:
- fprintf(stderr, "activ: unknown flag `%s'\n",
- *argv);
- }
- }
- }
-