Derek Southard's Completely Awesome fall 2014 Opus
The language of C and the culture of UNIX
I am a beginner in the world of computer science, but I thrive to learn. I am open to both positive and negative criticism. My MOTTO is, if it helps then let loose. I am open to anything that furthers my education. I am interested in learning new things and hearing about “others” technology experiences. I love games from first person shooters to MMORPG's, but that's not all. I enjoy working out and staying healthy. MIND AND BODY!
9 4, 2014
I learned a few interesting things today that I can reference to my experiences in VBS. When I first started VBS, I wrote some code for a number game. This game came along until I wrote a code to put data into a highscore file and read it back. I hadn't learned about variable-scopes yet, and I was racking my brain on why this variable's value would only work for some of the times I declared it. Finally, I asked for help from Joe and I discovered that I had set the variable locally; therefore, it would only have the set value inside of the function. In C You can declare the variable inside of a function also. You know you're in the function when you're in the {} curly brackets. Something I hadn't thought of was that setting global functions can make the code sloppy and also hinder you progress in obtaining better programming abilities. Another cool thing I learned was that inside of a function, you can create a sub-block in which the variables revert back to normal after-wards. One thing I am a little caught up on is grasping in the idea of pointers. I know that an asterisk is the symbol of a pointer, but I am still not entirely sure what they can do, besides point at integers. I am not ever sure what “pointing at an integer” is, but I am going to take a journey and try to grasp the concept by he end of the weekend.
9 5, 2014
I seem to be doing very well in this class so far. I have been reading my Unix book and performing the exercises in the book Unix for the beginning mage, it's pretty amazing to be navigating around playing with files on as OS I have never even attempted to use. I enjoy being able to copy a directory and move it, then delete an entire directory with a few strokes of a keyboard. If I can do all of this already, who knows what possibilities in my future in unix/linux usage hold. I am so excited to learn and do more.
9 10, 2014
I am starting to get a better grasp on the language of C and its syntax. I can now input and output and use the very basics of pointers. I can also perform math with a modulus on simple math programs. Something cool I did today was, converting a nott function from VBS to C. I am really enjoying this course and look forward to what it's future has to offer me.
9 10, 2014
The further I climb in the rabbit hole, the more interesting UNIX/linux becomes. I have been crawling around using all sorts of ls arguments. Sometimes I know what I am doing and sometimes I don't. Either way, I learn something new a lot of the times. The only thing I am currently having trouble with is symbolic linking directories. They seem to end up looping one another. At this point I feel kind of sort of comfortable woth the man pages. Overall, this OS is a blast and I don't ever want to stop learning.
9 14, 2014
Now I am learning arrays, and getting ideas for all sorts of programs. When I come to a problem it is sort of like a puzzle that is fun to solve. I find myself coming up with program ideas. I can't wait to further develop my skills.
9 15, 2014
I learned that in Linux, many of the tools needed for compressing and archiving are built in commands. I extracted files, sorted through them, and made my own archive. It is interesting for something I didn't know much about it. It was also pretty neat to lean that archiving lossy actually get rids of information. The thought of a lossy txt file is scary. It's a good thing we don't do that.
9 16, 2014
A.Get file b.Using file(1), what type of file does this appear to be? It appears to be ASCII. c.View the contents of this file using cat(1). Is it what it appears to be? YES! This is a simple text file. It contains ASCII text. d.Using gzip(1), compress this file with default compression. What does file(1) say? It says, file.txt.gz: gzip compressed data, was "file.txt", last modified: Tue Sep 16 22:13:57 2014, from Unix. e.Uncompress the file, and recompress using arguments for fastest (not highest) compression. What does file(1) report now? file.txt.gz: gzip compressed data, was "file.txt", last modified: Tue Sep 16 22:13:57 2014, max speed, from Unix.
It is interesting that the file command reveals that the compressed data was max speed.
9 19, 2014
This Code I created resembles “mental-math” logic in squaring roots ending in 5. As you would increment and multiple the tens+ digits and square the ones place. Then connect them together as one.
1 #include <stdio.h> 2 main() 3 { 4 int var1; 5 printf("Type a 2 digit number ending in 5: "); 6 scanf("%d",&var1); 7 int dig1 = (var1/10); 8 int dig2 = dig1+1; 9 int fdig1 = dig1*dig2; 10 float dig3 = (var1%10); 11 int fdig2 = (dig3*dig3); 12 int whole = 25+(fdig1*100); 13 printf("The sqaure root of %d is: %d\n",var1,whole); 14 return(0); 15 } ~
As you can see, I did more math to get the result of an integer, instead of sort of connecting the two separate numbers to appear as one. This trick can even work for eight digit numbers ending in 5, but some integers higher than that will malfunction.
9 26, 2014
I created a project involving an algorithm that produces what day new years is on.
+#include <stdio.h> +int main() +{ +int year, multiple; + printf("What year in the 21st century? : "); + scanf("%d",&year); + int tens = (year%100); + int percent = (tens/4); + if (tens%4==0) + { + percent = (percent-1); + } + int result=(percent+tens); + for (multiple=0;multiple<result;multiple+=7) + {} + multiple = (multiple-7); + int day = (result-multiple); + if (day == 1){printf("In the year %d new years is on monday, jan 1 \n",year);} + if (day == 2){printf("In the year %d new years is on tuesday, jan 1\n",year);} + if (day == 3){printf ("In the year %d new years is on wednesday, jan 1\n",year);} + if (day == 4){printf("In the year %d new years is on thursday, jan 1\n",year);} + if (day == 5){printf("In the year %d new years is on friday, jan 1\n",year);} + if (day == 6){printf("In the year %d new years is on saturday, jan 1\n",year);} + if (day == 7|0){printf("In the year %d new years is on sunday, jan 1\n",year);} + result=(0); +}
9 30, 2014
The PuzzleBox2 was my UNIX adventure this week. To do this project, I performed the following.
lab46:~$ unzip puzzlebox2.zip Archive: puzzlebox2.zip [puzzlebox2.zip] big_endian.ascii password:
I was then prompted for a password. This password was easy because it came in a README file.
replace big_endian.ascii? [y]es, [n]o, [A]ll, [N]one, [r]ename: y inflating: big_endian.ascii [puzzlebox2.zip] part1 password:
As you can see, I was given a file, and prompted for another password. I discovered that it was an ASCII file, so I converted the decimal to ASCII. Then I was left with Hex values to convert. I did this two times, first manually, second I ran this command.
lab46:~$ cat stage2 | cut -d':' -f2 > $(cat stage2 | cut -d':' -f1).ascii
This gave me the next password. Then I received 4 files with seemingly random contents named part1, part2, part3, and part4 (names not so random). Then I created the pipe command:
lab46:~$ sort>|cat part1>|cat part2>|cat part3>|cat part4> result.txt
BOOM! FILES ARE ALL SORTED TOGETHER IN A SINGLE FILE, ALL WITH 1 COMMAND.! :) This ends up making a picture using ASCII art.
10 7, 2014
Switches
Can be used for if cases if exact value known is wanted.They are not good if there are more than 20 values, due to a wasteful amount typing.
switch example
switch(variable) { case 0: code that describes the case. break; } repeat cases.
On another note
This is th command needed to compile my code from the SDL library.
gcc -o graphics graphics.c -lSDL -lSDL_image
This links to the SDL library and to an SDL img lib.
10 7, 2014
PID
process-program in action.ps is a command that stands for process status.
drep@Ghoste:~/Desktop$ ps PID TTY TIME CMD 3321 pts/1 00:00:00 bash 25153 pts/1 00:00:00 ps
drep@Ghoste:~/Desktop$ top - 21:04:27 up 14 days, 21:59, 9 users, load average: 0.13, 0.07, 0.06 Tasks: 191 total, 1 running, 188 sleeping, 2 stopped, 0 zombie %Cpu(s): 0.2 us, 0.0 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 1535680 total, 656464 used, 879216 free, 49028 buffers KiB Swap: 131068 total, 107788 used, 23280 free. 331720 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 13 root 20 0 0 0 0 S 0.3 0.0 31:56.26 ksoftirqd/1 1608 mp010784 20 0 19400 2328 648 S 0.3 0.2 22:43.79 tmux 20048 dsaunde6 20 0 129724 30260 5284 S 0.3 2.0 0:05.24 ruby 27183 dsoutha3 20 0 15912 1508 1048 R 0.3 0.1 0:00.04 top 1 root 20 0 15452 32 0 S 0.0 0.0 0:25.59 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 28:15.63 ksoftirqd/0 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:+ 7 root 20 0 0 0 0 S 0.0 0.0 36:59.56 rcu_sched 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 9 root rt 0 0 0 0 S 0.0 0.0 5:18.15 migration/0 10 root rt 0 0 0 0 S 0.0 0.0 2:43.12 watchdog/0 11 root rt 0 0 0 0 S 0.0 0.0 2:26.32 watchdog/1 12 root rt 0 0 0 0 S 0.0 0.0 4:49.83 migration/1 14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/1:0 15 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/1:+ 16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 khelper
kill
command that lets us generate signals
kill -l kill list
To just hang up kill kill -1 PID kill -HUP PUD
The numbers are mapped to the 64 ways of killing.
Number 9 cannot be stopped. It's the ultimate kill signal.
fms to see processes.
ps aux|grep $USER will list all
fg stands for foreground (re-animates stopped processes)
Shell History
parent shell is
bg stands for background
jobs lists sleeping commands
bg (job number)
10 23, 2014
*malloc - which stands for “memory-allocation” can be used to allocate specified amounts of memory.
sizeof - function that returns the size of a specified datatype.
EXAMPLE (goes with our funcfun program.)
scores=(int*)malloc(sizeof(int)*num); size of returns thesize of an int and multiply's it by the number of ints aka num,(num=4 in this case), then malloc allocates the specified amount of memory. In this case, it will take 4 bytes times 4 bytes giving 16 bytes, which is just enough to store 4 integers.*/ *(scores+0) dereferences what's at the scores address and if you add you can dereference the things at the address shifted up from the starting adress.
DATA STRUCTURES
/* * structs.c * * An example of using structs in C, along with arrays. * * To compile: gcc -o structs1 structs1.c * */ #include<stdio.h> //#include<string.h> int main() { int i; char entry[80], entries = 4, junk; struct person { char name[80]; int age; float height; }; do { printf("How many people in your database? "); scanf("%d", &entries); } while (entries <= 0); struct person people[entries]; for(i=0; i<entries; i++) { printf("Person %d of %d:\n", (i+1), entries); printf("==============\n"); // prompt for name (string) printf("Please enter the person's first name: "); scanf("%s", people[i].name); // fgets(entry, sizeof(entry), stdin); // strcpy(people[i].name, entry); // prompt for age (integer) printf("Please enter %s's age: ", people[i].name); scanf("%d", &people[i].age); // prompt for height (float) printf("Please enter %s's height: ", people[i].name); scanf("%f", &people[i].height); // Get newline out of the input stream junk = fgetc(stdin); // fgets(junk, sizeof(junk), stdin); } printf("\n\nThe names of the people are:\n"); for(i=0; i<entries; i++) { printf("#%d: %s\t", (i+1), people[i].name); } printf("\n\n"); printf("The full bios of the people are:\n"); for(i=0; i<entries; i++) { printf("#%d: %s, age: %d, height: %f\n", (i+1), people[i].name, people[i].age, people[i].height); } return(0); }
Author, Designer, & Reviewer
— Derek Southard 2014/10/24 20:39
10 23, 2014
ALIAS
lab46:~$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games all of the places that terminal
*PATH=$DesiredPath how to set command paths
SHELL SCRIPTING
1#!/bin/bash 2 echo -n "what is your name? " 3 read name 4 echo "hello, $name, nice to meet you" 5 exit 0
output
lab46:~$ ./src/unix/scripts/myscript.bash what is your name? Derek hello, Derek, nice to meet you
Useful Knoweledge For Bash Beginners
10 28, 2014
The bc command line calculator stands for binary calculator.
Here is my bash script that finds my average ect. with comments explaining my logic
#!/bin/bash #OPUS GRADE earned=`status unix|grep opus|cut -d':' -f1|grep '1'|wc -l` total=`status unix|grep opus|cut -d':' -f1|wc -l` average=`echo "scale=3; $earned/$total*100"|bc` average=`echo "scale=1; $average/1"|bc` #PROJECT GRADE earned2=`echo|status unix|grep '.:.'|grep -v 'opus:week'|cut -d':' -f1|grep '1'|wc -l` total2=`echo|status unix|grep '.:.'|grep -v 'opus:week'|wc -l` average2=`echo "scale=3; $earned2/$total2*100"|bc` average2=`echo "scale=1; $average2/1"|bc` #ATTENDANCE GRADE earned3=`status unix|grep dsoutha3|cut -d']' -f2|tr -d [X]|wc -w` total3=`status unix|grep dsoutha3|cut -d']' -f2|wc -w` average3=`echo "scale=3; $earned3/$total3*100"|bc` average3=`echo "scale=1; $average3/1"|bc` #TOTAL GRADE ta=`echo "$average+$average2+$average3"|bc` ta=`echo "scale=1; $ta/3"|bc` #PRINT TABLE printf "\nOPUS\tPROJECTS\tATTENDANCE\n =====================================\n $earned/$total\t$earned2/$total2\t\t$earned3/$total3\n $average\t$average2\t\t$average3\n =====================================\n TOTAL AVERAGE: $ta percent\n\n"
10 28, 2014
fopen
Some things we can do to files are open, read, write, append, create, remove/delete, and seek. We can do these things with the fopen function. This function has two parameters. p1 is for the path to filename, and p2 is for above mentioned thing to do. fopen returns a file pointer.
fgetc
From MAN: fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error. \n
int main() { char c,b; int i, count=0; FILE *fptr; //file data type. FILE *fptr2; fptr2=fopen("txtt.txt","a"); b=fgetc(fptr2); fprintf (fptr2, "hey"); fptr=fopen("text.txt","r");// assigns the adress of file to file pointer if(fptr==NULL)// checking if file exists and has permission rights. { fprintf(stdout,"No such file or directory\n"); exit(1); } while((c=fgetc(fptr))!=EOF) { //(c=fgetc(fptr));if i left this fgetc in I would get every othe char. // fgetc takes a file pointer for arg, so putting are fptr in the function and the declaring c as its val. this makes c = the first char in the file. Then, we loop getting the chars in the file until we get the end of the file fprintf(stdout,"%c",c); }//Then we printf all of the chars until the loop ends which is at end of file. fclose(fptr); //closing file return(0); }
int main (int argc, char * argv[]) { char chr, action; int wc=0,lc=0, cc=0,state; FILE *fptr;// declaring file pointer action = *(*(argv+2));// de-referencing argv2 twice and action setting it as the var actong get the charecter argument from the user. if (argc < 3)// checking if given args { fprintf(stderr, "You must specify agument(s)\n\nMAN PAGE\n\narg1\t\targ2\n======================\n\nFilename\tw\nFilename\tl\nFilename\tc\n\n======================\n\nw: counts words in file;\nl: counts lines in file;\nc: count charecters in file.\n\n"); exit(EXIT_FAILURE); //can use this or a non zero value for exit failure } fptr=fopen(argv[1],"r"); // setting the output of fopen which returns a fie pointer to file pointer. if (fptr == NULL)//check if file exists because fopen returns a value of NULL if the file isn't there or if you don't have the file permssions. { fprintf(stderr,"No such file or directory\n"); exit(EXIT_FAILURE); } while((chr=fgetc(fptr))!=EOF) //declaring chr as the charecters in the file until the file is empty. { cc++; // increment for every char if (chr=='\n') lc++; // increment ofr every new line if (chr==' '||chr=='\t'||chr=='\n') wc++;// increment every word } switch(action)// controll statement for which action was chosen by user { case 'w': fprintf(stdout,"%d words\n",wc); break; case 'l': fprintf(stdout,"%d lines\n",lc); break; case 'c': fprintf(stdout,"%d charecters\n",cc); break; } return(0); }
11 4, 14
Structures can't have functions, but they can have function pointers. Classes have member functions, but are only available in c++. Below, there is some code we wrote in the lab using creating a class named rectangle and using it.
class rectangle { public: // can be used outside of class int area(); int perimeter(); // member functions rectangle(); //function constructor, If class is instantiated (initiated) it runs automatically. rectangle(int,int); private: //can only be used in class int length; //member variables int width; }; int rectangle::area() //defining area as a member of the rectangle class { return((length*width)); } int rectangle::perimeter() //defining perimeter as a member of the rectangle class { return((length*2)+(width*2)); } rectangle::rectangle() { length=0; // looks in private, because there is no parameter. You variables and things you will need running in the constructor. width=0; } rectangle::rectangle(int length,int width) { this->length=length; // pointing at the class variables. this->width=width; } int main() { int area; int perimeter; area=0; perimeter=0; //declaring and defining the variables, then assigning them the value of 0 rectangle rect1; //defining an object rect1 from the rectangle class rectangle *rect2; //defining the object pointer, *rect2 rect2=new rectangle(4,10); //allocating memory from freestore using the key word "new" to create a pointer to my object. area=rect1.area();// assigning the value of the method area from tho object rect1 to the variable area. perimeter=rect1.perimeter(); // doing the same for method perimeter printf("rect1's area is %d\n",area); printf("rect1's perimeter is %d\n",perimeter); area=rect2->area();// assigns the output of the object pointer rect2 pointing to the method/member function area. perimeter=rect2->perimeter(); printf("rect2's area is %d\n",area); printf("rect2's perimeter is %d\n",perimeter); return(0); }
If there is a ~ before a function like, ~rectangle(); it is a destructor.
Access control
Don't forget that I am the designer for the class notes wiki.
11 4, 14
RegEx
Experimenting
Match lines with 4 or more chars that end with g
$ cat words|grep '...g'|wc -l
or
$ cat words|grep '^....*g'|wc -l
match lines with three or more only lower-case characters.
cat words|grep '^[a-z][a-z][a-z][a-z]*$'|wc -l
match all lines with at-least 3 or more lower-case vowels in it.
cat words|grep '^.*[aeiouy].*[aeiouy].*[aeiouy].*$'|wc -l
The .*'s Are for the possible characters in-between the vowels.
Extended RegEx
egrep for extended grep
match all of the lines that end with ed or ing,
cat words|egrep '(ed|ing)$'|wc -l
11 6, 14
sumbit unix statuscalc “scriptname”
Awesomeness with sed
lab46:~$ status unix|grep 'opus'|sed 's/^.*\([01]\):\([a-z][a-z]*\):\(week\)\([0-9]\)\(.*\)$/\5 for \3 \4 \2 [\1]/g'
lab46:~$ getent passwd| grep '^[djs]' | sed 's/^\([djs][a-z0-9]*\):x:\([0-9][0-9][0-9]
11 15, 14
LINKED NODE CODE FROM CLASS
#include <cstdio> #include "SinglyLinkedNode.h" int main() { int i; SinglyLinkedNode *start=NULL; SinglyLinkedNode *tmp=NULL; SinglyLinkedNode *tmp2=NULL; //setting up List of Singly Linked Nodes start=new SinglyLinkedNode(7); start->setNext(new SinglyLinkedNode(39)); tmp=start->getNext(); //inserting a new node tmp2=new SinglyLinkedNode(73); tmp2->setNext(start->getNext()); start->setNext(tmp2); //setting tmp to point to starting node tmp=start; //print out our list with a loop while (tmp!=NULL) { printf("%d->", tmp->getValue()); tmp=tmp->getNext(); } printf("NULL\n"); return (0); }
11 15, 14
[0-9]\):….:\(.*\):\/ho..*\(.*\).*$/\3 is user \1 with userid \2/g'\ for bash these variables are automatically made $# - count of arguments $* - all of your arguments “a b c” $0 - script name $1 - “a” $2 - “b” $3 - “c” man cron for status script every tuesday at 9 am put in tmp.
using last take command-line argument, or user input if no arg $1 will be the first arg if [$1 is not NULL] get user-name elif echo What user? Then get input and check if the user exists. Proceed only if it does. then for each month of the users semester determine -number of logins for the month in histogram form. -total time spent on the system that month in days, hours, and mins. Total logins for semester, total time for semester.
I came up with a pretty neat idea. Its a fun way to see how arrays are stored in adresses.
The program takes a string, preserves its contents by copying it, navigates through the copy usings the spaces, and prints out its string along with its acronym. It also prints the memory adresses in which each char of the acronym is located at. Therefore, it gives a visual of each address the acronym chars. are stored at increasing 1 byte per string char. from the last adress in the output.
Source-Code and sample
#include <stdio.h> #include <stdlib.h> void stringcopy(char*,char*); //declaring stringcopyfunction void getacr(char*); int main() { //int i=0; char string[50]; char copy[50]; printf("Type a string for an acronym: "); // storing string from command line to the array string fgets(string, sizeof(string), stdin); stringcopy(copy,string); //using string copy function i made(defined below) to get a copy of the string to preserve. fprintf(stdout,"\n\n%s\nACRONYM: ",string); getacr(copy);//using getacr function I made(defined below) to get acr of the copy. return(0); } void getacr(char* string) { printf("\n%c is at address of %p\n",*(string),(string)); while (*string!='\0') { string++; if ((*(string)==' ')||(*(string)=='-')) fprintf(stdout,"%c is at this address %p\n" ,*(string+1),(string+1)); } printf("\n"); //printf("%c",*(string)); //exit(0); } //printf("%c", *(copy+2)); void stringcopy(char *copy,char *string) //define stringcopy functions { while(*string!=EOF) // Loop while copy is not at string termination. { *copy=*string;//set the dereferenced value of string to copy then shift up to next adress space with next chat string++; copy++; } *copy='\0'; }
Sample
lab46:~/src/cscs1320-c$ ./acrAddress Type a string for an acronym: I Love The World Of Unix, And The Essence Of CSCI I Love The World Of Unix, And The Essence Of CSCI ACRONYM: I is at address of 0x7ffffdf70a60 L is at this address 0x7ffffdf70a62 T is at this address 0x7ffffdf70a67 W is at this address 0x7ffffdf70a6b O is at this address 0x7ffffdf70a71 U is at this address 0x7ffffdf70a74 A is at this address 0x7ffffdf70a7a T is at this address 0x7ffffdf70a7e E is at this address 0x7ffffdf70a82 O is at this address 0x7ffffdf70a8a C is at this address 0x7ffffdf70a8d
#!/bin/bash ########################################################################################################################################### # Program that calulates log-data, by: Derek Southard # #getting username from user user=$1 if [ "$#" -eq 0 ]; then echo -n "Enter A Username: " read user fi echo $user check=`id $user 2>/dev/null | wc -l` #checking if user exists if [ "$check" -eq 0 ]; then echo User does not exist. exit 113 fi #grep -c ^$1: /etc/passwd #0 if user doesn't exists, 1 if user does. declare -a month=("Aug" "Sep" "Oct" "Nov" "Dec" "..*") # Declaring array as variable month and assigning elements of the months then ..* to capture all of the months (regex pattern for 1 or more of anything. index=0 for index in {0..5} do echo ${month[$index]} if [ $index -gt 4 ]; then echo "Complete Semester" fi echo "<+:~+:~+:~+:~+>" #LO Logins during the month of current array element. LO=`last|grep "${month[$index]}"|grep "$user"|wc -l` #capturing all minutes spent logged in. AM=`last|grep "$user"|grep "${month[$index]}"|grep -v 'still'|cut -d'(' -f2|tr -d ')'|cut -d':' -f2|tr '\n' '+'|tr -d '/n'` AM=`echo $AM|tr -d ' '` AM=${AM::-1} AM=`echo $AM|bc` #echo $AM all minutes #all minutes only minutes H=`echo "scale=2; $AM/60"|bc|cut -d'.' -f1` #echo hours gained from mins $H #hours by itself gained from overflowed mins from mins M=`echo "scale=2; $AM/60"|bc|cut -d'.' -f2` M=`echo "scale=1; .$M*60/1"|bc` #echo $M minutes after overflow buffer #time in minutes after the overflow was buffered AH=`last|grep "$user"|grep "${month[$index]}"|grep -v 'still'|cut -d'(' -f2|tr -d ')'|cut -d':' -f1|tr '\n' '+'` AH=${AH::-1} #deletes last char because there was an extra + at the end of data due to new line translation. AH=`echo $AH|bc` #echo $AH only hours no overflow mins #All hours only hours w/o the overflow minutes EH=`echo "$AH+$H"|bc` #echo $EH hours added #All hours added together with overflow minutes D=`echo "scale=2; $EH/24"|bc|cut -d'.' -f1` #echo $D days #Complete amount of days using overflowed hours BH=`echo "scale=2; $EH/24"|bc|cut -d'.' -f2` BH=`echo "scale=1; .$BH*24/1"|bc` #echo $BH hours after days calculated #Hours after day buffer has taken overflow echo Logins: $LO Time logged in: $D Days, $BH Hours, and $M minutes. echo " " index=$index+1 done echo *HISTOGRAM* index=0 #embedded loop to print an = symbol for every login for every month. for index in {0..4} do j=0 LO=`last|grep "${month[$index]}"|grep "$user"|wc -l` printf "${month[$index]}: " while [ $j -lt $LO ]; do printf "=" let j=$j+1 done echo " $LO logins" printf "\n" done
dsoutha3 Aug <+:~+:~+:~+:~+> Logins: 20 Time logged in: 1 Days, 0 Hours, and 3.0 minutes. Sep <+:~+:~+:~+:~+> Logins: 124 Time logged in: 10 Days, 13.9 Hours, and 12.0 minutes. Oct <+:~+:~+:~+:~+> Logins: 113 Time logged in: 8 Days, 8.8 Hours, and 3.6 minutes. Nov <+:~+:~+:~+:~+> Logins: 41 Time logged in: 1 Days, 21.8 Hours, and 16.8 minutes. Dec <+:~+:~+:~+:~+> Logins: 7 Time logged in: Days, 9.8 Hours, and 3.6 minutes. .. Complete Semester <+:~+:~+:~+:~+> Logins: 305 Time logged in: 22 Days, 6.9 Hours, and 39.6 minutes. *HISTOGRAM* Aug: ==================== 20 logins Sep: ============================================================================================================================ 124 logins Oct: ================================================================================================================= 113 logins Nov: ========================================= 41 logins Dec: ======= 7 logins