home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume13 / ups / upsd.c < prev   
C/C++ Source or Header  |  1988-01-31  |  8KB  |  383 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: upsd.c,v 1.4 86/11/19 15:21:52 scooter Exp $";
  3. #endif
  4.  
  5. /*
  6.  * upsd - package delivery server
  7.  *
  8.  * upsd is the program that is called by inetd when a ups
  9.  * request is issued.  It will read and write to standard input
  10.  * and standard output.  Here is a description of the ups
  11.  * protocol:
  12.  *
  13.  *     ups            upsd                    type
  14.  *
  15.  *  user_name    ------>        login name of package receiver        String
  16.  *  from_name    ------>        login name of package sender        String
  17.  *  full_name    ------>        full name of package sender        String
  18.  *  message    ------>        mail message to send            String
  19.  *        <-----        0 for OK                Byte
  20.  * For each file:
  21.  *  file_name    ------>        name of file to be delivered        String
  22.  *  file_size    ------>        size of file in bytes            Long
  23.  *        <-----        0 for OK                Byte
  24.  *  file    ------>        file size bytes
  25.  *        <-----        0 for OK                Byte
  26.  *  file_mode    ------>        file mode                Int
  27.  *        <-----        0 for OK                Byte
  28.  *
  29.  * When its all done:
  30.  *  complete    ------>        We're done ('-Done-')            String
  31.  *        <-----        0 for OK                Byte
  32.  *
  33.  * $Author: scooter $
  34.  * $Revision: 1.4 $
  35.  * $Date: 86/11/19 15:21:52 $
  36.  *
  37.  * $Log:    upsd.c,v $
  38.  * Revision 1.4  86/11/19  15:21:52  scooter
  39.  * Changed error severity level from ERR to INFO
  40.  * 
  41.  * Revision 1.3  86/09/19  18:53:37  scooter
  42.  * Added -i option for mail specification.
  43.  * Also added syslog stuff.
  44.  * 
  45.  * Revision 1.2  85/08/21  22:28:11  scooter
  46.  * Release revision: added more complete RCS headers.
  47.  * 
  48.  *
  49.  */
  50.  
  51. #include    <stdio.h>
  52. #include    <pwd.h>
  53. #include    <grp.h>
  54. #include    <sys/file.h>
  55. #include    <sys/types.h>
  56. #include    <netinet/in.h>
  57. #include    <netdb.h>
  58. #include    <syslog.h>
  59.  
  60. long    atol();
  61. int    atoi();
  62.  
  63. char    buffer[BUFSIZ*5];    /* character input buffer */
  64. char    file_name[BUFSIZ];    /* file name */
  65. char    file_path[BUFSIZ];    /* full path to destination */
  66. char    user_name[BUFSIZ];    /* Receiver name */
  67. char    from_name[BUFSIZ];    /* Sender name */
  68. char    full_name[BUFSIZ];    /* Full name of sender */
  69. char    file_list[BUFSIZ];    /* List of all files */
  70. long    file_size;        /* number of bytes in file */
  71. int    file_mode;        /* mode of the file */
  72. char    mail_message[BUFSIZ*4];    /* mail message */
  73. int    mcount;            /* number of characters in mail buffer */
  74.  
  75. int    fid;            /* File descriptor for destination */
  76. int    debugflag;        /* Debug flag */
  77.  
  78. main(argc, argv)
  79. int argc;
  80. char **argv;
  81. {
  82.     char *ptr,*tptr,*mptr;
  83.     int f, i, file;
  84.     struct sockaddr_in sin;
  85.     struct hostent *peer;
  86.     struct passwd *pwent;
  87.     
  88.     while (*argv[1] == '-')
  89.     {
  90.         char     c;
  91.  
  92.         switch (c = *(++argv[1]))
  93.         {
  94.  
  95.         case 'd':
  96.             debugflag++;
  97.             break;
  98.  
  99.         default:
  100.             fprintf(stderr,"upsd: unknown option %c\n",c);
  101.  
  102.         }
  103.         argv++;
  104.         argc--;
  105.     }
  106.     
  107.  
  108.     openlog("upsd",LOG_ODELAY,LOG_DAEMON);
  109.     
  110.     if (debugflag)
  111.         syslog(LOG_DEBUG,"started");
  112.     
  113.     i = sizeof (sin);
  114.     if (getpeername(0, &sin, &i) < 0)
  115.         syslog(LOG_ERR,"getpeername failed: %m");
  116.  
  117.     if (debugflag)
  118.         syslog(LOG_DEBUG,"Calling gethostbyaddr");
  119.     
  120.     peer = gethostbyaddr((char *)&sin.sin_addr,
  121.                 sizeof(sin.sin_addr),sin.sin_family);
  122.  
  123.     buffer[0] = '\0';
  124.     file_list[0] = '\0';
  125.  
  126.     if (debugflag)
  127.         syslog(LOG_DEBUG,"Reading first buffer");
  128.  
  129.     read(0, buffer, BUFSIZ*5);  /* fetch receiver and sender names */
  130.  
  131.     if (debugflag)
  132.         syslog(LOG_DEBUG,"receiver/sender/message: %s",buffer);
  133.  
  134.     ptr = buffer;
  135.     while (*ptr != '\n')
  136.         ptr++;
  137.     *ptr++ = NULL;
  138.     strcpy(user_name, buffer);    /* save receiver name */
  139.     tptr = ptr;
  140.     while (*tptr != '\n')
  141.         tptr++;
  142.     *tptr++ = NULL;
  143.     strcpy(from_name, ptr);        /* save sender name */
  144.     mptr = tptr;
  145.     while ((*mptr != '\n') && (*mptr != '\0'))
  146.         mptr++;
  147.     *mptr++ = NULL;
  148.     strcpy (full_name, tptr);    /* save sender's full name */
  149.     strcpy (mail_message, mptr);    /* save the mail message */
  150.  
  151.     /*
  152.      * Check for a valid user
  153.      */
  154.     if ((pwent = getpwnam(user_name)))
  155.         ack();
  156.     else
  157.     {
  158.         error("Receiver name","No such person");
  159.         exit(1);
  160.     }
  161.     
  162.     mcount = strlen (mail_message);
  163.     if (debugflag)
  164.         syslog(LOG_DEBUG,"mail message (%d chars):\n %s", mcount, mail_message);
  165.  
  166.     for (file = 0 ;;)
  167.     {
  168.         if (read(0, buffer, BUFSIZ) <= 0) {
  169.             error("file name","premature EOF or file read error");
  170.             continue;
  171.         }
  172.         strcpy(file_name,buffer);
  173.  
  174.         if (debugflag)
  175.             syslog(LOG_DEBUG,"File name:%s",file_name);
  176.  
  177.  
  178.         /*
  179.          * Are we done??
  180.          */
  181.         if (!strncmp(file_name,"-Done-",6)) break;
  182.  
  183.         if ( (fid = opendest(user_name,file_name,
  184.                 pwent->pw_uid,pwent->pw_gid)) <= 0 ) 
  185.         {
  186.             continue;
  187.         }
  188.         ack();
  189.  
  190.         if (read(0, buffer, BUFSIZ) <= 0) {
  191.             error("file size","premature EOF or file read error");
  192.             continue;
  193.         }
  194.  
  195.         file_size = atol(buffer); /* get number of bytes */
  196.         ack();
  197.  
  198.         copyfile(&file);
  199.  
  200.         if (read(0, buffer, BUFSIZ) <= 0) {
  201.             error("file mode","premature EOF or file read error");
  202.             continue;
  203.         }
  204.         file_mode = atoi(buffer);     /* get the file mode */
  205.         file_mode &= 0700;        /* Strip the low order modes */
  206.         if (chmod(file_path,file_mode)) {
  207.             error("file mode","chmod failed");
  208.             continue;
  209.         }
  210.         ack();
  211.         chown(file_path,pwent->pw_uid,pwent->pw_gid);
  212.  
  213.     }
  214.     ack();
  215.  
  216.     if (file)
  217.         sendmail(from_name,full_name,peer->h_name,
  218.               user_name,file_list,file++,mail_message,mcount);
  219. }
  220.  
  221. /*
  222. copyfile
  223. copyfile will copy file_size many bytes from stdin to a temporarily created
  224. file. The filename will be passed back via buffer.
  225. */
  226.  
  227. copyfile(file)
  228. int *file;
  229. {
  230.     long cnt;                /* file size counter */
  231.     int i;
  232.  
  233.     cnt = file_size;        /* count down input bytes */
  234.     while (cnt > 0) {
  235.         i = read(0, buffer, BUFSIZ);
  236.         write(fid, buffer, i);
  237.         cnt -= i;
  238.     }
  239.     close(fid);
  240.  
  241.     ack();
  242.     sprintf(buffer,"%-15s",file_name);
  243.     if (*file%4)
  244.         strcat(file_list," ");
  245.     else
  246.         strcat(file_list,"\n\t");
  247.  
  248.     (*file)++;
  249.     strcat(file_list,buffer);
  250. }
  251.  
  252. /*
  253. error(option, string)
  254. char *option, *string;
  255. This routine is called when some error condition has been encountered.
  256. option contains an identifier message, while string contains the actual
  257. error message. Before message is printed, a non-null character is output
  258. first, then the string error message.
  259. */
  260.  
  261. error(option, string)
  262. char *option, *string;
  263. {
  264.     char buf[BUFSIZ];
  265.  
  266.  
  267.     buf[0] = 1;
  268.     write(1, buf, 1);    /* nak */
  269.     sprintf(buf, "upsd: %s: %s\n", option, string);
  270.     write(1, buf, strlen(buf)+1);
  271.  
  272.     syslog(LOG_INFO,"error - %s",buf);
  273. }
  274.  
  275.  
  276.  
  277. /*
  278.  * ack()
  279.  * This routine is called to return an OK to the remote host.
  280.  */
  281.  
  282. ack()
  283. {
  284.     buffer[0] = 0;
  285.     write(1,buffer,1);
  286. }
  287.  
  288.  
  289.  
  290. /*
  291.  * opendest(name,file)
  292.  * char *name,*file;
  293.  *
  294.  * Open the destination file "file" in UPSDIR/user, creating the
  295.  * file if necessary.
  296.  */
  297.  
  298. int
  299. opendest(name,file,uid,gid)
  300. char *name,*file;
  301. int uid,gid;
  302. {
  303.     int ret;
  304.  
  305.     sprintf(file_path,"%s/%s",UPSDIR,name); /* Form path to directory */
  306.  
  307.     if (access(file_path,F_OK) == (-1))
  308.     {
  309.         mkdir(file_path,0700);
  310.         chown(file_path,uid,gid);
  311.     }
  312.  
  313.     sprintf(file_path,"%s/%s/%s",UPSDIR,name,file);
  314.  
  315.     if (!access(file_path,F_OK))
  316.     {
  317.         error("file creation","A file by that name has already been sent to that user.");
  318.         return(0);
  319.     } else {
  320.         ret = open(file_path,O_WRONLY|O_CREAT,0600);
  321.         if (ret <= 0)
  322.         {
  323.             sprintf(buffer,"unable to open destination file: %s",
  324.                 file_path);
  325.             error("file open",buffer);
  326.             return(0);
  327.         }
  328.         return(ret);
  329.     }
  330. }
  331.  
  332.  
  333.  
  334. /*
  335.  * sendmail(from,full,from_host,to,list,mess,count)
  336.  * char *from,*full,*to,*from_host,*list,*mess;
  337.  * int    count;
  338.  *
  339.  * This routine sends mail to the destination user to inform
  340.  * them that ups files are awaiting them.
  341.  */
  342.  
  343. sendmail(from,full,from_host,to,list,file,mess,count)
  344. char *from,*full,*to,*from_host,*list,*mess;
  345. int file,count;
  346. {
  347.     FILE *send,*popen();
  348.     static char myhost[BUFSIZ];
  349.  
  350.     gethostname(myhost,BUFSIZ);
  351.     sprintf(buffer,"%s -f%s@%s -F\"%s\" -t",SENDMAIL,from,from_host,full);
  352.  
  353.     if(debugflag)
  354.         syslog(LOG_DEBUG,"sendmail\n%s",buffer);
  355.  
  356.     send = popen(buffer,"w");
  357.  
  358.     fprintf(send,"To: %s@%s\n",to,myhost);
  359.  
  360.     if(debugflag)
  361.         syslog(LOG_DEBUG,"To: %s@%s",to,myhost);
  362.  
  363.     fprintf(send,"Subject: UPS delivery\n");
  364.     if (file > 1)
  365.         strcpy(buffer,"files");
  366.     else
  367.         strcpy(buffer,"file");
  368.  
  369.     fprintf(send,"I have sent you the following %s using ups:\n",buffer);
  370.     fprintf(send,"%s\n\n",list);
  371.     if (file > 1)
  372.         strcpy(buffer,"these files");
  373.     else
  374.         strcpy(buffer,"this file");
  375.         
  376.     fprintf(send,"To retrieve %s, use the ups command.\n\n\n",buffer);
  377.     if (count)
  378.         fprintf(send,"%s\n",mess);
  379.     else
  380.         fprintf(send,"\n\n\n\n---ups\n");
  381.     pclose(send);
  382. }
  383.