/** * Gets the i/o for a shell script and outputs it. * * Usage: * replay_shell [-r] [-f filename] pid * * -r: Realtime. Wait for the correct times. * -f: Specify a shell replay file to take input from, rather than retrieving * it from the database. * */ #include #include #include #include int main (int argc, char * argv[]) { FILE * pd; // Process to read data from. char c = 0; // For handling input args. char cmd [256]; // Buffer to hold command string. char buf [32738]; // Buffer to hold input stream. char * filename; // Name of the file to read data from. int len; // Amount of data read from stream. int i; // Counter. int realtime = 0; // Should we display in realtime, or not? int from_file = 0; // Are we reading from a file, or not? int interval = -1; // Amount of time to wait before printing current i/o data. unsigned long long last_timestamp; // Time of last i/o event. while (c != -1) { c = getopt (argc, argv, "rf:"); switch (c) { case -1: break; case 'r': realtime = 1; break; case 'f': from_file = 1; filename = optarg; break; default: printf ("Usage: replay_shell [-r] [-f filename] pid\n"); return 1; } } if (argc == 1) { printf ("Usage: replay_shell [-r] [-f filename] pid\n"); return 1; } // Open the file (or process). if (from_file) { snprintf (cmd, 256, "cat %s", filename); pd = popen (cmd, "r"); if (!pd) { perror ("Unable to open file"); return 1; } } else { snprintf (cmd, 256, "./get_io 2> /dev/null %s", argv[optind]); pd = popen (cmd, "r"); if (!pd) { perror ("Unable to execute command"); return 1; } } // Get the data. while (1) { unsigned long long timestamp; unsigned long long data_len; // Get the timestamp i = 0; while ( 1 ) { len = fread (&buf[i], 1, 1, pd); if (len == 0) goto done; if (buf[i] == '\t') break; i++; } timestamp = strtoull (buf, NULL, 10); // Get the data length. i = 0; while (1) { len = fread (&buf[i], 1, 1, pd); if (len == 0) goto done; if (buf[i] == '\t') break; i++; } data_len = strtoull (buf, NULL, 10); // Get the data. Due to character-escaping, data_len may not // match the *actual* length, so read 'til we hit a '\t'. i = fread (buf, 1, data_len, pd); if (realtime) { if (interval == -1) { interval = 0; } else { interval = timestamp - last_timestamp; } usleep(interval); } write (fileno(stdout), buf, i); last_timestamp = timestamp; } done: pclose (pd); return 0; }