An Example of a Remote Directory Service Using Exec
#include "funcs.h"
#define PACKET 256
#define DIR_WONT_OPEN '\01'
#define ILLEGAL_DIR '\02'
#define TERMINATOR '\06'
#define QUIT "\07"
int active;
main()
{
char *dirname, filename[PACKET], packet[PACKET];
char *PromptAndGetResponse(void);
int MakeSocket(void);
int readn(int fd, char *buf, int bytes),
writen(int fd, char *buf, int bytes);
void SetUpSIGNALS(void);
void WriteQuit(void);
FILE *more;
atexit(WriteQuit);
active = MakeSocket();
SetUpSIGNALS();
while(dirname = PromptAndGetResponse(),
dirname ? strcmp(dirname, "quit") : 1)
{
if (!dirname) continue;
memset(packet, 0, PACKET);
strcpy(packet, dirname);
writen(active, packet, 1);
writen(active, packet + 1, PACKET - 1);
more = Popen("more", "w");
memset(filename, 0, PACKET);
alarm(50);
while(readn(active, filename, PACKET), *filename != TERMINATOR)
{
switch (*filename)
{
case DIR_WONT_OPEN:
fprintf(more, "Could not open %s.\n\n", dirname);
break;
case ILLEGAL_DIR:
fprintf(more, "Illegal search of %s!\n\n", dirname);
break;
default: fprintf(more, "%s\n", filename);
}
alarm(0);
memset(filename, 0, PACKET);
}
Pclose(more);
}
WriteQuit();
}
int MakeSocket(void)
{
struct sockaddr_in sin;
int active;
active = Socket(AF_INET, SOCK_STREAM, 0);
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_port = htons(3123);
sin.sin_family = AF_INET;
Inet_aton("153.18.17.12", &sin.sin_addr);
Connect(active, (struct sockaddr *) &sin, sizeof(sin));
return active;
}
void SetUpSIGNALS(void)
{
void handler(int sigtype);
struct sigaction sa;
Sigfillset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
Sigaction(SIGALRM, &sa, NULL);
Sigaction(SIGPIPE, &sa, NULL);
}
void handler(int signum)
{
void WriteQuit(void);
printf("Server disconnected!\n");
WriteQuit();
exit(0);
}
char *PromptAndGetResponse(void)
{
static char buf[PACKET];
char *token;
printf("Enter directory: ");
fgets(buf, PACKET, stdin);
token = strtok(buf, "\040\t\n");
if (!token) return NULL;
if (strtok(NULL, "\040\t\n"))
{
printf("Excess parameters! Try again!\n\n");
return NULL;
}
return token;
}
int readn(int active, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(active,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
break; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
int writen(int active, char *buf, int bytes)
{
int nleft;
int nwritten;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nwritten = write(active,mover,nleft)) < 0)
return -1; /**** Error!! ****/
nleft -= nwritten;
mover += nwritten;
}
return bytes;
}
void WriteQuit(void)
{
char packet[PACKET];
memset(packet, 0, PACKET);
strcpy(packet, QUIT);
writen(active, packet, 1);
writen(active, packet + 1, PACKET - 1);
}
#include "funcs.h"
#define PACKET 256
main()
{
int passive, active, clilen = sizeof(struct sockaddr_in);
pid_t pid;
struct sigaction sa;
struct sockaddr_in client;
char actives[PACKET];
int SocketSetup(void);
void SetUpSIGCHLD(void);
passive = SocketSetup();
SetUpSIGCHLD();
for (;;)
{
active = accept(passive, (struct sockaddr *) &client,
&clilen);
if (active < 0)
{
if (errno == EINTR) continue;
else
{
perror("accept");
exit(0);
}
}
pid = Fork();
if (pid > 0) /** Parent **/
{
Close(active);
continue;
}
else /** Child **/
{
Close(passive);
sprintf(actives, "%d", active);
if (execlp("getfiles", "getfiles", actives, NULL) < 0)
{
perror("execl");
exit(0);
}
exit(0);
}
}
}
int SocketSetup(void)
{
int passive;
struct sockaddr_in sin;
passive = Socket(AF_INET, SOCK_STREAM, 0);
sin.sin_port = htons(3123);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
Bind(passive, (struct sockaddr *) &sin, sizeof(sin));
Listen(passive, 20);
return passive;
}
void SetUpSIGCHLD(void)
{
struct sigaction sa;
void handler(int signum);
Sigfillset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
Sigaction(SIGCHLD, &sa, NULL);
}
void handler(int signum)
{
int status;
while(waitpid(-1, &status, WNOHANG) > 0) {}
}
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
return 0; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
#include "funcs.h"
#define PACKET 256
main()
{
int passive, active, clilen = sizeof(struct sockaddr_in);
pid_t pid;
struct sigaction sa;
struct sockaddr_in client;
char actives[PACKET];
int SocketSetup(void);
void SetUpSIGCHLD(void);
passive = SocketSetup();
SetUpSIGCHLD();
for (;;)
{
active = accept(passive, (struct sockaddr *) &client,
&clilen);
if (active < 0)
{
if (errno == EINTR) continue;
else
{
perror("accept");
exit(0);
}
}
pid = Fork();
if (pid > 0) /** Parent **/
{
Close(active);
continue;
}
else /** Child **/
{
Close(passive);
sprintf(actives, "%d", active);
if (execlp("getfiles", "getfiles", actives, NULL) < 0)
{
perror("execl");
exit(0);
}
}
}
}
int SocketSetup(void)
{
int passive;
struct sockaddr_in sin;
passive = Socket(AF_INET, SOCK_STREAM, 0);
sin.sin_port = htons(3123);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
Bind(passive, (struct sockaddr *) &sin, sizeof(sin));
Listen(passive, 20);
return passive;
}
void SetUpSIGCHLD(void)
{
struct sigaction sa;
void handler(int signum);
Sigfillset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
Sigaction(SIGCHLD, &sa, NULL);
}
void handler(int signum)
{
int status;
while(waitpid(-1, &status, WNOHANG) > 0) {}
}
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
return 0; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
#include "funcs.h"
#define PACKET 256
#define MAXFILES 100000
#define DIR_WONT_OPEN "\01"
#define ILLEGAL_DIR "\02"
#define TERMINATOR "\06"
#define QUIT '\07'
int main(int argc, char **argv)
{
char **GetFilesInDir(char *dirname), **files, **mover, dirname[PACKET];
char packet[PACKET];
int active;
void SetUpSignals(void);
active = atoi(argv[1]);
SetUpSignals();
while(alarm(20), readn(active, dirname, PACKET),
*dirname != QUIT)
{
alarm(0);
files = GetFilesInDir(dirname);
mover = files;
while (strcmp(*mover, TERMINATOR) != 0)
{
memset(packet, 0, PACKET);
strcpy(packet, *mover);
writen(active, packet, 1);
writen(active, packet + 1, PACKET - 1);
mover++;
}
memset(packet, 0, PACKET);
strcpy(packet, TERMINATOR);
writen(active, packet, 1);
writen(active, packet + 1, PACKET - 1);
for (mover = files; strcmp(*mover, TERMINATOR) != 0; mover++)
free(*mover);
}
}
void SetUpSignals(void)
{
void handler(int signum);
struct sigaction sa;
Sigfillset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
Sigaction(SIGPIPE, &sa, NULL);
Sigaction(SIGALRM, &sa, NULL);
}
/**** The exec'ed program ****/
char **GetFilesInDir(char *dirname)
{
DIR *dptr;
struct dirent *fname;
static char *filenames[MAXFILES];
char **mover = filenames, packet[PACKET], curdir[PACKET], newdir[PACKET];
int compare(const void *, const void *), count;
getcwd(curdir, PACKET); /** Where I am!! **/
if (chdir(dirname) < 0)
{
filenames[0] = (char *) Malloc(2);
strcpy(filenames[0], DIR_WONT_OPEN);
filenames[1] = (char *) Malloc(2);
strcpy(filenames[1], TERMINATOR);
Chdir(curdir);
return filenames;
}
getcwd(newdir, PACKET); /** My new dir after the chdir!! **/
if (strstr(newdir, curdir) != newdir || (newdir[strlen(curdir)] != '\0'
&& newdir[strlen(curdir)] != '/'))
{
filenames[0] = (char *) Malloc(2);
strcpy(filenames[0], ILLEGAL_DIR);
filenames[1] = (char *) Malloc(2);
strcpy(filenames[1], TERMINATOR);
Chdir(curdir);
return filenames;
}
Chdir(curdir);
if ((dptr = opendir(dirname)) == NULL)
{
filenames[0] = (char *) Malloc(2);
strcpy(filenames[0], DIR_WONT_OPEN);
filenames[1] = (char *) Malloc(2);
strcpy(filenames[1], TERMINATOR);
return filenames;
}
count = 0;
mover = filenames;
while(fname = readdir(dptr))
{
*mover = (char *) Malloc(strlen(fname->d_name) + 1);
strcpy(*mover, fname->d_name);
mover++;
count++;
}
Closedir(dptr);
qsort(filenames, (size_t) count, sizeof(char *), compare);
filenames[count] = (char *) Malloc(2);
strcpy(filenames[count], TERMINATOR);
return filenames;
}
int compare(const void *fname1, const void *fname2)
{
char **f1 = (char **) fname1, **f2 = (char **) fname2;
return strcmp(*f1, *f2);
}
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
else if (nread == 0)
return 0; /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
int writen(int fd, char *buf, int bytes)
{
int nleft;
int nwritten;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nwritten = write(fd,mover,nleft)) < 0)
return -1; /**** Error!! ****/
nleft -= nwritten;
mover += nwritten;
}
return bytes;
}
void handler(int signum)
{
exit(0);
}
/**************************** Sessions With Server **************************/
$ s&
[1] 4943
$ c
Enter directory:
Enter directory: sub1
Could not open sub1.
Enter directory: sub1dir
.
..
a
b
c
Enter directory: ../demos
Illegal search of ../demos!
Enter directory: ../homework
.
..
2c
2gc
2gc.c
2gs
2gs.c
4c.c
4gc.c
4gs.c
4s.c
a.out
a1.dat
asg1
asg1.answer
asg1.c
asg1.demo
asg1.log
asg1.out
asg1b
asg1b.c
asg1b.demo
[7m--More--[m[K
Enter directory: ../exams
Illegal search of ../exams!
Enter directory: sub2
.
..
d
e
f
Enter directory:
[2]+ Stopped c /* CTRL-Z */
$ c /* New client */
Enter directory: sub1
Could not open sub1. /* Same old error */
Enter directory: sub1dir
.
..
a
b
c
Enter directory: quit
$ fg
c
foo
Could not open foo. /* Old client still alive! */
Enter directory: ../foo
Could not open ../foo.
Enter directory: ../demos
Illegal search of ../demos!
Enter directory: quit
$ c
Enter directory: sub1dir
.
..
a
b
c
Enter directory: hello
Could not open hello.
Enter directory: hello
Server disconnected! /* Alarmed out by server */