[alt.sources] Workaround for SCO UNIX "ct"

dowjones@imp.com (Joachim Astel) (04/29/91)

This is a workaround for the SCO UNIX SysV R3.2 ct-bug. The following program
"callback" takes a phone number as an argument and calls back the specified
number at a fixed speed. Note my WARNING in callback.c, which reads that EVERY
person on the system can do a callback (because the system runs setuid root).
It uses /etc/init which can handle the correct permissions and so on.

You may feel free to modify the sources, but don't blame me with them. :-)
The program was a quick one, so I do not make gurantees for anything.

To make it run, you must do the following:

1. Unshar the following shar-archive

2. edit the Makefile to your personal needs

3. read the comments at the beginning of callback.c, and modify the "#defines"
   to your personal needs (baudrate in CT_CMDSTRING, etc.)

4. type ("make" and) "make install" at your shell-prompt

5. edit the /etc/inittab file and add an entry for /usr/bin/callout (this
   is mentioned in 'detail' at the beginning of callback.c)

Here we go...
--------------------------------- cut here ------------------------------------
:
# This is a shell archive, meaning:
# 1. Remove everything above the : line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	callback.c
#	Makefile
# This archive created: Mon Apr 29 02:12:26 1991 by dowjones@impch.imp.com
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'callback.c'
then
	echo shar: "will not over-write existing file 'callback.c'"
else
sed 's/^X//' << \SHAR_EOF > 'callback.c'
X/*
X * callback.c - Copyright (C) 1991 by Joachim Astel (dowjones@jattmp.imp.com)
X *
X * WARNING: the program runs as -rws--x--x root (suid-bit set for root),
X *          so EVERY person on the system can make the unix system to call
X *          him/her back. USE IT ON YOUR OWN RISK.
X * 
X * This program fetches superuser-permissions and creates a temporary
X * shell-script "CALL_FILE" with a "sleep 10" and "ct" command in it.
X * Afterwards, an "init"-command is executed, and the shell script is
X * activated from init as far as there is an appropriate line entry in
X * /etc/inittab, like the following:
X *
X * "cbc:c:once:/usr/bin/callout" (without quotation marks, of course)
X *      ^      ^^^^^^^^^^^^^^^^ Must be the same as in #define CALL_FILE
X *      ^
X *      if you have already an entry "c" in use, change the defined
X *	INITTAB_ID (see below) to "a" or "b"
X *
X * It works under SCO UNIX SysV R3.2, which has problems with its C2-system
X * if you try to execute "ct" directly.
X *
X * BUGS: the error handling could be better. All in all, the program was a
X *       a quick hack. I got reports from some users that this programm did
X *       not call back at some time. But that effect was non-reproduceable.
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <time.h>
X#include <pwd.h>
X
X/* You may feel free to change the following defines */
X
X#define LOG_FILE "/usr/adm/callback"
X#define CT_CMDSTRING "ct -s 2400 %s\n" /* (%s: phone-number.) */
X#define CALL_FILE "/usr/bin/callout" /* must be mentioned in /etc/inittab */
X#define INITTAB_ID "c" /* "slot" in /etc/inittab */
X#define NOTE \
X	"Please hang up now and reconfigure your modem to auto-answer mode."
X
X#ifndef GETLUID
X#define getluid getuid
X#endif
X
Xchar *Prgrm;
X
X#define SAME 0 /* for strcmp */
X
X/* return username of specific id */
Xchar *username(id)
X	int id;
X{
X	struct passwd *pwd;
X
X	setpwent(); /* rewind passwd file */
X	if ((pwd = getpwuid(id)) == NULL) {
X		fprintf(stderr, "%s: Unknown user-id: %d\n", Prgrm, id);
X		exit(1);
X	}
X	endpwent(); /* close passwd file */
X	return pwd->pw_name;
X}
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	FILE *call_file, *log_file;
X	char *phone_number;
X	int pid;
X
X	Prgrm = *argv;
X
X	if (argc != 2) {
X		fprintf(stderr, "Usage: %s phone-number\n", Prgrm);
X		exit(0);
X	}
X	phone_number = argv[1];
X
X	if (!(pid = fork())) { /* Child-process */
X		setgid(0); setuid(0); /* get root permissions */
X
X		if ((call_file = fopen(CALL_FILE, "w")) == NULL) {
X			fprintf(stderr, "Error: Cannot open %s\n", CALL_FILE);
X			kill(pid, 9); /* don't let parent process hangup */
X			exit(1); /* abort program */
X		}
X		fprintf(call_file, "sleep 10\n");
X		fprintf(call_file, CT_CMDSTRING, phone_number);
X		fclose(call_file);
X	  	chmod(CALL_FILE, 0755);
X
X		close(0); close(1); close(2); /* ignore signals etc. */
X		signal(SIGHUP, SIG_IGN);
X
X		if ((log_file = fopen(LOG_FILE, "w+")) != NULL) {
X			time_t t;
X			time(&t);
X			fprintf(log_file, "%s: %s %s\n", username(getluid()),
X				phone_number, ctime(&t));
X			fclose(log_file);
X		}
X		execl("/etc/init", "call-back", INITTAB_ID, NULL);
X	/* on error... */
X		fprintf(stderr, "Error: Cannot execute init\n");
X		kill(pid, 9); /* don't let parent-process hangup the line */
X		exit(1); /* abort program */
X	}
X}
SHAR_EOF
fi
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# Makefile for "callback.c"
X
XCC = cc
XBINFILE = callback
XINSTALLPATH = /usr/bin
X
XOBJECTS = callback.o
X
Xall: $(BINFILE)
X	@echo "Now start \"make install\""
X
X$(BINFILE): $(OBJECTS)
X	$(CC) $(CFLAGS) -o $(@) $(OBJECTS)
X
Xinstall: $(BINFILE)
X	cp $(BINFILE) $(INSTALLPATH)
X	strip $(INSTALLPATH)/$(BINFILE)
X	chmod 4111 $(INSTALLPATH)/$(BINFILE)
X	chgrp bin $(INSTALLPATH)/$(BINFILE)
X	chown root $(INSTALLPATH)/$(BINFILE)
X
Xclean:
X	-rm -f *.o core
X
Xclobber:
X	-rm -f *.o core $(BINFILE)
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 
Joachim Astel, E-MAIL: dowjones@jattmp.imp.com, dowjones@jattmp.nbg.sub.org