diff options
Diffstat (limited to 'remote_cmds/talkd.tproj')
-rw-r--r-- | remote_cmds/talkd.tproj/Makefile | 14 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/announce.c | 179 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/extern.h | 40 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/ntalk.plist | 29 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/ntalkd.8 | 98 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/print.c | 96 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/process.c | 279 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/table.c | 241 | ||||
-rw-r--r-- | remote_cmds/talkd.tproj/talkd.c | 145 |
9 files changed, 1121 insertions, 0 deletions
diff --git a/remote_cmds/talkd.tproj/Makefile b/remote_cmds/talkd.tproj/Makefile new file mode 100644 index 0000000..f67b40b --- /dev/null +++ b/remote_cmds/talkd.tproj/Makefile @@ -0,0 +1,14 @@ +Project = ntalkd +Install_Dir = /usr/libexec + +HFILES = talkd.h +CFILES = announce.c print.c process.c table.c talkd.c ../wall.tproj/ttymsg.c +MANPAGES = ntalkd.8 +LAUNCHD_PLISTS = ntalk.plist + +Extra_CC_Flags = -Wall -Werror -fPIE +Extra_LD_Flags = -dead_strip -pie + +Extra_CC_Flags += -D__FBSDID=__RCSID + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/remote_cmds/talkd.tproj/announce.c b/remote_cmds/talkd.tproj/announce.c new file mode 100644 index 0000000..5091513 --- /dev/null +++ b/remote_cmds/talkd.tproj/announce.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)announce.c 8.3 (Berkeley) 4/28/95"; +#endif +__attribute__((__used__)) +static const char rcsid[] = + "$FreeBSD: src/libexec/talkd/announce.c,v 1.16 2003/04/03 05:13:27 jmallett Exp $"; +#endif /* not lint */ + +#include <sys/cdefs.h> + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <sys/socket.h> + +#include <protocols/talkd.h> + +#include <errno.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <vis.h> + +#ifdef __APPLE__ +#include <util.h> +#else +#include "ttymsg.h" +#endif +#include "extern.h" + +extern char hostname[]; + +/* + * Announce an invitation to talk. + */ + +/* + * See if the user is accepting messages. If so, announce that + * a talk is requested. + */ +int +announce(CTL_MSG *request, const char *remote_machine) +{ + char full_tty[32]; + struct stat stbuf; + + (void)snprintf(full_tty, sizeof(full_tty), + "%s%s", _PATH_DEV, request->r_tty); + if (stat(full_tty, &stbuf) < 0 || (stbuf.st_mode&020) == 0) + return (PERMISSION_DENIED); + return (print_mesg(request->r_tty, request, remote_machine)); +} + +#define max(a,b) ( (a) > (b) ? (a) : (b) ) +#define N_LINES 5 +#define N_CHARS 256 + +/* + * Build a block of characters containing the message. + * It is sent blank filled and in a single block to + * try to keep the message in one piece if the recipient + * in in vi at the time + */ +int +print_mesg(const char *tty, CTL_MSG *request, + const char *remote_machine) +{ + struct timeval now; + time_t clock_sec; + struct timezone zone; + struct tm *localclock; + struct iovec iovec; + char line_buf[N_LINES][N_CHARS]; + int sizes[N_LINES]; + char big_buf[N_LINES*N_CHARS]; + char *bptr, *lptr, *vis_user; + int i, j, max_size; + + i = 0; + max_size = 0; + gettimeofday(&now, &zone); + clock_sec = now.tv_sec; + localclock = localtime(&clock_sec); + (void)snprintf(line_buf[i], N_CHARS, " "); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + (void)snprintf(line_buf[i], N_CHARS, + "Message from Talk_Daemon@%s at %d:%02d on %d/%.2d/%.2d ...", + hostname, localclock->tm_hour , localclock->tm_min, + localclock->tm_year + 1900, localclock->tm_mon + 1, + localclock->tm_mday); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + + vis_user = malloc(strlen(request->l_name) * 4 + 1); + strvis(vis_user, request->l_name, VIS_CSTYLE); + (void)snprintf(line_buf[i], N_CHARS, + "talk: connection requested by %s@%s", vis_user, remote_machine); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + (void)snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s", + vis_user, remote_machine); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + (void)snprintf(line_buf[i], N_CHARS, " "); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + bptr = big_buf; + *bptr++ = '\007'; /* send something to wake them up */ + *bptr++ = '\r'; /* add a \r in case of raw mode */ + *bptr++ = '\n'; + for (i = 0; i < N_LINES; i++) { + /* copy the line into the big buffer */ + lptr = line_buf[i]; + while (*lptr != '\0') + *(bptr++) = *(lptr++); + /* pad out the rest of the lines with blanks */ + for (j = sizes[i]; j < max_size + 2; j++) + *(bptr++) = ' '; + *(bptr++) = '\r'; /* add a \r in case of raw mode */ + *(bptr++) = '\n'; + } + *bptr = '\0'; + iovec.iov_base = big_buf; + iovec.iov_len = bptr - big_buf; + /* + * we choose a timeout of RING_WAIT-5 seconds so that we don't + * stack up processes trying to write messages to a tty + * that is permanently blocked. + */ + if (ttymsg(&iovec, 1, tty, RING_WAIT - 5) != NULL) + return (FAILED); + + return (SUCCESS); +} diff --git a/remote_cmds/talkd.tproj/extern.h b/remote_cmds/talkd.tproj/extern.h new file mode 100644 index 0000000..3b73236 --- /dev/null +++ b/remote_cmds/talkd.tproj/extern.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002 M. Warner Losh. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/libexec/talkd/extern.h,v 1.3 2003/04/03 05:13:27 jmallett Exp $ + */ + +int announce(CTL_MSG *, const char *); +int delete_invite(u_int32_t); +void do_announce(CTL_MSG *, CTL_RESPONSE *); +CTL_MSG *find_match(CTL_MSG *request); +CTL_MSG *find_request(CTL_MSG *request); +int find_user(const char *name, char *tty); +void insert_table(CTL_MSG *, CTL_RESPONSE *); +int new_id(void); +int print_mesg(const char *, CTL_MSG *, const char *); +void print_request(const char *, CTL_MSG *); +void print_response(const char *, CTL_RESPONSE *); +void process_request(CTL_MSG *mp, CTL_RESPONSE *rp); +void timeout(int sig); diff --git a/remote_cmds/talkd.tproj/ntalk.plist b/remote_cmds/talkd.tproj/ntalk.plist new file mode 100644 index 0000000..2e63da2 --- /dev/null +++ b/remote_cmds/talkd.tproj/ntalk.plist @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Disabled</key> + <true/> + <key>Label</key> + <string>com.apple.ntalkd</string> + <key>ProgramArguments</key> + <array> + <string>/usr/libexec/ntalkd</string> + </array> + <key>inetdCompatibility</key> + <dict> + <key>Wait</key> + <true/> + </dict> + <key>Sockets</key> + <dict> + <key>Listeners</key> + <dict> + <key>SockServiceName</key> + <string>ntalk</string> + <key>SockType</key> + <string>dgram</string> + </dict> + </dict> +</dict> +</plist> diff --git a/remote_cmds/talkd.tproj/ntalkd.8 b/remote_cmds/talkd.tproj/ntalkd.8 new file mode 100644 index 0000000..7fe81a5 --- /dev/null +++ b/remote_cmds/talkd.tproj/ntalkd.8 @@ -0,0 +1,98 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)talkd.8 8.2 (Berkeley) 12/11/93 +.\" $FreeBSD: src/libexec/talkd/talkd.8,v 1.7 2003/09/08 19:57:18 ru Exp $ +.\" +.Dd August 21, 2008 +.Dt TALKD 8 +.Os +.Sh NAME +.Nm talkd +.Nd remote user communication server +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +The +.Nm +utility +is the server that notifies a user that someone else wants to +initiate a conversation. +It acts as a repository of invitations, responding to requests +by clients wishing to rendezvous to hold a conversation. +In normal operation, a client, the caller, +initiates a rendezvous by sending a +.Tn CTL_MSG +to the server of +type +.Tn LOOK_UP +(see +.In protocols/talkd.h ) . +This causes the server to search its invitation +tables to check if an invitation currently exists for the caller +(to speak to the callee specified in the message). +.Pp +If the lookup fails, +the caller then sends an +.Tn ANNOUNCE +message causing the server to +broadcast an announcement on the callee's login ports requesting contact. +.Pp +When the callee responds, the local server uses the +recorded invitation to respond with the appropriate rendezvous +address and the caller and callee client programs establish a +stream connection through which the conversation takes place. +.Sh CONFIGURATION +The +.Nm +utility is managed by +.Xr launchd 8 +as specified in the +.Pa ntalk.plist +property list. +By default the property list contains the +.Em Disabled +key set to true, so +.Nm +is never invoked. +.Pp +Execute the following command as root to enable +.Nm talkd : +.Dl "launchctl load -w /System/Library/LaunchDaemons/ntalk.plist" +.Pp +.Sh SEE ALSO +.Xr talk 1 , +.Xr write 1 +.Sh HISTORY +The +.Nm +utility appeared in +.Bx 4.3 . diff --git a/remote_cmds/talkd.tproj/print.c b/remote_cmds/talkd.tproj/print.c new file mode 100644 index 0000000..add853c --- /dev/null +++ b/remote_cmds/talkd.tproj/print.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 6/4/93"; +#endif +__attribute__((__used__)) +static const char rcsid[] = + "$FreeBSD: src/libexec/talkd/print.c,v 1.12 2003/04/03 05:13:27 jmallett Exp $"; +#endif /* not lint */ + +#include <sys/cdefs.h> + +/* debug print routines */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <protocols/talkd.h> +#include <stdio.h> +#include <syslog.h> + +#include "extern.h" + +static const char *types[] = + { "leave_invite", "look_up", "delete", "announce" }; +#define NTYPES (sizeof (types) / sizeof (types[0])) +static const char *answers[] = + { "success", "not_here", "failed", "machine_unknown", "permission_denied", + "unknown_request", "badversion", "badaddr", "badctladdr" }; +#define NANSWERS (sizeof (answers) / sizeof (answers[0])) + +void +print_request(const char *cp, CTL_MSG *mp) +{ + const char *tp; + char tbuf[80]; + + if (mp->type > NTYPES) { + (void)snprintf(tbuf, sizeof(tbuf), "type %d", mp->type); + tp = tbuf; + } else + tp = types[mp->type]; + syslog(LOG_DEBUG, "%s: %s: id %lu, l_user %s, r_user %s, r_tty %s", + cp, tp, (long)mp->id_num, mp->l_name, mp->r_name, mp->r_tty); +} + +void +print_response(const char *cp, CTL_RESPONSE *rp) +{ + const char *tp, *ap; + char tbuf[80], abuf[80]; + + if (rp->type > NTYPES) { + (void)snprintf(tbuf, sizeof(tbuf), "type %d", rp->type); + tp = tbuf; + } else + tp = types[rp->type]; + if (rp->answer > NANSWERS) { + (void)snprintf(abuf, sizeof(abuf), "answer %d", rp->answer); + ap = abuf; + } else + ap = answers[rp->answer]; + syslog(LOG_DEBUG, "%s: %s: %s, id %d", cp, tp, ap, ntohl(rp->id_num)); +} diff --git a/remote_cmds/talkd.tproj/process.c b/remote_cmds/talkd.tproj/process.c new file mode 100644 index 0000000..e17d69e --- /dev/null +++ b/remote_cmds/talkd.tproj/process.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93"; +#endif +__attribute__((__used__)) +static const char rcsid[] = + "$FreeBSD: src/libexec/talkd/process.c,v 1.11 2005/05/06 15:28:54 delphij Exp $"; +#endif /* not lint */ + +#include <sys/cdefs.h> + +/* + * 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 <sys/param.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <protocols/talkd.h> +#include <ctype.h> +#include <err.h> +#include <netdb.h> +#include <paths.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> + +#include "extern.h" + +extern int debug; + +void +process_request(CTL_MSG *mp, CTL_RESPONSE *rp) +{ + CTL_MSG *ptr; + char *s; + + rp->vers = TALK_VERSION; + rp->type = mp->type; + rp->id_num = htonl(0); + if (mp->vers != TALK_VERSION) { + syslog(LOG_WARNING, "bad protocol version %d", mp->vers); + rp->answer = BADVERSION; + return; + } + mp->id_num = ntohl(mp->id_num); + mp->addr.sa_family = ntohs(mp->addr.sa_family); + if (mp->addr.sa_family != AF_INET) { + syslog(LOG_WARNING, "bad address, family %d", + mp->addr.sa_family); + rp->answer = BADADDR; + return; + } + mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); + if (mp->ctl_addr.sa_family != AF_INET) { + syslog(LOG_WARNING, "bad control address, family %d", + mp->ctl_addr.sa_family); + rp->answer = BADCTLADDR; + return; + } + for (s = mp->l_name; *s; s++) + if (!isprint(*s)) { + syslog(LOG_NOTICE, "illegal user name. Aborting"); + rp->answer = FAILED; + return; + } + mp->pid = ntohl(mp->pid); + if (debug) + print_request("process_request", mp); + switch (mp->type) { + + case ANNOUNCE: + do_announce(mp, rp); + break; + + case LEAVE_INVITE: + ptr = find_request(mp); + if (ptr != (CTL_MSG *)0) { + rp->id_num = htonl(ptr->id_num); + rp->answer = SUCCESS; + } else + insert_table(mp, rp); + break; + + case LOOK_UP: + ptr = find_match(mp); + if (ptr != (CTL_MSG *)0) { + rp->id_num = htonl(ptr->id_num); + rp->addr = ptr->addr; + rp->addr.sa_family = htons(ptr->addr.sa_family); + rp->answer = SUCCESS; + } else + rp->answer = NOT_HERE; + break; + + case DELETE: + rp->answer = delete_invite(mp->id_num); + break; + + default: + rp->answer = UNKNOWN_REQUEST; + break; + } + if (debug) + print_response("process_request", rp); +} + +void +do_announce(CTL_MSG *mp, CTL_RESPONSE *rp) +{ + struct hostent *hp; + CTL_MSG *ptr; + int result; + + /* see if the user is logged */ + result = find_user(mp->r_name, mp->r_tty); + if (result != SUCCESS) { + rp->answer = result; + return; + } +#define satosin(sa) ((struct sockaddr_in *)(sa)) + hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr, + sizeof (struct in_addr), AF_INET); + if (hp == (struct hostent *)0) { + rp->answer = MACHINE_UNKNOWN; + return; + } + ptr = find_request(mp); + if (ptr == (CTL_MSG *) 0) { + insert_table(mp, rp); + rp->answer = announce(mp, hp->h_name); + return; + } + if (mp->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 = new_id(); + rp->id_num = htonl(ptr->id_num); + rp->answer = announce(mp, hp->h_name); + } else { + /* a duplicated request, so ignore it */ + rp->id_num = htonl(ptr->id_num); + rp->answer = SUCCESS; + } +} + +#ifdef __APPLE__ +#include <utmpx.h> +#else +#include <utmp.h> +#endif + +/* + * Search utmp for the local user + */ +int +find_user(const char *name, char *tty) +{ +#ifdef __APPLE__ + struct utmpx *u; + int status; + struct stat statb; + + char line[sizeof(u->ut_line) + 1]; + char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)]; + + setutxent(); +#define SCMPN(a, b) strncmp(a, b, sizeof (a)) + status = NOT_HERE; + (void) strcpy(ftty, _PATH_DEV); + while ((u = getutxent()) != NULL) + if (u->ut_type == USER_PROCESS && SCMPN(u->ut_user, name) == 0) { + strncpy(line, u->ut_line, sizeof(u->ut_line)); + line[sizeof(u->ut_line)] = '\0'; + if (*tty == '\0') { + status = PERMISSION_DENIED; + /* no particular tty was requested */ + (void) strcpy(ftty + sizeof(_PATH_DEV) - 1, + line); + if (stat(ftty, &statb) == 0) { + if (!(statb.st_mode & 020)) + continue; + (void) strcpy(tty, line); + status = SUCCESS; + break; + } + } + if (strcmp(line, tty) == 0) { + status = SUCCESS; + break; + } + } + endutxent(); +#else + struct utmp ubuf; + int status; + FILE *fd; + struct stat statb; + time_t best = 0; + char line[sizeof(ubuf.ut_line) + 1]; + char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)]; + + if ((fd = fopen(_PATH_UTMP, "r")) == NULL) { + warnx("can't read %s", _PATH_UTMP); + return (FAILED); + } +#define SCMPN(a, b) strncmp(a, b, sizeof (a)) + status = NOT_HERE; + (void) strcpy(ftty, _PATH_DEV); + while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1) + if (SCMPN(ubuf.ut_name, name) == 0) { + strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line)); + line[sizeof(ubuf.ut_line)] = '\0'; + if (*tty == '\0' || best != 0) { + if (best == 0) + status = PERMISSION_DENIED; + /* no particular tty was requested */ + (void) strcpy(ftty + sizeof(_PATH_DEV) - 1, + line); + if (stat(ftty, &statb) == 0) { + if (!(statb.st_mode & 020)) + continue; + if (statb.st_atime > best) { + best = statb.st_atime; + (void) strcpy(tty, line); + status = SUCCESS; + continue; + } + } + } + if (strcmp(line, tty) == 0) { + status = SUCCESS; + break; + } + } + fclose(fd); +#endif + return (status); +} diff --git a/remote_cmds/talkd.tproj/table.c b/remote_cmds/talkd.tproj/table.c new file mode 100644 index 0000000..77c7d33 --- /dev/null +++ b/remote_cmds/talkd.tproj/table.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; +#endif +__attribute__((__used__)) +static const char rcsid[] = + "$FreeBSD: src/libexec/talkd/table.c,v 1.9 2003/04/03 05:13:27 jmallett Exp $"; +#endif /* not lint */ + +#include <sys/cdefs.h> + +/* + * Routines to handle insertion, deletion, etc on the table + * of requests kept by the daemon. Nothing fancy here, linear + * search on a double-linked list. A time is kept with each + * entry so that overly old invitations can be eliminated. + * + * Consider this a mis-guided attempt at modularity + */ +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <protocols/talkd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#include "extern.h" + +#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ + +#define NIL ((TABLE_ENTRY *)0) + +extern int debug; +struct timeval tp; +struct timezone txp; + +typedef struct table_entry TABLE_ENTRY; + +struct table_entry { + CTL_MSG request; + long time; + TABLE_ENTRY *next; + TABLE_ENTRY *last; +}; + +static void delete(TABLE_ENTRY *); + +TABLE_ENTRY *table = NIL; + +/* + * Look in the table for an invitation that matches the current + * request looking for an invitation + */ +CTL_MSG * +find_match(CTL_MSG *request) +{ + TABLE_ENTRY *ptr; + time_t current_time; + + gettimeofday(&tp, &txp); + current_time = tp.tv_sec; + if (debug) + print_request("find_match", request); + for (ptr = table; ptr != NIL; ptr = ptr->next) { + if ((ptr->time - current_time) > MAX_LIFE) { + /* the entry is too old */ + if (debug) + print_request("deleting expired entry", + &ptr->request); + delete(ptr); + continue; + } + if (debug) + print_request("", &ptr->request); + if (strcmp(request->l_name, ptr->request.r_name) == 0 && + strcmp(request->r_name, ptr->request.l_name) == 0 && + ptr->request.type == LEAVE_INVITE) + return (&ptr->request); + } + return ((CTL_MSG *)0); +} + +/* + * Look for an identical request, as opposed to a complimentary + * one as find_match does + */ +CTL_MSG * +find_request(CTL_MSG *request) +{ + TABLE_ENTRY *ptr; + time_t current_time; + + gettimeofday(&tp, &txp); + current_time = tp.tv_sec; + /* + * See if this is a repeated message, and check for + * out of date entries in the table while we are it. + */ + if (debug) + print_request("find_request", request); + for (ptr = table; ptr != NIL; ptr = ptr->next) { + if ((ptr->time - current_time) > MAX_LIFE) { + /* the entry is too old */ + if (debug) + print_request("deleting expired entry", + &ptr->request); + delete(ptr); + continue; + } + if (debug) + print_request("", &ptr->request); + if (strcmp(request->r_name, ptr->request.r_name) == 0 && + strcmp(request->l_name, ptr->request.l_name) == 0 && + request->type == ptr->request.type && + request->pid == ptr->request.pid) { + /* update the time if we 'touch' it */ + ptr->time = current_time; + return (&ptr->request); + } + } + return ((CTL_MSG *)0); +} + +void +insert_table(CTL_MSG *request, CTL_RESPONSE *response) +{ + TABLE_ENTRY *ptr; + time_t current_time; + + gettimeofday(&tp, &txp); + current_time = tp.tv_sec; + request->id_num = new_id(); + response->id_num = htonl(request->id_num); + /* insert a new entry into the top of the list */ + ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); + if (ptr == NIL) { + syslog(LOG_ERR, "insert_table: Out of memory"); + _exit(1); + } + ptr->time = current_time; + ptr->request = *request; + ptr->next = table; + if (ptr->next != NIL) + ptr->next->last = ptr; + ptr->last = NIL; + table = ptr; +} + +/* + * Generate a unique non-zero sequence number + */ +int +new_id(void) +{ + static int current_id = 0; + + current_id = (current_id + 1) % MAX_ID; + /* 0 is reserved, helps to pick up bugs */ + if (current_id == 0) + current_id = 1; + return (current_id); +} + +/* + * Delete the invitation with id 'id_num' + */ +int +delete_invite(u_int32_t id_num) +{ + TABLE_ENTRY *ptr; + + ptr = table; + if (debug) + syslog(LOG_DEBUG, "delete_invite(%d)", id_num); + for (ptr = table; ptr != NIL; ptr = ptr->next) { + if (ptr->request.id_num == id_num) + break; + if (debug) + print_request("", &ptr->request); + } + if (ptr != NIL) { + delete(ptr); + return (SUCCESS); + } + return (NOT_HERE); +} + +/* + * Classic delete from a double-linked list + */ +static void +delete(TABLE_ENTRY *ptr) +{ + + if (debug) + print_request("delete", &ptr->request); + if (table == ptr) + table = ptr->next; + else if (ptr->last != NIL) + ptr->last->next = ptr->next; + if (ptr->next != NIL) + ptr->next->last = ptr->last; + free((char *)ptr); +} diff --git a/remote_cmds/talkd.tproj/talkd.c b/remote_cmds/talkd.tproj/talkd.c new file mode 100644 index 0000000..1f28cb8 --- /dev/null +++ b/remote_cmds/talkd.tproj/talkd.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +__attribute__((__used__)) +static const char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)talkd.c 8.1 (Berkeley) 6/4/93"; +#endif +__attribute__((__used__)) +static const char rcsid[] = + "$FreeBSD: src/libexec/talkd/talkd.c,v 1.17 2004/06/14 22:44:13 bms Exp $"; +#endif /* not lint */ + +#include <sys/cdefs.h> + +/* + * 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 <sys/types.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <protocols/talkd.h> +#include <err.h> +#include <errno.h> +#include <paths.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +#include "extern.h" + +CTL_MSG request; +CTL_RESPONSE response; + +int debug = 0; +long lastmsgtime; + +char hostname[MAXHOSTNAMELEN + 1]; + +#define TIMEOUT 30 +#define MAXIDLE 120 + +int +main(int argc, char *argv[]) +{ + register CTL_MSG *mp = &request; + int cc; + struct sockaddr ctl_addr; + + /* + * removed so ntalkd can run in tty sandbox + */ + if (getuid()) + errx(1, "getuid: not super-user"); + + openlog("talkd", LOG_PID, LOG_DAEMON); + if (gethostname(hostname, sizeof(hostname) - 1) < 0) { + syslog(LOG_ERR, "gethostname: %m"); + _exit(1); + } + hostname[sizeof(hostname) - 1] = '\0'; + if (chdir(_PATH_DEV) < 0) { + syslog(LOG_ERR, "chdir: %s: %m", _PATH_DEV); + _exit(1); + } + if (argc > 1 && strcmp(argv[1], "-d") == 0) + debug = 1; + signal(SIGALRM, timeout); + alarm(TIMEOUT); + for (;;) { + cc = recv(0, (char *)mp, sizeof(*mp), 0); + if (cc != sizeof (*mp)) { + if (cc < 0 && errno != EINTR) + syslog(LOG_WARNING, "recv: %m"); + continue; + } + lastmsgtime = time(0); + (void)memcpy(&ctl_addr, &mp->ctl_addr, sizeof(ctl_addr)); + ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); + ctl_addr.sa_len = sizeof(ctl_addr); + process_request(mp, &response); + /* can block here, is this what I want? */ + cc = sendto(STDIN_FILENO, (char *)&response, + sizeof(response), 0, &ctl_addr, sizeof(ctl_addr)); + if (cc != sizeof (response)) + syslog(LOG_WARNING, "sendto: %m"); + } + /* NOTREACHED */ + return 0; +} + +void +timeout(int sig __unused) +{ + int save_errno = errno; + + if (time(0) - lastmsgtime >= MAXIDLE) + _exit(0); + alarm(TIMEOUT); + errno = save_errno; +} |