int main(int argc, char **argv) { int fd; int ret; enum usb_controller state = atoi(argv[1]); int val = atoi(argv[2]); fd = open("/dev/usb_accessory_debug",O_RDWR); err_chk(fd, open); switch (state) { case USB_CMD_SND: ret = ioctl(fd, USBCMDS, &val); err_chk(ret, ioctl); break; case USB_CMD_RCV: ret = ioctl(fd, USBCMDR, &val); err_chk(ret, ioctl); printf("The value = %d\n", val); break; default: printf("Currently not handled\n"); } return 0; }
/*********************************************************************** * new_region_list - initialize a new region_list * * * * Given a pid, new_region_list crawls through /proc/<pid>/maps and * * produces a linked list called region_list which contains the * * addresses for all the memory regions in the pid's address space. * * * * The flag RL_FLAG_ANON specifies whether it should include all the * * segments it can read in this list or just the interesting ones. * ***********************************************************************/ struct region_list * new_region_list(pid_t pid, int flags) { /* Variables */ char * path = NULL; int maps_fd = -1; int maps_len; char * maps = NULL; int i = 0; off_t offset = 0; char i_hate_proc; struct region_list * head; struct region_list * cur; char * tok/*en_of_my_appreciation*/; int chk; /* Initialize */ path = calloc(1, 25); err_chk(path == NULL); head = calloc(sizeof(struct region_list), 1); err_chk(head == NULL); cur = head; /* Open maps */ snprintf(path, 24, "%s%d%s", "/proc/", (int) pid, "/maps"); maps_fd = open(path, O_RDONLY); err_chk(maps_fd == -1); /* read maps into memory */ for(maps_len = 0; (chk = read(maps_fd, &i_hate_proc, 1)) == 1; maps_len++); /* find length because files in proc are silly */ err_chk(chk == -1); lseek(maps_fd, 0, SEEK_SET); maps = calloc(maps_len + 1, 1); err_chk(maps == NULL); while(offset != maps_len) { chk = read(maps_fd, maps + offset, maps_len - offset); err_chk(chk == -1); offset += chk; } /* parse */ while(1) { cur->next = calloc(sizeof(struct region_list), 1); err_chk(cur->next == NULL); cur->next->begin = (void *) strtol(maps + i, &tok, 16); cur->next->end = (void *) strtol(tok + 1, &tok, 16); for(;maps[i] != '\n';i++); if(flags & RL_FLAG_RWANON) { if(tok[1] != 'r' || tok[2] != 'w' || tok[21] != '0' || tok[22] != ' ') { free(cur->next); cur->next = NULL; i++; if(i == maps_len) break; else continue; } } else { if(tok[1] != 'r') { free(cur->next); cur->next = NULL; i++; if(i == maps_len) break; else continue; } } if(i+1 == maps_len) break; else i++; cur = cur->next; } /* clean up */ cur = head->next; free(head); free(path); free(maps); close(maps_fd); return cur; err: /* Error handling */ /* perror("new_region_list"); */ if(path) free(path); if(maps) free(maps); if(maps_fd != -1) close(maps_fd); return NULL; }
/* Main program logic */ int main(int argc, char * argv[]) { int event = 0; int umask = 0; pid_t pid = 0; int freq = DEFAULT_FREQ; int mmap_region = DEFAULT_BUFFER_SIZE; char * default_filename = DEFAULT_FILENAME; char * out = default_filename; int interval_ms = DEFAULT_INTERVAL; bool exit_error = false; /* Argument parsing */ char opt; char * strerr = NULL; long arg; struct stat chkstat; int chk; while((opt = getopt(argc, argv, "+hre:u:f:p:o:m:k:i:")) != -1) { switch(opt) { /* Set realtime mode (UNIMPLEMENTED) */ case 'r': err_msg("-r is unimplemented in this release.\n\n"); break; /* unreached */ /* Specify event code */ case 'e': if(OPT_E) err_msg("This program only monitors one event at a time for now, but two -e args specified!\n\n"); OPT_E = true; arg = strtol(optarg, &strerr, 16); if(strerr[0] != 0) err_msg("Unable to parse -e argument correctly, should be event code in hexadecimal\n\n"); if(arg < 0 || arg > 0xFFF) err_msg("Unable to parse -e argument, event code out of range 0x00-0xFFF\n\n"); event = arg; optarg = NULL; break; /* Specify event code */ case 'u': if(OPT_U) err_msg("This version only monitors one event at a time for now, but two -u args specified!\n\n"); OPT_U = true; arg = strtol(optarg, &strerr, 16); if(strerr[0] != 0) err_msg("Unable to parse -u argument correctly, should be umask in hexadecimal\n\n"); if(arg < 0 || arg > 0xFF) err_msg("Unable to parse -u argument, umask out of range 0x00-0xFF\n\n"); umask = arg; optarg = NULL; break; /* Specify pid to snapshot */ case 'p': if(OPT_P) err_msg("This version does not support more than one -p argument\n\n"); OPT_P = true; arg = strtol(optarg, &strerr, 10); if(arg > INT_MAX || arg < 0 || strerr[0] != 0) err_msg("Unable to parse -p argument correctly, should be a pid\n\n"); pid = arg; optarg = NULL; break; /* Specify frequency */ case 'f': if(OPT_F) fprintf(stderr, "-f already specified, ignoring previous value...\n\n"); OPT_F = true; arg = strtol(optarg, &strerr, 10); if(strerr[0] != 0) err_msg("Unable to parse -f argument correctly, should be a frequency in whole numbers of hz\n\n"); if(arg < 1) err_msg("Unable to parse -f argument correctly, frequency must be greater than 1\n\n"); if(arg < 2000) fprintf(stderr, "Warning: frequencies below 2000hz miss samples often in our testing.\n\n"); if(arg > 1000000000) err_msg("Unable to parse -f argument correctly, frequencies above 1ghz are unsupported\n\n"); freq = arg; optarg = NULL; break; /* Specify output file */ case 'o': if(OPT_O) err_msg("-o already specified\n\n"); OPT_O = true; arg = stat(dirname(optarg), &chkstat); if(arg == -1 && errno == ENOENT) err_msg("Unable to parse -o argument correctly, invalid path to file\n\n"); if(arg == -1) perr_msg("Unable to parse -o argument correctly: "); out = optarg; optarg = NULL; break; /* Specify mmap() region in megabytes or kilobytes */ case 'm': case 'k': if(OPT_MK) fprintf(stderr, "mmap region size already specified in previous -m or -k, ignoring previous...\n\n"); OPT_MK = true; arg = strtol(optarg, &strerr, 10); if(arg > INT_MAX || arg < 0 || strerr[0] != 0) { if(opt == 'm') err_msg("Unable to parse -m argument correctly, should be mmap buffer size in megabytes\n\n"); else err_msg("Unable to parse -k argument correctly, should be mmap buffer size in kilobytes\n\n"); } if(opt == 'm') arg *= 1024; if(arg > 128 * 1024) err_msg("mmap buffer specified is larger than 128mb. That seems large, don't you think? I refuse to be party to this.\n\n"); if(arg < 8) err_msg("mmap buffer must be at least 8kb.\n\n"); arg *= 1024; mmap_region = getpagesize(); while(mmap_region < arg) mmap_region <<= 1; if(mmap_region != arg) err_msg("mmap buffer must be specified as a power of two.\n\n"); optarg = NULL; break; /* Specify interval between data collection, in milliseconds */ case 'i': if(OPT_I) fprintf(stderr, "-i already specified, ignoring previous value...\n\n"); OPT_I = true; arg = strtol(optarg, &strerr, 10); if(strerr[0] != 0) err_msg("Unable to parse -i argument correctly, should be number of milliseconds\n\n"); if(arg < 0) err_msg("Unable to parse -i argument, must be a positive number\n\n"); interval_ms = arg * 1000; optarg = NULL; break; /* Print usage */ case 'h': default: print_usage(); return 0; } } /* Option validity checks */ if(!OPT_E) err_msg("No event code specified!\n\n"); if(!OPT_U) err_msg("No umask specified!\n\n"); /* Start a process if specified on the command line */ if(argc > optind) { if(OPT_P) err_msg("pid already specified, cannot also specify a process to run!\n\n"); /* Fork */ pid_t ret = 0; ret = fork(); err_chk(ret == -1); /* Which side of the fork are we on? */ if(ret == 0) /* We are the child */ { int i; char ** arglist; arglist = calloc((argc - optind) + 1, sizeof(char *)); /* Enough for all the args, plus a null */ for(i = optind;i <= argc;i++) arglist[i - optind] = argv[i]; arglist[argc - optind] = NULL; chk = execvp(argv[optind], arglist); /* Never returns */ err_chk(chk == -1); sleep(1); //XXX: Remove me? } else /* We are the parent */ { pid = ret; OPT_P = true; } } /* Check for pid */ if(!OPT_P) err_msg("No process specified!\n\n"); /* Configure perf_event_attr */ struct perf_event_attr e; memset(&e, 0, sizeof(struct perf_event_attr)); e.type = PERF_TYPE_RAW; e.size = sizeof(struct perf_event_attr); e.config = event | umask << 8; e.freq = 1; e.sample_freq = freq; e.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_READ; e.pinned = 1; e.exclude_user = 0; e.exclude_kernel = 0; e.exclude_hv = 1; /* Initialize performance events */ int pe_fd; pe_fd = perf_event_open(&e, pid, -1, -1, 0); err_chk(pe_fd == -1); /* mmap buffer */ void * pem = NULL; void * events = NULL; int tail = 0; struct perf_event_mmap_page * hdr = NULL; pem = mmap(NULL, mmap_region + getpagesize(), PROT_READ, MAP_SHARED, pe_fd, 0); /* Failing point */ err_chk(pem == MAP_FAILED); hdr = pem; events = (char *) pem + getpagesize(); /* Open output file */ int outfd = 0; void * outbuf = NULL; FILE * output = NULL; outfd = open(out, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); err_chk(outfd == -1); outbuf = calloc(1, mmap_region); err_chk(outbuf == NULL); output = fdopen(outfd, "w"); err_chk(output == NULL); while(1) /* Main Loop */ { usleep(interval_ms); int head = hdr->data_head; rmb(); if(head == tail) continue; if(head - tail > mmap_region) fprintf(stderr, "Missed samples! Enlarge mmap region!\n"); /* Copy into buffer */ if(head % mmap_region < tail % mmap_region) { memcpy(outbuf, (char *) events + (tail % mmap_region), mmap_region - (tail % mmap_region)); memcpy((char *) outbuf + (mmap_region - (tail % mmap_region)), events, head % mmap_region); } else memcpy(outbuf, (char *) events + (tail % mmap_region), head - tail); chk = fwrite(outbuf, 1, head - tail, output); err_chk(chk != head - tail); tail += head - tail; } /* Cleanup and exit cleanly */ goto cleanup; /* Error handler */ err: perror("event_count"); exit_error = true; /* Cleanup anything that needs to be cleaned up */ cleanup: if(pem && pem != MAP_FAILED) munmap(pem, mmap_region + getpagesize()); if(pe_fd && pe_fd != -1) close(pe_fd); if(output != NULL) fclose(output); if(outfd && outfd != -1 && output == NULL) close(outfd); if(outbuf) free(outbuf); /* Exit */ if(exit_error) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); }
int main ( /* int argc, char * argv[] */ ) { int pipe_d[2], pipe_u[2]; // Open two pipes err_chk (pipe (pipe_d) == -1, "pipe: failed to open pipe_d"); err_chk (pipe (pipe_u) == -1, "pipe: failed to open pipe_u"); printf ("Opened pipe_d (r:%d, w:%d)\n", pipe_d[PIPE_READ], pipe_d[PIPE_WRITE]); printf ("Opened pipe_u (r:%d, w:%d)\n", pipe_u[PIPE_READ], pipe_u[PIPE_WRITE]); // Create a child process pid_t pID = fork (); switch (pID) { /* FAILURE */ case -1: perror ("fork"); exit (EXIT_FAILURE); /* CHILD PROCESS */ case 0: // close write end of downstream pipe err_chk (close (pipe_d[PIPE_WRITE]) == -1, "close: dw"); // close read end of upstream pipe err_chk (close (pipe_u[PIPE_READ]) == -1, "close: ur"); // Message testing char c_msg_out[BUFSIZ] = "uw"; char c_msg_in[BUFSIZ]; // get message from parent ssize_t r_bytes_c = read (pipe_d[PIPE_READ], &c_msg_in, BUFSIZ); err_chk (r_bytes_c == 0, "read: unexpected EOF"); err_chk (r_bytes_c == -1, "read"); printf ("CHILD: writing on %d OK\n", pipe_d[PIPE_WRITE]); if (strcmp (c_msg_in, "dw") == 0) { printf ("CHILD: reading on %d OK\n", pipe_d[PIPE_READ]); fflush (stdout); } else { printf ("CHILD: unexpected message from parent\n"); exit (EXIT_FAILURE); } // send a response ssize_t w_bytes_c = write (pipe_u[PIPE_WRITE], &c_msg_out, BUFSIZ); err_chk (w_bytes_c == 0 || w_bytes_c == -1, "write"); // redirect stdout and stdin printf ("CHILD: duplicating downstream read (%d) onto stdin (%d)\n", pipe_d[PIPE_READ], STDIN_FILENO); dup2 (pipe_d[PIPE_READ], STDIN_FILENO); printf ("CHILD: duplicating upstream write (%d) onto stdout (%d)\n", pipe_u[PIPE_WRITE], STDOUT_FILENO); dup2 (pipe_u[PIPE_WRITE], STDOUT_FILENO); printf ("ready"); fflush (stdout); // starting sort execlp ("sort", "sort", "-k3,3", "-k1,1", NULL); // something went wrong if we got this far perror ("returned from execlp unexpectedly"); exit (EXIT_FAILURE); /* PARENT PROCESS */ default: // close read end of downstream pipe err_chk (close (pipe_d[PIPE_READ]) == -1, "close: dr"); // close write end of upstream pipe err_chk (close (pipe_u[PIPE_WRITE]) == -1, "close: uw"); // Message testing char p_msg_out[BUFSIZ] = "dw"; char p_msg_in[BUFSIZ]; // send message to child ssize_t w_bytes_p = write (pipe_d[PIPE_WRITE], &p_msg_out, BUFSIZ); err_chk (w_bytes_p == 0 || w_bytes_p == -1, "write"); // get response from child ssize_t r_bytes_p = read (pipe_u[PIPE_READ], &p_msg_in, BUFSIZ); err_chk (r_bytes_p == 0, "read: unexpected EOF"); err_chk (r_bytes_p == -1, "read"); printf ("PARENT: writing on %d OK\n", pipe_u[PIPE_WRITE]); if (strcmp (p_msg_in, "uw") == 0) { printf ("PARENT: reading on %d OK\n", pipe_u[PIPE_READ]); fflush (stdout); } else { perror ("PARENT: unexpected message from child"); exit (EXIT_FAILURE); } // see if stdout was redirected successfully char buffer[BUFSIZ]; r_bytes_p = read (pipe_u[PIPE_READ], &buffer, BUFSIZ); err_chk (r_bytes_p == 0, "read: unexpected EOF"); err_chk (r_bytes_p == -1, "read"); printf ("PARENT: child reports: %s\n", buffer); fflush (stdout); // ready to start sending data for sorting FILE *sort_data = fopen ("cs308a2_sort_data", "r"); while (fgets (buffer, BUFSIZ, sort_data) != NULL) // get one line { // send line of data to child running sort w_bytes_p = write (pipe_d[PIPE_WRITE], &buffer, strlen (buffer)); err_chk (w_bytes_p == 0 || w_bytes_p == -1, "write"); } // once fgets returns null, we hit EOF. // we'll close the pipe to child to trigger an EOF downstream. err_chk (close (pipe_d[PIPE_WRITE]) == -1, "close: dw"); // don't need the input file handle anymore fclose (sort_data); // now we'll await results and print them int prev_ac = 0, ac_count = 0; char name1[BUFSIZ], name2[BUFSIZ]; int ac, p1, p2; FILE *fp = fdopen (pipe_u[PIPE_READ], "r"); printf ("\n"); while (fgets (buffer, BUFSIZ, fp) != NULL) { buffer[strlen (buffer) - 1] = '\0'; sscanf (buffer, "%511s %511s %3d %3d %4d", name1, name2, &ac, &p1, &p2); ac_count++; if (ac != prev_ac) { printf (" Area code %d: %d instances\n", ac, ac_count); ac_count = 0; } prev_ac = ac; } printf ("\n"); // clean up err_chk (close (pipe_u[PIPE_READ]) == -1, "close: ur"); printf ("PARENT: waiting for child process to terminate\n"); wait (NULL); printf ("PARENT: all done, exiting\n"); exit (EXIT_SUCCESS); } // if we get here, something went wrong printf ("We shouldn't be here...\n"); exit (EXIT_FAILURE); }