<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Population</title>
</head>

<body>



<p align="center"><span lang="en-ca"><b><font size="6" color="#FF0000">Directory 
Viewer---</font></b><font size="5" color="#FF0000"><b>makefile</b></font></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A.<span lang="en-ca">Third</span> Edition</font></b></pre>
</div>
<div align="left">
  <pre><b>This is <span lang="en-ca">third edition of fifth</span> assignment of <span lang="en-ca">comp229. And there is some improvement such as the mode of file will</span></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>be displayed as &quot;ls&quot; does. Also a makefile makes compiling automatic. </b></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left">
  <font FACE="CenturySchoolbook-BoldItalic" SIZE="3"><i><b></b></i></font>
  <pre>　</pre>
</div>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  　</div>
<div align="left">
  <span lang="en-ca"><font color="#0000FF">1. How to make makefile? Makefile is 
  simply a script file specifying two things:</font></span></div>
<div align="left">
  <span lang="en-ca"><font color="#0000FF">&nbsp;&nbsp;&nbsp; Which file is 
  depending which file and how should do with each file.</font></span></div>
<div align="left">
  <span lang="en-ca"><font color="#0000FF">2. The file you specify is followed 
  with a &quot;:&quot; and behind &quot;:&quot; is the file it depends on.</font></span></div>
<div align="left">
  <span lang="en-ca"><font color="#0000FF">3. The label is also the file name.</font></span></div>
<div align="left">
  <span lang="en-ca"><font color="#0000FF">4. If you are using &quot;echo&quot;, make sure 
  you quote what you want to display.</font></span></div>
<div align="left">
  <span lang="en-ca"><font color="#0000FF">5. Setenv won't work, you have to 
  specify library path independently.</font></span></div>
<div align="left">
  　</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">C</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre>　</pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="4" color="#FF0000"><b>//this is main program: main.c</b></font></span></pre>
</div>
<pre>#include &lt;stdio.h&gt;

extern char* prompt;
//these are my own defined utility functions 
//this check the command of &quot;dl&quot; and &quot;cd&quot; then send all rest 
//arguments to &quot;checkOptions()&quot; 
extern int checkCmd(char* cmd);
 
//get user input string from keyboard and store in the parameter
extern int input(char* str);


int main()
{
	char str[256];
	write(0, prompt, strlen(prompt));
	//input will only return 0 unless &quot;exit&quot; met
	while (input(str))
	{
		checkCmd(str);	
		write(0, prompt, strlen(prompt));
	}
		
	return 0;
}
</pre>
<pre></pre>
<pre><span lang="en-ca"><font size="4" color="#FF0000"><b>//this is static library program: staticLib.c</b></font></span></pre>
<pre>////////////////////////////////////////////////////////////////////////////
//program: Assignment 3 of comp229
//author: Qingzhe Huang
//ID: 5037735
//date: Oct. 24, 2003
//purpose of program: to use system call to implement &quot;dv&quot; directory viewer
///////////////////////////////////////////////////////////////////////////// 


#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt; 
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt; 
#include &lt;strings.h&gt; 
#include &lt;unistd.h&gt; 
#include &lt;dirent.h&gt; 
#include &lt;time.h&gt;
//#include &lt;fcntl.h&gt;


//these are all functions defined in assignment and
//would be linked dynamically
extern int SelectMonth(char* month);
extern int ChangeDir(char* dir);
extern int GetAllFiles();
extern int RemoveHidden();
extern int SelectRange(char* begin, char* end);
extern int SelectDate(int date);
extern int SelectBigger(int size);
extern int SelectSmaller(int size);
extern void PrintList(char* sortby);

int sortIndex = 0;
extern int errno;
char* sortedBy[3] = {&quot;name&quot;, &quot;date&quot;, &quot;size&quot;};

enum SortBy
{ByName, ByDate, BySize};

//a record to store file info
struct FileInfo
{
	char name[31];
	char perm[10];
	long size;
	time_t  mdate;
} fileInfo[1024];

//the fileInfo counter
int infoCount =0;

//fileList stores the file index interested by user
int fileList[1024]={0};
//this is its counter
int listCount =0;




//the parameter for &quot;SelectRange()&quot;
char beginStr[2];
char endStr[2];

//flag for &quot;GetAllFiles()&quot;, 1 means re-read all files which is 
//default, until set to 0 by &quot;cd&quot; parameter
int reRead=1;

//a simple way to change string to index, is it faster than MIA's little
//switch function &quot;MonToStr&quot;?
char* months[12] = {&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, &quot;Apr&quot;, &quot;May&quot;, &quot;Jun&quot;, &quot;Jul&quot;, &quot;Aug&quot;, 
	&quot;Sep&quot;, &quot;Oct&quot;, &quot;Nov&quot;, &quot;Dec&quot;};

//the command prompt for our &quot;directory viewer&quot;
char* prompt = &quot;mydv: &quot;;

//this is the directory name, cause I need to display several times
//in different functions, I have to make it global.
char buffer[256];



//these are my own defined utility functions 
//this check the command of &quot;dl&quot; and &quot;cd&quot; then send all rest 
//arguments to &quot;checkOptions()&quot; 
int checkCmd(char* cmd);
 
//this will collect user input lines until &quot;exit&quot; int input(char* str); 
//check all options and call each &quot;selection&quot; functions by options accordingly 
int checkOptions(char** options, int count); 



//get user input string from keyboard and store in the parameter
int input(char* str);


int input(char* str)
{
	char* ptr = str;
	while (1)
	{
		read(0, ptr, 1);
		if (*ptr==10)
		{
			break;
		}
		ptr++;
	}
	*ptr = '\0';
	return strcmp(str, &quot;exit&quot;);
}


int checkCmd(char* cmd)
{
	char* ptr = cmd;
	//is there any limit for command line parameters? Yes, I said it is 20
	//who would say no????:)
	char* options[20];
	int count = 0, i;
	pid_t pid=0;
	//if user enters nothing, it is not NULL!!!
	if (!strcmp(cmd, &quot;&quot;))
	{
		return 0;
	}
	//\n should also be delimiter
	while (options[count]=strtok(ptr, &quot; \n&quot;))
	{
		ptr = NULL;
		count++;
	}
	//then we can pass options as char**
	options[count] = NULL; //just make sure it is null at end
	//the maximum and minimum of parameters
	if (count&lt;=11&amp;&amp;count&gt;=2)
	{
		if (!strcmp(options[0], &quot;cd&quot;))
		{
			//I won't check all other parameters
			if (ChangeDir(options[1])==1)
			{
				reRead =1;//need re-Getallfiles
				return 1;
			}
			else
			{
				return -1;
			}
		}
		if (!strcmp(options[0], &quot;dl&quot;))
		{
			if (reRead)
			{
				GetAllFiles();
				//make sure all files will be read only once with 
				//multiple &quot;dl&quot;
				reRead =0;
			}
			//passing char** 
			return checkOptions(&amp;options[1], count-1);
		
		}
	}
	
	//fork another process to execute whatever user input
	if ((pid = fork())==0)
	{
		execvp(options[0], options);
		printf(&quot;%s\n&quot;, strerror(errno));
		exit(-1);
	}
	//waiting utill user returns...
	wait(NULL);
	return 1;

}




int checkOptions(char** options, int count)
{
	int i=0;
	int result=0;
	int removeHidden=1;
	char string[256];
	//make sure there is any file
	while (i&lt;count&amp;&amp;listCount)
	{
		if (!strcmp(options[i], &quot;-range&quot;))
		{
			if (i+1&lt;count)
			{
				//since it is only a character
				beginStr[0] = options[i+1][0];
				beginStr[1] = '\0';
				endStr[0] = options[i+1][2];
				endStr[1] = '\0';

				listCount=SelectRange(beginStr, endStr);
				i+=2;	
				continue;
			}	
			else
			{
				printf(&quot;%s\n&quot;, &quot;missing parameter for -range options&quot;);
				return -1;
				
			}
		}
		if (!strcmp(options[i], &quot;-modified&quot;))
		{
			if (i+1&lt; count)
			{
				//this is for month
				listCount=SelectMonth(options[i+1]);
				i+=2;
			}
			else
			{
				printf(&quot;%s\n&quot;, &quot;missing parameter for -modified options&quot;);
			    return -1;
			}

			if (i&lt;count)
			{
				if (strcmp(options[i], &quot;-all&quot;)&amp;&amp;strcmp(options[i], &quot;-range&quot;)
					&amp;&amp;strcmp(options[i], &quot;-biggerthan&quot;)&amp;&amp;strcmp(options[i],&quot;-smallerthan&quot;))
				{
					listCount=SelectDate(atoi(options[i]));
					i++;
				}
			}
			continue;
		}	
			
		if (!strcmp(options[i], &quot;-biggerthan&quot;))
		{
			if (i+1&lt;count)
			{
				listCount = SelectBigger(atoi(options[i+1]));
				i+=2;
				continue;
			}
			else
			{
				printf(&quot;%s\n&quot;, &quot;missing parameter for -biggerthan options&quot;);
				return -1;
			}
		}

		if (!strcmp(options[i], &quot;-smallerthan&quot;))
		{
			if (i+1&lt;count)
			{
				listCount=SelectSmaller(atoi(options[i+1]));
				i+=2;
				continue;
			}
			else
			{
				printf(&quot;%s\n&quot;, &quot;missing parameter for -smallerthan options&quot;);
				return -1;
			}					
		}

		if (!strcmp(options[i], &quot;-all&quot;))
		{
			removeHidden=0;
			i++;
			sortIndex = ByName;
			continue;
		}
		if (i==0)
		{
			printf(&quot;%s\n&quot;, &quot;invalide parameter!&quot;);
			return -1;
		}
		i++;
	}
	if (removeHidden)
	{
		listCount = RemoveHidden();
		
	}
	//if there is no more files,
	if (!listCount)
	{
		//I cannot understand why printf doesn't work properly
		//it won't display until the function returns, so I have to 
		//use system call &quot;write&quot; which is very fast
		strcpy(string, &quot;Directory &quot;);
		strcat(string, buffer);
		strcat(string, &quot; does not contain any files.\n&quot;);
		write(0, string, strlen(string));
//		printf(&quot;Directory %s does not contain any files.&quot;, buffer);
	}
	else
	{
		PrintList(sortedBy[sortIndex]);
		return result;
	}
}

</pre>
<pre>　</pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre>		</pre>

<pre><span lang="en-ca"><font size="4" color="#FF0000"><b>//this is dynamic library program: dynamicLib.c</b></font></span></pre>

<pre>　</pre>

<pre>#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt; 
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt; 
#include &lt;strings.h&gt; 
#include &lt;unistd.h&gt; 
#include &lt;dirent.h&gt; 
#include &lt;time.h&gt;

struct FileInfo
{
	char name[31];
	char perm[10];
	long size;
	time_t  mdate;
};

extern int fileList[1024];
extern int errno;
extern struct FileInfo fileInfo[1024];
extern int infoCount;
extern int listCount;
extern char* months[12];
extern char buffer[256];

//these are all functions defined in assignment
int SelectMonth(char* month);
int ChangeDir(char* dir);
int GetAllFiles();
int RemoveHidden();
int SelectRange(char* begin, char* end);
int SelectDate(int date);
int SelectBigger(int size);
int SelectSmaller(int size);
void PrintList(char* sortby);


short octArray[9]={0400,0200,0100,0040,0020,0010,0004,0002,0001};
char permStr[10]= &quot;rwxrwxrwx&quot;;


enum SortBy
{ByName, ByDate, BySize};

//parameter for &quot;PrintList()&quot; to indicate what field to be sorted by

//the actual enum SortBy variable for index of &quot;sortedBy[3]&quot;
extern int sortIndex;
extern char* sortedBy[3];

//a utility function does the printing job 
int printInfo();
void setPermStr(struct stat* s, char* perm);


//three callback function for &quot;qsort&quot;
int compName(const void*, const void*);
int compDate(const void*, const void*);
int compSize(const void*, const void*);

//a function pointer array so as to be used in &quot;qsort&quot;
int (*compFuns[3])(const void*, const void*) = {compName, compDate, compSize};


void setPermStr(struct stat* s, char* perm)
{
	int i;
	for (i=0; i&lt;9; i++)
	{
		if (s-&gt;st_mode&amp;octArray[i])
		{
			perm[i]=permStr[i];
		}
		else
		{
			perm[i]='-';
		}
	}
	perm[9]='\0';
}


int ChangeDir(char* dir)
{
	int temp =0;
	if ((temp=chdir(dir))==-1)
	{
		printf(&quot;Directory %s does not exist.\n&quot;, dir);
		return -1;
	}
	else
	{		
		return 1;

	}
}


int GetAllFiles()
{
	char fileName[256];
	DIR *dp=NULL;
	struct dirent *d;
	struct stat s;
	
	//maybe MIA's way is simple---dir = &quot;.&quot;;
	if (!(dp = opendir(getcwd(buffer, 256))))
	{
		printf(&quot;%s\n&quot;, strerror(errno));
		return -1;
	}
	//strcat(buffer, buffer[strlen(buffer)]=='/'?&quot;&quot;:&quot;/&quot;);
	infoCount=listCount=0;
	while (d=readdir(dp))
	{
		if (stat(d-&gt;d_name, &amp;s)==-1)
		{
			printf(&quot;cannot access file %s\n&quot;, d-&gt;d_name);
			continue;
		}
		else
		{
			//we shall not select directories
			if (S_ISDIR(s.st_mode))
			{
				continue;
			}
		}
		
		if (d-&gt;d_ino!=0)
		{
			//strcpy(fileInfo[infoCount].name, buffer);
			//printf(&quot;%s\n&quot;, d-&gt;d_name);
			if (stat(d-&gt;d_name, &amp;s)!=-1)
			{
				strcpy(fileInfo[infoCount].name, d-&gt;d_name);
				fileInfo[infoCount].size = s.st_size;
				fileInfo[infoCount].mdate = s.st_mtime;
				setPermStr(&amp;s, fileInfo[infoCount].perm);
				infoCount++;
				fileList[listCount]=listCount; //means there is an index to...
				listCount++;				
			}
				
		}
	}
	return infoCount;			
}

int printInfo()
{
	int i=0;
	char str[23];
	struct tm* t;
	for (i=0; i&lt;listCount; i++)
	{
		printf(&quot;%s&quot;, fileInfo[fileList[i]].perm);
		t = gmtime(&amp;fileInfo[fileList[i]].mdate);
		sprintf(str, &quot;%s %02d, %4d; %02d:%02d:%02d&quot;, months[t-&gt;tm_mon], t-&gt;tm_mday, 
			t-&gt;tm_year + 1900, 	t-&gt;tm_hour, t-&gt;tm_min, t-&gt;tm_sec);
		
		printf(&quot;  %8d   %s %-30s \n&quot;, fileInfo[fileList[i]].size, str, fileInfo[fileList[i]].name);
	}
}

int SelectMonth(char* month)
{
	int i, temp=0;
	int imonth=0;//the month
	//find out the index of month
	for (i=0; i&lt;12; i++)
	{
		if (!strcmp(month, months[i]))
		{
			imonth=i;
			break;
		}
	}

	for (i=0; i&lt;listCount; i++)
	{
		if (gmtime(&amp;fileInfo[fileList[i]].mdate)-&gt;tm_mon==imonth)
		{
			fileList[temp]=fileList[i];
			temp++;
		}
		
	}
	listCount = temp;
	sortIndex = ByDate;
	return listCount;
}		
		
int RemoveHidden()
{
	int i, temp=0;
	for (i=0; i&lt;listCount; i++)
	{	
		if (fileInfo[fileList[i]].name[0]!='.')
		{
			fileList[temp]=fileList[i];
			temp++;
		}
		
	}
	listCount=temp;
	return listCount;
}		

int SelectBigger(int size)
{
	int i, temp=0;
	for (i=0; i&lt;listCount; i++)
	{	
		if (fileInfo[fileList[i]].size&gt;=size)
		{
			fileList[temp]=fileList[i];
			temp++;
		}		
	}
	listCount =temp;
	sortIndex = BySize;
	return listCount;
}

int SelectSmaller(int size)
{
	int i, temp=0;
	for (i=0; i&lt;listCount; i++)
	{	
		if (fileInfo[fileList[i]].size&lt;=size)
		{
			fileList[temp]=fileList[i];
			temp++;
		}		
	}
	listCount =temp;
	sortIndex = BySize;
	return listCount;
}
	
int SelectRange(char* begin, char* end)
{
	int i, temp=0;
	char* ptr;
	for (i=0; i&lt;listCount; i++)
	{	
		if (fileInfo[fileList[i]].name[0]=='.')
		{
			ptr = fileInfo[fileList[i]].name + 1;
		}
		else
		{
			ptr = fileInfo[fileList[i]].name;
		}
		//so it uses the first character to compare 
		if (ptr[0]&gt;=begin[0]&amp;&amp;ptr[0]&lt;=end[0])
		{
			fileList[temp]=fileList[i];
			temp++;
		}

/*
		if (strcmp(ptr, begin)&gt;=0
			&amp;&amp;strcmp(ptr, end)&lt;=0)
		{
			fileList[temp]=fileList[i];
			temp++;
		}		
		*/
	}
	listCount =temp;
	sortIndex = ByName;
	return listCount;
}

//this is mad! I already defined an enum type global variable to 
//indicate what should by sorted, however, I was forced to pass a 
//string instead of an enum index which I need to use a loop to find out!!!
void PrintList(char* sortby)
{
	int i=0;
	int (*comp)(const void*, const void*);//comp function pointer
	for (i=0; i&lt;3; i++)
	{
		if (!strcmp(sortby, sortedBy[i]))
		{
			comp = compFuns[i];
			break;
		}
	}
	
	qsort(fileList, listCount, sizeof(int), comp);
	printInfo();
}


int SelectDate(int date)
{
	int i, temp=0;
	for (i=0; i&lt;listCount; i++)
	{
		if (gmtime(&amp;fileInfo[fileList[i]].mdate)-&gt;tm_mday==date)
		{
			fileList[temp]=fileList[i];
			temp++;
		}
		
	}
	listCount = temp;
	sortIndex = ByDate;
	return listCount;
}



//the help for UNIX is so BAAAAAAAAAAD that they give a wrong example
//which won't work under gcc which doesn't allow modify const pointer!!!!
int compName(const void*first, const void*second)
{
	//int* pi = first, *pj = second;
	//int i = *pi;
	//int j = *pj;
	int i = *((int*)first);
	int j = *((int*)second);
	return strcmp(fileInfo[i].name, fileInfo[j].name);

}


//this is the bug place
int compDate(const void*first, const void*second)
{
	int tempi = *((int*)first);  //is it strange?
	int tempj = *((int*)second);//is it strange?
	long i=fileInfo[tempi].mdate;
	long j=fileInfo[tempj].mdate;

	if ( i&lt; j)
	{
		return -1;
	}
	else
	{
		if (i&gt;j)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
}

int compSize(const void*first, const void*second)
{
	int pi = *((int*)first);
	int pj = *((int*)second);
	
	int i=fileInfo[pi].size;
	int j=fileInfo[pj].size;
	
	if ( i&lt; j)
	{
		return -1;
	}
	else
	{
		if (i&gt;j)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
}

</pre>

<pre><span lang="en-ca"><font size="4" color="#FF0000"><b>//this is makefile: makefile</b></font></span></pre>

<pre>all:dynamic.a mydv
	@echo &quot;make complete.&quot;
dynamic.a : dynamicLib.c
	@echo &quot;compiling dynamic library...&quot;
	gcc -shared -fPIC dynamicLib.c -o dynamic.a
mydv : main.c static.a
	@echo &quot;creating executable program(mydv) ...&quot;
	gcc main.c static.a dynamic.a -o mydv
static.a : static.o
	@echo &quot;creating static library(static.a)...&quot;
	ar rcs static.a static.o
static.o:staticLib.c
	@echo &quot;compiling static library(static.o)...&quot;
	gcc -c staticLib.c -o static.o
clear : 
	rm *.a *.o mydv</pre>

<pre>　</pre>

<pre>　</pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp; <a href="WhoAmI.htm">                  







                       <img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35">          


</p>

</body>

</html>