home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / nn.tar / nn-6.5.1 / inews / inews.c < prev    next >
C/C++ Source or Header  |  1995-04-29  |  8KB  |  398 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)inews.c    1.16    (Berkeley) 8/27/89";
  3. #endif
  4.  
  5. /*
  6.  * Itty-bitty inews for talking to remote server.
  7.  * Simply accept input on stdin (or via a named file) and dump this
  8.  * to the server; add a From: and Path: line if missing in the original.
  9.  * Print meaningful errors from the server.
  10.  * Limit .signature files to MAX_SIGNATURE lines.
  11.  * No processing of command line options.
  12.  *
  13.  * Original by Steven Grady <grady@ucbvax.Berkeley.EDU>, with thanks from
  14.  * Phil Lapsley <phil@ucbvax.berkeley.edu>
  15.  * Send bug reports to Stan Barber <sob@bcm.tmc.edu>
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <pwd.h>
  20. #include <ctype.h>
  21. #include "conf.h"
  22. #include "nntp.h"
  23. #ifndef FOR_NN
  24. #ifdef USG
  25. #include <string.h>
  26. #else not USG
  27. #include <strings.h>
  28. #endif not USG
  29. #endif
  30.  
  31. #define    MAX_SIGNATURE    4
  32.  
  33. extern    FILE    *ser_wr_fp;
  34.  
  35. char    host_name[256];
  36.  
  37. main(argc, argv)
  38. int    argc;
  39. char    *argv[];
  40. {
  41.     char    line[NNTP_STRLEN], s[NNTP_STRLEN];
  42.     int    seen_fromline, in_header, seen_header;
  43.     int    response;
  44.     char    *server;
  45.     char    *getserverbyfile();
  46.     register char    *cp;
  47.  
  48.     ++argv;
  49.     while (argc > 1)
  50.         if (*argv[0] == '-') {
  51.             ++argv;
  52.             --argc;
  53.         } else
  54.             break;
  55.  
  56.     if (argc > 1) {
  57.         if (freopen(*argv, "r", stdin) == NULL) {
  58.             perror(*argv);
  59.             exit(1);
  60.         }
  61.     }
  62.  
  63.     uname(host_name);
  64.  
  65.     server = getserverbyfile(SERVER_FILE);
  66.     if (server == NULL) {
  67.         fprintf(stderr,
  68.             "Can't get the name of the news server from %s.\n",
  69.             SERVER_FILE);
  70.         fprintf(stderr,
  71.            "Either fix this file, or put NNTPSERVER in your enviroment.\n");
  72.         exit(1);
  73.     }
  74.  
  75.     response = server_init(server);
  76.     if (response < 0) {
  77.         printf("Couldn't connect to %s news server, try again later.\n",
  78.             server);
  79.         exit(1);
  80.     }
  81.  
  82.     if (handle_server_response(response, server) < 0
  83.         || response == OK_NOPOST) {
  84.         close_server();
  85.         exit(1);
  86.     }
  87.  
  88.     put_server("POST");
  89.     (void) get_server(line, sizeof(line));
  90.     if (*line != CHAR_CONT) {
  91.         if (atoi(line) == ERR_NOPOST) {
  92.             close_server();
  93.             fprintf(stderr,
  94.                 "Sorry, you can't post from this machine.\n");
  95.             exit(1);
  96.         } else {
  97.             close_server();
  98.                 fprintf(stderr, "Remote error: %s\n", line);
  99.             exit(1);
  100.         }
  101.     }
  102.  
  103.     in_header = 1;
  104.     seen_header = 0;
  105.     seen_fromline = 0;
  106.  
  107.     while (fgets(s, sizeof(s), stdin) != NULL) {
  108.         if (cp = index(s, '\n'))
  109.             *cp = '\0';
  110.         if (s[0] == '.')    /* Single . is eof, so put in extra one */
  111.             (void) fputc('.', ser_wr_fp);
  112.         if (in_header && strneql(s, "From:", sizeof("From:")-1)) {
  113.                     seen_header = 1;
  114.             seen_fromline = 1;
  115.         }
  116.         if (in_header && s[0] == '\0') {
  117.                     if (seen_header) {
  118.                         in_header = 0;
  119.                     if (!seen_fromline)
  120.                         gen_frompath();
  121.             } else {
  122.                     continue;
  123.             }
  124.         } else if (in_header) {
  125.                 if (valid_header(s))
  126.                     seen_header = 1;
  127.                     else
  128.                                 continue;
  129.         }
  130.         fprintf(ser_wr_fp, "%s\r\n", s);
  131.     }
  132.  
  133.     append_signature();
  134.  
  135.     fprintf(ser_wr_fp, ".\r\n");
  136.     (void) fflush(ser_wr_fp);
  137.     (void) get_server(line, sizeof(line));
  138.     if (*line != CHAR_OK) {
  139.         if (atoi(line) == ERR_POSTFAIL) {
  140.             close_server();
  141.             printf("Article not accepted by server; not posted.\n");
  142.             for (cp = line + 4; *cp && *cp != '\r'; cp++)
  143.                 if (*cp == '\\')
  144.                     putchar('\n');
  145.                 else
  146.                     putchar(*cp);
  147.             exit(1);
  148.         } else {
  149.             close_server();
  150.             fprintf(stderr, "Remote error: %s\n", line);
  151.             exit(1);
  152.         }
  153.     }
  154.  
  155.     /*
  156.      * Close server sends the server a
  157.      * "quit" command for us, which is why we don't send it.
  158.      */
  159.  
  160.     close_server();
  161.  
  162.     exit(0);
  163. }
  164.  
  165. /*
  166.  * append_signature -- append the person's .signature file if
  167.  * they have one.  Limit .signature to MAX_SIGNATURE lines.
  168.  * The rn-style DOTDIR environmental variable is used if present.
  169.  */
  170.  
  171. append_signature()
  172. {
  173.     char    line[256], sigfile[256];
  174.     char    *cp;
  175.     struct    passwd    *passwd;
  176.     FILE    *fp;
  177.     char    *index(), *getenv();
  178.     int    count = 0;
  179.     char    *dotdir;
  180.  
  181.     passwd = getpwuid(getuid());
  182.     if (passwd == NULL)
  183.       return;
  184. #ifdef DO_DOTDIR
  185.     if ((dotdir = getenv("DOTDIR")) == NULL)
  186. #endif
  187.     {
  188.       dotdir = passwd->pw_dir;
  189.     }
  190.  
  191.     if (dotdir[0] == '~') {
  192.       (void) strcpy(sigfile, passwd->pw_dir);
  193.       (void) strcat(sigfile, &dotdir[1]);
  194.     } else {
  195.       (void) strcpy(sigfile, dotdir);
  196.     }
  197.     (void) strcat(sigfile, "/");
  198.     (void) strcat(sigfile, ".signature");
  199.  
  200. #ifdef DEBUG
  201.   fprintf(stderr,"sigfile = '%s'\n", sigfile);
  202. #endif
  203.  
  204.     fp = fopen(sigfile, "r");
  205.     if (fp == NULL)
  206.         return;
  207.  
  208. #ifdef DEBUG
  209.   fprintf(stderr,"sigfile opened OK\n");
  210. #endif
  211.  
  212.     fprintf(ser_wr_fp, "--\r\n");
  213.     while (fgets(line, sizeof (line), fp)) {
  214.         count++;
  215.         if (count > MAX_SIGNATURE) {
  216.             fprintf(stderr,
  217.           "Warning: .signature files should be no longer than %d lines.\n",
  218.             MAX_SIGNATURE);
  219.             fprintf(stderr,
  220.             "(Only %d lines of your .signature were posted.)\n",
  221.             MAX_SIGNATURE);
  222.             break;
  223.         }
  224.         if (cp = index(line, '\n'))
  225.             *cp = '\0';
  226.         fprintf(ser_wr_fp, "%s\r\n", line);
  227.     }
  228.     (void) fclose(fp);
  229. #ifdef DEBUG
  230.     printf(".signature appended (from %s)\n", sigfile);
  231. #endif
  232. }
  233.  
  234.  
  235. /*
  236.  * gen_frompath -- generate From: and Path: lines, in the form
  237.  *
  238.  *    From: user@host.domain (full_name)
  239.  *    Path: host!user
  240.  *
  241.  * This routine should only be called if the message doesn't have
  242.  * a From: line in it.
  243.  */
  244.  
  245. gen_frompath()
  246. {
  247.     char    *full_name;
  248.     char    *cp;
  249.     struct    passwd *passwd;
  250.     char    *index(), *getenv();
  251.  
  252.     passwd = getpwuid(getuid());
  253.  
  254.     full_name = getenv("NAME");
  255.     if (full_name == NULL) {
  256.         full_name = passwd->pw_gecos;
  257.         if ((cp = index(full_name, ',')))
  258.             *cp = '\0';
  259.     }
  260.  
  261. #ifdef DOMAIN
  262. #ifdef HIDDENNET
  263.         fprintf(ser_wr_fp, "From: %s@%s (",
  264.             passwd->pw_name,
  265.             DOMAIN);
  266. #else /* HIDDENNET */
  267.  
  268.     /* A heuristic to see if we should tack on a domain */
  269.  
  270.     cp = index(host_name, '.');
  271.     if (cp)
  272.         fprintf(ser_wr_fp, "From: %s@%s (",
  273.             passwd->pw_name,
  274.             host_name);
  275.     else
  276.         fprintf(ser_wr_fp, "From: %s@%s.%s (",
  277.             passwd->pw_name,
  278.             host_name,
  279.             DOMAIN);
  280. #endif /* HIDDENNET */
  281. #else
  282.     fprintf(ser_wr_fp, "From: %s@%s (",
  283.         passwd->pw_name,
  284.         host_name);
  285. #endif
  286.  
  287.     for (cp = full_name; *cp != '\0'; ++cp)
  288.         if (*cp != '&')
  289.             putc(*cp, ser_wr_fp);
  290.         else {        /* Stupid & hack.  God damn it. */
  291.             putc(toupper(passwd->pw_name[0]), ser_wr_fp);
  292.             fprintf(ser_wr_fp, passwd->pw_name+1);
  293.         }
  294.  
  295.     fprintf(ser_wr_fp, ")\r\n");
  296.  
  297. #ifdef HIDDENNET
  298.     /* Only the login name - nntp server will add uucp name */
  299.     fprintf(ser_wr_fp, "Path: %s\r\n", passwd->pw_name);
  300. #else /* HIDDENNET */
  301.     fprintf(ser_wr_fp, "Path: %s!%s\r\n", host_name, passwd->pw_name);
  302. #endif /* HIDDENNET */
  303. }
  304.  
  305.  
  306. /*
  307.  * strneql -- determine if two strings are equal in the first n
  308.  * characters, ignoring case.
  309.  *
  310.  *    Parameters:    "a" and "b" are the pointers
  311.  *            to characters to be compared.
  312.  *            "n" is the number of characters to compare.
  313.  *
  314.  *    Returns:    1 if the strings are equal, 0 otherwise.
  315.  *
  316.  *    Side effects:    None.
  317.  */
  318.  
  319. strneql(a, b, n)
  320. register char *a, *b;
  321. int    n;
  322. {
  323.     char    lower();
  324.  
  325.     while (n && lower(*a) == lower(*b)) {
  326.         if (*a == '\0')
  327.             return (1);
  328.         a++;
  329.         b++;
  330.         n--;
  331.     }
  332.     if (n)
  333.         return (0);
  334.     else
  335.         return (1);
  336. }
  337.  
  338. /*
  339.  * lower -- convert a character to lower case, if it's
  340.  *    upper case.
  341.  *
  342.  *    Parameters:    "c" is the character to be
  343.  *            converted.
  344.  *
  345.  *    Returns:    "c" if the character is not
  346.  *            upper case, otherwise the lower
  347.  *            case eqivalent of "c".
  348.  *
  349.  *    Side effects:    None.
  350.  */
  351.  
  352. char lower(c)
  353. register char c;
  354. {
  355.     if (isascii(c) && isupper(c))
  356.         c = c - 'A' + 'a';
  357.     return(c);
  358. }
  359.  
  360.  
  361. /*
  362.  * valid_header -- determine if a line is a valid header line
  363.  *
  364.  *    Parameters:    "h" is the header line to be checked.
  365.  *
  366.  *    Returns:     1 if valid, 0 otherwise
  367.  *
  368.  *    Side Effects:    none
  369.  *
  370.  */
  371.  
  372. int valid_header(h)
  373. register char *h;
  374. {
  375.   char *index();
  376.   char *colon, *space;
  377.  
  378.   /*
  379.    * blank or tab in first position implies this is a continuation header
  380.    */
  381.   if (h[0] == ' ' || h[0] == '\t')
  382.     return (1);
  383.  
  384.   /*
  385.    * just check for initial letter, colon, and space to make
  386.    * sure we discard only invalid headers
  387.    */
  388.   colon = index(h, ':');
  389.   space = index(h, ' ');
  390.   if (isalpha(h[0]) && colon && space == colon + 1)
  391.     return (1);
  392.  
  393.   /*
  394.    * anything else is a bad header -- it should be ignored
  395.    */
  396.   return (0);
  397. }
  398.