BSD 4_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 11 May 1983 13:28:27 +0000 (05:28 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 11 May 1983 13:28:27 +0000 (05:28 -0800)
Work on file usr/src/ucb/talk/talk.h
Work on file usr/src/ucb/talk/talkd.c
Work on file usr/src/ucb/talk/ctl.h
Work on file usr/src/ucb/talk/talk_ctl.h
Work on file usr/src/ucb/talk/process.c
Work on file usr/src/ucb/talk/print.c
Work on file usr/src/ucb/talk/talk.c
Work on file usr/src/ucb/talk/get_names.c
Work on file usr/src/ucb/talk/display.c
Work on file usr/src/ucb/talk/get_addrs.c
Work on file usr/src/ucb/talk/README
Work on file usr/src/ucb/talk/look_up.c

Synthesized-from: CSRG/cd1/4.2

12 files changed:
usr/src/ucb/talk/README [new file with mode: 0644]
usr/src/ucb/talk/ctl.h [new file with mode: 0644]
usr/src/ucb/talk/display.c [new file with mode: 0644]
usr/src/ucb/talk/get_addrs.c [new file with mode: 0644]
usr/src/ucb/talk/get_names.c [new file with mode: 0644]
usr/src/ucb/talk/look_up.c [new file with mode: 0644]
usr/src/ucb/talk/print.c [new file with mode: 0644]
usr/src/ucb/talk/process.c [new file with mode: 0644]
usr/src/ucb/talk/talk.c [new file with mode: 0644]
usr/src/ucb/talk/talk.h [new file with mode: 0644]
usr/src/ucb/talk/talk_ctl.h [new file with mode: 0644]
usr/src/ucb/talk/talkd.c [new file with mode: 0644]

diff --git a/usr/src/ucb/talk/README b/usr/src/ucb/talk/README
new file mode 100644 (file)
index 0000000..93f4a22
--- /dev/null
@@ -0,0 +1,35 @@
+Talk consists of two parts:
+
+    talk itself, which is the user interface. Talk initiates the
+        talk requests and negotiates with the suitable talk daemons.
+
+    talkd, the talk daemon. Talkd announces an invitation to talk
+        to a user on its' local machine and acts like a rendezvous
+        point for inter-machine talks. The socket address's of
+        the invitING talk process is kept at the local talkd of
+        the invitEE. Talkd must run as root, and should be forked
+        off on boot along with the other daemons. There is
+        no provision for automatic restart of talkd. If for
+        some reason it dies, it must be restarted by hand. Since
+        talkd opens a special addresses socket (517 at the present 
+        time), the first talkd to run will lock out any other
+        talkd. The locked out talkd will sit and bitch every
+        15 seconds for about five minutes, so don't leave it running.
+
+
+So, to install:
+
+       run 'make install' from the top of the talk source directory.
+       The install will fail if an older version of talkd is still
+       running. If it does fail because of a 'text file busy' error,
+       kill the old talkd and 'make install' again.
+
+       execute '/usr/lib/talkd' to start the daemon immediately.
+
+       Install a line in /etc/rc or /etc/rc.local to fork talkd off in
+       background on reboot. 
+
+       Try talk. If it immediately fails with 'Bad system call', then
+       you should recompile ctl.c with the -DGETSOCK flag and remake
+       talk. This makes talk use getsockname (actually syscall(150))
+       instead socketaddr(). This will go away once 4.1c stabilizes.
diff --git a/usr/src/ucb/talk/ctl.h b/usr/src/ucb/talk/ctl.h
new file mode 100644 (file)
index 0000000..d21befd
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Header: ctl.h 1.4 83/03/28 20:46:27 moore Exp $ */
+
+/* ctl.h describes the structure that talk and talkd pass back
+   and forth
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#define NAME_SIZE 9
+#define TTY_SIZE 16
+#define HOST_NAME_LENGTH 256
+
+#define MAX_LIFE 60 /* maximum time an invitation is saved by the
+                        talk daemons */
+#define RING_WAIT 30  /* time to wait before refreshing invitation 
+                        should be 10's of seconds less than MAX_LIFE */
+
+    /* the values for type */
+
+#define LEAVE_INVITE 0
+#define LOOK_UP 1
+#define DELETE 2
+#define ANNOUNCE 3
+
+    /* the values for answer */
+
+#define SUCCESS 0
+#define NOT_HERE 1
+#define FAILED 2
+#define MACHINE_UNKNOWN 3
+#define PERMISSION_DENIED 4
+#define UNKNOWN_REQUEST 5
+
+typedef struct ctl_response CTL_RESPONSE;
+
+struct ctl_response {
+    char type;
+    char answer;
+    int id_num;
+    struct sockaddr_in addr;
+};
+
+typedef struct ctl_msg CTL_MSG;
+
+struct ctl_msg {
+    char type;
+    char l_name[NAME_SIZE];
+    char r_name[NAME_SIZE];
+    int id_num;
+    int pid;
+    char r_tty[TTY_SIZE];
+    struct sockaddr_in addr;
+    struct sockaddr_in ctl_addr;
+};
diff --git a/usr/src/ucb/talk/display.c b/usr/src/ucb/talk/display.c
new file mode 100644 (file)
index 0000000..22615a0
--- /dev/null
@@ -0,0 +1,170 @@
+/* $Header: display.c 1.2 83/04/23 02:09:33 moore Exp $ */
+
+/* The window 'manager', initializes curses and handles the actual
+ * displaying of text
+ */
+
+#include "talk.h"
+
+xwin_t my_win;
+xwin_t his_win;
+WINDOW *line_win;
+
+int curses_initialized = 0;
+
+    /* max HAS to be a function, it is called with
+     * a argument of the form --foo at least once.
+     */
+
+max(a,b)
+int a, b;
+{
+    if (a > b) {
+       return(a);
+    } else {
+       return(b);
+    }
+}
+
+/*
+ * Display some text on somebody's window, processing some control
+ * characters while we are at it.
+ */
+
+display(win, text, size)
+register xwin_t *win;
+register char *text;
+int size;
+{
+    register int i;
+    char cch;
+
+    for (i = 0; i < size; i++) {
+
+       if (*text == '\n') {
+           xscroll(win, 0);
+           text++;
+           continue;
+       }
+
+           /* erase character */
+
+       if (*text == win->cerase) {
+           wmove(win->x_win, win->x_line, max(--win->x_col, 0));
+           getyx(win->x_win, win->x_line, win->x_col);
+           waddch(win->x_win, ' ');
+           wmove(win->x_win, win->x_line, win->x_col);
+           getyx(win->x_win, win->x_line, win->x_col);
+           text++;
+           continue;
+       }
+       /*
+        * On word erase search backwards until we find
+        * the beginning of a word or the beginning of
+        * the line.
+        */
+       if (*text == win->werase) {
+           int endcol, xcol, i, c;
+
+           endcol = win->x_col;
+           xcol = endcol - 1;
+           while (xcol >= 0) {
+               c = readwin(win->x_win, win->x_line, xcol);
+               if (c != ' ')
+                       break;
+               xcol--;
+           }
+           while (xcol >= 0) {
+               c = readwin(win->x_win, win->x_line, xcol);
+               if (c == ' ')
+                       break;
+               xcol--;
+           }
+           wmove(win->x_win, win->x_line, xcol + 1);
+           for (i = xcol + 1; i < endcol; i++)
+               waddch(win->x_win, ' ');
+           wmove(win->x_win, win->x_line, xcol + 1);
+           getyx(win->x_win, win->x_line, win->x_col);
+           continue;
+       }
+           /* line kill */
+       if (*text == win->kill) {
+           wmove(win->x_win, win->x_line, 0);
+           wclrtoeol(win->x_win);
+           getyx(win->x_win, win->x_line, win->x_col);
+           text++;
+           continue;
+       }
+       if (*text == '\f') {
+           if (win == &my_win)
+               wrefresh(curscr);
+           text++;
+           continue;
+       }
+
+       if (win->x_col == COLS-1) {
+               /* check for wraparound */
+           xscroll(win, 0);
+       }
+
+       if (*text < ' ' && *text != '\t') {
+           waddch(win->x_win, '^');
+           getyx(win->x_win, win->x_line, win->x_col);
+
+           if (win->x_col == COLS-1) {
+                   /* check for wraparound */
+               xscroll(win, 0);
+           }
+
+           cch = (*text & 63) + 64;
+           waddch(win->x_win, cch);
+       } else {
+           waddch(win->x_win, *text);
+       }
+
+       getyx(win->x_win, win->x_line, win->x_col);
+       text++;
+
+    }
+wrefresh(win->x_win);
+}
+
+/*
+* Read the character at the indicated position in win
+*/
+readwin(win, line, col)
+WINDOW *win;
+{
+int oldline, oldcol;
+register int c;
+
+getyx(win, oldline, oldcol);
+wmove(win, line, col);
+c = winch(win);
+wmove(win, oldline, oldcol);
+return(c);
+}
+
+/*
+* Scroll a window, blanking out the line following the current line
+* so that the current position is obvious
+*/
+
+xscroll(win, flag)
+register xwin_t *win;
+int flag;
+{
+    if (flag == -1) {
+       wmove(win->x_win, 0, 0);
+       win->x_line = 0;
+       win->x_col = 0;
+       return;
+    }
+    win->x_line = (win->x_line + 1) % win->x_nlines;
+    win->x_col = 0;
+    wmove(win->x_win, win->x_line, win->x_col);
+    wclrtoeol(win->x_win);
+    wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col);
+    wclrtoeol(win->x_win);
+    wmove(win->x_win, win->x_line, win->x_col);
+}
diff --git a/usr/src/ucb/talk/get_addrs.c b/usr/src/ucb/talk/get_addrs.c
new file mode 100644 (file)
index 0000000..0a57e71
--- /dev/null
@@ -0,0 +1,77 @@
+/* $Header: get_addrs.c 1.5 83/04/01 17:55:41 moore Exp $ */
+
+#include "talk_ctl.h"
+
+struct hostent *gethostbyname();
+struct servent *getservbyname();
+
+get_addrs(my_machine_name, his_machine_name)
+char *my_machine_name;
+char *his_machine_name;
+{
+    struct hostent *hp;
+    struct servent *sp;
+
+    msg.pid = getpid();
+
+       /* look up the address of the local host */
+
+    hp = gethostbyname(my_machine_name);
+
+    if (hp == (struct hostent *) 0) {
+       printf("This machine doesn't exist. Boy, am I confused!\n");
+       exit(-1);
+    }
+
+    if (hp->h_addrtype != AF_INET) {
+       printf("Protocal mix up with local machine address\n");
+       exit(-1);
+    }
+
+    bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
+
+       /* if he is on the same machine, then simply copy */
+
+    if ( bcmp((char *)&his_machine_name, (char *)&my_machine_name,
+               sizeof(his_machine_name)) == 0) {
+       bcopy((char *)&my_machine_addr, (char *)&his_machine_addr,
+               sizeof(his_machine_name));
+    } else {
+
+       /* look up the address of the recipient's machine */
+
+       hp = gethostbyname(his_machine_name);
+
+       if (hp == (struct hostent *) 0 ) {
+           printf("%s is an unknown host\n", his_machine_name);
+           exit(-1);
+       }
+
+       if (hp->h_addrtype != AF_INET) {
+           printf("Protocol mix up with remote machine address\n");
+           exit(-1);
+       }
+
+       bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
+    }
+
+       /* find the daemon portal */
+
+#ifdef NTALK
+    sp = getservbyname("ntalk", "udp");
+#else
+    sp = getservbyname("talk", "udp");
+#endif
+
+    if (strcmp(sp->s_proto, "udp") != 0) {
+       printf("Protocol mix up with talk daemon\n");
+       exit(-1);
+    }
+
+    if (sp == 0) {
+           p_error("This machine doesn't support a tcp talk daemon");
+           exit(-1);
+    }
+
+    daemon_port = sp->s_port;
+}
diff --git a/usr/src/ucb/talk/get_names.c b/usr/src/ucb/talk/get_names.c
new file mode 100644 (file)
index 0000000..71dd4b7
--- /dev/null
@@ -0,0 +1,103 @@
+/* $Header: get_names.c 1.2 83/03/26 14:35:54 moore Exp $ */
+
+#include "talk.h"
+#include "ctl.h"
+
+char *getlogin(), *ttyname(), *rindex();
+
+extern CTL_MSG msg;
+
+/*
+ * Determine the local and remote user, tty, and machines
+ */
+
+struct hostent *gethostbyname();
+
+get_names(argc, argv)
+int argc;
+char *argv[];
+{
+    char hostname[HOST_NAME_LENGTH];
+    char *his_name;
+    char *my_name;
+    char *my_machine_name;
+    char *his_machine_name;
+    char *my_tty;
+    char *his_tty;
+    char *ptr;
+    int name_length;
+
+    if (argc < 2 ) {
+       printf("Usage:  talk user [ttyname]\n");
+       exit(-1);
+    }
+    if ( !isatty(0) ) {
+       printf("Standard input must be a tty, not a pipe or a file\n");
+       exit(-1);
+    }
+
+    my_name = getlogin();
+    if (my_name == NULL) {
+       printf("You don't exist. Go away.\n");
+       exit(-1);
+    }
+
+    name_length = HOST_NAME_LENGTH;
+    gethostname(hostname, &name_length);
+    my_machine_name = hostname;
+
+    my_tty = rindex(ttyname(0), '/') + 1;
+
+       /* check for, and strip out, the machine name 
+           of the target */
+
+    for (ptr = argv[1]; *ptr != '\0' &&
+                        *ptr != '@' &&
+                        *ptr != ':' &&
+                        *ptr != '!' &&
+                        *ptr != '.'     ; ptr++) {
+    }
+
+    if (*ptr == '\0') {
+
+           /* this is a local to local talk */
+
+       his_name = argv[1];
+       his_machine_name = my_machine_name;
+
+    } else {
+
+       if (*ptr == '@') {
+               /* user@host */
+           his_name = argv[1];
+           his_machine_name = ptr + 1;
+       } else {
+               /* host.user or host!user or host:user */
+           his_name = ptr + 1;
+           his_machine_name = argv[1];
+       }
+       *ptr = '\0';
+    }
+
+
+    if (argc > 2) {
+       his_tty = argv[2];      /* tty name is arg 2 */
+    } else {
+       his_tty = (char *) 0;
+    }
+
+    get_addrs(my_machine_name, his_machine_name);
+
+       /* Load these useful values into the standard message header */
+
+    msg.id_num = 0;
+
+    strncpy(msg.l_name, my_name, NAME_SIZE);
+    msg.l_name[NAME_SIZE - 1] = '\0';
+
+    strncpy(msg.r_name, his_name, NAME_SIZE);
+    msg.r_name[NAME_SIZE - 1] = '\0';
+
+    strncpy(msg.r_tty, his_tty, TTY_SIZE);
+    msg.r_tty[TTY_SIZE - 1] = '\0';
+}
diff --git a/usr/src/ucb/talk/look_up.c b/usr/src/ucb/talk/look_up.c
new file mode 100644 (file)
index 0000000..fe9087c
--- /dev/null
@@ -0,0 +1,78 @@
+/* $Header: look_up.c 1.2 83/03/28 00:34:22 moore Exp $ */
+
+#include "talk_ctl.h"
+
+    /* see if the local daemon has a invitation for us */
+
+check_local()
+{
+    CTL_RESPONSE response;
+
+       /* the rest of msg was set up in get_names */
+
+    msg.ctl_addr = ctl_addr;
+
+    if (!look_for_invite(&response)) {
+
+           /* we must be initiating a talk */
+
+       return(0);
+    }
+
+        /*
+        * there was an invitation waiting for us, 
+        * so connect with the other (hopefully waiting) party 
+        */
+
+    current_state = "Waiting to connect with caller";
+
+    while (connect(sockt, &response.addr, sizeof(response.addr)) != 0) {
+       if (errno == ECONNREFUSED) {
+
+               /* the caller gave up, but his invitation somehow
+                * was not cleared. Clear it and initiate an 
+                * invitation. (We know there are no newer invitations,
+                * the talkd works LIFO.)
+                */
+
+           ctl_transact(his_machine_addr, msg, DELETE, &response);
+           close(sockt);
+           open_sockt();
+           return(0);
+       } else if (errno == EINTR) {
+               /* we have returned from an interupt handler */
+           continue;
+       } else {
+           p_error("Unable to connect with initiator");
+       }
+    }
+
+    return(1);
+}
+
+    /* look for an invitation on 'machine' */
+
+look_for_invite(response)
+CTL_RESPONSE *response;
+{
+    struct in_addr machine_addr;
+
+    current_state = "Checking for invitation on caller's machine";
+
+    ctl_transact(his_machine_addr, msg, LOOK_UP, response);
+
+       /* the switch is for later options, such as multiple 
+          invitations */
+
+    switch (response->answer) {
+
+       case SUCCESS:
+
+           msg.id_num = response->id_num;
+           return(1);
+
+       default :
+               /* there wasn't an invitation waiting for us */
+           return(0);
+    }
+}
diff --git a/usr/src/ucb/talk/print.c b/usr/src/ucb/talk/print.c
new file mode 100644 (file)
index 0000000..0d05d2a
--- /dev/null
@@ -0,0 +1,25 @@
+/* $Header: print.c 1.4 83/03/28 00:34:25 moore Exp $ */
+
+/* debug print routines */
+
+#include <stdio.h>
+#include "ctl.h"
+
+print_request(request)
+CTL_MSG *request;
+{
+    
+    printf("type is %d, l_user %s, r_user %s, r_tty %s\n",
+           request->type, request->l_name, request->r_name,
+           request->r_tty);
+    printf("        id = %d\n", request->id_num);
+    fflush(stdout);
+}
+
+print_response(response)
+CTL_RESPONSE *response;
+{
+    printf("type is %d, answer is %d, id = %d\n\n", response->type, 
+           response->answer, response->id_num);
+    fflush(stdout);
+}
diff --git a/usr/src/ucb/talk/process.c b/usr/src/ucb/talk/process.c
new file mode 100644 (file)
index 0000000..0075354
--- /dev/null
@@ -0,0 +1,155 @@
+/* $Header: process.c 1.5 83/03/28 20:16:07 moore Exp $ */
+
+    /* process.c handles the requests, which can be of three types:
+
+               ANNOUNCE - announce to a user that a talk is wanted
+
+               LEAVE_INVITE - insert the request into the table
+               
+               LOOK_UP - look up to see if a request is waiting in
+                         in the table for the local user
+
+               DELETE - delete invitation
+
+     */
+
+#include "ctl.h"
+char *strcpy();
+CTL_MSG *find_request();
+CTL_MSG *find_match();
+
+process_request(request, response)
+CTL_MSG *request;
+CTL_RESPONSE *response;
+{
+    CTL_MSG *ptr;
+
+    response->type = request->type;
+    response->id_num = 0;
+
+    switch (request->type) {
+
+       case ANNOUNCE :
+
+           do_announce(request, response);
+           break;
+
+       case LEAVE_INVITE :
+
+           ptr = find_request(request);
+           if (ptr != (CTL_MSG *) 0) {
+               response->id_num = ptr->id_num;
+               response->answer = SUCCESS;
+           } else {
+               insert_table(request, response);
+           }
+           break;
+
+       case LOOK_UP :
+
+           ptr = find_match(request);
+           if (ptr != (CTL_MSG *) 0) {
+               response->id_num = ptr->id_num;
+               response->addr = ptr->addr;
+               response->answer = SUCCESS;
+           } else {
+               response->answer = NOT_HERE;
+           }
+           break;
+
+       case DELETE :
+
+           response->answer = delete_invite(request->id_num);
+           break;
+
+       default :
+
+           response->answer = UNKNOWN_REQUEST;
+           break;
+
+    }
+}
+
+struct hostent *gethostbyaddr();
+
+do_announce(request, response)
+CTL_MSG *request;
+CTL_RESPONSE *response;
+{
+    struct hostent *hp;
+    CTL_MSG *ptr;
+    int result;
+
+       /* see if the user is logged */
+
+    result = find_user(request->r_name, request->r_tty);
+
+    if (result != SUCCESS) {
+       response->answer = result;
+       return;
+    }
+
+    hp = gethostbyaddr(&request->ctl_addr.sin_addr,
+                         sizeof(struct in_addr), AF_INET);
+
+    if ( hp == (struct hostent *) 0 ) {
+       response->answer = MACHINE_UNKNOWN;
+       return;
+    }
+
+    ptr = find_request(request);
+    if (ptr == (CTL_MSG *) 0) {
+       insert_table(request,response);
+       response->answer = announce(request, hp->h_name);
+    } else if (request->id_num > ptr->id_num) {
+           /*
+            * this is an explicit re-announce, so update the id_num
+            * field to avoid duplicates and re-announce the talk 
+            */
+       ptr->id_num = response->id_num = new_id();
+       response->answer = announce(request, hp->h_name);
+    } else {
+           /* a duplicated request, so ignore it */
+       response->id_num = ptr->id_num;
+       response->answer = SUCCESS;
+    }
+
+    return;
+}
+
+#include <utmp.h>
+
+/*
+ * Search utmp for the local user
+ */
+
+find_user(name, tty)
+char *name;
+char *tty;
+{
+    struct utmp ubuf;
+
+    int fd;
+
+    if ((fd = open("/etc/utmp", 0)) == -1) {
+       print_error("Can't open /etc/utmp");
+       return(FAILED);
+    }
+
+    while (read(fd, (char *) &ubuf, sizeof ubuf) == sizeof(ubuf)) {
+       if (strncmp(ubuf.ut_name, name, sizeof ubuf.ut_name) == 0) {
+           if (*tty == '\0') {
+                   /* no particular tty was requested */
+               (void) strcpy(tty, ubuf.ut_line);
+               close(fd);
+               return(SUCCESS);
+           } else if (strcmp(ubuf.ut_line, tty) == 0) {
+               close(fd);
+               return(SUCCESS);
+           }
+       }
+    }
+
+    close(fd);
+    return(NOT_HERE);
+}
diff --git a/usr/src/ucb/talk/talk.c b/usr/src/ucb/talk/talk.c
new file mode 100644 (file)
index 0000000..6f625ea
--- /dev/null
@@ -0,0 +1,41 @@
+/* $Header: talk.c 1.3 83/04/23 02:08:25 moore Exp $ */
+
+#include "talk.h"
+
+/*
+ * talk:       A visual form of write. Using sockets, a two way 
+ *             connection is set up between the two people talking. 
+ *             With the aid of curses, the screen is split into two 
+ *             windows, and each users text is added to the window,
+ *             one character at a time...
+ *
+ *             Written by Kipp Hickman
+ *             
+ *             Modified to run under 4.1a by Clem Cole and Peter Moore
+ *             Modified to run between hosts by Peter Moore, 8/19/82
+ *             Modified to run under 4.1c by Peter Moore 3/17/83
+ */
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       get_names(argc, argv);
+
+       init_display();
+
+       open_ctl();
+       open_sockt();
+
+       start_msgs();
+
+       if ( !check_local() ) {
+           invite_remote();
+       }
+
+       end_msgs();
+
+       set_edit_chars();
+
+       talk();
+}
diff --git a/usr/src/ucb/talk/talk.h b/usr/src/ucb/talk/talk.h
new file mode 100644 (file)
index 0000000..c998662
--- /dev/null
@@ -0,0 +1,33 @@
+/* $Header: talk.h 1.2 83/04/23 02:15:12 moore Exp $ */
+
+#include <curses.h>
+#include <utmp.h>
+
+#define        forever         for(;;)
+
+#define        BUF_SIZE        512
+
+FILE *popen();
+int quit(), sleeper();
+
+extern int sockt;
+extern int curses_initialized;
+extern int invitation_waiting;
+
+extern char *current_state;
+extern int current_line;
+
+typedef struct xwin {
+       WINDOW *x_win;
+       int x_nlines;
+       int x_ncols;
+       int x_line;
+       int x_col;
+       char kill;
+       char cerase;
+       char werase;
+} xwin_t;
+
+extern xwin_t my_win;
+extern xwin_t his_win;
+extern WINDOW *line_win;
diff --git a/usr/src/ucb/talk/talk_ctl.h b/usr/src/ucb/talk/talk_ctl.h
new file mode 100644 (file)
index 0000000..d9b6f6f
--- /dev/null
@@ -0,0 +1,16 @@
+/* $Header: talk_ctl.h 1.1 83/03/26 14:36:39 moore Exp $ */
+
+#include "ctl.h"
+#include "talk.h"
+#include <errno.h>
+
+extern int errno;
+
+extern struct sockaddr_in daemon_addr;
+extern struct sockaddr_in ctl_addr;
+extern struct sockaddr_in my_addr;
+extern struct in_addr my_machine_addr;
+extern struct in_addr his_machine_addr;
+extern u_short daemon_port;
+extern int ctl_sockt;
+extern CTL_MSG msg;
diff --git a/usr/src/ucb/talk/talkd.c b/usr/src/ucb/talk/talkd.c
new file mode 100644 (file)
index 0000000..c5a2a70
--- /dev/null
@@ -0,0 +1,193 @@
+/* $Header: talkd.c 1.5 83/05/10 13:57:29 moore Exp $ */
+
+/* The top level of the daemon, the format is heavily borrowed
+   from rwhod.c. Basically: find out who and where you are; 
+   disconnect all descriptors and ttys, and then endless
+   loop on waiting for and processing requests
+ */
+
+#include "ctl.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <sgtty.h>
+#include <sys/ioctl.h>
+
+#define MAX_ERR 20     /* Number of times to attempt to open the 
+                          control socket */
+
+extern errno;
+
+struct sockaddr_in sin = { AF_INET };
+
+CTL_MSG request;
+CTL_RESPONSE response;
+int sockt;
+char hostname[HOST_NAME_LENGTH];
+
+struct hostent *gethostbyname();
+struct servent *getservbyname();
+
+int debug = 0;
+
+main(argc)
+int argc;
+{
+    struct sockaddr_in from;
+    int from_size;
+    int cc;
+    int name_length = sizeof(hostname);
+    struct servent *sp;
+    struct hostent *hp;
+
+
+    if ( argc > 1 ) {
+       debug = 1;
+    }
+
+    if ( !debug ) {
+       if (fork()) {
+           exit(0);
+       }
+    }
+
+    gethostname(hostname, &name_length);
+
+    hp = gethostbyname(hostname);
+    if (hp == (struct hostent *) 0) {
+           fprintf(stderr, "talkd: Cannot obtain local address\n");
+           exit(1);
+    }
+
+#ifdef NTALK
+    sp = getservbyname("ntalk", "udp");
+#else
+    sp = getservbyname("talk", "udp");
+#endif
+
+    if (sp == 0) {
+           fprintf(stderr, "talkd: udp/talk: unknown service\n");
+           exit(1);
+    }
+
+    if (getuid()) {
+       fprintf(stderr, "Talkd : not super user\n");
+       exit(1);
+    }
+
+    setup_desc();
+
+    sin.sin_port = sp->s_port;
+    sockt = socket(AF_INET, SOCK_DGRAM, 0, 0);
+    if (sockt < 0) {
+           print_error("talkd: socket");
+           exit(1);
+    }
+
+    if (bind(sockt, (caddr_t)&sin, sizeof (sin), 0) < 0) {
+       print_error("bind");
+       exit(1);
+    }
+
+    for (;;) {
+
+       from_size = sizeof(from);
+       cc = recvfrom(sockt, (char *)&request, sizeof (request), 0, 
+                     &from, &from_size);
+
+       if (cc != sizeof(request)) {
+           if (cc < 0 && errno != EINTR) {
+               print_error("receive");
+           }
+       } else {
+
+           if (debug) printf("Request received : \n");
+           if (debug) print_request(&request);
+
+           process_request(&request, &response);
+
+           if (debug) printf("Response sent : \n");
+           if (debug) print_response(&response);
+
+               /* can block here, is this what I want? */
+
+           cc = sendto(sockt, (char *) &response, sizeof(response), 0,
+                       &request.ctl_addr, sizeof(request.ctl_addr));
+
+           if (cc != sizeof(response)) {
+               print_error("Send");
+           }
+       }
+    }
+}
+
+    /* disconnect all descriptors, remove ourself from the process
+     * group that spawned us
+     */
+
+setup_desc()
+{
+    int s;
+
+    if (debug) return;
+
+    for (s = 0; s < 10; s++) {
+       (void) close(s);
+    }
+
+    (void) open("/dev/null", 0);
+    (void) dup2(0, 1);
+    (void) dup2(0, 2);
+
+    s = open("/dev/tty", 2);
+
+    if (s >= 0) {
+       ioctl(s, TIOCNOTTY, (struct sgttyb *) 0);
+       (void) close(s);
+    }
+
+    (void) chdir("/dev");
+}
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+print_error(string)
+char *string;
+{
+    FILE *cons;
+    char *err_dev = "/dev/console";
+    char *sys;
+    int val, pid;
+
+    if (debug) err_dev = "/dev/tty";
+
+    sys = "Unknown error";
+
+    if(errno < sys_nerr) {
+       sys = sys_errlist[errno];
+    }
+
+       /* don't ever open tty's directly, let a child do it */
+    if ((pid = fork()) == 0) {
+       cons = fopen(err_dev, "a");
+       if (cons != NULL) {
+           fprintf(cons, "Talkd : %s : %s(%d)\n\r", string, sys,
+                   errno);
+           fclose(cons);
+       }
+       exit(0);
+    } else {
+           /* wait for the child process to return */
+       do {
+           val = wait(0);
+           if (val == -1) {
+               if (errno == EINTR) {
+                   continue;
+               } else if (errno == ECHILD) {
+                   break;
+               }
+           }
+       } while (val != pid);
+    }
+}