Advertisement
SirNickolas

OS 7 server_lite.c

Nov 28th, 2014
511
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.68 KB | None | 0 0
  1. /*
  2.     Это упрощенная версия сервера с последовательной обработкой запросов,
  3.     т. е. пока обслуживается один клиент, остальные ждут своей очереди.
  4. */
  5.  
  6. #include <errno.h>
  7. #include <pthread.h>
  8. #include <stdbool.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <sys/iomsg.h>
  14. #include <sys/neutrino.h>
  15. #include "httpd_pid.h"
  16.  
  17. const char HELP_MESSAGE[ ] = "\
  18. OS Lab 5 Server v1.2 Lite\n\
  19. \n\
  20. Available commands:\n\
  21.  help\n\
  22.  ls\n\
  23.  cat\n\
  24.  cp\n\
  25.  rm\n\
  26.  echo\n\
  27.  delay\n\
  28.  calc\n\
  29. ";
  30.  
  31. const char ERROR_MESSAGE[ ] = "Invalid command; use 'help' for more information\n"
  32.  
  33. const size_t BUFFER_SIZE   = 65535;
  34. const size_t RESPONSE_SIZE = 65535;
  35.  
  36. enum {
  37.     CMD_ERROR,
  38.     CMD_SHELL,
  39.     CMD_HELP,
  40.     CMD_ECHO,
  41.     CMD_DELAY,
  42.     CMD_CALC,
  43. };
  44.  
  45. short CheckCommand(const char cmd[ ]) {
  46.     switch (cmd[0]) {
  47.         case 'c': {
  48.             if (cmd[1] == 'a') {
  49.                 if (cmd[2] == 'l') {
  50.                     if (!strncmp(cmd + 3, "c ", 2))
  51.                         return CMD_CALC;
  52.                 } else if (!strncmp(cmd + 2, "t ", 2))
  53.                     return CMD_SHELL;
  54.             } else if (!strncmp(cmd + 1, "p ", 2))
  55.                 return CMD_SHELL;
  56.             break;
  57.         }
  58.  
  59.         case 'd': {
  60.             if (!strncmp(cmd + 1, "elay ", 5))
  61.                 return CMD_DELAY;
  62.             break;
  63.         }
  64.  
  65.         case 'e': {
  66.             if (!strncmp(cmd + 1, "cho ", 4))
  67.                 return CMD_ECHO;
  68.             break;
  69.         }
  70.  
  71.         case 'h': {
  72.             if (!strcmp(cmd + 1, "elp"))
  73.                 return CMD_HELP;
  74.             break;
  75.         }
  76.  
  77.         case 'l': {
  78.             if (cmd[1] == 's' && (cmd[2] == ' ' || !cmd[2]))
  79.                 return CMD_SHELL;
  80.             break;
  81.         }
  82.  
  83.         case 'r': {
  84.             if (!strncmp(cmd + 1, "m ", 2))
  85.                 return CMD_SHELL;
  86.         }
  87.     }
  88.     return CMD_ERROR;
  89. }
  90.  
  91. void ProcessClient(int clientId, const char _msg[ ], char* buffer, size_t maxLength) {
  92.     const char* response = buffer;
  93.     size_t responseSize;
  94.     const char* msg = _msg;
  95.     short cmd;
  96.     while ((cmd = CheckCommand(msg)) == CMD_DELAY) {
  97.         double delay;
  98.         int offset;
  99.         msg += 6;
  100.         if (sscanf(msg, "%lf%n", &delay, &offset) != 1) {
  101.             cmd = CMD_ERROR;
  102.             break;
  103.         }
  104.         usleep((useconds_t)(delay * 1e6));
  105.         msg += offset + 1;
  106.     }
  107.     switch (cmd) {
  108.         case CMD_ERROR: {
  109.             response = ERROR_MESSAGE;
  110.             responseSize = sizeof ERROR_MESSAGE;
  111.             break;
  112.         }
  113.  
  114.         case CMD_SHELL: {
  115.             FILE* p = popen(msg, "r");
  116.             responseSize = fread(buffer, sizeof(char), maxLength, p);
  117.             buffer[responseSize / sizeof(char)] = '\0';
  118.             responseSize += sizeof(char);
  119.             pclose(p);
  120.             break;
  121.         }
  122.  
  123.         case CMD_HELP: {
  124.             response = HELP_MESSAGE;
  125.             responseSize = sizeof HELP_MESSAGE;
  126.             break;
  127.         }
  128.  
  129.         case CMD_ECHO: {
  130.             puts(msg + 5);
  131.             *buffer = '\0';
  132.             responseSize = sizeof(char);
  133.             break;
  134.         }
  135.  
  136.         case CMD_CALC: {
  137.             double a, b;
  138.             char op, guard;
  139.             if (sscanf(msg + 5, "%lf %1[-+*/] %lf %c", &a, &op, &b, &guard) == 3) {
  140.                 switch (op) {
  141.                     case '+': { a += b; break; }
  142.                     case '-': { a -= b; break; }
  143.                     case '*': { a *= b; break; }
  144.                     case '/': { a /= b; break; }
  145.                 }
  146.                 if (a == (int)a)
  147.                     responseSize = sprintf(buffer, "%d", (int)a);
  148.                 else
  149.                     responseSize = sprintf(buffer, "%lf", a);
  150.                 responseSize = (responseSize + 1) * sizeof(char);
  151.             } else {
  152.                 response = ERROR_MESSAGE;
  153.                 responseSize = sizeof ERROR_MESSAGE;
  154.             }
  155.         }
  156.     }
  157.     MsgReply(clientId, EOK, response, responseSize);
  158. }
  159.  
  160. char buffer[BUFFER_SIZE];
  161.  
  162. int main(void) {
  163.     int channelId = ChannelCreate(0);
  164.     FILE* f = fopen(HTTPD_PID, "w");
  165.     if (!f) {
  166.         fputs("Cannot open \"" HTTPD_PID "\"\n", stderr);
  167.         return 1;
  168.     }
  169.     fprintf(f, "0/%d/%d\n", getpid(), channelId);
  170.     fclose(f);
  171.     fputs(HELP_MESSAGE, stdout);
  172.     while (true) {
  173.         int clientId = MsgReceive(channelId, buffer, BUFFER_SIZE * sizeof(char), NULL);
  174.         ProcessClient(clientId, buffer, buffer, BUFFER_SIZE);
  175.     }
  176.     return 0;
  177. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement