├── .gitignore
├── scott.jpg
├── Makefile
├── page2.html
├── index.html
├── README.md
└── server.c
/.gitignore:
--------------------------------------------------------------------------------
1 | #Don't upload log files
2 | *.log
3 |
--------------------------------------------------------------------------------
/scott.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labcoder/simple-webserver/HEAD/scott.jpg
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for server
2 | server: server.c
3 | gcc server.c -o server
4 |
5 |
--------------------------------------------------------------------------------
/page2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Oscar's web server example
4 |
5 |
6 | PAGE 2
7 |
8 | This is page 2! Welcome :)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Oscar's web server example
4 |
5 |
6 | Welcome to the default homepage!
7 |
8 | Here's an image of scott pilgrim... he's really cool and you can learn about him here.
9 |
10 |
11 | Just some basic default page. For another page... go here.
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Simple webserver
3 | This example of a simple webserver is inspired by IBM's really small webserver example, nweb.
4 |
5 | Uses
6 | This is obviously not meant to be used for real deployment, and is just out here in case someone wants to see a small c-based webserver in use. Basic socket use examples are in here from nweb. Also included are two small pages to serve up.
7 |
8 | Example
9 | Run the Makefile
10 | make
11 | You run the server like this:
12 | ./server [port] [location to serve pages from] [& - to run in background]
13 | For example, to run it on port 8080, you'd do something like this:
14 | ./server 8080 ./ &
15 |
16 |
--------------------------------------------------------------------------------
/server.c:
--------------------------------------------------------------------------------
1 | /*
2 | * project: miniweb
3 | * author: Oscar Sanchez (oms1005@gmail.com)
4 | * HTTP Server
5 | * WORKS ON BROWSERS TOO!
6 | * Inspired by IBM's nweb
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #define BUFSIZE 8096
22 | #define ERROR 42
23 | #define SORRY 43
24 | #define LOG 44
25 |
26 | struct {
27 | char *ext;
28 | char *filetype;
29 | } extensions [] = {
30 | {"gif", "image/gif" },
31 | {"jpg", "image/jpeg"},
32 | {"jpeg","image/jpeg"},
33 | {"png", "image/png" },
34 | {"zip", "image/zip" },
35 | {"gz", "image/gz" },
36 | {"tar", "image/tar" },
37 | {"htm", "text/html" },
38 | {"html","text/html" },
39 | {"php", "image/php" },
40 | {"cgi", "text/cgi" },
41 | {"asp","text/asp" },
42 | {"jsp", "image/jsp" },
43 | {"xml", "text/xml" },
44 | {"js","text/js" },
45 | {"css","test/css" },
46 |
47 | {0,0} };
48 |
49 | void log(int type, char *s1, char *s2, int num)
50 | {
51 | int fd ;
52 | char logbuffer[BUFSIZE*2];
53 |
54 | switch (type) {
55 | case ERROR: (void)sprintf(logbuffer,"ERROR: %s:%s Errno=%d exiting pid=%d",s1, s2, errno,getpid()); break;
56 | case SORRY:
57 | (void)sprintf(logbuffer, "Web Server Sorry: %s %s
\r\n", s1, s2);
58 | (void)write(num,logbuffer,strlen(logbuffer));
59 | (void)sprintf(logbuffer,"SORRY: %s:%s",s1, s2);
60 | break;
61 | case LOG: (void)sprintf(logbuffer," INFO: %s:%s:%d",s1, s2,num); break;
62 | }
63 |
64 | if((fd = open("server.log", O_CREAT| O_WRONLY | O_APPEND,0644)) >= 0) {
65 | (void)write(fd,logbuffer,strlen(logbuffer));
66 | (void)write(fd,"\n",1);
67 | (void)close(fd);
68 | }
69 | if(type == ERROR || type == SORRY) exit(3);
70 | }
71 |
72 | void web(int fd, int hit)
73 | {
74 | int j, file_fd, buflen, len;
75 | long i, ret;
76 | char * fstr;
77 | static char buffer[BUFSIZE+1];
78 |
79 | ret =read(fd,buffer,BUFSIZE);
80 | if(ret == 0 || ret == -1) {
81 | log(SORRY,"failed to read browser request","",fd);
82 | }
83 | if(ret > 0 && ret < BUFSIZE)
84 | buffer[ret]=0;
85 | else buffer[0]=0;
86 |
87 | for(i=0;i 0 ) {
129 | (void)write(fd,buffer,ret);
130 | }
131 | #ifdef LINUX
132 | sleep(1);
133 | #endif
134 | exit(1);
135 | }
136 |
137 |
138 | int main(int argc, char **argv)
139 | {
140 | int i, port, pid, listenfd, socketfd, hit;
141 | size_t length;
142 | static struct sockaddr_in cli_addr;
143 | static struct sockaddr_in serv_addr;
144 |
145 | if( argc < 3 || argc > 3 || !strcmp(argv[1], "-?") ) {
146 | (void)printf("usage: server [port] [server directory] &"
147 | "\tExample: server 80 ./ &\n\n"
148 | "\tOnly Supports:");
149 | for(i=0;extensions[i].ext != 0;i++)
150 | (void)printf(" %s",extensions[i].ext);
151 |
152 | (void)printf("\n\tNot Supported: directories / /etc /bin /lib /tmp /usr /dev /sbin \n"
153 | );
154 | exit(0);
155 | }
156 | if( !strncmp(argv[2],"/" ,2 ) || !strncmp(argv[2],"/etc", 5 ) ||
157 | !strncmp(argv[2],"/bin",5 ) || !strncmp(argv[2],"/lib", 5 ) ||
158 | !strncmp(argv[2],"/tmp",5 ) || !strncmp(argv[2],"/usr", 5 ) ||
159 | !strncmp(argv[2],"/dev",5 ) || !strncmp(argv[2],"/sbin",6) ){
160 | (void)printf("ERROR: Bad top directory %s, see server -?\n",argv[2]);
161 | exit(3);
162 | }
163 | if(chdir(argv[2]) == -1){
164 | (void)printf("ERROR: Can't Change to directory %s\n",argv[2]);
165 | exit(4);
166 | }
167 |
168 | if(fork() != 0)
169 | return 0;
170 | (void)signal(SIGCLD, SIG_IGN);
171 | (void)signal(SIGHUP, SIG_IGN);
172 | for(i=0;i<32;i++)
173 | (void)close(i);
174 | (void)setpgrp();
175 |
176 | log(LOG,"http server starting",argv[1],getpid());
177 |
178 | if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0)
179 | log(ERROR, "system call","socket",0);
180 | port = atoi(argv[1]);
181 | if(port < 0 || port >60000)
182 | log(ERROR,"Invalid port number try [1,60000]",argv[1],0);
183 | serv_addr.sin_family = AF_INET;
184 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
185 | serv_addr.sin_port = htons(port);
186 | if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0)
187 | log(ERROR,"system call","bind",0);
188 | if( listen(listenfd,64) <0)
189 | log(ERROR,"system call","listen",0);
190 |
191 | for(hit=1; ;hit++) {
192 | length = sizeof(cli_addr);
193 | if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0)
194 | log(ERROR,"system call","accept",0);
195 |
196 | if((pid = fork()) < 0) {
197 | log(ERROR,"system call","fork",0);
198 | }
199 | else {
200 | if(pid == 0) {
201 | (void)close(listenfd);
202 | web(socketfd,hit);
203 | } else {
204 | (void)close(socketfd);
205 | }
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------