Advertisement
danielhilst

ddstats.c

Mar 23rd, 2015
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.45 KB | None | 0 0
  1. /* compilation: cc    -lnewt -o build/ddstats ddstats.c */
  2. #include <assert.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <signal.h>
  8. #include <sys/wait.h>
  9. #include <sys/stat.h>
  10. #include <poll.h>
  11. #include <newt.h>
  12.  
  13. #define pabort(x)                               \
  14.         do {                                    \
  15.                 perror(x);                      \
  16.                 abort();                        \
  17.         } while (0);
  18.  
  19. #define fabort(fmt, args...)                            \
  20.         do {                                            \
  21.                 fprintf(stderr, fmt "\n", ##args);      \
  22.                 abort();                                \
  23.         } while (0);
  24.  
  25. int main(int argc, char **argv)
  26. {
  27.         pid_t child;
  28.         int pipes[2];
  29.         long unsigned filesize = 0;
  30.         int i;
  31.  
  32.         for (i = 0; i < argc; i++)
  33.                 if (!strncmp("if=", argv[i], 3)) {
  34.                         struct stat st;
  35.                         char *eq = strchr(argv[i], '=');
  36.  
  37.                         if (!eq)
  38.                                 fabort("Can't find input file (if=*) on command line");
  39.  
  40.                         eq++;   /* forwards pointer to filename, after `=' */
  41.  
  42.                         if (stat(eq, &st))
  43.                                 pabort("stat");
  44.  
  45.                         if (S_ISLNK(st.st_mode)) {
  46.                                 int status;
  47.                                 char *tmp = strdup(eq);
  48.  
  49.                                 eq = malloc(st.st_size);
  50.                                 readlink(tmp, eq, st.st_size); /* follow syslink */
  51.                                 free(tmp);
  52.                                 status = stat(eq, &st);
  53.                                 free(eq);
  54.                                 if (status)
  55.                                         pabort("stat");
  56.                                 filesize = st.st_size;
  57.                                 break; /* get out loop */
  58.                         } else if (S_ISREG(st.st_mode)) {
  59.                                 filesize = st.st_size;
  60.                                 break;
  61.                         } else
  62.                                 fabort("%s is not a file or a symbolic link", eq);
  63.                 }
  64.  
  65.         assert(filesize > 0);
  66.  
  67.         if (pipe(pipes))
  68.                 pabort("pipe");
  69.  
  70.         child = fork();
  71.         if (!child) {           /* child process */
  72.                 dup2(pipes[1], STDERR_FILENO);
  73.                 argv[0] = "dd";
  74.                 execvp(argv[0], argv);
  75.         } else if (child == -1) {
  76.                 pabort("fork");
  77.         } else {                  /* parent process */
  78.                 newtComponent form;
  79.                 newtComponent cancel;
  80.                 newtComponent progress;
  81.                 char line[64];
  82.                 FILE *fp = fdopen(pipes[0], "r");
  83.                 struct pollfd pfd = {
  84.                         .fd = pipes[0],
  85.                         .events = POLLIN,
  86.                 };
  87.  
  88.                 memset(line, '\0', sizeof(line));
  89.                 sleep(1);       /* give dd time to install signal hanlder */
  90.  
  91.                 newtInit();
  92.                 newtCls();
  93.                 newtCenteredWindow(64, 12, "DD PROGRESS");
  94.                 form = newtForm(NULL, NULL, 0);
  95.                 cancel = newtButton(28, 8, "cancel");
  96.                 progress = newtScale(4, 4, 56, filesize);
  97.                 newtFormAddComponent(form, progress);
  98.                 newtFormAddComponent(form, cancel);
  99.                 newtDrawForm(form);
  100.                 newtRefresh();
  101.                
  102.                 while (!waitpid(child, NULL, WNOHANG)) { /* while child lives */
  103.  
  104.                         kill(child, SIGUSR1); /* send signal to write stats on stderr */
  105.  
  106.                         while (poll(&pfd, 1, 1000)) {
  107.                                 int status;
  108.                                 int bytes;
  109.  
  110.                                 fgets(line, 64, fp);
  111.                                 if (!strstr(line, "bytes")) /* skip lines that doesn't match */
  112.                                         continue;
  113.                                 status = sscanf(line, "%d bytes", &bytes);
  114.                                 if (status == 1)
  115.                                         newtScaleSet(progress, bytes);
  116.                                 newtRefresh();
  117.                         }
  118.                 }
  119.  
  120.                 newtRunForm(form);
  121.                 newtFormDestroy(form);
  122.                 newtFinished();
  123.         }
  124.  
  125.         return 0;
  126. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement