⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloads.c

📁 著名的手机浏览器开源代码
💻 C
字号:
/* A simple download server to demonstrate dpid. * It uses wget to download a link.  This has been tested with wget 1.8.1 * The server accepts multiple connections once it has been started. * If there are no requests within 5 minutes it waits for all child processes * to finish and then it exits. */#include <config.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/un.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <signal.h>#include <sys/wait.h>#include <errno.h>#include <sys/time.h>#include <glib.h>/* Uncomment for verbose output *///#define DEBUG_MSG/* Convinience for the error message stream */#define eprintf(fmt...) fprintf(stderr, fmt)#ifdef DEBUG_MSG#  define ceprintf(fmt...) eprintf(fmt)#else#  define ceprintf(fmt...)#endif#define BUFLEN 256#define TOUT 300extern int errno;pid_t origpid, fpid;/*---------------------------------------------------------------------------*//* * Task: given a tag and an attribute name, return its value. *       (character stuffing is removed here) * Return value: the attribute value, or NULL if not present or malformed. * (copied from bookmarks.c) */char *Get_attr_value(char *tag, int tagsize, char *attrname){   char *p, *q, *ltag, quote, *start, *val = NULL;   ltag = g_strndup(tag, tagsize);   if ((p = strstr(ltag, attrname)) &&       (p = strchr(p, '=')) && (p = strpbrk(p, "'\""))) {      quote = *p;      start = ++p;      while ((q = strchr(p, quote)) && q[1] == quote)         p = q + 2;      if (q) {         val = g_strndup(start, q - start);         for (p = q = val; (*q = *p); ++p, ++q)            if ((*p == '"' || *p == '\'') && p[1] == p[0])               ++p;      }   }   g_free(ltag);   return val;}/* * Make a new name and place it in 'dl_dest'. */void make_new_name(gchar **dl_dest, const gchar *url){   GString *gstr = g_string_new(*dl_dest);   gint idx = gstr->len;   if (gstr->str[idx - 1] != '/'){      g_string_append_c(gstr, '/');      ++idx;   }   /* Use a mangled url as name */   g_string_append(gstr, url);   for (   ; idx < gstr->len; ++idx)      if (!isalnum(gstr->str[idx]))         gstr->str[idx] = '_';   /* free memory */   g_free(*dl_dest);   *dl_dest = gstr->str;   g_string_free(gstr, FALSE);}/*---------------------------------------------------------------------------*//* * SIGCHLD handler */void sigchld(int sig){   ceprintf("downloads server %d: sigchld\n", origpid);   fflush(stderr);   while (waitpid(0, NULL, WNOHANG) > 0) {   }}/* * Establish SIGCHLD handler */void est_sigchld(void){   struct sigaction act;   sigset_t block;   sigemptyset(&block);   sigaddset(&block, SIGCHLD);   act.sa_handler = sigchld;   act.sa_mask = block;   act.sa_flags = SA_NOCLDSTOP;   sigaction(SIGCHLD, &act, NULL);}/* * Read a single line from a socket and store it in a GString. */ssize_t readline(int socket, GString ** msg){   ssize_t rdlen;   char buf[BUFLEN], c = 0;   ssize_t i = 0;   buf[0] = '\0';   for (i = 0;        (rdlen = read(socket, &c, 1)) != 0 && c != '\n' && rdlen != -1; i++)      g_string_append_c(*msg, c);   if (rdlen == -1) {      perror("downloads server:readline: read");      exit(EXIT_FAILURE);   }   return i;}/*! * \bug Does not check cmd field for a valid command in dpi tag. */int main(void){   int new_socket, ns;   socklen_t csz;   ssize_t rdlen;   struct sockaddr_un clnt_addr;   //char *wget_cmd = "wget --no-parent -t 1 -nc -k -nH --cut-dirs=30 -P";   //char *wget_cmd = "wget -t 1 -nH -P";  --doesn't rename, +other problems   char *wget_cmd = "wget -O - ";   char *url = NULL, *dl_dest = NULL, *cmd = NULL;   GString *gs_dl_cmd, *tag;   fd_set active_set, selected_set;   struct timeval tout;   sigset_t blockSC;   origpid = getpid();   fpid = origpid;   printf("\n\nDL_SRV PARENT %u: DOWNLOAD SERVER STARTED\n", origpid);   fflush(stdout);   sigemptyset(&blockSC);   sigaddset(&blockSC, SIGCHLD);   est_sigchld();   csz = (socklen_t) sizeof(clnt_addr);   FD_ZERO(&active_set);   FD_SET(STDIN_FILENO, &active_set);   while (1) {      do {         /* exit if there are no download requests after this time */         tout.tv_sec = TOUT;         tout.tv_usec = 0;         selected_set = active_set;         ns = select(STDIN_FILENO + 1, &selected_set, NULL, NULL, &tout);      } while (ns == -1 && errno == EINTR);      if (ns == -1) {         perror("downloads server: select");         exit(1);      } else if (ns == 0) {     /* exit if no download requests */         close(STDIN_FILENO);         printf("downloads server %d:Terminating.\n"                "Waiting for children to finish\n", origpid);         fflush(stdout);         /* BUG? Any further calls to downloads server will be queued by dpid          * until all the children have finished.  This could be a long time */         while (waitpid(-1, NULL, 0) >= 0) {         }         printf("\n\nDL_SRV %d: EXITING\n", origpid);         fflush(stdout);         exit(0);      } else {         /* accept the request */         do {            new_socket = accept(STDIN_FILENO, (struct sockaddr *) &clnt_addr,                                &csz);         } while (new_socket == -1 && errno == EINTR);         if (new_socket == -1) {            perror("downloads server: accept");            exit(1);         }      }      sigprocmask(SIG_BLOCK, &blockSC, NULL);      tag = g_string_new(NULL);      rdlen = readline(new_socket, &tag);      if ((cmd = Get_attr_value(tag->str, tag->len, "cmd")) == NULL) {         eprintf("Failed to parse 'cmd' in %s\n", tag->str);         exit(1);      }      if (strcmp(cmd, "DpiBye") == 0) {         printf("downloads dpi: Got DpiBye, terminating.\n");         exit(0);      }      fpid = fork();      if (fpid == 0) {         pid_t ppid, cpid;         FILE *in_stream, *out_stream;         gchar buf[4096];         struct stat sb;         gint n;         origpid = cpid = getpid();         ppid = getppid();         ceprintf("\n\ndownloads server child %u: Started- Parent=%d\n", cpid,                  ppid);         if ((url = Get_attr_value(tag->str, tag->len, "url")) == NULL) {            eprintf("Failed to parse 'url' in %s\n", tag->str);            exit(1);         }         if ((dl_dest =              Get_attr_value(tag->str, tag->len, "destination")) == NULL) {            eprintf("Failed to parse 'destination' in %s\n", tag->str);            exit(1);         }         ceprintf("downloads server child %u:parent=%u, url = %s\n",                  cpid, ppid, url);         ceprintf("downloads server child %u:parent=%u, dl_dest = %s\n",                  cpid, ppid, dl_dest);         /* 'dl_dest' may be a directory */         if (stat(dl_dest, &sb) == 0 && S_ISDIR(sb.st_mode))            make_new_name(&dl_dest, url);         /* open the target stream */         if ((out_stream = fopen(dl_dest, "w")) == NULL) {            perror("downloads server child");            exit(1);         }         /* make the download command string */         gs_dl_cmd = g_string_new(NULL);         g_string_sprintf(gs_dl_cmd, "%s '%s'", wget_cmd, url);         eprintf(" cmd: %s\n", gs_dl_cmd->str);         eprintf("  to: %s\n", dl_dest);         g_free(dl_dest);         g_free(url);         ceprintf("downloads server child %u:parent=%u, Running: %s\n", cpid,                  ppid, gs_dl_cmd->str);         /* fork through popen */         if ((in_stream = popen(gs_dl_cmd->str, "r")) == NULL) {            perror("popen");            exit(1);         }         /* do the file transfer */         while ((n = fread (buf, 1, 4096, in_stream)) > 0)            fwrite(buf, 1, n, out_stream);         /* close transfer */         if (pclose(in_stream) != 0)            perror("pclose");         if (fclose(out_stream) != 0)            perror("fclose");         g_string_free(gs_dl_cmd, TRUE);         if (close(new_socket) == -1) {            perror("downloads server: close");            exit(EXIT_FAILURE);         }         ceprintf("downloads server child %u:parent=%u, Child finished\n",                  cpid, ppid);         exit(0);      }      g_string_free(tag, TRUE);      sigprocmask(SIG_UNBLOCK, &blockSC, NULL);      close(new_socket);   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -