1: #ifndef lint 2: static char *sccsid = "@(#)inews.c 1.15 (Berkeley) 2/6/88"; 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>, who is now responsible for it. 15: */ 16: 17: #include <stdio.h> 18: #include <pwd.h> 19: #include <ctype.h> 20: #include "../common/conf.h" 21: #include "../common/nntp.h" 22: #ifdef USG 23: #include <string.h> 24: #else not USG 25: #include <strings.h> 26: #endif not USG 27: 28: #define MAX_SIGNATURE 4 29: 30: extern FILE *ser_wr_fp; 31: 32: char host_name[256]; 33: 34: main(argc, argv) 35: int argc; 36: char *argv[]; 37: { 38: char line[NNTP_STRLEN], s[NNTP_STRLEN]; 39: int seen_fromline, in_header; 40: int response; 41: char *server; 42: char *getserverbyfile(); 43: register char *cp; 44: 45: ++argv; 46: while (argc > 1) 47: if (*argv[0] == '-') { 48: ++argv; 49: --argc; 50: } else 51: break; 52: 53: if (argc > 1) { 54: if (freopen(*argv, "r", stdin) == NULL) { 55: perror(*argv); 56: exit(1); 57: } 58: } 59: 60: uname(host_name); 61: 62: server = getserverbyfile(SERVER_FILE); 63: if (server == NULL) { 64: fprintf(stderr, 65: "Can't get the name of the news server from %s.\n", 66: SERVER_FILE); 67: fprintf(stderr, 68: "Either fix this file, or put NNTPSERVER in your enviroment.\n"); 69: exit(1); 70: } 71: 72: response = server_init(server); 73: if (response < 0) { 74: printf("Couldn't connect to %s news server, try again later.\n", 75: server); 76: exit(1); 77: } 78: 79: if (handle_server_response(response, server) < 0 80: || response == OK_NOPOST) { 81: close_server(); 82: exit(1); 83: } 84: 85: put_server("POST"); 86: (void) get_server(line, sizeof(line)); 87: if (*line != CHAR_CONT) { 88: if (atoi(line) == ERR_NOPOST) { 89: close_server(); 90: fprintf(stderr, 91: "Sorry, you can't post from this machine.\n"); 92: exit(1); 93: } else { 94: close_server(); 95: fprintf(stderr, "Remote error: %s\n", line); 96: exit(1); 97: } 98: } 99: 100: in_header = 1; 101: seen_fromline = 0; 102: 103: while (gets(s) != NULL) { 104: if (s[0] == '.') /* Single . is eof, so put in extra one */ 105: (void) fputc('.', ser_wr_fp); 106: if (in_header && strneql(s, "From:", sizeof("From:")-1)) 107: seen_fromline = 1; 108: if (in_header && s[0] == '\0') { 109: in_header = 0; 110: if (!seen_fromline) 111: gen_frompath(); 112: } 113: fprintf(ser_wr_fp, "%s\r\n", s); 114: } 115: 116: append_signature(); 117: 118: fprintf(ser_wr_fp, ".\r\n"); 119: (void) fflush(ser_wr_fp); 120: (void) get_server(line, sizeof(line)); 121: if (*line != CHAR_OK) { 122: if (atoi(line) == ERR_POSTFAIL) { 123: close_server(); 124: printf("Article not accepted by server; not posted.\n"); 125: for (cp = line + 4; *cp && *cp != '\r'; cp++) 126: if (*cp == '\\') 127: putchar('\n'); 128: else 129: putchar(*cp); 130: exit(1); 131: } else { 132: close_server(); 133: fprintf(stderr, "Remote error: %s\n", line); 134: exit(1); 135: } 136: } 137: 138: /* 139: * Close server sends the server a 140: * "quit" command for us, which is why we don't send it. 141: */ 142: 143: close_server(); 144: 145: exit(0); 146: } 147: 148: /* 149: * append_signature -- append the person's .signature file if 150: * they have one. Limit .signature to MAX_SIGNATURE lines. 151: */ 152: 153: append_signature() 154: { 155: char line[256], sigfile[256]; 156: char *cp; 157: struct passwd *passwd; 158: FILE *fp; 159: char *index(); 160: int count = 0; 161: 162: passwd = getpwuid(getuid()); 163: if (passwd == NULL) 164: return; 165: 166: (void) strcpy(sigfile, passwd->pw_dir); 167: (void) strcat(sigfile, "/"); 168: (void) strcat(sigfile, ".signature"); 169: 170: fp = fopen(sigfile, "r"); 171: if (fp == NULL) 172: return; 173: 174: while (fgets(line, sizeof (line), fp)) { 175: count++; 176: if (count > MAX_SIGNATURE) { 177: fprintf(stderr, 178: "Warning: .signature files should be no longer than %d lines.\n", 179: MAX_SIGNATURE); 180: fprintf(stderr, 181: "(Only %d lines of your .signature were posted.)\n", 182: MAX_SIGNATURE); 183: break; 184: } 185: if (cp = index(line, '\n')) 186: *cp = '\0'; 187: fprintf(ser_wr_fp, "%s\r\n", line); 188: } 189: (void) fclose(fp); 190: } 191: 192: 193: /* 194: * gen_frompath -- generate From: and Path: lines, in the form 195: * 196: * From: user@host.domain (full_name) 197: * Path: host!user 198: * 199: * This routine should only be called if the message doesn't have 200: * a From: line in it. 201: */ 202: 203: gen_frompath() 204: { 205: char *full_name; 206: char *cp; 207: struct passwd *passwd; 208: char *index(), *getenv(); 209: 210: passwd = getpwuid(getuid()); 211: 212: full_name = getenv("NAME"); 213: if (full_name == NULL) { 214: full_name = passwd->pw_gecos; 215: if ((cp = index(full_name, ','))) 216: *cp = '\0'; 217: } 218: 219: #ifdef DOMAIN 220: 221: /* A heuristic to see if we should tack on a domain */ 222: 223: cp = index(host_name, '.'); 224: if (cp) 225: fprintf(ser_wr_fp, "From: %s@%s (", 226: passwd->pw_name, 227: host_name); 228: else 229: fprintf(ser_wr_fp, "From: %s@%s.%s (", 230: passwd->pw_name, 231: host_name, 232: DOMAIN); 233: #else 234: fprintf(ser_wr_fp, "From: %s@%s (", 235: passwd->pw_name, 236: host_name); 237: #endif 238: 239: for (cp = full_name; *cp != '\0'; ++cp) 240: if (*cp != '&') 241: putc(*cp, ser_wr_fp); 242: else { /* Stupid & hack. God damn it. */ 243: putc(toupper(passwd->pw_name[0]), ser_wr_fp); 244: fprintf(ser_wr_fp, passwd->pw_name+1); 245: } 246: 247: fprintf(ser_wr_fp, ")\r\n"); 248: 249: fprintf(ser_wr_fp, "Path: %s!%s\r\n", host_name, passwd->pw_name); 250: } 251: 252: 253: /* 254: * strneql -- determine if two strings are equal in the first n 255: * characters, ignoring case. 256: * 257: * Parameters: "a" and "b" are the pointers 258: * to characters to be compared. 259: * "n" is the number of characters to compare. 260: * 261: * Returns: 1 if the strings are equal, 0 otherwise. 262: * 263: * Side effects: None. 264: */ 265: 266: strneql(a, b, n) 267: register char *a, *b; 268: int n; 269: { 270: char lower(); 271: 272: while (n && lower(*a) == lower(*b)) { 273: if (*a == '\0') 274: return (1); 275: a++; 276: b++; 277: n--; 278: } 279: if (n) 280: return (0); 281: else 282: return (1); 283: } 284: 285: /* 286: * lower -- convert a character to lower case, if it's 287: * upper case. 288: * 289: * Parameters: "c" is the character to be 290: * converted. 291: * 292: * Returns: "c" if the character is not 293: * upper case, otherwise the lower 294: * case eqivalent of "c". 295: * 296: * Side effects: None. 297: */ 298: 299: char lower(c) 300: register char c; 301: { 302: if (isascii(c) && isupper(c)) 303: c = c - 'A' + 'a'; 304: return(c); 305: }