home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre1.z / postgre1 / sample / pftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-02  |  9.1 KB  |  483 lines

  1. /*    
  2.  *     pftp -- postgres file transport protocol program.
  3.  *
  4.  *    WARNING:  The interface supported here is unstable.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <sys/file.h>
  10. #include <sys/socket.h>
  11. #include <sys/stat.h>
  12. #include <sys/errno.h>
  13. #include <sys/time.h>
  14. #include <netinet/in.h>
  15. #include <netdb.h>
  16. #include <ctype.h>
  17.  
  18. #ifndef sprite
  19. #include <sys/signal.h>
  20. #endif /* !sprite */
  21.  
  22. #include "tmp/c.h"
  23. #include "tmp/oid.h"
  24. #include "tmp/libpq-fe.h"
  25.  
  26. /* just in case someone left memory debugging turned on... */
  27. #undef palloc
  28. #undef pfree
  29.  
  30. RcsId("$Header: /private/postgres/sample/RCS/pftp.c,v 1.2 1991/12/10 05:12:20 mao Exp $");
  31.  
  32. extern char     *getenv();
  33. extern char    *get_attr();
  34.  
  35. extern char     *PQhost;     /* machine on which the backend is running */
  36. extern char     *PQport;     /* comm. port with the postgres backend. */
  37.  
  38. #define STARTSOCK    1991
  39. #define DEFHOST        "olympus.Berkeley.EDU"
  40. #define FILEDB        "file_db"
  41.  
  42. typedef struct _ucmd_data {
  43.     char *cmdname;
  44.     char *cmdarg;
  45. } ucmd_data;
  46.  
  47. int SocketNumber;
  48. char QryBuf[512];
  49.  
  50. void parse();
  51. int waitsock();
  52. int opensock();
  53. int pftp_readport();
  54. int pftp_writeport();
  55. void pgls();
  56. void pgget();
  57. void pgput();
  58. char *get_attr();
  59.  
  60. main(argc,argv)
  61.      int argc;
  62.      char **argv;
  63. {
  64.     char *cmd;
  65.     ucmd_data ucmd;
  66.     char *lbuf[80];
  67.  
  68.     if (argc == 1)
  69.     PQhost = DEFHOST;
  70.     else if (argc == 2)
  71.     PQhost = argv[1];
  72.     else {
  73.         fprintf(stderr, "usage: %s [host]\n", *argv);
  74.         exit (1);
  75.     }
  76.  
  77.     PQsetdb(FILEDB);
  78.  
  79.     fprintf(stdout, "> ");
  80.     fflush(stdout);
  81.     while ((cmd = gets(lbuf)) != (char *) NULL) {
  82.     parse(cmd, &ucmd);
  83.     if (ucmd.cmdname == (char *) NULL)
  84.         continue;
  85.     if (strcmp(ucmd.cmdname, "ls") == 0)
  86.         pgls(ucmd.cmdarg);
  87.     else if (strcmp(ucmd.cmdname, "put") == 0)
  88.         pgput(ucmd.cmdarg);
  89.     else if (strcmp(ucmd.cmdname, "get") == 0)
  90.         pgget(ucmd.cmdarg);
  91.     else if (strcmp(ucmd.cmdname, "quit") == 0)
  92.         break;
  93.     else
  94.         fprintf(stderr, "command '%s' unknown\ntry: ls, put, get, or quit\n", ucmd.cmdname);
  95.  
  96.     fprintf(stdout, "> ");
  97.     fflush(stdout);
  98.     }
  99.  
  100.     PQfinish();
  101.     exit (0);
  102. }
  103.  
  104. void
  105. parse(cmd, ucmd)
  106.     char *cmd;
  107.     ucmd_data *ucmd;
  108. {
  109.     ucmd->cmdname = ucmd->cmdarg = (char *) NULL;
  110.  
  111.     while (isspace(*cmd))
  112.     cmd++;
  113.  
  114.     if (*cmd == '\0')
  115.     return;
  116.  
  117.     ucmd->cmdname = cmd;
  118.  
  119.     while (!isspace(*cmd) && *cmd != '\0')
  120.     cmd++;
  121.  
  122.     while (isspace(*cmd) && *cmd != '\0')
  123.     *cmd++ = '\0';
  124.  
  125.     if (*cmd == '\0')
  126.     return;
  127.  
  128.     ucmd->cmdarg = cmd;
  129. }
  130.  
  131. void
  132. pgls(fname)
  133.     char *fname;
  134. {
  135.     PortalBuffer *portalbuf;
  136.     char *res;
  137.     int ngroups, ntups, grpno;
  138.     int nflds;
  139.     int tupno;
  140.  
  141.     if (fname == (char *) NULL)
  142.     sprintf(QryBuf, "retrieve (mao_dirinfo.all)");
  143.     else
  144.     sprintf(QryBuf, "retrieve (mao_dirinfo.all) where mao_dirinfo.fname = \"%s\"::text");
  145.  
  146.     res = PQexec(QryBuf);
  147.  
  148.     if (*res == 'E') {
  149.     fprintf(stderr, "%s\nls failed\n", ++res);
  150.     return;
  151.     }
  152.  
  153.     if (*res != 'P') {
  154.     fprintf(stderr, "pgstats:  no portal?!?\n");
  155.     exit (1);
  156.     }
  157.  
  158.     /* count result tuples -- get portal first */
  159.     portalbuf = PQparray(++res);
  160.     ngroups = PQngroups(portalbuf);
  161.  
  162.     for (grpno = 0; grpno < ngroups; grpno++) {
  163.     ntups = PQntuplesGroup(portalbuf, grpno);
  164.     if ((nflds = PQnfieldsGroup(portalbuf, grpno)) != 3) {
  165.         fprintf(stderr, "pgls: expected 3 attributes, got %d\n", nflds);
  166.         return;
  167.     }
  168.  
  169.     for (tupno = 0; tupno < ntups; tupno++) {
  170.         fprintf(stdout, "%s\t<%s>\t%s bytes\n", 
  171.                 get_attr(portalbuf, tupno, 0),
  172.                 get_attr(portalbuf, tupno, 1),
  173.                 get_attr(portalbuf, tupno, 2));
  174.     }
  175.     }
  176. }
  177.  
  178. void
  179. pgput(fname)
  180.     char *fname;
  181. {
  182.     PortalBuffer *portalbuf;
  183.     char *res;
  184.     int ngroups, ntups, grpno;
  185.     int nflds;
  186.     int tupno;
  187.     int port;
  188.     oid toid;
  189.     int len;
  190.     struct timezone tz;
  191.     struct timeval tstart, tend;
  192.     char hostname[64];
  193.  
  194.     gethostname(hostname, 64);
  195.     if ((port = pftp_writeport(fname)) < 0)
  196.     return;
  197.  
  198.     sprintf(QryBuf, "retrieve (x = pftp_write(\"%s\"::text, %d))",
  199.          hostname, port);
  200.  
  201.     gettimeofday(&tstart, &tz);
  202.     res = PQexec(QryBuf);
  203.     gettimeofday(&tend, &tz);
  204.  
  205.     if (*res == 'E') {
  206.     fprintf(stderr, "%s\nput failed\n", ++res);
  207.     return;
  208.     }
  209.  
  210.     if (*res != 'P') {
  211.     fprintf(stderr, "put: no portal?!?\n");
  212.     return;
  213.     }
  214.  
  215.     portalbuf = PQparray(++res);
  216.     toid = atoi(get_attr(portalbuf, 0, 0));
  217.     len = getsize(fname);
  218.     sprintf(QryBuf, "append mao_dirinfo (fname = \"%s\"::text, foid = \"%d\"::oid, fsize = %d)", fname, toid, len);
  219.  
  220.     res = PQexec(QryBuf);
  221.  
  222.     if (*res == 'E') {
  223.     fprintf(stderr, "%s\nput failed\n", ++res);
  224.     return;
  225.     }
  226.  
  227.     showtime(&tstart, &tend, len);
  228. }
  229.  
  230. void
  231. pgget(fname)
  232.     char *fname;
  233. {
  234.     PortalBuffer *portalbuf;
  235.     char *res;
  236.     int ngroups, ntups, grpno;
  237.     int nflds;
  238.     int tupno;
  239.     oid toid;
  240.     int port;
  241.     int len;
  242.     struct timezone tz;
  243.     struct timeval tstart, tend;
  244.     char hostname[64];
  245.  
  246.     if (fname == (char *) NULL) {
  247.     fprintf(stderr, "missing file name");
  248.     return;
  249.     }
  250.  
  251.     sprintf(QryBuf, "retrieve (mao_dirinfo.foid) where mao_dirinfo.fname = \"%s\"::text", fname);
  252.  
  253.     res = PQexec(QryBuf);
  254.  
  255.     if (*res == 'E') {
  256.     fprintf(stderr, "%s\nget failed\n", ++res);
  257.     return;
  258.     }
  259.  
  260.     if (*res != 'P') {
  261.     fprintf(stderr, "get:  no portal?!?\n");
  262.     exit (1);
  263.     }
  264.  
  265.     /* count result tuples -- get portal first */
  266.     portalbuf = PQparray(++res);
  267.     ngroups = PQngroups(portalbuf);
  268.  
  269.     for (grpno = 0; grpno < ngroups; grpno++) {
  270.     ntups = PQntuplesGroup(portalbuf, grpno);
  271.     if (ntups = 0) {
  272.         fprintf(stderr, "%s not found\n", fname);
  273.         return;
  274.     }
  275.  
  276.     toid = atoi(get_attr(portalbuf, 0, 0));
  277.     }
  278.  
  279.     gethostname(hostname, 64);
  280.     if ((port = pftp_readport(fname)) < 0)
  281.     return;
  282.  
  283.     sprintf(QryBuf, "retrieve (x = pftp_read(\"%s\"::text, %d, \"%d\"::oid))",
  284.          hostname, port, toid);
  285.  
  286.     gettimeofday(&tstart, &tz);
  287.     res = PQexec(QryBuf);
  288.     gettimeofday(&tend, &tz);
  289.  
  290.     if (*res == 'E') {
  291.     fprintf(stderr, "%s\nput failed\n", ++res);
  292.     return;
  293.     }
  294.  
  295.     if (*res != 'P') {
  296.     fprintf(stderr, "put: no portal?!?\n");
  297.     return;
  298.     }
  299.  
  300.     portalbuf = PQparray(++res);
  301.  
  302.     len = atoi(get_attr(portalbuf, 0, 0));
  303.     showtime(&tstart, &tend, len);
  304. }
  305.  
  306. #define FBUFSIZ    8092
  307. char fbuf[FBUFSIZ];
  308.  
  309. int
  310. pftp_writeport(fname)
  311.     char *fname;
  312. {
  313.     int fd;
  314.     int nbytes;
  315.     int port;
  316.  
  317.     if ((fd = open(fname, O_RDONLY, 0666)) < 0) {
  318.     perror(fname);
  319.     return (-1);
  320.     }
  321.  
  322.     if ((port = opensock()) < 0)
  323.     return (-1);
  324.  
  325.     if (fork() != 0) {
  326.     /* parent sends the query */
  327.     close (fd);
  328.     close (port);
  329.     return (SocketNumber);
  330.     } else {
  331.     /* child sends the file */
  332.     port = waitsock(port);
  333.     while ((nbytes = read(fd, fbuf, FBUFSIZ)) > 0)
  334.         write(port, fbuf, nbytes);
  335.     close(fd);
  336.     close(port);
  337.     exit (0);
  338.     }
  339. }
  340.  
  341. int
  342. pftp_readport(fname)
  343.     char *fname;
  344. {
  345.     int fd;
  346.     int nbytes;
  347.     int port;
  348.  
  349.     if ((fd = open(fname, O_WRONLY|O_CREAT, 0600)) < 0) {
  350.     perror(fname);
  351.     return (-1);
  352.     }
  353.  
  354.     if ((port = opensock()) < 0)
  355.     return (-1);
  356.  
  357.     if (fork() != 0) {
  358.     /* parent sends the query */
  359.     close (fd);
  360.     close (port);
  361.     return (SocketNumber);
  362.     } else {
  363.     /* child sends the file */
  364.     port = waitsock(port);
  365.     while ((nbytes = read(port, fbuf, FBUFSIZ)) > 0)
  366.         write(fd, fbuf, nbytes);
  367.     close(fd);
  368.     close(port);
  369.     exit (0);
  370.     }
  371. }
  372.  
  373. int
  374. opensock()
  375. {
  376.     int sock;
  377.     int msgsock;
  378.     struct sockaddr_in server;
  379.     int i;
  380.  
  381.     /* get a socket on which to listen for connections */
  382.     sock = socket(AF_INET, SOCK_STREAM, 0);
  383.     server.sin_family = AF_INET;
  384.     server.sin_addr.s_addr = INADDR_ANY;
  385.  
  386.     SocketNumber = STARTSOCK;
  387.  
  388.     for (;;) {
  389.     server.sin_port = htons(SocketNumber);
  390.  
  391.     /* bind the socket's name */
  392.     if (bind(sock, &server, sizeof(server)) != 0) {
  393.         if (errno == EADDRINUSE)
  394.         SocketNumber++;
  395.         else {
  396.         perror("binding stream socket");
  397.         return (-1);
  398.         }
  399.     } else
  400.         break;
  401.     }
  402.  
  403.     return(sock);
  404. }
  405.  
  406. int
  407. waitsock(sock)
  408.     int sock;
  409. {
  410.     int i;
  411.     int msgsock;
  412.     struct hostent *h;
  413.     struct sockaddr_in from_client;
  414.  
  415.     listen(sock, 5);
  416.  
  417.     /* wait for a connection from front-end */
  418.     i = sizeof(from_client);
  419.     msgsock = accept(sock, &from_client, &i);
  420.  
  421.     /* figure out who's connected */
  422.     h = gethostbyaddr((char *)&from_client.sin_addr,
  423.               sizeof (struct in_addr),
  424.               AF_INET);
  425.  
  426.     if (h == (struct hostent *) NULL) {
  427.         fprintf(stderr, "cannot get foreign host name\n");
  428.         exit (1);
  429.     }
  430.  
  431.     /* we can use the fe's socket, so we close the original */
  432.     close (sock);
  433.  
  434.     return (msgsock);
  435. }
  436.  
  437. char *
  438. get_attr(portalbuf, tupno, attno)
  439.     PortalBuffer *portalbuf;
  440.     int tupno;
  441.     int attno;
  442. {
  443.     char *attval;
  444.     char *result;
  445.  
  446.     attval = PQgetvalue(portalbuf, tupno, attno);
  447.     result = (char *) palloc(strlen(attval) + 1);
  448.     strcpy(result, attval);
  449.  
  450.     return (result);
  451. }
  452.  
  453. int
  454. getsize(fname)
  455.     char *fname;
  456. {
  457.     struct stat sbuf;
  458.  
  459.     if (stat(fname, &sbuf) < 0) {
  460.     perror(fname);
  461.     return (-1);
  462.     } else
  463.     return (sbuf.st_size);
  464. }
  465.  
  466. showtime(ts, te, len)
  467.     struct timeval *ts;
  468.     struct timeval *te;
  469.     int len;
  470. {
  471.     float etime;
  472.  
  473.     if (te->tv_usec < ts->tv_usec) {
  474.     te->tv_sec--;
  475.     te->tv_usec += 1000000;
  476.     }
  477.     etime = ((te->tv_sec - ts->tv_sec) * 1.0)
  478.         + ((te->tv_usec - ts->tv_usec) / 1000000.0);
  479.  
  480.     fprintf(stdout, "%d bytes transerred in %8.2f sec (%6.2f Kb/sec)\n",
  481.             len, etime, ((len / 1024.0)/ etime));
  482. }
  483.