======Systems Programming Journal====== ====01/22/2014==== On the first day of class we started our discussion with the topic of file operations. We were asked to create code that will sort the numbers that the program takes out of the text file. The code in its entirety can be found below. #include #include int main() { FILE *fptr; int *data; int *data2; int i, count = 0, j; fptr = fopen("numbers.txt", "r"); if(fptr == NULL) { fprintf(stdout, "Error opening file!\n"); exit(1); } while(fscanf(fptr, "%d", &i) != EOF) { count++; } fclose(fptr); fptr = fopen("numbers.txt", "r"); data = (int *)malloc(sizeof(int)*count); data2 = (int *)malloc(sizeof(int)*count); for(i = 0; i < count; i++) { fscanf(fptr, "%d", &j); *(data + i) = j; fprintf(stdout, "%d\n", *(data + i)); } i = 0; while(i != count) { int numb = *(data + i); for(int first = 1; first < count; first++) { if(numb < *(data + first)) { numb = *(data + first); } } *(data2 + first) = numb; fprintf(stdout, "%d\n", *(data2 + i)); i++; } fclose(fptr); return(0); } ====01/24/2014==== The other day in class we created code to sort to output of our original code. The updated code is shown below. #include #include int main() { FILE *fptr; int *data; int *data2; int i, count = 0, j, low = 9999, pos = -1; fptr = fopen("numbers.txt", "r"); if(fptr == NULL) { fprintf(stdout, "Error opening file!\n"); exit(1); } while(fscanf(fptr, "%d", &i) != EOF) { count++; } fclose(fptr); fptr = fopen("numbers.txt", "r"); data = (int *)malloc(sizeof(int)*count); for(i = 0; i < count; i++) { fscanf(fptr, "%d", &j); *(data + i) = j; //fprintf(stdout, "%d\n", *(data + i)); } fclose(fptr); for(i = 0; i < count; i++) { low = 9999; pos = -1; for(j = 0; j < (count - i); j++) { if(*(data + j) < low) { low = *(data + j); pos = j; } } j = *(data + (count - i - 1)); *(data + (count - i - 1)) = low; *(data + pos) = j; } if((fptr = fopen("out.txt", "w")) == NULL) { fprintf(stderr, "Error opening file for write\n"); exit(2); } for(i = 0; i < count; i++) { fprintf(fptr, "%d, ", *(data+i)); } fprintf(fptr, "END\n"); fclose(fptr); return(0); } We also created new code based on our old code that will take in a specific file to grab the numbers from and will take in a specific file to serve as an output location after the numbers have been sorted, code shown below. #include #include int main(int argc, char **argv) { FILE *fptr; char filename[20]; int *data; int *data2; int i, count = 0, j, low = 9999, pos = -1; if(argc == 1) { sprintf(filename, "data.txt"); } else { sprintf(filename, "%s", argv[1]); } fptr = fopen(filename, "r"); if(fptr == NULL) { fprintf(stdout, "Error opening file!\n"); exit(1); } while(fscanf(fptr, "%d", &i) != EOF) { count++; } fclose(fptr); fptr = fopen(filename, "r"); data = (int *)malloc(sizeof(int)*count); for(i = 0; i < count; i++) { fscanf(fptr, "%d", &j); *(data + i) = j; //fprintf(stdout, "%d\n", *(data + i)); } fclose(fptr); for(i = 0; i < count; i++) { low = 9999; pos = -1; for(j = 0; j < (count - i); j++) { if(*(data + j) < low) { low = *(data + j); pos = j; } } j = *(data + (count - i - 1)); *(data + (count - i - 1)) = low; *(data + pos) = j; } if(argc > 2) { sprintf(filename, "%s", argv[2]); } else { sprintf(filename, "out.txt"); } if((fptr = fopen(filename, "w")) == NULL) { fprintf(stderr, "Error opening file for write\n"); exit(2); } for(i = 0; i < count; i++) { fprintf(fptr, "%d, ", *(data+i)); } fprintf(fptr, "END\n"); fclose(fptr); return(0); } ====01/28/2014==== The code that we created today #include #include #include int main(int argc, char **argv) { int c; int digit_optind = 0; while(1) { int this_option_optind = optind?optind:1; int option_index = 0; static struct option long_options[]={ {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 1, 0, 'c'}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "abc:d:012", long_options, &option_index); if(c == -1) break; switch(c) { case 0: printf("option %s", long_options[option_index].name); if(optarg) printf("with arg %s", optarg); printf("\n"); break; case '0': case '1': case '2': if(digit_optind !=0 && digit_optind != this_option_optind) printf("digits occur in two different argv elements \n"); digit_optind = this_option_optind; printf("option %c\n",c); break; case 'a': printf("option a\n"); break; case 'b': printf("option b\n"); break; case 'c': printf("option c with value '%s'\n", optarg); break; case 'd': printf("option d with value '%s'\n", optarg); break; case '?': break; default: printf("?? getopt returned character code 0%o??\n", c); } } if(optind < argc) { printf("non-option ARGV elements: "); printf("%s ", argv[optind++]); printf("\n"); } return(0); } ====01/30/2014==== Started the group of project #include #include #include int main(int argc, char **argv) { while(1) { Static struct option long_options[]={ {"add animal", 1, 0, -a}, {"add group", 1, 0, -g}, {"verbose", 0, 0, -v}, {"list", 0, 0, -l}, {"help", 0, 0, -h}, {"count", 0, 0, -c}, {0, 0, 0, 0,} }; ====02/04/2014==== Today was really cool because we created our own chmod program. I'm a little lost with what systems programming is but I think I'm starting to get it #include #include #include #include #include int main(char argc, char **argv) { if(argc != 3) { fprintf(stdout, "%s: missing operand\n", argv[0]); exit(1); } if(chmod(argv[2], strtol(argv[1], NULL, 8)) < 0) { fprintf(stderr, "%s: error in chmod(%s, %s) - %d(%s)\n", argv[0], argv[2], argv[1], errno, strerror(errno)); exit(1); } return(0); } ====02/06/2014==== Today in class we created our own ls. It's really cool that we are seeing how the tools that we have used for almost a year now work. #include #include #include void process(char *); int main(int argc, char **argv) { if(argc == 1) process("."); else { while(--argc) { fprintf(stdout, "%s:\n", *++argv); process(*argv); } } return(0); } void process(char *dirname) { DIR *dirPtr; struct dirent *direntp; if((dirPtr = opendir(dirname)) == NULL) fprintf(stderr, "ls: cannot open %s\n", dirname); else { while((direntp = readdir(dirPtr)) != NULL) { fprintf(stdout, "name: %s, reclen: %hu, type: %hhu\n", direntp->d_name, direntp->d_reclen, direntp->d_type); } closedir(dirPtr); } } ====02/11/2014==== Today we worked on the spwd code from the book. We learned that for some reason it does not work on lab46 but will work if used through the system regularly. #include #include #include #include #include #include ino_t get_inode(char *); void printpathto(ino_t); void inum_to_name(ino_t, char *, int); int main() { printpathto(get_inode(".")); putchar('\n'); return(0); } void printpathto(ino_t this_inode) { ino_t my_inode; char its_name[BUFSIZ]; if(get_inode("..") != this_inode) { chdir(".."); inum_to_name(this_inode,its_name,BUFSIZ); my_inode = get_inode("."); printpathto(my_inode); printf("/%s", its_name); } } void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen) { DIR *dir_ptr; struct dirent *direntp; dir_ptr = opendir("."); if(dir_ptr == NULL) { perror("."); exit(1); } while((direntp = readdir(dir_ptr)) != NULL) if(direntp->d_ino == inode_to_find) { strncpy(namebuf, direntp->d_name, buflen); namebuf[buflen-1] = '\0'; closedir(dir_ptr); return; } fprintf(stdout, "error looking for inum %d\n", inode_to_find); exit(1); } ino_t get_inode(char *fname) { struct stat info; if(stat(fname, &info) == -1) { fprintf(stderr, "Cannot stat "); perror(fname); exit(1); } return info.st_ino; } ====02/12/2014==== For fun I decided to do the code that is found in book. In the first chapter I created my own version of the more command. #include #include #define PAGELEN 24 #define LINELEN 512 void do_more(FILE *); int see_more(FILE *); int main(int ac, char *av[]) { FILE *fp; if(ac == 1) do_more(stdin); else while(--ac) { if((fp = fopen(*++av, "r")) != NULL) { do_more(fp); fclose(fp); } else exit(1); } return(0); } void do_more(FILE *fp) { char line[LINELEN]; int num_of_lines = 0; int reply; FILE *fp_tty; fp_tty = fopen("/dev/tty", "r"); if(fp_tty == NULL) exit(1); while(fgets(line, LINELEN, fp)) { if(num_of_lines == PAGELEN) { reply = see_more(fp_tty); if(reply == 0) break; num_of_lines -= reply; } if(fputs(line, stdout) == EOF) exit(1); num_of_lines++; } } int see_more(FILE *cmd) { int c; printf("\033[7m more? \033[m"); while((c=getc(cmd)) != EOF) { if(c == 'q') return(0); if(c == ' ') return(PAGELEN); if(c == '\n') return(1); } return(0); } I really need to take the time to sit down and walk through the code I've written line by line to get a better understanding of what each program is doing. ====02/13/2014==== Today we worked on the matrix multiplier. I think I'm very close to figuring it out, but I can't seem to figure out the algorithm. #include int main() { int TableA[2][2] = { {1,2}, {3,4}, }; int TableB[2][2] = { {4,3}, {2,1}, }; int TableC[2][2]; int a, b, c = 0; int x, y, z; for(a = 0; a < 2; a++) { x = 0; for(b = 0; b < 2; b++) { y = TableA[a][b]; for(c = 0; c < 2; c++) { for(d = 0; d < 2; d++) { z = TableB[c][d]; } x = x + (y*z); } } } ====02/18/2014==== Today I finished my Matrix multiplier. It turns out I was actually really close with my first attempt. I also added a lot of user input, so that it will work with any size. #include int main() { int a, b, c, d, e, f, g, h = 0; //Creating and assigning values for the first matrix fprintf(stdout, "What are the dimensions of the first matrix?\n"); fscanf(stdin, "%d%d", &a, &b); int MatrixA[a][b]; fprintf(stdout, "Enter the values for the matrix: "); for(e = 0; e < a; e++) { for(f = 0; f < b; f++) { fscanf(stdin, "%d", &MatrixA[e][f]); } } //Creating and assign values for the second matrix fprintf(stdout, "What are the dimensions of the second matrix?\n"); fscanf(stdin, "%d%d", &c, &d); int MatrixB[c][d]; fprintf(stdout, "Enter the values for the matrix: "); for(g = 0; g < c; g++) { for(h = 0; h < d; h++) { fscanf(stdin, "%d", &MatrixB[g][h]); } } int MatrixC[a][d]; //Checks to see if the matrixes can be multiplied if(b != c) { fprintf(stdout, "Error Invalid Matrix Dimensions\n"); } else { int i, x = 0; for(g = 0; g < a; g++) { for(h = 0; h < d; h++) { for(i = 0; i < c; i++) { x = x + MatrixA[g][i]*MatrixB[i][h]; } MatrixC[g][h] = x; x = 0; } } //Display final Matrix for(g = 0; g < a; g++) { for(h = 0; h < d; h++) { fprintf(stdout, " %d", MatrixC[g][h]); } fprintf(stdout, "\n"); } } return(0); } ====02/19/2014==== Today I did the chapter two book programs and created my own who and copy commands who #include #include #include #include #include #include //#define SHOWHOST void showtime(long); void show_info(struct utmp *); int main() { struct utmp utbuf; int utmpfd; //int reclen = sizeof(current_record); if((utmpfd = open(UTMP_FILE, O_RDONLY) == -1)) { perror(UTMP_FILE); exit(1); } while(read(utmpfd, &utbuf, sizeof(utbuf)) == sizeof(utbuf)) show_info(&utbuf); close(utmpfd); return(0); } void show_info(struct utmp *utbufp) { if(utbufp->ut_type != USER_PROCESS) return; printf("%-8.8s", utbufp->ut_name); printf(" "); printf("%-8.8s", utbufp->ut_line); printf(" "); showtime(utbufp->ut_time); #ifdef SHOWHOST if(utbufp->ut_host[0] != '\0')) printf(" (%s)", utbufp->ut_host); #endif printf("\n"); } void showtime(long timeval) { char *cp; cp = ctime(&timeval); printf("%12.12s", cp+4); } For some reason this code compiles but it does not do what it is supposed to do when it is run Copy #include #include #include #include #define BUFFERSIZE 4096 #define COPYMODE 0644 void oops(char *, char *); void main(int ac, char *av[]) { int in_fd, out_fd, n_chars; char buf[BUFFERSIZE]; if(ac != 3) { fprintf(stderr, "usage: %s source destination\n", *av); } if((in_fd = open(av[1], O_RDONLY)) == -1) oops("Cannot open ", av[1]); if((out_fd = creat(av[2], COPYMODE)) == -1) oops("Cannot creat ", av[2]); while((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0) if(write(out_fd, buf, n_chars) != n_chars) oops("Write error to ", av[2]); if(n_chars == -1) oops("Read error from ", av[1]); if(close(in_fd) == -1 || close(out_fd) == -1) oops("Error closing files", ""); } void oops(char *s1, char *s2) { fprintf(stderr, "Error: %s ", s1); perror(s2); exit(1); } This code works fine This is still really cool. The fact that I am seeing that the commands that I use everyday are not even a lot of code, is fascinating. Something that people use everyday are smaller than most programs that I write. ====02/25/2014==== Today we wrote the write command from the book #include #include #include #include int main(int argc, char **argv) { int fd; char buf[BUFSIZ]; if(argc != 2) { fprintf(stderr, "usage: %sttyname\n", argv[0]); exit(1); } fd = open(argv[1], O_WRONLY); if(fd == -1) { perror(argv[1]); exit(1); } while(fgets(buf, BUFSIZ, stdin) != NULL) { if(write(fd, buf, strlen(buf)) == -1) break; } close(fd); return(0); } I think I am starting to understand how these commands work, I still need to sit down and dissect them ====02/27/2014==== Today in class we went over the chapter 5 code examples and I also worked on the groupof program for a little bit setecho.c #include #include #include #define oops(s,x) {perror(s); exit(x);} main(int ac, char *av[]) { struct termios info; if(ac == 1) exit(0); if(tcgetattr(0, &info) == -1) oops("tcgetattr", 1); if(av[1][0] == 'y') info.c_lflag |= ECHO; else info.c_lflag &= ~ECHO; if(tcsetattr(0, TCSANOW, &info) == -1) oops("tcgetattr", 2); } echostate.c #include #include #include main() { struct termios info; int rv; rv = tcgetattr(0, &info); if(rv == -1) { perror("tcgetattr"); exit(1); } printf("info.c_lfag is: %X\n", info.c_lflag); printf("ICANON is: %X\n", ICANON); if(info.c_lflag & ICANON) printf(" ICANON is on, since its bit is 1\n"); else printf(" ICANON is OFF, since its bit is 0\n"); } ====03/04/2014==== Today we created the playagain3 program from chapter 6 #include #include #include #include #include #define ASK "Do you want another transaction?" #define TRIES 3 #define SLEEPTIME 2 #define BEEP putchar('\a') int main() { int response; tty_mode(0); set_cr_noecho_mode(); set_nodedelay_mode(); response = get_response(ASK, TRIES); tty_mode(1); return(response); } int get_response(char *question, int maxtries) { int input; printf("%s(y/n)?", question); fflush(stdout); while(1) { sleep(SLEEPTIME); input = tolower(get_ok_char()); if(input == 'y') printf("Yes\n"); return(0); if(input == 'n') printf("No\n"); return(1); if(maxtries-- == 0) printf("Timeout\n"); return(2); BEEP; } } int get_ok_char() { int c; while((c = getchar()) != EOF && strchr("yYnN", c) == NULL) ; return(c); } void set_cr_noecho_mode() { struct termios ttystate; tcgetattr(0, &ttystate); ttystate.c_lflag &= ~ICANON; ttystate.c_lflag &= ~ECHO; ttystate.c_cc[VMIN] = 1; tcsetattr(0, ICANON, &ttystate); } void set_nodedelay_mode() { int termflags; termflags - fcntl(0, F_GETFL); printf("termflags: %X, O_NDELAY: %X\n", termflags, O_NDELAY); termflags |= O_NDELAY; fcntl(0, F_SETFL, termflags); } tty_mode(int how) { static struct termios original_mode; static int original_flags; if(how == 0) { tcgetattr(0, &original_mode); original_flags = fcntl(0, F_GETFL); } else { tcsetattr(0, TCSANOW, &original_mode); fcntl(0, F_SETFL, original_flags); } } ====03/05/2014==== Created the completed ls program from the book #include #include #include #include #include void do_ls(char[]); void dostat(char *); void show_file_info(char *, struct stat *); void mode_to_letters(int , char []); char *uid_to_name(uid_t); char *gid_to_name(gid_t); int main(int ac, char *av[]) { if(ac == 1) do_ls("."); else { while(--ac) { fprintf(stdout, "%s:\n", *++av); do_ls(*av); } } return(0); } void do_ls(char dirname[]) { DIR *dirPtr; struct dirent *direntp; if((dirPtr = opendir(dirname)) == NULL) fprintf(stderr, "ls: cannot open %s\n", dirname); else { while((direntp = readdir(dirPtr)) != NULL) { dostat(direntp->d_name); } closedir(dirPtr); } } void dostat(char *filename) { struct stat info; if(stat(filename, &info) == -1) perror(filename); else show_file_info(filename, &info); } void show_file_info(char *filename, struct stat *info_p) { char *uid_to_name(), *ctime(), *gid_to_name(), *filemode(); void mode_to_letters(); char modestr[11]; mode_to_letters(info_p->st_mode, modestr); printf("%s ", modestr); printf("%4d ", (int) info_p->st_nlink); printf("%-8s ", uid_to_name(info_p->st_uid)); printf("%-8s ", gid_to_name(info_p->st_gid)); printf("%8ld ", (long)info_p->st_size); printf(".12s ", 4+ctime(&info_p->st_mtime)); printf("%s\n", filename); } void mode_to_letters(int mode, char str[]) { strcpy(str, "----------"); if( S_ISDIR(mode)) str[0] = 'd'; if( S_ISCHR(mode)) str[0] = 'c'; if( S_ISBLK(mode)) str[0] = 'b'; if(mode & S_IRUSR) str[1] = 'r'; if(mode & S_IWUSR) str[2] = 'w'; if(mode & S_IXUSR) str[3] = 'x'; if(mode & S_IRGRP) str[4] = 'r'; if(mode & S_IWGRP) str[5] = 'w'; if(mode & S_IXGRP) str[6] = 'x'; if(mode & S_IROTH) str[7] = 'r'; if(mode & S_IWOTH) str[8] = 'w'; if(mode & S_IXOTH) str[9] = 'x'; } #include char *uid_to_name(uid_t uid) { struct passwd *getpwuid(), *pw_ptr; static char numstr[10]; if((pw_ptr = getpwuid(uid)) == NULL) { sprintf(numstr, "%d", uid); return(numstr); } else return(pw_ptr->pw_name); } #include char *gid_to_name(gid_t gid) { struct group *getgrgid(), *grp_ptr; static char numstr[10]; if((grp_ptr = getgrgid(gid)) == NULL) { sprintf(numstr, "%d", gid); return(numstr); } else return(grp_ptr->gr_name); } ====03/11/2014==== Today we created a signal program from chapter six #include #include #include void thing1(); void thing2(); void thing3(); int main() { signal(SIGQUIT, thing1); signal(SIGINT, thing2); sleep(10); fprintf(stdout, "you can't stop me!\n"); signal(SIGINT, thing3); while(1) { sleep(1); fprintf(stdout, "loop\n"); } return(0); } void thing1() { fprintf(stdout, "QUIT signal given, exiting...\n"); exit(0); } void thing2() { fprintf(stdout, "HAHA!\n"); } void thing3() { fprintf(stdout, "RAWR!\n"); } I like this program because it is the first time I am seeing something new that systems programming can do. I've created programs that simulate commands, but I knew about those commands already. I also went back and read chapter 4 of the book and had a nice refresher on how UNIX trees work. One thing that was new that I thought was interesting is the of inodes. This put a whole different spin on directories and files in UNIX. Even though we created in class I will included the spwd code from the chapter. #include #include #include #include #include #include ino_t get_inode(char *); void printpathto(ino_t); void inum_to_name(ino_t, char *, int); int main() { printpathto(get_inode(".")); putchar('\n'); return(0); } void printpathto(ino_t this_inode) { ino_t my_inode; char its_name[BUFSIZ]; if(get_inode("..") != this_inode) { chdir(".."); inum_to_name(this_inode,its_name,BUFSIZ); my_inode = get_inode("."); printpathto(my_inode); printf("/%s", its_name); } } void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen) { DIR *dir_ptr; struct dirent *direntp; dir_ptr = opendir("."); if(dir_ptr == NULL) { perror("."); exit(1); } while((direntp = readdir(dir_ptr)) != NULL) if(direntp->d_ino == inode_to_find) { strncpy(namebuf, direntp->d_name, buflen); namebuf[buflen-1] = '\0'; closedir(dir_ptr); return; } fprintf(stdout, "error looking for inum %d\n", inode_to_find); exit(1); } ino_t get_inode(char *fname) { struct stat info; if(stat(fname, &info) == -1) { fprintf(stderr, "Cannot stat "); perror(fname); exit(1); } return info.st_ino; } ====03/18/2014==== Today we discussed the concept of processes, including the use of the fork command to lead to the creation of children processes. fork.c #include #include #include #include int main() { pid_t me, you, parent; me = getpid(); parent = getppid(); printf("Run top in another terminal and hit ENTER when ready"); fgetc(stdin); printf("PID of me: %d\n", me); you = fork(); if(me == getpid()) { printf("Parent PID: %d\n", me); printf("Child PID: %d\n", you); printf("PPID: %d\n", parent); sleep(5); } else { //signal(SIGCHLD, SIG_IGN); sleep(10); me = getpid(); parent = getppid(); printf("New Parent PID: %d\n", me); printf("New Child PID: %d\n", you); printf("New PPID: %d\n", parent); sleep(5); printf("Child is done waitng\n"); } //sleep(8); return(0); } fork2.c #include #include #include #include int main(int argc, char **argv) { pid_t me, you; char input, *fname; FILE *fptr; int i, j, data[100][2], rank = 0, numproc = 0; int pidlist[5]; for(i=0; i<100; i++) { data[i][0] = i * i; } pidlist[0] = getpid(); for(i = 1; i <= 4; i++) { if(pidlist[0] == getpid()) { rank = rank + 1; pidlist[i] = fork(); } } if (getpid() == pidlist[0]) { printf("I am PID %i, my child processes are: ", pidlist[0]); for(i=1; i<=4; i++) printf("%i ", pidlist[i]); printf("\n"); // could put code to wait for child process termination here } else { me = getpid(); printf("I am child %i (pid %i), so I will process ", rank, me); printf("elements %i-%i ...\n", ((rank*25)-25), ((((rank+1)*25)-1)-25)); for(i = ((rank*25)-25); i < (((rank+1)*25)-25); i++) data[i][1] = data[i][0] * rank; fname = (char *) malloc (sizeof(char) * 8); sprintf(fname, "rank%i", rank); fptr = fopen(fname, "w"); fprintf(fptr, "%i\n", (rank*25)-25); fprintf(fptr, "%i\n", (((rank+1)*25)-1)-25); for(i = rank*25-25; i < ((rank+1)*25)-25; i++) fprintf(fptr, "%i\t%i\n", data[i][0], data[i][1]); fclose(fptr); } return(0); } I also read the chapter 6 material. I feel really good with signals but I need to get a better understanding of what tty is and how to use it. ====03/20/2014==== Today we kept working with different process examples. First we looked at fork3.c, in which we utilized the wait function #include #include #include #include int main(int argc, char **argv) { pid_t me, you; char input, *fname; FILE *fptr; int i, j, data[100][2], rank = 0, numproc = 0; int pidlist[5]; for(i=0; i<100; i++) { data[i][0] = i * i; } pidlist[0] = getpid(); for(i = 1; i <= 4; i++) { if(pidlist[0] == getpid()) { rank = rank + 1; pidlist[i] = fork(); } } if (getpid() == pidlist[0]) { printf("I am PID %i, my child processes are: ", pidlist[0]); for(i=1; i<=4; i++) printf("%i ", pidlist[i]); printf("\n"); // could put code to wait for child process termination here for(i = 0; i < rank; i++) { you = wait(&j); printf("child PID %d has finished with status %d\n", you, j); } } else { me = getpid(); printf("I am child %i (pid %i), so I will process ", rank, me); printf("elements %i-%i ...\n", ((rank*25)-25), ((((rank+1)*25)-1)-25)); for(i = ((rank*25)-25); i < (((rank+1)*25)-25); i++) data[i][1] = data[i][0] * rank; fname = (char *) malloc (sizeof(char) * 8); sprintf(fname, "rank%i", rank); fptr = fopen(fname, "w"); fprintf(fptr, "%i\n", (rank*25)-25); fprintf(fptr, "%i\n", (((rank+1)*25)-1)-25); for(i = rank*25-25; i < ((rank+1)*25)-25; i++) fprintf(fptr, "%i\t%i\n", data[i][0], data[i][1]); fclose(fptr); sleep(rank * 2 + 60); } return(0); } Next we explored the use of exec. I really liked this one because it replaces processes with whatever you want to do instead. #include #include #include #include int main(int argc, char **argv) { pid_t me, you; char input, *fname; FILE *fptr; int i, j, data[100][2], rank = 0, numproc = 0; int pidlist[5]; for(i=0; i<100; i++) { data[i][0] = i * i; } pidlist[0] = getpid(); for(i = 1; i <= 4; i++) { if(pidlist[0] == getpid()) { rank = rank + 1; pidlist[i] = fork(); } } if (getpid() == pidlist[0]) { printf("I am PID %i, my child processes are: ", pidlist[0]); for(i=1; i<=4; i++) printf("%i ", pidlist[i]); printf("\n"); // could put code to wait for child process termination here for(i = 0; i < rank; i++) { you = wait(&j); printf("child PID %d has finished with status %d\n", you, j); } } else { if(rank == 2) execl("/bin/ls", "ls", "-l", NULL); me = getpid(); printf("I am child %i (pid %i), so I will process ", rank, me); printf("elements %i-%i ...\n", ((rank*25)-25), ((((rank+1)*25)-1)-25)); for(i = ((rank*25)-25); i < (((rank+1)*25)-25); i++) data[i][1] = data[i][0] * rank; fname = (char *) malloc (sizeof(char) * 8); sprintf(fname, "rank%i", rank); fptr = fopen(fname, "w"); fprintf(fptr, "%i\n", (rank*25)-25); fprintf(fptr, "%i\n", (((rank+1)*25)-1)-25); for(i = rank*25-25; i < ((rank+1)*25)-25; i++) fprintf(fptr, "%i\t%i\n", data[i][0], data[i][1]); fclose(fptr); sleep(rank * 2 + 60); } return(0); } ====03/25/2014==== Today we didn't have a standard class due to the amount of people that came. I did however work through the chapter 8 material. exec1.c main() { char *arglist[3]; arglist[0] = "ls"; arglist[1] = "-l"; arglist[2] = 0; printf("* * *About to esec ls -l\n"); execvp("ls", arglist); printf("* * *ls is done. Bye\n"); } This program taught me a couple things. First, the whole idea that when a new process is started the previous process vanishes from existence, I remember Matt saying that but now it has really been inserted into my mind. Second, this program does not have and "include" statements, I did not even know that this was possible and I will have to ask Matt about this. psh1.c #include #include #include #define MAXARGS 20 #define ARGLEN 100 int main() { char *arglist[MAXARGS + 1]; int numargs; char argbuf[ARGLEN]; char *makestring(); numargs = 0; while(numargs < MAXARGS) { printf("Arg[%d]? ", numargs); if(fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n') arglist[numargs++] = makestring(argbuf); else { if(numargs > 0) { arglist[numargs] = NULL; execute(arglist); numargs = 0; } } } return(0); } int execute(char *arglist[]) { execvp(arglist[0], arglist); perror("execvp failed"); exit(1); } char *makestring(char *buf) { char *cp, *malloc(); buf[strlen(buf)-1] = '\0'; cp = malloc(strlen(buf)+1); if(cp == NULL) { fprintf(stderr, "No memory\n"); exit(1); } strcpy(cp, buf); return(cp); } waitdemo1.c #include #define DELAY 2 main() { int newpid; void child_code(), parent_code(); printf("before: mypid is %d\n", getpid()); if((newpid = fork()) == -1) perror("fork"); else if(newpid == 0) child_code(DELAY); else parent_code(newpid); } void child_code(int delay) { printf("child %d here. will sleep for %d seconds\n", getpid(), delay); sleep(delay); printf("child done. about to exit\n"); exit(17); } void parent_code(int childpid) { int wait_rv; wait_rv = wait(NULL); printf("done waiting for %d. wait returned: %d\n", childpid, wait_rv); } I think I fully understand this code but I need to talk to Matt and make sure what I think is happening is actually what is happening waitdemo2.c #include #define DELAY 5 main() { int newpid; void child_code(), parent_code(); printf("before: mypid is %d\n", getpid()); if((newpid = fork()) == -1) perror("fork"); else if(newpid == 0) child_code(DELAY); else parent_code(newpid); } void child_code(int delay) { printf("child %d here. will sleep for %d seconds\n", getpid(), delay); sleep(delay); printf("child done. about to exit\n"); exit(17); } void parent_code(int childpid) { int wait_rv; int child_status; int high_8, low_7, bit_7; wait_rv = wait(&child_status); printf("done waiting for %d. wait returned: %d\n", childpid, wait_rv); high_8 = child_status >> 8; low_7 = child_status & 0X7F; bit_7 = child_status & 0X80; printf("status: exit=%d, sig=%d, core=%d\n", high_8, low_7, bit_7); } This code is pretty much what we did in class, just not nearly as in depth psh2.c #include #include #include #define MAXARGS 20 #define ARGLEN 100 int main() { char *arglist[MAXARGS + 1]; int numargs; char argbuf[ARGLEN]; char *makestring(); numargs = 0; while(numargs < MAXARGS) { printf("Arg[%d]? ", numargs); if(fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n') arglist[numargs++] = makestring(argbuf); else { if(numargs > 0) { arglist[numargs] = NULL; execute(arglist); numargs = 0; } } } return(0); } execute(char *arglist[]) { int pid, exitstatus; pid = fork(); switch(pid) { case -1: perror("fork failed"); exit(1); case 0: execvp(arglist[0], arglist); perror("execvp failed"); exit(1); default: while(wait(&exitstatus) != pid) ;//ask matt about this printf("child exited with status %d, %d\n", exitstatus >> 8, exitstatus&0377); } } char *makestring(char *buf) { char *cp, *malloc(); buf[strlen(buf)-1] = '\0'; cp = malloc(strlen(buf)+1); if(cp == NULL) { fprintf(stderr, "No memory\n"); exit(1); } strcpy(cp, buf); return(cp); } For some reason I cannot run the psh1 from earlier like the book can, do not know if I am just entering it wrong or if I screwed up some where.