#include #include #include #include #include /* Name of news Server */ #define SERVER "miner.mathematik.uni-ulm.de" /* Port of news Server */ #define PORT "8080" /* Name of group to examine */ #define GROUP "miner.local.softss02" /* Number of post to look up */ #define NR 5 /* Skip rest of line until we find the \r\n sequence. This works for * lines of arbitrary length and also handles things like eof and \r\r\r\n * correctly. */ void skipline (FILE * in ) { int c, gotr; gotr = 0; while (1) { c = fgetc (in); if (c < 0) break; if (gotr && (c == '\n')) break; gotr = (c == '\r'); } } /* This function reads a line starting with a integer return code * from the file in. The return code is converted to an integer and * returned, the rest of the line is discared. Note that this * function works for lines of arbitrary length. */ int codeline (FILE * in) { int code; if (fscanf (in, "%d", &code) != 1) return -1; skipline (in); return code; } /* Print the Subject, From and Date Line of the header to stdout. */ void summary (FILE * in) { char line[100]; int header = 1, print; while (1) { fgets (line, 100, in); /* End of file? */ if (feof (in)) break; /* End of text for this article ? */ if (strcmp (line, ".\r\n") == 0) break; /* End of Message header? */ if (strcmp (line, "\r\n") == 0) header = 0; /* Subject, From or Date line? */ if (!header) continue; print = 0; if ((strncmp (line, "Subject: ", 9) == 0) || (strncmp (line, "From: ", 6) == 0) || (strncmp (line, "Date: ", 6) == 0)) { printf ("%s", line); print = 1; } /* Skip/Print rest of line */ while (1) { if (strstr (line, "\r\n")) break; fgets (line, 100, in); if (feof (in)) break; if (print) printf ("%s", line); } } printf ("\n"); } int main () { int p1[2], p2[2], pid, min, max, code, pos, found, cnt; FILE * out, * in; /* Buffered file-Descriptors for parent */ char line[100]; /* Create two pipes for stdin and stdout */ if (pipe (p1) < 0) { perror ("pipe"); exit (1); } if (pipe (p2) < 0) { perror ("pipe"); exit (1); } /* Create Child-Process for network kommunication */ pid = fork (); if (pid < 0) { perror ("fork"); exit (1); } if (pid == 0) { /* Child Process */ /* Make pipe p1 our stdinput */ close (p1[1]); close (0); dup (p1[0]); close (p1[0]); /* Make pipe p2 out stdoutput */ close (p2[0]); close (1); dup (p2[1]); close (p2[1]); /* Start nc Process */ execlp ("nc", "nc", SERVER, PORT, NULL); /* Exec failed. Try netcat instead */ perror ("execlp"); execlp ("netcat", "netcat", SERVER, PORT, NULL); perror ("execlp"); exit (1); } /* End of child */ /* Parent */ /* Close pipe ends that we don't need */ close (p1[0]); out = fdopen (p1[1], "w"); close (p2[1]); in = fdopen (p2[0], "r"); /* Handle the NNTP dialog */ /* Wait for welcome message from server */ code = codeline (in); if ((code != 200) && (code != 201)) { fprintf (stderr, "No connection to server (code %d)\n", code); exit (1); } /* Select newsgroup */ fprintf (out, "group %s\r\n", GROUP); fflush (out); cnt = fscanf (in, "%d %*d %d %d", &code, &min, &max); /* The server must send at least a return code. */ if (cnt < 1) { fprintf (stderr, "Bad response from server while selecting group\n"); exit (1); } /* If the code is not 211 group selection failed. */ if (code != 211) { fprintf (stderr, "Error selecting group (code %d)\n", code); exit (1); } /* If the code is 211 the server must send meaningful min and max * values. */ if (cnt != 3) { fprintf (stderr, "Bad response from server while selecting group\n"); exit (1); } /* Group selection successful. Skip rest of group selection line. */ skipline (in); /* Retrieve at most 5 article headers and From and Subject lines. */ pos = max; found = 0; while ((pos >= min) && (pos <= max) && (found < 5)) { /* Try to get header of posting at current position. */ fprintf (out, "head %d\r\n", pos); fflush (out); code = codeline (in); switch (code) { case 220: /* Head and body follows */ case 221: /* Head follows */ /* Print message summary to stdout. */ summary (in); found++; break; case 222: /* Only body follows */ case 223: /* No text follows. */ fprintf (stderr, "Server won't send requested header (code %d)\n", code); exit (1); break; case 412: /* Server says: No newsgroup selected */ case 420: /* Server says: No current article selected */ fprintf (stderr, "Server is in strange state (code %d)\n", code); exit (1); break; case 423: /* No such article number */ case 430: /* No such article */ /* Just skip this article number and try the next. */ break; default: /* Unexpected Error message */ fprintf (stderr, "Server sent unexpected error message (code %d)\n", code); break; } pos--; } /* Terminate connection */ fprintf (out, "quit\r\n"); fflush (out); fclose (out); /* Do not just close the pipe, wait for end of file! The child * process may still write data to the pipe. */ while (1) { fgets (line, 100, in); if (feof (in)) break; } /* Wait for termination of child. */ wait (NULL); return 0; }