home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / ups / ups.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-01-31  |  9.8 KB  |  553 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: ups.c,v 1.8 86/12/11 15:58:18 scooter Exp $";
  3. #endif
  4.  
  5. /*
  6.  * ups - user interface to the package delivery system
  7.  *
  8.  * usage: ups user@host file1 file2 ...
  9.  *
  10.  * $Author: scooter $
  11.  * $Revision: 1.8 $
  12.  * $Date: 86/12/11 15:58:18 $
  13.  *
  14.  * $Log:    ups.c,v $
  15.  * Revision 1.8  86/12/11  15:58:18  scooter
  16.  * Added alias expansion code which allows ups to follow /usr/lib/aliases.
  17.  * 
  18.  * Revision 1.7  86/09/19  18:53:15  scooter
  19.  * Added -i option for mail specification
  20.  * 
  21.  * Revision 1.6  86/09/18  15:19:45  scooter
  22.  * More fixes to the '.' problam
  23.  * 
  24.  * Revision 1.5  86/09/17  09:43:38  scooter
  25.  * Added code to do automatic renaming of "." files for delivery to
  26.  * avoid the "cannot delete" problem
  27.  * 
  28.  * Revision 1.4  85/08/21  22:27:45  scooter
  29.  * Release revision: added more complete RCS headers.
  30.  * 
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <pwd.h>
  35. #include <ndbm.h>
  36. #include <sys/wait.h>
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <sys/socket.h>
  40. #include <sys/file.h>
  41. #include <netinet/in.h>
  42. #include <netdb.h>
  43. #include <ctype.h>
  44.  
  45. #define    LS "/bin/ls"
  46.  
  47. struct    passwd *getpwuid();
  48. FILE     *fopen();
  49. int    rem;
  50. int    qflg = 0;
  51. int    iflg = 0;
  52. int    on   = 1;
  53. char    buffer[BUFSIZ*5];
  54. char    mbuffer[BUFSIZ*4];
  55.  
  56. struct    user_list {
  57.     char    *u_user;
  58.     char    *u_host;
  59.     struct    user_list *u_next;
  60. };
  61.  
  62. main(argc, argv)
  63. char **argv;
  64. int argc;
  65. {
  66.     char    myhost[BUFSIZ];
  67.     int    file;
  68.     int    ret;
  69.     char    *user,*host,*tmp,*rindex(),*index();
  70.     struct    passwd *mypwent;
  71.     struct    user_list *u_list,*u_top, *alias_expand();
  72.  
  73.     gethostname(myhost,BUFSIZ);
  74.  
  75.     if( (mypwent = getpwuid(getuid())) == NULL )
  76.     {
  77.         fprintf(stderr,"ups: who are you?\n");
  78.         exit(1);
  79.     }
  80.  
  81.     while (*argv[1] == '-')
  82.     {
  83.         char     c;
  84.  
  85.         switch (c = *(++argv[1]))
  86.         {
  87.  
  88.         case 'q':
  89.             qflg++;
  90.             break;
  91.  
  92.         case 'i':
  93.             iflg++;
  94.             break;
  95.  
  96.         default:
  97.             fprintf(stderr,"ups: unknown option %c\n",c);
  98.  
  99.         }
  100.         argv++;
  101.         argc--;
  102.     }
  103.  
  104.     if (argc == 1 || qflg)
  105.         upsread(mypwent);
  106.     
  107.     if (argc == 2) {
  108.         fprintf(stderr,"usage: ups user@host file1 file2 ...\n");
  109.         exit(0);
  110.     }
  111.  
  112. /*
  113.  * Get the name of the destination user and host
  114.  */
  115.  
  116.     user = argv[1];
  117.     host = rindex(user,'@');
  118. #ifndef    ALIASES
  119.     if (host == NULL)
  120.         host = myhost;
  121.     else
  122.         *host++ = '\0';
  123. #else
  124.     if (host != NULL)
  125.         *host++ = '\0';
  126.      
  127.     u_top = alias_expand(user,host,myhost);
  128.     
  129. #endif    ALIASES
  130.  
  131.     if (iflg)
  132.         upsgetmsg(mbuffer);
  133.     else
  134.         mbuffer[0] = '\0';
  135.  
  136.     while (u_top != NULL)
  137.     {
  138.  
  139. #ifdef    DEBUG
  140.     printf("Connecting to %s for user %s\n",u_top->u_host,u_top->u_user);
  141. #endif    DEBUG
  142.         rem = upsconnect(u_top->u_host);    /* Connect to the server */
  143.  
  144.         /*
  145.          * Send the to name, from name, and our name
  146.          */
  147.  
  148.         tmp = index(mypwent->pw_gecos,',');
  149.         if (tmp)
  150.             *tmp = '\0';
  151.  
  152.         sprintf(buffer, "%s\n%s\n%s\n%s", u_top->u_user,
  153.             mypwent->pw_name, mypwent->pw_gecos,mbuffer);
  154.  
  155. #ifdef    DEBUG
  156.     printf("Sending: %s\n",buffer);
  157.     fflush(stdout);
  158. #endif    DEBUG
  159.  
  160.         write(rem, buffer, strlen(buffer)+1);
  161.         ret = read(rem, buffer, BUFSIZ);
  162.         if (buffer[0])
  163.             problem(1);
  164.     
  165.         for (file = 2 ; file < argc ; file++)
  166.         {
  167.  
  168. #ifdef    DEBUG
  169.         printf("Sending file: %s",argv[file]);
  170. #endif    DEBUG
  171.  
  172.             sendfile(argv[file]);
  173.         }
  174.  
  175.         sprintf(buffer, "-Done-");
  176.         write(rem, buffer, strlen(buffer)+1);
  177.         read(rem, buffer, BUFSIZ);    /* get result */
  178.         if (buffer[0])        /* problem? */
  179.             problem(1);    /* yes, go handle it */
  180.  
  181.         close(rem);
  182.         u_top = u_top->u_next;
  183.      }
  184.  
  185. }
  186.  
  187.  
  188.  
  189.  
  190. upsconnect(host)
  191. char *host;
  192. {
  193.     struct hostent *hp;
  194.     struct servent *sp;
  195.     struct    sockaddr_in sin;
  196.     int s;
  197.  
  198.     hp = gethostbyname(host);
  199.     if (hp == NULL) {
  200.         static struct hostent def;
  201.         static struct in_addr defaddr;
  202.         static char namebuf[128];
  203.         int inet_addr();
  204.  
  205.         defaddr.s_addr = inet_addr(host);
  206.         if (defaddr.s_addr == -1) {
  207.             printf("unknown host: %s\n", host);
  208.             exit(1);
  209.         }
  210.         strcpy(namebuf, host);
  211.         def.h_name = namebuf;
  212.         def.h_addr = (char *)&defaddr;
  213.         def.h_length = sizeof (struct in_addr);
  214.         def.h_addrtype = AF_INET;
  215.         def.h_aliases = 0;
  216.         hp = &def;
  217.     }
  218.     sp = getservbyname("ups", "tcp");
  219.     if (sp == 0) {
  220.         fprintf(stderr,"tcp/ups: unknown service\n");
  221.         exit(1);
  222.     }
  223.     sin.sin_family = hp->h_addrtype;
  224.     bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
  225.     sin.sin_port = sp->s_port;
  226.     s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  227.     if (s < 0) {
  228.         fflush(stderr);
  229.         perror("ups (socket)");
  230.         exit(1);
  231.     }
  232.     setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&on,sizeof(on));
  233. #ifdef    DEBUG
  234.     setsockopt(s,SOL_SOCKET,SO_DEBUG,&on,sizeof(on));
  235. #endif    DEBUG
  236.     if (connect(s, (char *)&sin, sizeof (sin)) < 0) {
  237.         fflush(stderr);
  238.         perror("ups (connect)");
  239.         close(s);
  240.         exit(1);
  241.     }
  242.     return(s);
  243. }
  244.  
  245.  
  246.  
  247.  
  248. sendfile(file)
  249. char *file;
  250. {
  251.     struct    stat fstatus;
  252.     int    loc,n;
  253.     char    *tmp,*fname;
  254.  
  255.     if ( (loc = open(file,O_RDONLY)) <= 0 ) {
  256.         perror("ups (open)");
  257.         return(1);
  258.     }
  259.     if (fstat(loc, &fstatus)) {
  260.         perror("ups (fstat)");
  261.         return(1);
  262.     }
  263.  
  264.     if ((fstatus.st_mode&S_IFMT) != S_IFREG) {
  265.         switch (fstatus.st_mode&S_IFMT)
  266.         {
  267.         case S_IFDIR:
  268.             tmp = "directory";
  269.             break;
  270.         case S_IFCHR:
  271.             tmp = "character device";
  272.             break;
  273.         case S_IFBLK:
  274.             tmp = "block device";
  275.             break;
  276.         case S_IFLNK:
  277.             tmp = "symbolic link";
  278.             break;
  279.         case S_IFSOCK:
  280.             tmp = "socket";
  281.             break;
  282.         }
  283.  
  284.         fprintf(stderr,
  285.             "ups: %s is a %s, only regular files may be sent\n",
  286.             file,tmp);
  287.         fflush(stderr);
  288.         return(1);
  289.     }
  290.  
  291.     /*
  292.      * Send the file name
  293.      */
  294.  
  295.     /*
  296.      * First strip off the directory path
  297.      */
  298.     sprintf(buffer,"%s",file);
  299.     tmp = rindex(buffer,'/');
  300.     if (tmp) 
  301.         *tmp++ = '\0';
  302.     else
  303.         tmp = buffer;
  304.  
  305.     fname = tmp;
  306.  
  307.     if (*tmp == '.')
  308.     {
  309.         while ( (*tmp == '.') && (*tmp != '\0') )tmp++;
  310.  
  311.         fprintf(stdout,
  312.           "WARNING: file %s has been renamed to %s for delivery\n",
  313.           fname,tmp);
  314.     }
  315.  
  316.     write(rem, tmp, strlen(tmp)+1);
  317.     read(rem, buffer, BUFSIZ);
  318.     if (buffer[0])        /* problem */
  319.     {
  320.         problem(0);
  321.         return(1);
  322.     }
  323.  
  324.     /*
  325.      * Send the file size in bytes
  326.      */
  327.  
  328.     sprintf(buffer, "%D",fstatus.st_size);
  329.     write(rem, buffer, strlen(buffer)+1);
  330.     read(rem, buffer, BUFSIZ);
  331.     if (buffer[0])        /* problem */
  332.     {
  333.         problem(0);
  334.         return(1);
  335.     }
  336.  
  337.     /*
  338.      * Send the file
  339.      */
  340.     while (n = read(loc, buffer, BUFSIZ))
  341.         write(rem, buffer, n);
  342.     close(loc);
  343.     read(rem, buffer, BUFSIZ); /* get result */
  344.     if (buffer[0])        /* problem */
  345.     {
  346.         problem(0);
  347.         return(1);
  348.     }
  349.     sprintf(buffer, "%u", fstatus.st_mode);
  350.     write(rem, buffer, strlen(buffer)+1);
  351.     read(rem, buffer, BUFSIZ); /* get result */
  352.     if (buffer[0])        /* problem */
  353.     {
  354.         problem(0);
  355.         return(1);
  356.     }
  357.     return(0);
  358. }
  359.  
  360.  
  361.  
  362. upsread(mypwent)
  363. struct    passwd *mypwent;
  364. {
  365.     union    wait status;
  366.     int    pid;
  367.     char    c,line[BUFSIZ],*tmp;
  368.  
  369.     sprintf(buffer,"%s/%s",UPSDIR,mypwent->pw_name);
  370.     if (qflg)
  371.     {
  372.         if (!access(buffer,F_OK)) {
  373.         fprintf(stderr,
  374.     "You have ups files awaiting you (type ups to accept delivery)\n");
  375.         }
  376.         exit(0);
  377.     }
  378.     if (access(buffer,F_OK)) {
  379.         fprintf(stderr,"Nothing waiting in ups\n");
  380.         exit(0);
  381.     }
  382.     fprintf(stdout,"\nYou have the following files awaiting delivery:\n\n");
  383.     if (pid = vfork())
  384.     {
  385.         wait(&status);
  386.     } else {
  387.         execl(LS,"ls","-C",buffer,(char *)0);
  388.         perror("ups (exec)");
  389.         return(0);
  390.     }
  391.     fprintf(stdout,"\n");
  392.  
  393.     fprintf(stdout,
  394.         "Do you wish to accept delivery in your\n");
  395.     fprintf(stdout,
  396.         "current directory (%s)? ",
  397.         getwd(line));
  398.  
  399. getinp:
  400.     if (fgets(line,BUFSIZ,stdin) == NULL) {
  401.         fprintf(stdout,"\n");
  402.         exit(0);
  403.     }
  404.  
  405.     tmp = &line[0];
  406.     while (isspace(*tmp)) tmp++;
  407.  
  408.     switch (*tmp) {
  409.     case 'y':
  410.     case 'Y':
  411.         sprintf(line,"mv -i %s/* . ; rmdir %s",buffer,buffer);
  412.         system(line);
  413.         exit(0);
  414.  
  415.     case 'n':
  416.     case 'N':
  417.         exit(0);
  418.  
  419.     default:
  420.         fprintf(stdout,"Please answer 'yes' or 'no': ");
  421.         goto getinp;
  422.     }
  423. }
  424.  
  425.  
  426.  
  427. /*
  428.  * problem() is called when the install demon process return a non-zero reply.
  429.  * This usually means something recognizable went wrong and we should expect
  430.  * a reason to follow. Read in the reason, output it on the terminal and die.
  431.  */
  432.  
  433. problem(die)
  434. int die;
  435. {
  436.     char buf[BUFSIZ];    /* place to read into */
  437.  
  438.     if (read(rem, buf, BUFSIZ) > 0)        /* if we have something */
  439.         fprintf(stderr, "ups: %s", buf);
  440.     if (die) {
  441.         close(rem);        /* close network channel */
  442.         exit(1);
  443.     }
  444. }
  445.  
  446. int
  447. upsgetmsg(mailbuffer)
  448. char *mailbuffer;
  449. {
  450.     int done = 0;
  451.  
  452.     fprintf(stdout,
  453.         "Enter your message followed by '.<RETURN>' or a <CTRL>D:\n");
  454.     
  455.     while (!done)
  456.     {
  457.         fprintf(stdout,"> ");
  458.         if (gets(mailbuffer) == NULL)
  459.         {
  460.             fprintf(stdout,"\n");
  461.             done++;
  462.         } else if ( (*mailbuffer == '.') && (*(mailbuffer+1) == '\0')) 
  463.         {
  464.             done++;
  465.             *mailbuffer = '\0';
  466.         } else {
  467.             while(*mailbuffer != '\0')
  468.                 mailbuffer++;
  469.             *mailbuffer++ = '\n';
  470.             *mailbuffer = '\0';
  471.         }
  472.     }
  473.     fprintf(stdout,"[EOT]\n");
  474. }
  475.  
  476.  
  477.  
  478. struct user_list *
  479. alias_expand(user,host,myhost)
  480. char *user,*host,*myhost;
  481. {
  482.     char    *malloc();
  483.     DBM    *dp;
  484.     datum    key,content;
  485.     struct    user_list *list,*top,*alloc_list();
  486.     char    *cp,*tp,*hp;
  487.     
  488.     list = top = (struct user_list *)NULL;
  489.  
  490.     if (host != NULL)
  491.         return(alloc_list(user,host));
  492.         
  493.     dp = dbm_open("/usr/lib/aliases", O_RDONLY, 0644);
  494.     if (dp == NULL)
  495.         return(alloc_list(user,host));
  496.     
  497.     key.dptr = user;
  498.     key.dsize = strlen(user) + 1;
  499.     
  500.     content = dbm_fetch(dp,key);
  501.     if (content.dptr == NULL)
  502.         return(alloc_list(user,myhost));
  503.     cp = content.dptr;
  504.     while (cp != NULL)
  505.     {
  506.         tp = cp;
  507.         cp = index(cp,',');
  508.         if (cp != NULL)
  509.             *cp++ = '\0';
  510.         if (index(tp,'!')) {
  511.           fprintf(stderr,
  512.              "ups: WARNING: cannot alias %s to %s (no ups over uucp)\n",
  513.               user,hp);
  514.           continue;
  515.         } else if(index(tp,'|')) {
  516.           fprintf(stderr,
  517.              "ups: WARNING: cannot alias %s to %s (no shells allowed)\n",
  518.               user,hp);
  519.           continue;
  520.         }
  521.         hp = tp;
  522.         hp = index(tp,'@');
  523.         if (hp == NULL)
  524.             hp = myhost;
  525.         else
  526.             *hp++ = '\0';
  527.         if (top == NULL)
  528.             top = list = alloc_list(tp,hp);
  529.         else
  530.         {
  531.             list->u_next = alloc_list(tp,hp);
  532.             list = list->u_next;
  533.         }
  534.     }
  535.     return(top);
  536. }
  537.  
  538. struct    user_list *
  539. alloc_list(user,host)
  540. char *user,*host;
  541. {
  542.     char *malloc();
  543.     struct    user_list *list;
  544.  
  545.     list = (struct user_list *)malloc(sizeof(struct user_list));
  546.     list->u_user = malloc(strlen(user) + 1);
  547.     list->u_host = malloc(strlen(host) + 1);
  548.     strcpy(list->u_user,user);
  549.     strcpy(list->u_host,host);
  550.     list->u_next = (struct user_list *)NULL;
  551.     return(list);
  552. }
  553.