orville-write-2.55/0040755000076500007650000000000010126436714012375 5ustar janjanorville-write-2.55/README0100644000076500007650000001731110126425625013254 0ustar janjanORVILLE WRITE PROGRAM - version 2.55 by Jan Wolter The orville write program is a version of the standard Unix write program that adds many nice features. It has been heavily used on M-Net since 1985, on Grex since 1991 and on a few other systems. It is a ground-up reimplementation using no proprietary code. The current version is quite portable. Write was written for use on M-Net and Grex, both public access unix systems in Ann Arbor. As such, many of the features are designed to support a system featuring a delicate mix of novice users and hostile pranksters, plus a lot of people who just want to talk. It's user interface is pretty much identical to the normal write program, but it offers many extensions and improvements: - It is always possible to write someone who is writing you, even if his permissions are off. - Doing "write" without arguments replies to whoever is writing you. Similarly if you do "write whoever" and whoever is logged in more than once it will always write to the tty he is writing you from. - Optionally, orville write can be configured to allow users to turn on write permissions for only a selected list of users, or to turn off write permissions for all but a selected list of users. - If you write a person who is writing someone else, you will be asked if you want to interupt before the connection is made. - All control characters are expanded before sending them to the other user. - When you disconnect, the user will receive an "EOF (your-login)" instead of a simple "EOF". (This is done to aid users in identifying who just did a "write whomever < /etc/termcap" to them. The identification at the head of the messages scrolls off.) - It is possible to set up a link to write (called, perhaps, "jot") that will send each character to the other user as you type it. This is less boring for the other user, since he doesn't have to sit there waiting for you to finish a whole line before he has anything to read. However, it will not go into character-by-character mode until the other person has replied. (Since it's really annoying to have loose characters from someone chatting you getting mixed into the output from other programs you are running.) - It is possible to set up a link to write (called, perhaps, "tel") to send quick one-line telegram messages to other users. Many people like to use this as a way to hold a conversation by sending telegrams back and forth while still doing something else on their terminals. You can always write or tel a person for up to four minutes after he sent you a tel, even if his permissions are off. There are provisions to prevent flooding people with tels. - Doing "write ." writes again to the last person you wrote. This is especially handy with the "tel" command. - Users can set a switch so write won't ring bells when a message is received. - There is a facility for users to designate themselves as "helpers". Then If a novice does "write help" he is connected to one of the helpers currently not busy writing someone else. If there is more than one candidate, one is selected at random to distribute the workload. It is possible to configure the system so only users listed in a file may designate themselves as helpers. Helpers can do "mesg -h y" to turn on their helper status, or "mesg -h n" to turn it off. This is our main mechanism for helping newusers on M-Net and Grex. We also have the "finger" program display question marks by the names of users who are helpers, though source for finger is not included in this package. - There are two additional shell escapes. Doing "!ls" at the begining of a line does the normal shell escape. Doing "|ls" sends the output to the other user instead of to you. Doing "&ls" sends the output to both of you. These are useful in instructing users about Unix commands through write and for including files into your conversation (with "&cat file"). - When you receive a message from someone who is su'ed to some other account, you are notified of both of his identities. The name from /etc/utmp is, of course, the one you reply to, but on many systems this is not as reliable an indicator of the identity of the person who is writing you as his uid, so mentioning this name as well can reduce confusion. - There is a configuration file, which an administrator can edit to among other thing, disallow piping files through write by disabling the & and | shell escapes and requiring standard input to the program to be a tty. This is meant to be turned on when you have a temporary excess of twits annoying other users. - The "mesg" command may be used to set a flag telling the system to record telegrams sent to you. If you have this turned on, the "huh" command will redisplay the last message sent. This is useful when telegrams get swallowed by other activity on your screen. - It is possible to separately set "write" and "telegram" permissions with the "mesg" command. Thus you can depermit telegrams being sent to you, without depermitting writes. You can also specify a preference for being writting in character mode or line mode. - The "mesg" program may optionally be compiled to allow a disconnect option. Doing "mesg N" (as opposed to "mesg n") will not only turn you message permissions off, but disconnect anyone who is currently writing you. - There is an "amin" program (that's "am in", not the Ugandan guy), that lets you do "amin vi filename". The runs "vi filename" normally, but if anyone writes you while you are running that process, he will be told that you are running "vi" and asked if he still wants to write you. "amin -n vi file" just turns your message permissions off for the duration of the vi session. "amin -np vi file" will record any telegrams anyone send you while you are editing, and automatically display them when you are done editing. CAVEATS: This program must run SUID-root or SGID-tty (where 'tty' is whatever group the tty devices are on in your system). (Otherwise you couldn't write people who are writing you even when their message perms are off.) Security holes have been found in it from time to time over the years. I like to think they've all been fixed now. As mentioned in the HELPERS discussion, we have made some associated mods to the finger program. The finger source I have is someone's cheap clone, and is probably not useful for any serious modern Unix system. Someday I'll do a set of patches for Gnu's finger. Our original purpose in rewriting write was that our old system had people's tty's writable to others when their message perms were on, and this led to too much "cat /etc/termcap > /dev/tty04" kind of stuff. The orville write program supports a choice of two different workarounds for that problem, but neither is simple to install. You either have to modify login (and possibly finger and other programs) or you have to live with some inconveniences. Of course, nearly all modern Unix system don't have this problem (tty's are owned by some "terminal" or "tty" group and only group permissions are ever turned on). If you have one of those systems, or you don't mind leaving tty's writable, there should be no problem installing write. We've tried hard to make Orville write very portable. It should build easily on almost all versions of Unix. If you'd like a copy of the distribution goto Orville Write's homepage at http:/www.unixpapa.com/write.html . By the way, if you'd like to give M-Net or Grex a try, telnet arbornet.org or cyberspace.org respectively (or aim your browser at them). Both systems give away Unix accounts which may be used free of charge without validation. orville-write-2.55/INSTALLATION0100644000076500007650000002523707665700412014232 0ustar janjan INSTALLATION INSTRUCTIONS ORVILLE WRITE PROGRAM Version 2.54 Jan Wolter Installation of Orville write is fairly simple on most modern Unix systems. 1. Unpack the archive and cd into the directory. 2. If you have an really old Unix system, check that tty devices on your system aren't permitted to others. Do mesg y ls -l `tty` Normally you will see that your tty is permitted only to group, not to others. If it is permitted to others, read the section at the end of this file. 3. Run './configure' There are lots of flags that can be given on the ./configure command, but a few are worth special note: --prefix= default: /usr/local --sysconfdir= default: PREFIX/etc --bindir= default: PREFIX/bin --mandir= default: PREFIX/man Where the software will be installed. All the programs will be put in bindir. The orville.conf file will be put in sysconfdir. The manual pages will be put in mandir. It is especially important to get sysconfdir set the way you want it before compiling, because the location of the orville.conf file is compiled into all Orville programs, so it cannot be moved without rebuilding the programs. --with-talk If you have a talk or ntalk program that has been modified to work with Orville write, flick this switch. --with-slow-passwd If password file lookups on your system are slow (say you have lots of users, and a non-hashed password database), setting this flag will speed things up, but the writee won't be notified if the writer's uid does not match his login name. 4. Run 'make' This will build the 'write', 'mesg', 'amin' and 'helpers' programs. 5. Find the standard versions of write and mesg on your system. Depermit them and move them to a safe place. You may want them back someday. 6. If you are upgrading from a previous version of Orville write, you may want to save a copy of your old 'orville.conf' file. You should be forwarned that users currently logged in will have some of their write permissions reset to the default settings. This is because the format of the 'wrttmp' file may change, and is thus emptied during each install. 7. Run 'make install' as root. 8. Edit the installed copy of the orville.conf file (which is, by default, in /usr/local/etc/orville.conf). This is where most site configuration is done. If you enable any of the other files (write.log, write.help, write.nohelp, helperlist), you must create them and put in sensible data. If you don't plan to enable helpers, you could remove the helper program and man page. OTHER PROGRAMS On M-Net and Grex, we have modifed 'finger' so that if a person is a helper, a '?' is placed next to their tty (where the '*' would be if they're message permissions were off). We have also modified ntalkd to respect Orville's permissions. Neither of these modified programs is really in good enough shape for general distribution at this point. Maybe later. FILE PERMISSIONS Orville write has a lot of files, whose permissions need to be set in specific and rather odd ways. The install script should do things correctly. For manual installers, here is a summary: FILE OWNER GROUP PERMS ----------------------------------- write root tty 6711 mesg root - 4711 amin root - 4711 huh root - 4711 helpers root - 4711 orville.conf root - 644 wrttmp root - 600 wrthist root - 600 * write.log root - 600 * write.help - - - * helperlist - - - * write.nohelp - - - tty means whichever group owns all tty devices on your system. - means I don't care. * means this file is only used if you configure it into orville.conf and is not installed by 'make install' Note the decidedly odd permissions of the write program, which as suid root as well as sgid tty. It really does need this, because it uses it's group identity to check tty's for readability. I should probably change this someday. An alternate configuration with a few fewer suid-root programs. Maybe this should be the default, I haven't had the time to work on figuring out how to make the configure script work out the names of your tty group. FILE OWNER GROUP PERMS ----------------------------------- write root tty 6711 mesg root - 6711 amin - tty 2711 huh - tty 2711 helpers - tty 2711 orville.conf root - 644 wrttmp root tty 660 wrthist root tty 660 * write.log root - 600 The 'mesg' program can be made sgid-tty instead of suid-root if you don't want to be able to turn on the 'disconnect' option in orville.conf. If you make wrttmp and wrthist readable to others then you can get rid of a sgid bits on 'huh' and 'helpers'. This allows people to figure out more about how other users message permissions are set, and who they have been writing recently. It's probably not worthwhile. OLD-STYLE TTY PERMISSIONS In the olden days, Unix systems were normally set up so that if you turned on your message permissions, then your tty device was permitted to everyone. The basic problem with systems of this type is that if you have your message permissions on then people can do annoying things like send files to your screen with: cat /etc/termcap > /dev/yourtty We had all too much trouble with this kind of frolicsome behavior on M-Net back in 1985, and the original purpose of doing a re-implementation of write was to block this kind of thing. That means changing the way tty permissions are handled, and doing that is going to cause headaches because it effects every program that does anything with tty permissions. There are several options (A and D are the easy ones): (A) Leave tty permissions working the same old way. People will still be able to 'cat' garbage to your tty, but you won't have to worry about modifying any other programs on your system and there will be no strange side effects. This is not true of any of the other options below. To use this option, edit the config.h file after running ./configure. Remove the TTY_GROUP definition, and add the TTY_OTHERS definition. Continue as above. (B) Revise the tty permissions to work with group permissions as on the systems described in the first part of this file. To do this you will need, at a minimum, to modify the login program so it initially sets up your tty permissions and group that way. Programs like "uucp", that just need to be able to turn off write permissions, will work without change. Programs like "pr" and "nroff" that turn off permissions while running and then turn them on again afterwards could be a problem, because they may turn the unwanted permissions to others back on. Other write-like programs (talkd?) may have to be modified, though it is possible that you may be able to get away with just running them SGID tty. If you go this route, then the installation of write should be done as described in the first section of this document. I've never tried converting a system this way. To use this option, build write just as above. (C) Leave tty devices depermitted at all times, and have write store the message permissions to be used in the /etc/wrttmp file, with the other status information. This requires that the login program be modified so that tty's are depermitted, though if you are any kind of guru dude, you can make this fix without source by hacking argument to the chmod() call in the binary (do people still do that?). This will have the odd effect of having message permissions default OFF when people log in. This is good for uucp, which doesn't like people writing it, but normal users will need to put a "mesg y" in their .logins. Unless modified, programs like "pr" will fail to turn off the message permissions when they start, and then will throw your tty permissions wide open when they finish. Other write-like programs may require even larger modifications to work right. To use this option, edit the config.h file after running ./configure. Remove the both the TTY_GROUP definition and the TTY_OTHERS definition. Continue as above. (D) Leave tty devices depermitted at most times, and have write store the real message permissions in the /etc/wrttmp file. You don't modify the login program, so initially people's ttys will be writable to others. You have the users put either "mesg y" or "mesg n" in their .login files. As a side effect these will depermit the tty devices, so that for ever afterwards no catting will be possible. Uucp will be fine, since all message permissions in the wrttmp file initially default off, and the uucp program turns off the tty device permissions itself. However other programs that fiddle with tty permissions will still have problems as in option C. To use this option, edit the config.h file after running ./configure. Remove the both the TTY_GROUP definition and the TTY_OTHERS definition. Continue as above. (E) Leave tty devices depermitted at all times, and have login initialize the message permissions in the /etc/wrttmp file. Add code to the login program to depermit the tty device and to make an appropriate entry in the user's slot of the /etc/wrttmp file. Default the permissions on, unless there is a file named ".mesgn" in the user's home directory. Give uucp an ".mesgn" file. This actually what was done on M-Net while it was still running under System III, but it isn't anymore. It's complicated, but it does give you un-writable tty devices and message permissions that default on for normal users. You still have the other incompatibility problems mentioned in option C. To use this option, edit the config.h file after running ./configure. Remove the both the TTY_GROUP definition and the TTY_OTHERS definition. Continue as above. orville-write-2.55/CHANGES0100644000076500007650000001302110126436474013365 0ustar janjan Version 2.55: Sep 28, 2004 - Rename log() function to wrtlog() to avoid conflicts with math.h log() function. - Add distclean target to Makefile. Version 2.54: May 30, 2003 - Fixed a couple buffer overrun problems that might have constituted a possible security hole. - Small portability fixes. Version 2.53: Jul 6, 2000 - Minor portability improvements to install scripts. Version 2.52: Jun 19, 2000 - Fixed a buffer overflow possibility in huh.c. This is a major problem if 'huh' is installed as root. Older versions should not be installed that way. Version 2.51: Feb 20, 2000 - Renamed lib_utmp.c as getutent.c, and cleaned it up to work more similarly to the standard getutent() functions. Fixed some bugs Karyl Stein pointed out with Linux utmp files. Version 2.50: Jan 28, 2000 - Add -pk and -x* flags to mesg, so if we have a cooperative talkd, we can control talk permissions seperately from write/tel permissions. - Can optionally include hostnames in "Message from" headers. - If a user is logged on more than once, write least idle tty. - Use autoconf to generate ./configure script which makes Makefile and and config.h. - Replace old wrttab file with new orville.conf file, and move most site configuration into there. - Include timezone in message header, since sender's timezone is not necessarily the same as the recipients. - Lots of rearrangements of header files and such. - Miscellaneous protability improvements. - Write -r option supported for more different kinds of password files. - Changed default name of the 'write -c' link to write from 'chat' to 'jot'. Chat is a better name, and I had it first, but the other chat is more widely distributed. Version 2.41: Mar 17, 1999 - ANSIfication of all function declarations. - Use getutent() on systems that have it. Need this when a utmp daemon is used instead of a utmp file (thanks to Shane Wegner ). - Be a bit more careful about printing/deleting .lastmesg to ensure we aren't root when we do it. - clean target added to Makefile (thanks to Shane Wegner ). - Renamed "common.c" to "lib_common.c" because I wanted to. - Lots of minor code cleanup. Version 2.40: - "mesg -bn" turns off bells. - Fixed bug in disconnect so it disconnects multiple writes. - exceptions through .yeswrite and .nowrite files and "mesg ye/ne" setting - telegram mode no longer sets wrt_what, since it is too transient. - telegram mode ignores -p, -y, -n, -c, -l flags (unless switch to write) - added helpers command. - Day of week in log file dates. - mesg command prints warning if people still can write you. - If previous helper is still available, another "write help" selects him. - Disable core dumps and check that stderr is open. - Security patches to .lastmesg file creation. [e] - Security patches to .lastmesg reading. [f] - Portability improvements to input flushing code Version 2.34: - Sizes of wrttmp entries stored in wrttmp header. - Can write back to someone writing you even if he prefers tels. - "mesg d" is like "mesg N" but doesn't change permissions. - Linux bug fixes. - Made writhist more resistant to system clock errors. Version 2.33: - Include uid name in message banner if different from utmp name. - Root can override recipient's write/tel preferences. - Optional recording of telegrams (with mesg -r, amin -p and huh) - "mesg -hY" makes you a helper even when permissions are off. Version 2.32: - wrthist file added, permitting tel replys and regulating flooding. - expand control-characters on local echo as well as send. - teach it to echo tabs and backspaces more accurately. - some low-grade word-wrap in character mode. - HELPLOG option for logging help requests only. Version 2.31: - "write ." writes again to the last user written. - write/telegram and line/character mode preferences added. - support for login names with more than 8 characters. - optional logging of all write requests. - added -v to mesg. [2.31e] - NOHELPER defines a file to print if there are no helpers. [2.31f] Version 2.30: - Integration of telegram option into write. - Fix bug with shell escapes in "write -n" making "mesg n" perminant. - Shell escapes use user's SHELL instead of always using /bin/sh. Version 2.20: - Reorganization of source code for greater modularity. - If multiple helpers are available, choose one at random. - When input is redirected, don't ask use stdin to ask user if he wants to interupt a conversation. - Don't go into character mode till other person has replied. - Starting a line with ) in character mode does that line in line mode. - If compiled with the NOVICEHELP variable and run with the NOVICE environment variable set, prints the contents of the file named in NOVICEHELP before running. - Fixed amin's job control. Version 2.11: - If user is logged on more than once, prefer tty that is permitted. - Clearer "Permission denied" message. Version 2.12: - Added TTY_OTHERS Version 2.10: - Attempted SYSV Compatible system. - Added HELPERS Version 2.00: First BSD Compatible system. - Added wrttab. - Added consistancy checking between utmp and wrttmp to eliminate need for modifications to /bin/login. - Added support for job control and other BSD-isms. Version 1.05: Last M-Net system III specific version. Version 1.00: First release - Sept 1985. orville-write-2.55/wrt_main.c0100644000076500007650000002534510126436545014371 0ustar janjan/* suid WRITE command Version 2.50 * * This is a replacement for the unix 'write' command with a large number of * enhancements. See the manual page for details. * * (C) Copyright, Nov 1995 - Jan Wolter * * This program may be used, distributed and modified free of charge. * * History has been moved to "CHANGES" file. * * Acknowledgements: Russ Cage first implemented a version of the disconnect * option, but his version of the source was lost. The reimplementation here * is probably similar to his. The idea of helpers more or less originated * with Eoin Cain. The telegram command was originally a separate command * implemented in C by Jeff Spindler and improved by Russ Cage. Discussions * with Marcus Watts were helpful in the design of the TTY_GROUP version. * The record options were inspired by Jef Poskanzer's "say" command. * Jim Knight installed zillions of versions on M-Net and added logging. * Valerie Mates installed zillions of versions on Grex and sent back lots * of valuable bug reports and suggestions. Jared Mauch supplied some * Linux compatibility fixes. Input from John Remmers was useful in the * design of the exception files. Shane Wegner made some patches to support * use of getutent() and various installation scripts. Karyl Stein has * supplied various good Linux bug fixes and reports. M-Netters and * Grexers by the thousands have served (willy-nilly) as beta testers. */ char *version= "2.55"; #include "write.h" #include char linebuf[LBSIZE+1]; /* A place to stash lines of typed in stuff */ char *telmsg; /* Index of second word of telegram text in linebuf */ char myname[UT_NAMESIZE+1]= ""; /* my name (based on utmp file) */ char myuidname[UT_NAMESIZE+1]; /* my name (based on uid number) */ char *mytty; /* my tty name in "tty##" format */ #ifdef TTYPERMS int myperms; /* my original tty perms */ #endif /*TTYPERMS*/ FILE *histerm; /* Opened version of device to write to */ struct wrttmp hiswrt; /* His wrttmp entry - later used for my tmp wrttmp */ char hisname[UT_NAMESIZE+1]= "";/* his name */ char histty[UT_LINESIZE+1]= ""; /* his tty name in "tty##" format */ char hisdevname[UT_LINESIZE+7]; /* Name of device to write to */ /* Mode flags are set by run time options */ bool char_by_char=FALSE;/* Run in character by character mode */ bool ask_root= FALSE; /* Ask for root password? */ bool telegram= FALSE; /* send a telegram? */ bool no_switch= FALSE; /* don't switch between tel and write? */ char tmp_mesg='s'; /* How to set messages while running: y, n or s */ bool postpone= FALSE; /* Postpone all tel interuptions */ bool am_root; /* Either uid is 0, or gave root passwd */ bool rec_only= FALSE; /* Do a postponed telegram, recorded, but not sent */ /* Exit flags tell what to do to restore sanity upon exiting */ bool fixed_modes= FALSE; /* On exiting, change wrttmp to mywrt? */ bool in_cbreak= FALSE; /* On exiting, get out of cbreak mode? */ bool is_writing= FALSE; /* On exiting, print goodbye message? */ bool insys= FALSE; /* Am I in | or & escape? */ bool readyn(void); void type_help(char *file); void wrtlog(char *outcome); main(int argc, char **argv) { long pos; struct wrttmp tmpwrt; char hisperms; extern struct wrttmp mywrt; bool nl,file_input,replying= 0; struct rlimit rlim; char *tty; int tmp; /* Turn off signals while we are starting up - I don't remember why */ /* On the whole, probably a good idea */ sigoff(); /* Check that stdin/stdout/stderr all exist and are open (from mdw) */ if ((tmp=dup(0)) < 3) { /* We haven't got stderr, so don't print an error message. */ exit(25); } close(tmp); #ifdef RLIMIT_CORE /* Disable core dumps -- may have part of shadow password file in memory */ rlim.rlim_cur= rlim.rlim_max= 0; setrlimit(RLIMIT_CORE, &rlim); #endif /* Set up options */ default_opts(argv[0]); /* Read options from orville.conf */ user_opts(argc,argv); /* Read options from command line */ file_input= !isatty(0); if (!telegram && !file_input && f_novicehelp != NULL && getenv("NOVICE")) type_help(f_novicehelp); /* If -f has been specified, make sure standard input is a tty */ if (!f_pipes && file_input) { printf("%s: input from non-tty disabled\n",progname); done(1); } /* Never allow standard output to be redirected - discourages tel bombs */ if (!isatty(1)) { fprintf(stderr,"%s: standard output may not be redirected\n",progname); done(1); } /* Get user's tty name safely */ if (getdevtty()) done(1); mytty= mydevname+5; #ifdef TTYPERMS if (saveperms()) done(1); #endif /*TTYPERMS*/ /* Set terminators on various names */ myname[UT_NAMESIZE]= hisname[UT_NAMESIZE]= histty[UT_LINESIZE]= '\0'; /* Open the wrttmp file */ if (init_wstream(O_RDWR)) done(1); /* Set up ttynames and usernames and get our wrttmp entries */ find_us(); if (telegram) fflush(stdout); nl= telegram; if (!iswritable()) { if (telegram) putchar('\n'); printf("Permission denied: %s is not accepting messages\n",hisname); wrtlog("FAIL: denied"); done(1); } /* If he is busy, confirm that we want to interupt him */ if (*hiswrt.wrt_what != '\000' && !(replying= !strncmp(hiswrt.wrt_what,myname,UT_NAMESIZE))) { /* his mesgs are on, but he is writing someone else ... */ if (nl) putchar('\n'); nl= FALSE; if (hiswrt.wrt_what[0] == '!') printf("%s is running %0.*s\n",hisname, UT_NAMESIZE-1, hiswrt.wrt_what+1); else printf("%s is now writing %0.*s.\n", hisname, UT_NAMESIZE, hiswrt.wrt_what); if (rec_only || (telegram && hiswrt.wrt_record == 'a')) { telegram= TRUE; rec_only= TRUE; } if (rec_only) printf("Do you want to leave %s message for when %s is done? ", (telmsg == NULL || telmsg[0] == '\0' || telmsg[0] == '\n') ? "a" : "your", hisname); else printf("Do you still want to write %s? ",hisname); fflush(stdout); if (!readyn()) { wrtlog("ABANDON: interupting"); done(1); } } /* Switch from tel to write (or vice versa) on recipient's preference */ if (!(am_root && no_switch) && !rec_only && (((telegram || file_input) && !(hiswrt.wrt_telpref & TELPREF_TEL)) || (!telegram && !(hiswrt.wrt_telpref & TELPREF_WRITE) && !replying))) { if (nl) putchar('\n'); nl= FALSE; printf("%s is not accepting %ss.\n", hisname, (telegram||file_input)?"telegram":"write"); if (!(hiswrt.wrt_telpref & (TELPREF_WRITE|TELPREF_TEL)) ) { if (!no_switch) printf("Try the \042talk\042 command.\n"); wrtlog("FAIL: can't switch - talk only"); done(1); } if (no_switch || file_input) { if (!no_switch) printf("Try the \042write\042 command " "(with no input redirection).\n"); wrtlog("FAIL: can't switch"); done(1); } else { printf("%s instead? ", telegram?"write":"send telegram"); fflush(stdout); if (!readyn()) { if (!am_root) { wrtlog("ABANDON: won't switch"); done(1); } } else telegram= !telegram; } printf("%s to %s on %s...\n", telegram?"Telegram":"Writing", hisname, histty); } /* Switch between character and line mode on recipient's preference */ if (!telegram) { if (file_input) char_by_char= FALSE; else { if (char_by_char && hiswrt.wrt_modepref == 'l') { printf("[Changing to line mode by %s's preference]\n",hisname); char_by_char= FALSE; } else if (!char_by_char && hiswrt.wrt_modepref == 'c') { printf("[Changing to character mode by %s's preference]\n", hisname); char_by_char= TRUE; } } } else { /* Turn off various options irrelevant to telegrams */ char_by_char= FALSE; tmp_mesg= 's'; postpone= FALSE; } /* Open his terminal */ if (rec_only) { if ((histerm= fopen("/dev/null","w")) == NULL) { printf("%s:Panic - Cannot open /dev/null to write\n",progname); done(1); } } else { if ((histerm= fopen(hisdevname,"w")) == NULL) { printf("%s:Panic - Cannot open %s to write\n",progname,hisdevname); done(1); } fcntl(fileno(histerm),F_SETFD,1); /* Close over execs */ } if (telegram || file_input) open_record(); open_hist(); wrtlog(rec_only?"POSTPONED":"OK"); /* Now that his terminal and the wrttmp file are open, abandon superuser */ setuid(getuid()); setgid(getgid()); /* Fix my entry in wrttmp */ set_modes(); /* Get rid of any previously recorded messages */ if (postpone) init_lastmesg(); siginit(); if (telegram) dotelegram(nl); else dowrite(); done(0); } /* READYN - Read a "yes" or "no" from /dev/tty (in case stdin is redirected). * Return TRUE if yes. */ bool readyn() { FILE *fp; char ynbuf[LBSIZE]; if ((fp= fopen("/dev/tty","r")) == NULL) fp= stdin; flushinput(fileno(fp)); fgets(ynbuf,LBSIZE,fp); if (fp != stdin) fclose(fp); return (*ynbuf == 'y' || *ynbuf == 'Y'); } /* DONE -- This is the standard exit routine. It prints the EOF message (if * we are actually writing the other user) and cleans up ttymodes and the * wrttmp file. */ void done(int code) { extern FILE *recfp; /* Put all those signals to sleep */ sigoff(); /* If we were writing, print the exit message */ if (is_writing && !nested_write()) { fprintf(histerm,"EOF (%s)\n",myname); fflush(histerm); if (recfp) fprintf(recfp,"EOF (%s)\n",myname); } if (postpone) show_lastmesg(); /* If we changed our wrttmp entry, restore it */ reset_modes(); /* If we were in cbreak, restore old tty modes */ if (in_cbreak) cbreak(FALSE); exit(code); /* This should be the only call to exit() */ } /* TYPE_HELP -- This prints out a help file. */ void type_help(char *file) { FILE *fp; int ch; if ((fp= fopen(file,"r")) != NULL) { while ((ch= getc(fp)) != EOF) putchar(ch); fclose(fp); } } /* LOG - This logs a write execution. */ void wrtlog(char *outcome) { FILE *fp; time_t tock; extern bool helpseeker; /* If we aren't logging, just get out */ if (f_loglevel == 0 || (f_loglevel == 1 && !helpseeker)) return; /* If log file exist, open it, otherwise leave without creating it */ if (f_log == NULL || access(f_log,0) || (fp= fopen(f_log,"a")) == NULL) return; tock= time((time_t *)0); if (helpseeker) { fprintf(fp,"%20.20s %-*.*s %s help (%s %s): %s\n", ctime(&tock)+4, UT_NAMESIZE, UT_NAMESIZE, myname, progname, (hisname[0] && strcmp(hisname,"help"))?hisname:"-", histty[0]?histty:"-", outcome); } else { fprintf(fp,"%20.20s %-*.*s %s %s %s: %s\n", ctime(&tock)+4, UT_NAMESIZE, UT_NAMESIZE, myname, progname, hisname[0]?hisname:"-", histty[0]?histty:"-", outcome); } fclose(fp); } orville-write-2.55/wrt_type.c0100644000076500007650000002611407665676545014445 0ustar janjan/* WRITE TYPING ROUTINES -- This does the actual write conversation, letting * me type in characters and sending them to him. This whole module is too * kludgy and needs a rewrite. */ #include "write.h" #include #include #include #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif /* HAVE_SYS_TIME_H */ #endif /* TIME_WITH_SYS_TIME */ extern char eof_char, bs_char, kill_char; extern bool helpseeker; bool holdline; /* True if we don't want to send line till it is done */ struct passwd *getpwnam(); #ifndef HOTZONE #define HOTZONE 9 #endif #ifndef MAXLASTMESG #define MAXLASTMESG 16000 #endif FILE *recfp= NULL; struct passwd *hispwd= NULL; #define putb(ch) {putc(ch,histerm); if (recfp) putc(ch,recfp);} #define putsb(st) {fputs(st,histerm); if (recfp) fputs(st,recfp);} void backcol(int *col,int to); void sendchar(int ch); void sendline(char *ln, int start, int ind); void sendbanner(void); int isexcept(char *dir, int yesfile, char *login); /* GETHISPWD - This routine ensures that the hispwd variable has been set. * Returns true if it fails. */ int gethispwd() { if (hispwd != NULL) return (0); return ((hispwd= getpwnam(hisname)) == NULL); } /* The following routines are for fooling with tabs and other multi-column * characters. Column numbers are from 0 to 79. * * TABCOL(c) - If the cursor was in column c, this returns the column it would * be in after hitting a tab. * * OUTCOL(str,i) - What column would the cursor appear in after typing the * string from str[0] through str[n-1]? */ #define tabcol(c) (((c)+8)&(-8)) int outcol(char *str, int n) { int i,c= 0; for (i= 0; i < n && str[i] != '\0'; i++) { if (!isascii(str[i])) c+= isprint(toascii(str[i])) ? 3 : 4; else if (str[i] == '\t') c= tabcol(c); else if (str[i] == '\b') c--; else if (!isprint(str[i])) c+= 2; else c++; } return(c); } /* DOWRITE -- Do the actual write conversation */ void dowrite() { int ch; int ind= 0; /* Current index into linebuf */ int start; /* Index of 1st unprinted char (during holdline only) */ int col= 0; /* Current column on screen */ int maxcol= get_cols(); /* Number of columns on screen (sort of) */ bool command= FALSE; /* True if we are doing a shell escape */ bool connected; /* True if the other person has replied (during char_by_char mode only) */ /* send him a banner, if we weren't writing him already */ if (!nested_write()) sendbanner(); connected= !char_by_char; /* only character mode cares if connected */ is_writing= TRUE; holdline= FALSE; /* Go into cbreak mode, if that's what is desired */ if (char_by_char) cbreak(TRUE); /* Start copying text from my terminal to his */ while((ch= getchar()) != EOF) { ch &= 0377; if (char_by_char) { /* Fix odd backspace */ if (ch == bs_char) ch= '\b'; /* low-grade word-wrap */ if ((!holdline || !connected) && (ch == ' ' || ch == '\t') && col > maxcol-HOTZONE && col < maxcol) ch= '\n'; } /* Echo the character in the line buffer */ switch(ch) { case '\n': if (char_by_char) putchar(ch); if (holdline) { if (command && ind > 0) { linebuf[ind]= '\000'; dosystem(linebuf); } else { linebuf[ind]= '\n'; sendline(linebuf,start,ind+1); start= 1; } col= ind= 0; continue; } col= ind= 0; break; case '\b': /* BACKSPACE */ if (char_by_char) { if (col == 0) continue; if (ind > 0) ind--; backcol(&col,outcol(linebuf,ind)); continue; } break; case '\027': /* ^W */ if (char_by_char) { if (col == 0 || ind == 0) continue; while (ind > 0 && isspace(linebuf[ind-1])) ind--; while (ind > 0 && !isspace(linebuf[ind-1])) ind--; backcol(&col,outcol(linebuf,ind)); continue; } case '\022': /* ^R */ if (char_by_char) { linebuf[ind]= '\000'; printf("\n%s",linebuf); continue; } default: if (ind == 0) { if (!connected && char_by_char && he_replied()) connected= TRUE; command= (ch == '!' || ch == '|' || ch == '&'); holdline= (!connected || command || ch == ')'); start= (ch == ')') ? 1 : 0; } /* Simulate function of ^D for char_by_char mode */ if (ch == eof_char) { if (ind == 0) return; else { if (holdline) { linebuf[ind]= '\000'; if (command && ind > 0) { putchar('\n'); dosystem(linebuf); ind= 0; } else { sendline(linebuf,start,ind); start= ind; } } continue; } } if (ch == kill_char) { ind= 0; backcol(&col,0); continue; } if (ind < LBSIZE) linebuf[ind++]= ch; if (char_by_char) { int tch= ch; if (tch == '\t') { putchar(tch); col= tabcol(col); break; } if (!isascii(tch)) { putchar('M'); putchar('-'); col+= 2; tch= toascii(tch); } if (!isprint(tch)) { putchar('^'); col++; if (tch == '\177') tch= '?'; else tch+= '@'; } putchar(tch); col++; } break; } if (!holdline) sendchar(ch); } } /* DOTELEGRAM -- Send a telegram */ void dotelegram(bool nl) { int ch; /* Ask the user for a message if we don't already have one */ if (telmsg == NULL || telmsg[0] == '\0' || telmsg[0] == '\n') { if (nl) putchar('\n'); printf("Msg: "); fgets(telmsg= linebuf, LBSIZE, stdin); if (telmsg[0] == '\n') done(0); } /* slow down if we are sending stuff too fast */ if (f_wrthist != NULL) { sleep(check_flood()); register_tel(); } /* send him a banner, if we weren't writing him already */ if (!nested_write()) sendbanner(); /* Send the telegram */ is_writing= TRUE; while (*telmsg != '\0') sendchar(*(telmsg++)); if (rec_only) printf("SAVED\n"); else printf("SENT\n"); } /* BACKCOL - Erase back until the current column col is to */ void backcol(int *col,int to) { for ( ; *col > to; (*col)--) { putchar('\b'); putchar(' '); putchar('\b'); if (!holdline) putsb("\b \b"); } fflush(histerm); } /* SENDCHAR: Send a character to his tty, expanding out control characters, * and storing a copy in the record file, if open. */ void sendchar(int ch) { if (ch == '\n' || ch == '\b' || ch == '\t' || ch == '\r') putb(ch) else { if (!isascii(ch)) { putsb("M-"); ch= toascii(ch); } if (!isprint(ch)) { putb('^'); ch= ((ch == '\177') ? '?' : ch + '@'); } putb(ch); } fflush(histerm); } /* SENDLINE: Send a string to his tty, expanding out control characters. * Start at start and go to ind. If ind is less than start, backspace to it. */ void sendline(char *ln, int start, int ind) { int i; if (start < ind) for (i= start; i < ind; i++) sendchar(ln[i]); else { for (i= start; i > ind; i--) putsb("\b \b"); fflush(histerm); } } /* SENDBANNER: Send a banner to him, notifying him that we want to talk */ void sendbanner() { time_t tock; struct tm *tm; char bf[300]; char *bell, *zone; extern struct wrttmp hiswrt; char host[1026]; #ifdef HAVE_TZNAME extern char *tzname[2]; #endif host[0]= '@'; if (f_fromhost && gethostname(host+1,1024)) f_fromhost= 0; tock= time((time_t *)0); tm= localtime(&tock); #ifdef HAVE_TZNAME if (tm->tm_isdst >= 0) zone= tzname[tm->tm_isdst]; else zone= NULL; #else #ifdef HAVE_TM_ZONE zone= (char *)tm->tm_zone; #endif #endif bell= (hiswrt.wrt_bells == 'y') ? "\007\007\007":""; if (myuidname[0] == '\0') sprintf(bf,"%s from %s%s%.90s on %s at %d:%02d %.20s ...\n%s", telegram ? "Telegram" : "Message", helpseeker ? "help-seeker " : "", myname, f_fromhost ? host : "", mytty, tm->tm_hour, tm->tm_min, zone == NULL ? "" : zone, bell); else sprintf(bf, "%s from %s%s%.90s (%s) on %s at %d:%02d %.20s ...\n%s", telegram ? "Telegram" : "Message", helpseeker ? "help-seeker " : "", myname, f_fromhost ? host : "", myuidname, mytty, tm->tm_hour, tm->tm_min, zone == NULL ? "" : zone, bell); fputs(bf,histerm); if (recfp) fputs(bf,recfp); fflush(histerm); } /* OPEN_RECORD - Open a record file in the target users' home directory */ void open_record() { char fname[LBSIZE], *dir, *his_dir(); extern struct wrttmp hiswrt; int fd; struct stat st; recfp= NULL; if (hiswrt.wrt_record == 'n') return; if (gethispwd()) { printf("%s: cannot find %s in passwd file -- not recording.\n", progname,hisname); if (rec_only) done(1); return; } sprintf(fname,"%.400s/.lastmesg",hispwd->pw_dir); /* First try to open an existing file */ if ((fd= open(fname, O_WRONLY|O_APPEND)) >= 0) { /* Check that .lastmesg file is owned by the right person */ if (fstat(fd,&st) || st.st_uid != hispwd->pw_uid || !(st.st_mode & 0200)) { close(fd); printf("%s: improper ownership of %s -- not recording.\n", progname,fname); if (rec_only) done(1); return; } /* If we are recorded only most recent message, truncate file */ if (hiswrt.wrt_record == 'y') { ftruncate(fd,0L); lseek(fd,0L,0); /* rewind (probably unnecessary) */ } else if (lseek(fd,0L,1) > MAXLASTMESG) /* not a seek -- just tell */ { printf("%s: %s overfull -- not recording.\n",progname,fname); if (rec_only) done(1); return; } } else { /* Could not open existing file - try creating one */ if ((fd= open(fname,O_WRONLY|O_CREAT|O_EXCL|O_APPEND,0600)) < 0) { printf("%s: cannot open %s -- not recording.\n", progname,fname); if (rec_only) done(1); return; } /* Set ownership of file to target user */ fchown(fd,hispwd->pw_uid,hispwd->pw_gid); } fcntl(fd, F_SETFD, 1); /* Close over execs */ recfp= fdopen(fd,"a"); } /* ISHISEXCEPTION - is listed in the .yeswrite/.nowrite in HIS home * directory? * * ISUEXECPTION - is listed in the .yeswrite/.nowrite in user's home * directory? */ int ishisexception(int yesfile, char *login) { if (gethispwd()) return(0); return(isexcept(hispwd->pw_dir, yesfile, login)); } int isuexception(char *user, int yesfile, char *login) { struct passwd *pwd; char u[UT_NAMESIZE+1]; /* Make sure the name is null terminated */ strncpy(u, user, UT_NAMESIZE); u[UT_NAMESIZE]= '\0'; if ((pwd= getpwnam(u)) == NULL) return(0); return(isexcept(pwd->pw_dir, yesfile, login)); } int isexcept(char *dir, int yesfile, char *login) { char buf[LBSIZE+1]; char *b,*e; FILE *fp; sprintf(buf, "%.400s/%s", dir, yesfile ? ".yeswrite" : ".nowrite"); if ((fp= fopen(buf,"r")) == NULL) return(0); buf[LBSIZE]= '\0'; while (fgets(buf,LBSIZE,fp) != NULL) { if (buf[0] == '#') continue; e= buf-1; for (;;) { /* Skip leading blanks and punctuation */ for (b= e+1; *b!='\0' && strchr(" ,;:\t\n\r",*b)!=NULL; b++) ; if (*b == '\0') break; /* Find next blank or punctuation character */ for (e= b+1; *e!='\0' && strchr(" ,;:\t\n\r",*e)==NULL; e++) ; *e= '\0'; if (!strcmp(b,login)) { fclose(fp); return(1); } } } fclose(fp); return(0); } orville-write-2.55/wrt_him.c0100644000076500007650000003645110126426275014221 0ustar janjan/* WRITE FINDHIM ROUTINES -- This searchs the wrttmp file for the person * to write. */ #include "write.h" #include #include #ifndef TCFLSH #include #endif /*TCFLSH*/ #ifdef HAVE_GETSPNAM # define PW_GETSPNAM # include struct spwd *getspnam(); # ifdef HAVE_KG_PWHASH char *pw_encrypt(); char *kg_pwhash(char *clear, char *user, char *result, int resultlen); # else # ifdef HAVE_PW_ENCRYPT char *pw_encrypt(); # define pcrypt(l,p,s) pw_encrypt(p, s) # else # define pcrypt(l,p,s) crypt(p, s) # endif # endif #else # ifdef HAVE_GETUSERPW # define PW_GETUSERPW # define pcrypt(l,p,s) crypt(p, s) # include # else # define PW_GETPWNAM # define pcrypt(l,p,s) crypt(p, s) # endif #endif /* HAVE_GETSPNAM */ long hispos; /* The offset of his entry in the wrttmp file */ bool helpseeker= FALSE; /* Did we write to a random helper? */ char *what[2] = {"Writing", "Telegram"}; extern struct wrttmp hiswrt; extern struct wrthdr wt_head; void find_him(void); int find_tty(void); void find_answer(void); void find_helper(void); int perms_on(struct wrttmp *thewrt, time_t *atime); /* Password encryption for Grex */ #ifdef HAVE_KG_PWHASH char *pcrypt(char *login, char *plain, char *salt) { static char bf[40]; char *cpass; if (salt[0] != '%') cpass= pw_encrypt(plain, salt); else if ((cpass= kg_pwhash(plain, login, bf, 40)) == NULL) { bf[0]= '\0'; cpass= bf; } return cpass; } #endif /* HAVE_KG_PWHASH */ /* FIXPERF: Fix old-style wrt_telpref fields in the given wrttmp structure. */ void fixpref(struct wrttmp *wrt) { if (wrt->wrt_telpref & TELPREF_OLD) { switch (wrt->wrt_telpref) { case 'w': wrt->wrt_telpref= TELPREF_WRITE; break; case 't': wrt->wrt_telpref= TELPREF_TEL; break; #ifdef WITH_TALK case 'k': wrt->wrt_telpref= TELPREF_TALK; break; #endif case 'a': case '-': wrt->wrt_telpref= TELPREF_ALL; break; } } } /* FIND_US: This digs the two of us out of the utmp file and sets up myname, * mytty, mydevname, mypos, hisname, histty, hisdevname and hispos. * * Finding myself is straightforward, but there are several cases for finding * him: * (1) Both name and tty are given: Check that that person is really * on that tty. * (2) Just the tty is given. Find the name on that tty, if any. * (3) Just the name is given. Find all tty's occupied by someone by * that name. If there are more than one, look for one who is * writing me or one with his permissions on. * (4) Neither name nor tty is given. Find if anyone is writing me. * use that. * (5) The name "help" was given. Find a helper who is not busy. * (6) The name "." was given. Try writing to the last person written. * * If any of these fail, an appropriate error message is printed and * we exit. If the succeed, a message is printed describing who we * ended up writing. */ void find_us() { int rc; extern struct wrttmp mywrt; /* Open utmp file */ setutent(); /* Look me up */ find_me(); /* Find his name and wrttmp entry */ if (*hisname == '\0' && *histty == '\0') { /* No name was given - search wrttmp for someone writing me */ find_answer(); } else if (f_helpers && *histty == '\0' && !strcmp(hisname,f_helpername)) { /* Search for a helper who has his perms on and is not busy */ find_helper(); } else if (*histty == '\0') { /* If name is "." get name from last field */ if (hisname[0] == '.' && hisname[1] == '\0') { if (mywrt.wrt_last[0] == '\0') { printf("No previous write or telegram. Can't repeat\n"); wrtlog("FAIL: no previous"); done(1); } strncpy(hisname,mywrt.wrt_last,UT_NAMESIZE); } /* Just the name given...look for him */ find_him(); } else { if ((rc= find_tty()) > 0) { /* In telegram mode, if ttyname doesn't work, it is probably the * first word of the message, and not the ttyname at all */ if (telegram) { telmsg= linebuf; histty[0]= '\0'; if (hisname[0] == '\0') find_answer(); else if (f_helpers && !strcmp(hisname,f_helpername)) find_helper(); else find_him(); } else if (rc == 1) { printf("No such tty\n"); wrtlog("FAIL: no such tty"); done(1); } else { printf("%s not logged onto %s\n",hisname,histty); wrtlog("FAIL: not on tty"); done(1); } } } sprintf(hisdevname,"/dev/%.*s",UT_LINESIZE,histty); fixpref(&hiswrt); fixpref(&mywrt); endutent(); } /* FIND_HIM: Given just his name, search wrttmp for the person to write. * If he is logged on more than once, we'll take any one of them, but we'd * prefer one who is writing us, or at least has his perms on. If he isn't * on, print an error message and exit. */ void find_him() { int cnt= 0; int write_me; int perm, hisperm= 0; time_t hisatime= 0; time_t atime; struct utmp *ut; struct wrttmp tmpwrt; long tmppos; setutent(); while ((ut= getutent()) != NULL) { /* Check if this is the target user, ignoring X-window lines */ if (ut->ut_line[0] != ':' && #ifdef USER_PROCESS ut->ut_type == USER_PROCESS && #endif !strncmp(hisname, ut->ut_name, UT_NAMESIZE)) { /* Count matches */ cnt++; /* Find wrttmp entry */ find_wrttmp(ut->ut_line, ut->ut_time, &tmpwrt, &tmppos); /* Is this guy writing me? */ write_me= !strncmp(tmpwrt.wrt_what,myname,UT_NAMESIZE); /* Do I have write access? How long has he been idle? */ if (!write_me) perm= perms_on(&tmpwrt,&atime); /* If writing me, is less idle, or is first to be permitted, save */ if (write_me || (perm && !hisperm) || (atime > hisatime && (perm == hisperm)) ) { strncpy(histty, ut->ut_line, UT_LINESIZE); hiswrt= tmpwrt; hispos= tmppos; hisatime= atime; hisperm= perm; /* If this guy is writing me, look no further */ if (write_me) break; } } } /* Check for abnormal results */ if (cnt == 0) { /* didn't find any matches, trouble */ printf("%s is not logged on\n",hisname); { wrtlog("FAIL: not on"); done(1); } } else if (cnt == 1) { /* Found one match - the usual */ printf("%s to %s on %s...",what[telegram],hisname,histty); if (!telegram) putchar('\n'); } else { /* Found multiple matches -- tell which we used */ printf("%s logged on more than once\n",hisname); printf("%s to %s...",what[telegram],histty); if (!telegram) putchar('\n'); } } /* FIND_TTY: Given his ttyname, and possibly his login name, find a matching * user. If none match, print an error message and exit. Set if hisname if * it wasn't given. Return code: * 0 - success. * 1 - no such tty. * 2 - named user not on named tty. */ int find_tty() { struct utmp *ut; if ((ut= find_utmp(histty)) == NULL) return(1); if (*hisname != '\0') { /* Does the name not match? */ if (strncmp(hisname, ut->ut_name, UT_NAMESIZE)) return(2); } else { /* Is anyone on that line? */ if (*ut->ut_name == '\0') { printf("No one logged onto %s\n",histty); wrtlog("FAIL: empty tty"); done(1); } strncpy(hisname, ut->ut_name, UT_NAMESIZE); } printf("%s to %s on %s...",what[telegram],hisname,histty); if (!telegram) putchar('\n'); find_wrttmp(histty,ut->ut_time,&hiswrt,&hispos); return(0); } /* FIND_ANSWER: Find a user who is writing me. Set up histty and hisname if * a match is found. Note that if the time in the wrttmp entry doesn't match * the time in the utmp entry, then we presume it is a dude wrttmp left over * from some other login and we ignore it. If not found, print an error * message and terminate. */ void find_answer() { struct utmp *ut; int slot; lseek(wstream,hispos= wrttmp_offset(slot= 0),0); while (read(wstream, &hiswrt, sizeof(struct wrttmp)) == sizeof(struct wrttmp)) { if (!strncmp(myname, hiswrt.wrt_what, UT_NAMESIZE)) { /* Found someone writing me - get his name from utmp */ strncpy(histty,hiswrt.wrt_line,UT_LINESIZE); if ((ut= find_utmp(histty)) != NULL && ut->ut_name[0] != '\0') { strncpy(hisname,ut->ut_name,UT_NAMESIZE); printf("Replying to %s on %s...",hisname,histty); if (!telegram) putchar('\n'); return; } } lseek(wstream,hispos= wrttmp_offset(++slot),0); } printf("You are not being written\n"); wrtlog("FAIL: not written"); done(0); } /* FIND_HELPER: Find an unoccupied user who has his helper flag set. If * found, set up histty and hisname. If there is none, print an error message * and terminate. As usual, ignore wrttmp entries who's login times don't * agree with the times in utmp. If there is more than one helper available, * one is selected at random. */ void find_helper() { extern struct wrttmp mywrt; int nhelpers= 0; /* Number of helpers on */ int ahelpers= 0; /* Number of helpers available */ int previous; int slot= 0; struct utmp *ut; struct wrttmp tmpwrt; long tmppos; helpseeker= TRUE; SEEDRAND((unsigned)time((time_t *)0)); for (;;) { /* Read in the next line of the file, remembering our offset */ lseek(wstream, tmppos= wrttmp_offset(slot++), 0); if (read(wstream, &tmpwrt, sizeof(struct wrttmp)) != sizeof(struct wrttmp)) break; /* Reject obvious non-helpers */ if (tmpwrt.wrt_help == 'n' || /* Helper flag off */ !strncmp(tmpwrt.wrt_line, mytty, UT_LINESIZE)) /* I can't help myself! */ continue; /* Find the helper candidate in utmp - if he's not there skip out */ if ((ut= find_utmp(tmpwrt.wrt_line)) == NULL || ut->ut_name[0] == '\0' || ut->ut_time != tmpwrt.wrt_time) continue; /* Reject helpers with their message permissions off */ if (tmpwrt.wrt_help != 'Y') { if (!perms_on(&tmpwrt,NULL)) { /* Perms off - but am I in .yeswrite file? */ if (!f_exceptions || tmpwrt.wrt_except != 'y' || !isuexception(ut->ut_name, 1, myname)) continue; } else { /* Perms on - but am I in .nowrite file? */ if (f_exceptions && tmpwrt.wrt_except == 'y' && isuexception(ut->ut_name, 0, myname)) continue; } } /* Whoopie! We have found a real live helper */ nhelpers++; /* Reject helpers who are busy writing someone else */ if (tmpwrt.wrt_what[0] != '\0' && /* He busy and ... */ strncmp(tmpwrt.wrt_what, myname, UT_NAMESIZE)) /* ...not writing me */ continue; /* Zowie! He's not only there, he's available to help us */ ahelpers++; /* Has he helped us before? */ previous= !strncmp(ut->ut_name, mywrt.wrt_last, UT_NAMESIZE); /* So roll the dice to see if we will choose him */ if (!previous && (unsigned)RAND() > (unsigned)RAND_MAX / ahelpers) continue; /* We chose him, so make him our helper candidate so far */ strncpy(histty, tmpwrt.wrt_line, UT_LINESIZE); strncpy(hisname, ut->ut_name, UT_NAMESIZE); hiswrt= tmpwrt; hispos= tmppos; /* If he helped us before, choose him now */ if (previous) break; } if (ahelpers == 0) { if (nhelpers == 0) { printf("Sorry, no helpers are available right now.\n"); if (f_nohelp) type_help(f_nohelp); wrtlog("FAIL: no helpers"); } else { printf("Sorry, all helpers currently available are busy.\n"); if (f_nohelp) type_help(f_nohelp); printf("Try again later...\n"); wrtlog("FAIL: help busy"); } done(0); } printf("%s to helper %s on %s...",what[telegram],hisname,histty); if (!telegram) putchar('\n'); } /* PERMS_ON: Return true if permissions for the user whose wrttmp entry is * passed in are on. This is a less thorough version of iswritable() used * while selecting a user to write. Also returns last access time of tty, if * atime is not null. * */ int perms_on(struct wrttmp *thewrt, time_t *atime) { char devname[UT_LINESIZE+7]; struct stat stb; short flag; #ifndef TTYPERMS if (atime != NULL || thewrt->wrt_mesg != 'n') { /* Even if wrttmp perms are off, user may still be writable if * physical perms are on, so we need to stat the tty anyway in that * case, or if we want the last access time. */ #endif /*TTYPERMS*/ /* Stat the terminal */ sprintf(devname,"/dev/%.*s",UT_LINESIZE,thewrt->wrt_line); if (stat(devname,&stb)) { printf("%s: Panic - can't stat %s\n",progname,devname); done(1); } if (atime != NULL) *atime= stb.st_atime; #ifndef TTYPERMS } if (thewrt->wrt_mesg != 'n') return(TRUE); #endif /*TTYPERMS*/ /* Is his tty physically writable? */ if (getuid() == stb.st_uid) flag= stb.st_mode & 0200; else if (getegid() == stb.st_gid || getgid() == stb.st_gid) flag= stb.st_mode & 0020; else flag= stb.st_mode & 0002; return(flag != 0); } /* ISWRITABLE: Check if he is writtable, either because his permissions are * on, he is writing me, I am root, his tty is writable, or I can give the * right root password with the -r option. */ bool iswritable() { char *cpass; #ifdef PW_GETPWNAM struct passwd *pwd; #endif /* Can I give the root password? * We always test this first, so that we always ask for the root password * when -r is given. This reduces the chance of accidentally sending the * root password to the writtee because you expected it to ask for the * root password and it didn't. */ if (ask_root) { #ifdef PW_GETPWNAM pwd= getpwuid(0); cpass= pcrypt("root",getpass("Password:"),pwd->pw_passwd); flushinput(0); /* discard typeahead */ if (am_root= !strcmp(cpass,pwd->pw_passwd)) return (TRUE); #endif #ifdef PW_GETSPNAM struct spwd *spwd; spwd= getspnam("root"); cpass= pcrypt("root",getpass("Password:"),spwd->sp_pwdp); flushinput(0); /* discard typeahead */ if (am_root= !strcmp(cpass,spwd->sp_pwdp)) return (TRUE); #endif #ifdef PW_GETUSERPW struct userpw *upwd; upwd= getuserpw("root"); cpass= pcrypt("root",getpass("Password:"),upwd->upw_passwd); flushinput(0); /* discard typeahead */ if (am_root= !strcmp(cpass,upwd->upw_passwd)) return (TRUE); #endif printf("Password incorrect\n"); } /* Is he writing me? */ if (!strncmp(hiswrt.wrt_what, myname, UT_NAMESIZE)) return(TRUE); /* Am I already root? */ if (am_root= (getuid() == 0)) return(TRUE); /* Are his permissions on? */ if (perms_on(&hiswrt,NULL)) { /* Permissions are on, but are we an exception? */ if (!f_exceptions || hiswrt.wrt_except != 'y' || !ishisexception(0,myname)) return(TRUE); } else { /* Permissions are off, but are we an exception? */ if (f_exceptions && hiswrt.wrt_except == 'y' && ishisexception(1,myname)) return(TRUE); } if (f_wrthist != NULL && may_answer_tel()) return(TRUE); /* Is he running "amin -p"? */ if (hiswrt.wrt_what[0] != '\0' && hiswrt.wrt_record == 'a') { /* NOTE: rec_only is only set if his perms are otherwise off. * Later it gets set for all other cases too. */ rec_only= TRUE; return(TRUE); } if (helpseeker && hiswrt.wrt_help == 'Y') return(TRUE); return(FALSE); } /* HE_REPLIED -- This routine returns true if the person we are writing appears * to be writing us back. It should only be called after a call to find_us(). */ bool he_replied() { struct wrttmp wbuf; lseek(wstream, hispos, 0); if (read(wstream, &wbuf, sizeof(struct wrttmp)) != sizeof(struct wrttmp)) return(FALSE); return(!strncmp(wbuf.wrt_what, myname, UT_NAMESIZE)); } orville-write-2.55/wrt_me.c0100644000076500007650000001172007665673473014057 0ustar janjan/* WRITE ROUTINES TO MANAGE MY WRTTMP ENTRY */ #include "write.h" #include #include struct wrttmp mywrt; /* My old wrttmp entry, to be restored at exit time */ long mypos= -1; /* offset of my entry in the wrttmp file */ /* FIND_ME: Find my name and ttyline. Use these to dig up my wrttmp entry. */ void find_me() { struct utmp *ut; struct passwd *pw; int myuid; /* Search utmp for myself */ if ((ut= find_utmp(mytty)) == NULL || ut->ut_name[0] == '\0') { printf("%s: Panic - Unable to find your tty (%s) in "_PATH_UTMP"\n", progname, mytty); done(1); } strncpy(myname, ut->ut_name, UT_NAMESIZE); /* Check if this is our real identity */ #ifndef SLOWPASSWD myuid= getuid(); if ((pw= getpwnam(myname)) == NULL || pw->pw_uid != myuid) { if ((pw= getpwuid(myuid)) == NULL) { printf("%s: Panic - No passwd file entry for uid %d (uname %s)\n", progname,myuid, myname); done(1); } strncpy(myuidname,pw->pw_name,UT_NAMESIZE); myuidname[UT_NAMESIZE]= '\0'; } else #endif myuidname[0]= '\0'; /* ie: myuidname is the same as myname */ /* Find my wrt_tmp entry */ find_wrttmp(mytty, ut->ut_time, &mywrt, &mypos); } /* SET_MODES: This sets our runtime modes into the wrttmp file and makes any * temporary changes to our ttymodes. A copy of our original modes is left * unchanged in mywrt and myperms. This is called as we go into write mode. * For telegrams, the only change we make is to update the "last" field, if * necessary. No transient changes are made. */ void set_modes() { struct wrttmp tmpwrt; if (telegram) { /* If not writing same user again, update last field in wrttmp file */ if (strncmp(mywrt.wrt_last, hisname, UT_NAMESIZE)) { strncpy(mywrt.wrt_last, hisname, UT_NAMESIZE); lseek(wstream,mypos,0); if (write(wstream,&mywrt,sizeof(struct wrttmp)) != sizeof(struct wrttmp)) { printf("%s: Panic - Cannot write to wrttmp file\n",progname); done(1); } } } else { /* Set last field - this should persist after we exit so do in mywrt */ strncpy(mywrt.wrt_last, hisname, UT_NAMESIZE); tmpwrt= mywrt; /* Make temporary changes to wrttmp entry */ strncpy(tmpwrt.wrt_what, hisname, UT_NAMESIZE); tmpwrt.wrt_pid= getpid(); #ifdef TTYPERMS setperms(tmp_mesg); #else if (tmp_mesg != 's') tmpwrt.wrt_mesg= mywrt.wrt_mesg; #endif /*TTYPERMS*/ if (postpone) tmpwrt.wrt_record= 'a'; lseek(wstream,mypos,0); fixed_modes= TRUE; if (write(wstream,&tmpwrt,sizeof(struct wrttmp)) != sizeof(struct wrttmp)) { printf("%s: Panic - Cannot write to wrttmp file\n",progname); done(1); } } } /* UPDATE_MODES: This is called after a shell escape or a suspend to see if * the user changed his message permissions while he was gone. If so, it * copies the change into our copy of his old wrttmp entry so it will be * restored to that after we exit write. */ void update_modes() { struct wrttmp tmpwrt; #ifdef TTYPERMS if (saveperms()) done(1); #endif /*TTYPERMS*/ lseek(wstream,mypos,0); if (read(wstream,&tmpwrt,sizeof(struct wrttmp))==sizeof(struct wrttmp)) { strncpy(tmpwrt.wrt_last, mywrt.wrt_last, UT_NAMESIZE); #ifndef TTYPERMS mywrt.wrt_mesg= tmpwrt.wrt_mesg; #endif /*TTYPERMS*/ mywrt.wrt_record= tmpwrt.wrt_record; mywrt.wrt_telpref= tmpwrt.wrt_telpref; mywrt.wrt_modepref= tmpwrt.wrt_modepref; mywrt.wrt_help= tmpwrt.wrt_help; mywrt.wrt_bells= tmpwrt.wrt_bells; mywrt.wrt_except= tmpwrt.wrt_except; } } /* RESET_MODES: Before exiting, restore wrttmp modes to original state (aside * from any modifications made through update_modes()). */ void reset_modes() { if (fixed_modes) { lseek(wstream,mypos,0); write(wstream,&mywrt,sizeof(struct wrttmp)); fixed_modes= FALSE; #ifdef TTYPERMS resetperms(); #endif /*TTYPERMS*/ } } /* NESTED_WRITE: Returns true if this write was run from within a write * process with a shell escape */ bool nested_write() { return(!strncmp(mywrt.wrt_what, hisname, UT_NAMESIZE)); } /* INIT_LASTMESG - Figure out what my lastmesg file is and empty it. */ char lmfile[100]= ""; void init_lastmesg() { char *dir; struct passwd *pwd; /* A little insurance that we aren't root anymore */ if (getuid() != geteuid()) return; /* Try the environment variable first */ if ((dir= getenv("HOME")) == NULL) { /* Otherwise get directory from passwd file */ setpwent(); pwd= getpwuid(getuid()); endpwent(); if (pwd == NULL) { postpone= FALSE; return; } dir= pwd->pw_dir; } sprintf(lmfile, "%.80s/.lastmesg", dir); unlink(lmfile); } /* SHOW_LASTMESG - Print the .lastmesg file. */ void show_lastmesg() { FILE *fp; int ch; /* A little insurance that we aren't root anymore */ if (getuid() != geteuid()) return; if (lmfile[0] == '\0' || (fp= fopen(lmfile,"r")) == NULL) return; unlink(lmfile); printf("Messages received while you were busy...\n"); while ((ch= getc(fp)) != EOF) if (ch != '\007') putchar(ch); } orville-write-2.55/wrt_opt.c0100644000076500007650000001033307044212343014227 0ustar janjan/* WRITE OPTION ROUTINES -- Code to set options from orville.conf file or * command line. */ #include "write.h" /* SET_OPTS: Given a pointer to a string of one character option flags, * terminated by a null or by white space, this sets the global variables * corresponding to those flags. It returns 1 if any of the characters were * illegal, 0 otherwise. */ int set_opts(char *str) { for(;;str++) switch(*str) { case 'S': no_switch= TRUE; break; case 'c': char_by_char= TRUE; break; case 'l': char_by_char= FALSE; break; case 'n': case 'y': case 's': tmp_mesg= *str; break; case 'f': f_pipes= FALSE; break; case 't': telegram= TRUE; break; case 'r': ask_root= TRUE; break; case 'p': postpone= TRUE; break; case 'v': fprintf(stderr,"Orville Write version %s\n",version); break; case '\0': case '\n': case '\t': case ' ': return(0); default: return(1); } } /* SET_DFLT: Called for each "options" line in the configuration file. It * is passed the rest of the line after the "options" keyword and any spaces. * It checks if the filename matchs our program name, and if so, sets the * options on that line. */ void set_dflt(char *p) { int len; /* Does file line start with progname or a star? */ if (*p == '*') p++; else { len= strlen(progname); if (!strncmp(progname,p,len)) p= p+len; else return; } /* Is that name followed by a space character? */ if (*p != ' ' && *p != '\t') return; /* Scan the rest of the line for dashes, and set anything after it */ for (p++ ;*p != '\n' && *p != '\0'; p++) if (*p == '-' && set_opts(p+1)) fprintf(stderr,"%s: Unknown flag on options line in " ORVILLE_CONF"\n", progname); } /* DEFAULT_OPTS: This reads through the orville.conf file loading configuration * settings and looking for "options" lines that match progname. (Either * progname itself or a "*"). If a match is found, the rest of the line is * scanned for strings starting with a "-" that we can interpret as option * flags. Those flags are set. Then we continue scanning for more matches. */ void default_opts(char *argname) { /* Strip leading components off invocation name of program */ progname= leafname(argname); /* Use common reading routine */ readconfig(set_dflt); } /* USER_OPTS: This parses the command line arguments. It sets options, and * also gets the name or tty of the person to write, if given. If there are * problems in the argument syntax, then it prints a usage message. Note * that with the telegram option, all arguments after the user name (possibly * including the ttyname) are stuck into linebuf. telmsg is pointed at the * part after the first word which might be the target tty rather than part * of the message. */ void user_opts(int argc, char **argv) { int i; char *c; bool gotname=FALSE; bool gottty=FALSE; int wastelegram= telegram; char *telegram_end= linebuf; telmsg= NULL; for (i=1; i UT_LINESIZE) telmsg= linebuf; else strncpy(histty, c, UT_LINESIZE); gottty= TRUE; } if (telegram) { if (telegram_end != linebuf) { *(telegram_end++)= ' '; if (telmsg == NULL) telmsg= telegram_end; } while (*c != '\0' & telegram_end < linebuf+LBSIZE-1) { *(telegram_end++)= *c; /* Erase message words so they don't show on "ps" */ /* what needs to be done to do this varies on unixes */ /* but this should work most places */ *(c++)= ' '; } } } else goto usage; } *(telegram_end++)= '\n'; *telegram_end= '\0'; return; usage: if (wastelegram) printf("usage: %s [-ynsr] user [ttyname] [message...]\n", progname); else printf("usage: %s [-clynsptr] user [ttyname]\n",progname); done(1); } orville-write-2.55/wrt_sig.c0100644000076500007650000001321407044212361014210 0ustar janjan/* WRITE SIGNAL HANDLING ROUTINES -- Code to handle suspends and interputs and * fun stuff like that, as well as the normal exit routines. Support for * system calls is here too. */ #include "write.h" #include #include #ifdef USER_SHELL void wsystem(char *cmd); FILE *wpopen(char *cmd, char *mode); void xwpclose(void); #define wpclose(s) xwpclose() #else #define wsystem(s) system(s) #define wpopen(s,m) popen(s,m) #define wpclose(s) pclose(s) #endif jmp_buf sysenv; /* Where to jump on intrupt during | and & escapes */ /* SIGINIT -- Set up the signal handler routines. */ void siginit() { signal(SIGTERM,(RETSIGTYPE (*)())intr); signal(SIGINT,(RETSIGTYPE (*)())intr); signal(SIGHUP,(RETSIGTYPE (*)())intr); #ifdef JOB_CONTROL signal(SIGTSTP,(RETSIGTYPE (*)())susp); #endif /*JOB_CONTROL*/ } /* SIGOFF -- Turn off all signals the signal handler routines. */ void sigoff() { signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGTERM,SIG_IGN); #ifdef JOB_CONTROL signal(SIGTSTP,SIG_IGN); #endif /*JOB_CONTROL*/ } /* INTR -- Leave on an interupt. If the interupt was during a shell escape, * resume as if the shell escape exited. */ RETSIGTYPE intr(int sig) { if (insys && (sig == SIGINT)) { signal (SIGINT, (RETSIGTYPE (*)())intr); longjmp(sysenv,1); } done(1); } /* SUSP -- Suspend the process. Unlike shell escapes, we restore the wrttmp * entry before stopping. This is because, unlike shell escapes, we can't * assume that stopped processes will be restarted in the reverse order in * which they were stopped. */ #ifdef JOB_CONTROL RETSIGTYPE susp() { int was_cbreak= in_cbreak; int mask; /* Disable further signals */ mask= sigblock(sigmask(SIGTSTP)); /* Restore modes and make wrttmp look like we exited */ if (in_cbreak) cbreak(FALSE); if (postpone) show_lastmesg(); reset_modes(); signal(SIGTSTP,SIG_DFL); sigsetmask(0); kill(getpid(),SIGTSTP); /* STOP HERE */ sigsetmask(mask); signal(SIGTSTP,(RETSIGTYPE (*)())susp); /* Reinstate cbreak mode and wrttmp entry */ if (was_cbreak) cbreak(TRUE); update_modes(); if (!telegram) set_modes(); } #endif /*JOB_CONTROL*/ /* DOSYSTEM: This routine does a system call of one of three types. If the * first character is a "!" then we do the normal system call. If the first * character is a "&" then we open a pipe to that command and send one copy * of it's output to the other person, and one copy to me. If the first * character is a "|" we only send the output to him. * * This routine absolutely must not be called until after we are no longer * root. The wpopen() and wsystem() calls used here are not secure, even with * full paths given. */ void dosystem(char *cmd) { char was_cbreak= in_cbreak; FILE *pip, *wpopen(); int ch; if (in_cbreak) cbreak(FALSE); if (*cmd == '!') { wsystem(cmd+1); } else if (!f_pipes) printf("%s: piped shell escapes disabled\n",progname); else { if ((pip= wpopen(cmd+1,"r")) == NULL) printf("%s:Panic - Unable to start command\n",progname); else { if (!setjmp(sysenv)) { insys= TRUE; while((ch= getc(pip)) != EOF) { if (*cmd == '&') putchar(ch); sendchar(ch); } } insys= FALSE; wpclose(pip); } } /* Restore cbreak mode */ if (was_cbreak) cbreak(TRUE); if (tmp_mesg == 's') update_modes(); printf("%c\n",*cmd); } #ifdef USER_SHELL /* WSYSTEM: A modified version of the system() command that uses the user's * own shell (as specified by the "SHELL" environment variable) instead of * always using sh. */ void wsystem(char *cmd) { register int cpid,wpid; RETSIGTYPE (*old_intr)(), (*old_quit)(); char *shell; if ((cpid = fork()) == 0) { dup2(2,1); /*setuid(getuid()); setgid(getgid());*/ endutent(); if ((shell= getenv("SHELL")) == NULL) shell= "/bin/sh"; execl(shell,leafname(shell),"-c",cmd,(char *)NULL); fprintf(stderr,"%s: cannot execute shell %s\n", progname,shell); exit(-1); } old_intr = signal(SIGINT,SIG_IGN); old_quit = signal(SIGQUIT,SIG_IGN); while ((wpid = wait((int *)0)) != cpid && wpid != -1) ; signal(SIGINT,old_intr); signal(SIGQUIT,old_quit); } /* WPOPEN/WPCLOSE - Run command on a pipe * * This is similar to the Unix popen() and pclose() calls, except * (1) upopen() closes the last upopen() whenever it is called. * (2) upclose() closes the last upopen(), and takes no args. * (3) the user's own shell is used to process commands. */ FILE *f_lastpop = NULL; /* current upopened stream (NULL means none) */ int p_lastpop; /* process id of last upopened command */ FILE *wpopen(char *cmd, char *mode) { int pip[2]; register int chd_pipe,par_pipe; FILE *fdopen(); char *shell; if (f_lastpop) xwpclose(); /* Make a pipe */ if (pipe(pip)) return((FILE *)0); /* Choose ends */ par_pipe= (*mode == 'r') ? pip[0] : pip[1]; chd_pipe= (*mode == 'r') ? pip[1] : pip[0]; switch (p_lastpop= fork()) { case 0: /* Child - run command */ close(par_pipe); if (chd_pipe != (*mode == 'r'?1:0)) { dup2(chd_pipe,(*mode == 'r'?1:0)); close(chd_pipe); } /*setuid(getuid()); setgid(getgid());*/ endutent(); /* Dunno if close-on-exec is set */ if ((shell= getenv("SHELL")) == NULL) shell= "/bin/sh"; execl(shell,leafname(shell),"-c",cmd,(char *)NULL); fprintf(stderr,"%s: cannot execute shell %s\n", progname,shell); exit(-1); case -1: close(chd_pipe); close(par_pipe); return((FILE *)0); default: close(chd_pipe); return(f_lastpop=fdopen(par_pipe,mode)); } } void xwpclose() { int pid; if (f_lastpop == NULL || fclose(f_lastpop)) return; f_lastpop=NULL; while ((pid=wait((int *)0)) != -1 && pid != p_lastpop ) ; } #endif orville-write-2.55/wrt_tty.c0100644000076500007650000000703207042776222014260 0ustar janjan/* WRITE TTY ROUTINES -- Routine to get user's tty in and out of cbreak mode. */ #include "write.h" #ifdef F_TERMIO #include #endif /*F_TERMIO*/ #ifdef F_TERMIOS #include #endif /*F_TERMIOS*/ #ifdef F_STTY #include #endif /*F_STTY*/ #if !defined(TCFLSH) && !defined(TCIFLUSH) #include #endif char eof_char; /* User's end of file character */ char bs_char; /* User's backspace character */ char kill_char; /* User's kill character */ /* CBREAK: cbreak(TRUE) turns on cbreak mode, cbreak(FALSE) restores the * original tty modes. */ #ifdef F_STTY void cbreak(bool flag) { struct tchars ctrlchars; static struct sgttyb sgtty; static tfg; if (flag) { /* Get current modes */ ioctl(0,TIOCGETP,&sgtty); tfg= sgtty.sg_flags; bs_char= sgtty.sg_erase; kill_char= sgtty.sg_kill; ioctl(0,TIOCGETC,&ctrlchars); eof_char= ctrlchars.t_eofc; /* Remember that we are in cbreak mode */ in_cbreak= TRUE; /* Turn on cbreak mode */ sgtty.sg_flags &= ~ECHO; sgtty.sg_flags |= CBREAK; ioctl(0,TIOCSETN,&sgtty); } else { /* Turn off cbreak mode - that is restore original modes */ sgtty.sg_flags= tfg; ioctl(0,TIOCSETN,&sgtty); in_cbreak= FALSE; } } #endif /*F_STTY*/ #ifdef F_TERMIO void cbreak(bool flag) { static struct termio tio; static tfg; static char eol_char; if (flag) { /* Get current modes */ ioctl(0,TCGETA,&tio); tfg= tio.c_lflag; eof_char= tio.c_cc[VEOF]; eol_char= tio.c_cc[VEOL]; bs_char= tio.c_cc[VERASE]; kill_char= tio.c_cc[VKILL]; /* Remember that we are in cbreak mode */ in_cbreak= TRUE; /* Turn on cbreak mode - that is turn off ICANON */ tio.c_lflag= tfg & ~ICANON; tio.c_lflag &= ~ECHO; tio.c_cc[VEOF]= 1; tio.c_cc[VEOL]= 0; ioctl(0,TCSETA,&tio); } else { /* Turn off cbreak mode - that is restore original modes */ tio.c_lflag= tfg; tio.c_cc[VEOF]= eof_char; tio.c_cc[VEOL]= eol_char; ioctl(0,TCSETA,&tio); in_cbreak= FALSE; } } #endif /*F_TERMIO*/ #ifdef F_TERMIOS void cbreak(bool flag) { static struct termios tio; static tfg; static char eol_char; if (flag) { /* Get current modes */ tcgetattr(0,&tio); tfg= tio.c_lflag; eof_char= tio.c_cc[VEOF]; eol_char= tio.c_cc[VEOL]; bs_char= tio.c_cc[VERASE]; kill_char= tio.c_cc[VKILL]; /* Remember that we are in cbreak mode */ in_cbreak= TRUE; /* Turn on cbreak mode - that is turn off ICANON */ tio.c_lflag= tfg & ~ICANON; tio.c_lflag &= ~ECHO; tio.c_cc[VEOF]= 1; tio.c_cc[VEOL]= 0; tcsetattr(0,TCSANOW,&tio); } else { /* Turn off cbreak mode - that is restore original modes */ tio.c_lflag= tfg; tio.c_cc[VEOF]= eof_char; tio.c_cc[VEOL]= eol_char; tcsetattr(0,TCSANOW,&tio); in_cbreak= FALSE; } } #endif /*F_TERMIOS*/ /* FLUSHINPUT: Flush input on tty on filedescriptor dev. */ void flushinput(int dev) { #ifdef TCIFLUSH tcflush(dev, TCIFLUSH); /* TERMIOS way to flush input */ #else #ifdef TCFLSH ioctl(dev,TCFLSH,0); /* SysIII way to flush input */ #else int flushcode= FREAD; ioctl(dev,TIOCFLUSH,&flushcode); /* BSD way to flush input */ #endif /*TCFLSH*/ #endif /*TCIFLUSH*/ } /* GET_COLS: Return number of columns on user's terminal. Sort of. Since * this is going to be used for wrapping on both my terminal and his, we * won't let it be more than 80, since his terminal probably doesn't have * more than 80 columns even if ours does. */ int get_cols() { #ifdef TIOCGWINSZ struct winsize x; ioctl(2,TIOCGWINSZ,&x); if (x.ws_col == 0 || x.ws_col > 80) return(80); else return(x.ws_col); #else return(80); #endif } orville-write-2.55/wrt_hist.c0100644000076500007650000000641007043367514014407 0ustar janjan/* WRITE HISTORY ROUTINES -- Stuff to keep track of the last time I wrote * various people and enforce rules about flooding. */ #include "write.h" int hist_fd= -1; /* file descriptor for wrthist file */ struct wrthist myhist; /* Copy of my wrthist entry */ extern struct wrttmp hiswrt; /* OPEN_HIST - Open the history file for read/write, if it is not already * open. */ void open_hist() { if (hist_fd >= 0) return; if ((hist_fd= open(f_wrthist,O_RDWR|O_CREAT,0600)) < 0) { printf("%s: Unable to open %s to read/write\n", progname, f_wrthist); done(1); } fcntl(hist_fd, F_SETFD, 1); /* close over execs */ } /* EMPTY_HIST - blank out a history field to say no write has occurred for * one heck of a long time. */ void empty_hist(hist) struct wrthist *hist; { int i; hist->tm= 0; #if MAX_TEL_N > 1 for (i= 0; i < MAX_TEL_N - 1; i++) hist->intv[i]= MAX_TEL_T + 1; #endif } #ifdef DEBUG /* PRINT_HIST - A debugging output routine */ void print_hist(struct wrthist *hist) { int i; printf("last=%ld %s",hist->tm,ctime(&hist->tm)); printf("intervals=( "); #if MAX_TEL_N > 1 for (i= 0; i < MAX_TEL_N - 1; i++) printf("%d ",hist->intv[i]); #endif printf(")\n"); } #endif /* GET_HIST - Get the history file entry for the last times the person in * slot "writer" wrote the person in slot "writee". */ void get_hist(long writer, long writee, struct wrthist *hist) { if (writee > MAXSLOTS) { empty_hist(hist); return; } open_hist(); lseek(hist_fd,whindex(writer,writee),0); if (read(hist_fd,hist,sizeof(struct wrthist)) != sizeof(struct wrthist)) empty_hist(hist); } /* PUT_HIST - Write the history file entry for the last times the person in * slot "writer" wrote the person in slot "writee". */ put_hist(long writer, long writee, struct wrthist *hist) { if (writee > MAXSLOTS) return; open_hist(); lseek(hist_fd,whindex(writer,writee),0); if (write(hist_fd,hist,sizeof(struct wrthist)) != sizeof(struct wrthist)) printf("%s: Error writing history entry\n",progname); } /* MAY_ANSWER_TEL - Check if he sent me a tel in the last f_answertel seconds. */ bool may_answer_tel() { int his_slot= hispos / sizeof(struct wrttmp); int my_slot= mypos / sizeof(struct wrttmp); struct wrthist hist; get_hist(his_slot,my_slot,&hist); return (hist.tm > hiswrt.wrt_time && time((time_t *)0) - hist.tm <= f_answertel); } /* CHECK_FLOOD - return a number of seconds we should sleep before sending * another tel. This must be called before register_tel(). */ int check_flood() { int his_slot= hispos / sizeof(struct wrttmp); int my_slot= mypos / sizeof(struct wrttmp); time_t now= time((time_t *)0); int total; int i,tmp,sft; get_hist(my_slot,his_slot,&myhist); if (myhist.tm > now) empty_hist(&myhist); total= now - myhist.tm; myhist.tm= now; #if MAX_TEL_N > 1 sft= (total > MAX_TEL_T) ? MAX_TEL_T + 1 : total; for (i= MAX_TEL_N-2; i >= 0; i--) { total+= myhist.intv[i]; tmp= myhist.intv[i]; myhist.intv[i]= sft; sft= tmp; } #endif return ((total >= MAX_TEL_T) ? 0 : MAX_TEL_T - total); } /* REGISTER_TEL() - Record that we did do a tel. Must be called after * check_flood(). */ void register_tel() { int his_slot= hispos / sizeof(struct wrttmp); int my_slot= mypos / sizeof(struct wrttmp); put_hist(my_slot,his_slot,&myhist); } orville-write-2.55/lib_common.c0100644000076500007650000002115110126436611014650 0ustar janjan/* ROUTINES COMMON BETWEEN WRITE, AMIN, MESG, ETC */ #include "orville.h" #include /* CONFIGURATION OPTION TABLE - various commands that can be set in the * orville.conf file. The options are actually stored in the global variables * declared here (with their default values). The conftab[] structure is used * by the readconf() program to load them up easily. */ #define CO_OPT 0 /* 'options' command */ #define CO_STR 1 /* String-valued command */ #define CO_FLG 2 /* Flag-valued command */ #define CO_INT 3 /* Int-valued command */ char *f_wrttmp= D_WRTTMP; /* The who's-talking-to-whom file */ char *f_wrthist= D_WRTHIST; /* The who-talked-to-whom file */ char *f_novicehelp= NULL; /* Type this if "NOVICE" env var is defined */ char *f_log= NULL; /* Log for all write connections */ char *f_helperlist= NULL; /* File of users who may be helpers */ char *f_helpername= "help"; /* Name you write to get help */ char *f_nohelp= NULL; /* File to print if no helpers available */ int f_disconnect= TRUE; /* Does 'mesg d' disconnect users? */ int f_exceptions= TRUE; /* Do 'mesg ne' and 'mesg ye' work? */ int f_fromhost= FALSE; /* Include hostname in 'Message from' banner? */ int f_helpers= FALSE; /* Does 'write help' work? */ int f_pipes= TRUE; /* Can I cat files through write? */ int f_loglevel= 0; /* How much logging to do? */ int f_answertel= 240; /* How many seconds to answer telegrams? */ struct { char *cmd; int len; int type; void *var; } conftab[]= { {"answertel", 9, CO_INT, (void *)&f_answertel}, {"disconnect", 10, CO_FLG, (void *)&f_disconnect}, {"exceptions", 10, CO_FLG, (void *)&f_exceptions}, {"fromhost", 8, CO_FLG, (void *)&f_fromhost}, {"helperlist", 10, CO_STR, (void *)&f_helperlist}, {"helpername", 10, CO_STR, (void *)&f_helpername}, {"helpers", 7, CO_FLG, (void *)&f_helpers}, {"log", 3, CO_STR, (void *)&f_log}, {"loglevel", 8, CO_INT, (void *)&f_loglevel}, {"nohelp", 6, CO_STR, (void *)&f_nohelp}, {"novicehelp", 10, CO_STR, (void *)&f_novicehelp}, {"options", 7, CO_OPT, NULL}, {"pipes", 5, CO_FLG, (void *)&f_pipes}, {"wrthist", 7, CO_STR, (void *)&f_wrthist}, {"wrttmp", 6, CO_STR, (void *)&f_wrttmp}, {NULL, 0, 0, NULL}}; char *progname; /* The name of this program */ int wstream; /* File descriptor for open wrttmp file */ struct wrthdr wt_head; /* Header read out of wrttmp file */ char mydevname[UT_LINESIZE+10]; /* my tty name in /dev/tty?? format */ /* LEAFNAME: return pointer to last component of a pathname */ char *leafname(char *fullpath) { char *leaf; if ((leaf= strrchr(fullpath,'/')) == NULL) leaf= fullpath; else leaf++; return(leaf); } /* GETDEVTTY: Store the ttyname in the global mydevname variable. * Print and error message and return non-zero if stderr not a tty open for * read. This is to prevent people from pretending they are writing from a * terminal other than their own by redirecting stderr to fool ttyname(). * They are unlikely to have read access to anyone else's tty. */ int getdevtty() { char *tty; if (!(fcntl(2,F_GETFL,0) & O_RDWR) || !isatty(2)) { printf("%s: stderr improperly redirected\n",progname); return 1; } if ((tty= ttyname(2)) == NULL || strlen(tty) < 5) { printf("%s: Not on a valid tty\n"); return 2; } strncpy(mydevname,tty,UT_LINESIZE+10); return 0; } /* INIT_WSTREAM - open the wrttmp file, loading and checking the header. * Mode can be either O_RDONLY or O_RDWR. Prints error message and returns * true if it fails. */ int init_wstream(int mode) { if ((wstream= open(f_wrttmp,mode)) < 0) { printf("%s: Unable to open %s to read/write\n", progname, f_wrttmp); return(1); } fcntl(wstream,F_SETFD,1); /* Close over execs */ /* Read in wrttmp file header */ if (read(wstream,&wt_head,sizeof(struct wrthdr)) == sizeof(struct wrthdr)) { if ( wt_head.hdr_size < sizeof(struct wrthdr) || wt_head.tmp_size < sizeof(struct wrttmp) ) { printf("%s: %s file has undersized entries. Old version?\n", progname, f_wrttmp); return(1); } } else { /* Initialize header for new wrttmp file */ wt_head.hdr_size= sizeof(struct wrthdr); wt_head.tmp_size= sizeof(struct wrttmp); if (mode != O_RDONLY) { lseek(wstream, 0L, 0); write(wstream, &wt_head, sizeof(struct wrthdr)); lseek(wstream, 0L, 1); /* must seek between write and read */ } } return(0); } /* FIND_UTMP -- Find the named tty in the utmp file, returning NULL if we * fail. The tty name need not be null terminated. */ struct utmp *find_utmp(char *tty) { struct utmp tmputmp; strncpy(tmputmp.ut_line, tty, UT_LINESIZE); setutent(); /* open and/or rewind */ return getutline(&tmputmp); } /* FIND_WRTTMP: Find the named tty in the wrttmp file and return the wrttmp * field and the offset of that line's entry. If the entry's login time * doesn't match the given one, or if there is no entry in the file, then * return a default wrttmp entry instead. In the latter case, the position * returned will be the offset of the first blank slot at the end of the file. */ void find_wrttmp(char *tty, time_t time,struct wrttmp *wbuf, long *pos) { register int slot; slot= 0; for(;;) { lseek(wstream, *pos= wrttmp_offset(slot++),0); if (read(wstream, wbuf, sizeof(struct wrttmp)) != sizeof(struct wrttmp)) break; if (!strncmp(tty, wbuf->wrt_line, UT_LINESIZE)) { if (wbuf->wrt_time == time) return; else break; } } /* Set wbuf to default value */ dflt_wrttmp(wbuf,tty,time); } /* DFLT_WRTTMP -- set a wrttmp entry to default status */ void dflt_wrttmp(struct wrttmp *wbuf, char *tty, time_t time) { /* Set wbuf to default value */ strncpy(wbuf->wrt_line,tty,UT_LINESIZE); wbuf->wrt_time= time; wbuf->wrt_what[0]= '\0'; wbuf->wrt_last[0]= '\0'; wbuf->wrt_pid= -1; wbuf->wrt_record= DFLT_RECO; wbuf->wrt_telpref= DFLT_PREF; wbuf->wrt_modepref= DFLT_MODE; wbuf->wrt_bells= DFLT_BELL; #ifndef TTYPERMS wbuf->wrt_mesg= DFLT_MESG; #endif /*TTYPERMS*/ wbuf->wrt_help= DFLT_HELP; wbuf->wrt_except= DFLT_EXCP; } #ifdef TTYPERMS int myperms; /* my original tty perms */ extern char mydevname[]; /* SAVEPERMS: Remember the current tty permissions of my terminal. Returns * 1 on failure. */ int saveperms() { struct stat stb; if (stat(mydevname,&stb)) { printf("%s: Panic - can't stat %s\n",progname,mydevname); return(1); } myperms= stb.st_mode; return(0); } /* SETPERMS: Set the tty permissions to yes (perm='y'), no (perm='n'), or * leave them alone (perm='s'). */ void setperms(char perm) { if (perm == 'n') chmod(mydevname,PERMS_OFF); if (perm == 'y') chmod(mydevname,PERMS_ON); } /* RESETPERMS: Set the tty permissions back to saved state. */ void resetperms() { chmod(mydevname,myperms); } #endif /*TTYPERMS*/ /* READCONFIG: This reads through the orville.conf file loading configuration * settings. It calls set_dflt() on any 'options' lines it sees, and saves * all configuration filenames. If set_dflt is NULL, it isn't called. */ void readconfig(void (*set_dflt)(char *)) { FILE *fp; #define BFSZ 1024 char buf[BFSZ+1]; int i; char *p, *q; if ((fp= fopen(ORVILLE_CONF,"r")) == NULL) { fprintf(stderr,"Unable to open "ORVILLE_CONF" to read\n"); exit(1); } while (fgets(buf,BFSZ,fp)) { if (buf[0] == '#' || buf[0] == '\n') continue; for (i= 0; conftab[i].cmd != NULL; i++) { if (strncmp(buf, conftab[i].cmd, conftab[i].len) || strchr(" \n\t\r", buf[conftab[i].len]) == NULL) continue; /* skip white space */ p= buf + conftab[i].len + 1; while (*p != '\0' && strchr(" \t\n\r",*p) != NULL) p++; if (*p == '\0' || *p == '\n' || *p == '\r') { fprintf(stderr,"%s: No value given for %s in " ORVILLE_CONF"\n", progname, conftab[i].cmd); exit(1); } switch (conftab[i].type) { case CO_OPT: /* "options" command */ if (set_dflt != NULL) (*set_dflt)(p); break; case CO_STR: /* string-valued commands */ /* Find end of word */ for (q= p; *q != '\0' && strchr(" \t\n\r",*q) == NULL; q++) ; *q= '\0'; /* Save the new value, without freeing any previous value, * which might be static. */ *(char **)conftab[i].var= malloc(q-p+1); strcpy(*(char **)conftab[i].var,p); break; case CO_FLG: /* flag-valued commands */ *(int *)conftab[i].var= (*p == 'y' || *p == 'Y'); break; case CO_INT: /* integer-valued commands */ *(int *)conftab[i].var= atoi(p); break; } break; } } fclose(fp); } orville-write-2.55/getutent.c0100644000076500007650000000460207045473405014403 0ustar janjan/* GETUTENT ROUTINES FOR SYSTEMS THAT HAVEN'T GOT THEM */ #include "orville.h" #ifndef HAVE_GETUTENT #include static struct { char *fname; /* Filename. If NULL, name is _PATH_UTMP */ int fd; /* file descriptor for open utmp file */ int state; /* 0 = not open; 1 = open; -1 = cannot open */ } utmp= {NULL,0,0}; /* OPENUTENT - Ensure the utmp file is open. Return non-zero if it can't be * opened. This routine is not exported. */ static int openut() { if (utmp.state == 0) { if ((utmp.fd= open(utmp.fname ? utmp.fname : _PATH_UTMP, O_RDONLY)) < 0) { utmp.state= -1; return -1; } else { utmp.state= 1; fcntl(utmp.fd, F_SETFD, 1); /* Close over execs */ return 0; } } } /* ENDUTENT - Close the utmp file. */ void endutent() { if (utmp.state == 1) close(utmp.fd); utmp.state= 0; } /* SETUTENT - Rewind the utmp file. */ void setutent() { if (utmp.state == 1) lseek(utmp.fd, 0L, 0); } /* UTMPNAME - Set the name of the utmp file. */ int utmpname(const char *file) { /* Close any currently open file */ endutent(); if (utmp.fname != NULL) free(utmp.fname); utmp.fname= strdup(file); return 0; } /* GETUTENT - Read the next entry from the utmp file into static storage. */ struct utmp *getutent() { static struct utmp ut; switch (utmp.state) { case 0: openut(); /* Drop through */ case 1: if (read(utmp.fd, &ut, sizeof(struct utmp)) == sizeof(struct utmp)) return &ut; /* Drop through */ default: return (struct utmp *)NULL; } } /* GETUTLINE - Return utmp entry for the next entry in the utmp file whose * ut_line field matches in->ut_line. It's obnoxious that this wants a * whole utmp structure passed in instead of just a char pointer, but * we conform with Linux and Solaris. */ struct utmp *getutline(const struct utmp *in) { static struct utmp ut; switch (utmp.state) { case 0: openut(); /* Drop through */ case 1: while (read(utmp.fd, &ut, sizeof(struct utmp)) == sizeof(struct utmp)) { if ( #if defined(USER_PROCESS) && defined(LOGIN_PROCESS) (ut.ut_type == USER_PROCESS || ut.ut_type == LOGIN_PROCESS) && #endif !strncmp(ut.ut_line, in->ut_line, UT_LINESIZE)) { return &ut; } } /* Drop through */ default: return (struct utmp *)NULL; } } #endif /* HAVE_GETUTENT */ orville-write-2.55/write.h0100644000076500007650000000331207665675415013715 0ustar janjan/* Standard header for all files that make up the Orville 'write' program */ #ifndef WRITE_H #define WRITE_H #include "orville.h" #define LBSIZE 1024 /* Size of the input line buffer */ /* ======================== GLOBAL VARIABLES =========================== */ extern bool char_by_char, ask_root, fixed_modes, in_cbreak, is_writing, insys, telegram, no_switch, am_root, rec_only, postpone; extern char tmp_mesg; extern char *progname, *mytty, *version, *telmsg; extern char myname[], hisname[], hisdevname[], histty[], linebuf[]; extern char myuidname[]; extern FILE *histerm; extern int wstream; extern long hispos,mypos; /* =================== PROCEDURE DEFINITIONS ===-----================== */ /* wrt_him.c functions */ void find_us(void); bool iswritable(void); bool he_replied(void); /* wrt_hist.c functions */ void open_hist(void); bool may_answer_tel(void); int check_flood(void); void register_tel(void); /* wrt_main.c functions */ void done(int code); /* wrt_me.c functions */ void find_me(void); void set_modes(void); void reset_modes(void); bool nested_write(void); void init_lastmesg(void); void show_lastmesg(void); /* wrt_opt.c functions */ char *leafname(char *fullpath); void default_opts(char *argname); void user_opts(int argc, char **argv); /* wrt_sig.c functions */ void siginit(void); void sigoff(void); RETSIGTYPE intr(int sig); RETSIGTYPE susp(void); void dosystem(char *cmd); /* wrt_tty.c functions */ void cbreak(bool flag); void flushinput(int dev); int get_cols(void); /* wrt_type.c functions */ void dowrite(void); void dotelegram(bool nl); void open_record(void); int ishisexception(int yesfile, char *login); int isuexception(char *user, int yesfile, char *login); #endif /* WRITE_H */ orville-write-2.55/wrttmp.h0100644000076500007650000001311207043473533014102 0ustar janjan/* WRTTMP FILE * * The wrttmp file consists of a single "wrthdr" entry, followed by multiple * wrttmp entries. The wrttmp entries each describe one user on one tty line, * and correspond to lines in the utmp file. "wrthdr" is mostly version info. * * This is the structure for each wrttmp file entry. Write can be configured * to either use permissions stored in the wrtmp file, or to use the physical * device permissions (if TTYPERMS is defined). The latter configuration is * preferred, for easier coexistance with other programs, espeically if your * old write program ran group "tty". * * Preferences (telegram vs write and line-mode vs character-mode) are also * stored here. Normally these are set to "-" meaning that the choice is up * to the sender. But if a preference is set by the reciever, it overrules * the sender's choice. * * Also the name of the person currently being written is stored here. This is * used by the auto-reply feature and the gizmo that asks about interupting. * * The name of the last person a telegram was sent to is also kept. This is so * the next telegram can be sent to the same person. * * New entries in the wrthdr or wrttmp structures should be added to the end, * leaving the old structures alone. This will ensure that the file can still * be shared with programs compiled with an older version of wrttmp. */ #ifndef WRTTMP_H #define WRTTMP_H #include #include /* BSDI is only Unix I know of that threatens to change namesize from 8 to * anything else. Most don't even have a define for it. Here we default * NAMESIZE and LINESIZE to 8, if the operating system doesn't set them * for us. */ #ifndef UT_NAMESIZE #define UT_NAMESIZE 8 #endif #ifndef UT_LINESIZE #define UT_LINESIZE 8 #endif #if defined(TTY_GROUP) || defined(TTY_OTHERS) #define TTYPERMS #endif /* Weird alignment stuff borrowed from Marcus. Is it needed? */ #if defined(__GNUC__) && defined(WEIRD) #define WORD_ALIGN __attribute__ ((packed)) #else #ifdef _IBMR2 #pragma options align=twobyte #endif #define WORD_ALIGN /**/ #endif struct wrthdr { long hdr_size; /* sizeof(struct wrthdr) */ long tmp_size; /* sizeof(struct wrttmp) */ }; struct wrttmp { char wrt_line[UT_LINESIZE]; /* a tty line */ char wrt_what[UT_NAMESIZE]; /* what this user is doing? */ char wrt_last[UT_NAMESIZE]; /* Who did he last write to? */ #ifndef TTYPERMS char wrt_mesg; /* user's write perms (y or n) */ #endif /*TTYPERMS*/ char wrt_record; /* Should we record tels? y, n, or a */ char wrt_telpref; /* user's program prefs (TELPREF_*) */ char wrt_modepref; /* user's mode prefs (c, l or -) */ char wrt_help; /* user is a helper? y or n */ int wrt_pid WORD_ALIGN; /* our process id */ time_t wrt_time WORD_ALIGN; /* should match ut_time in utmp file */ char wrt_bells; /* ring bells? y or n */ char wrt_except; /* use exception file? y or n */ }; /* wrt_telperf bit masks: If TELPREF_OLD is set, then wrt_telperf has one of * the following values: * '-' any program - equivalent to new value 0 * 'w' write program only - equivalent to new value TELPREF_WRITE * 't' tel program only - equivalent to new value TELPREF_TEL * If TELPREF_OLD is not set, then any of the programs whose bits are set are # acceptable. */ #define TELPREF_OLD 0x20 /* Use old-style flag value */ #define TELPREF_WRITE 0x01 /* Accept writes */ #define TELPREF_TEL 0x02 /* Accept tels */ #ifdef WITH_TALK #define TELPREF_TALK 0x04 /* Accept talks */ #define TELPREF_ALL (TELPREF_WRITE | TELPREF_TEL | TELPREF_TALK) #else #define TELPREF_ALL (TELPREF_WRITE | TELPREF_TEL) #endif #ifdef _IBMR2 #pragma options align=reset #endif /* These are the tty modes to use when permissions are on and off */ #define PERMS_OFF 0600 /* To depermit everything */ #define PERMS_OPEN 0622 /* To allow cats to your device */ #ifdef TTY_OTHERS #define PERMS_ON PERMS_OPEN /* To allow writes and telegrams and what not */ #else #define PERMS_ON 0620 /* To allow writes and telegrams and what not */ #endif /*TTY_OTHERS*/ /* Initial (at login) settings of various flags in wrttmp */ #define DFLT_MESG 'n' /* this effects only TTYPERMS versions */ #define DFLT_HELP 'n' #define DFLT_RECO 'n' #define DFLT_MODE 'a' #define DFLT_PREF TELPREF_ALL #define DFLT_BELL 'y' #define DFLT_EXCP 'n' /* Offset of the nth entry in the wrttmp file */ #define wrttmp_offset(n) (wt_head.hdr_size + (n)*wt_head.tmp_size) /* WRTHIST file * * The wrthist file keeps track of when each user last wrote each other user. * It is used to allow telegrams to be sent to people who recently sent you * telegrams, even if their permisions are off, and enforce rules about * flooding -- repeatedly sending many telegrams in a short period of time. * * It functions as a two dimensional array indexed by my slot number and * his slot number. Slot numbers are the index our wrttmp entry have in the * wrttmp file. It's like an array "struct wrthist table[][MAXSLOTS], where * the first index is myslot number and the second is his slot number. */ #ifndef MAXSLOTS #define MAXSLOTS 512 #endif /* At most MAX_TEL_N telegrams may be sent in any MAX_TEL_T second period */ #ifndef MAX_TEL_T #define MAX_TEL_T 25 #endif #ifndef MAX_TEL_N #define MAX_TEL_N 4 #endif struct wrthist { time_t tm; /* last time I wrote him */ #if MAX_TEL_N > 1 unsigned short intv[MAX_TEL_N-1]; /* intervals to pervious times */ #endif }; /* Location of slot describing last time a wrote b -- b should be < MAXSLOTS */ #define whindex(a,b) (long)((a * MAXSLOTS + b) * sizeof(struct wrthist)) #endif /* WRTTMP_H */ orville-write-2.55/orville.h0100644000076500007650000000354007044463314014222 0ustar janjan/* Standard header for all Orville Write programs */ #ifndef ORVILLE_H #define ORVILLE_H #include "config.h" #include #ifdef HAVE_FCNTL_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr(), *strrchr(), *getenv(), *malloc(); #endif #ifdef HAVE_SYS_TIME_H # include #else # include #endif #ifdef HAVE_CRYPT_H # include #endif #ifdef HAVE_UNISTD_H # include char *getpass(); /* Some unistd's don't define this - foo */ #else char *getpass(), *ttyname(); # ifndef HAVE_CRYPT_H char *crypt(); # endif #endif #include "wrttmp.h" #include "lib_common.h" typedef char bool; /* Boolean type */ #define TRUE 1 #define FALSE 0 /* Method to set cbreak/cooked modes */ #ifdef HAVE_TERMIOS_H # define F_TERMIOS #else # ifdef HAVE_TERMIO_H # define F_TERMIO # else # ifdef HAVE_SGTTY_H # define F_STTY # endif /* HAVE_SGTTY_H */ # endif /* HAVE_TERMIO_H */ #endif /* HAVE_TERMIOS_H */ /* Random Number Generator */ #ifdef HAVE_RANDOM # define RAND() random() # define SEEDRAND(x) srandom(x) # ifndef RAND_MAX # define RAND_MAX 2147483647 # endif #else # define RAND() rand() # ifndef RAND_MAX # define RAND_MAX 32767 # endif # define SEEDRAND(x) srand(x) #endif /* HAVE_RANDOM */ #define JOB_CONTROL /* support job-control */ #define USER_SHELL /* shell escapes run with user's shell */ /* These are the tty modes to use when permissions are on and off */ #define PERMS_OFF 0600 /* To depermit everything */ #define PERMS_OPEN 0622 /* To allow cats to your device */ #ifdef TTY_OTHERS # define PERMS_ON PERMS_OPEN /* To allow writes and talks and what not */ #else # define PERMS_ON 0620 /* To allow writes and talks and what not */ #endif /*TTY_OTHERS*/ #endif /* ORVILLE_H */ orville-write-2.55/lib_common.h0100644000076500007650000000145207045471726014673 0ustar janjan/* Header file for routines common between write, amin, mesg, etc */ #ifndef LIB_COMMON_H #define LIB_COMMON_H #include "getutent.h" int init_wstream(int mode); struct utmp *find_utmp(char *tty); void find_wrttmp(char *tty, time_t time,struct wrttmp *wbuf, long *pos); void dflt_wrttmp(struct wrttmp *wbuf, char *tty, time_t time); char *leafname(char *fullpath); int mydevtty(void); extern char *f_wrttmp, *f_wrthist, *f_novicehelp, *f_log, *f_helperlist, *f_nohelp, *f_helpername; extern int f_disconnect, f_exceptions, f_helpers, f_loglevel, f_answertel, f_pipes, f_fromhost; extern char *progname; extern char mydevname[]; extern int wstream; struct wrthdr wt_head; #ifdef TTYPERMS int saveperms(void); void setperms(char perm); void resetperms(void); #endif /*TTYPERMS*/ #endif /* LIB_COMMON_H */ orville-write-2.55/getutent.h0100644000076500007650000000063407045473251014410 0ustar janjan/* Header file for utmp reading routines */ #ifndef GETUTENT_H #define GETUTENT_H #ifdef HAVE_PATHS_H # include #endif #ifndef _PATH_UTMP # define _PATH_UTMP "/etc/utmp" #endif #ifndef HAVE_GETUTENT int utmpname(const char *file); void endutent(void); void setutent(void); struct utmp *getutent(void); struct utmp *getutline(const struct utmp *ut); #endif /*HAVE_GETUTENT*/ #endif /* GETUTENT_H */ orville-write-2.55/mesg.c0100644000076500007650000004366310126436542013504 0ustar janjan/* MESG command for Orville write * * This 'mesg' command is an extended version of the standard Unix 'mesg' * command. It is designed to work with Orville write * * (C) Copyright, Sept 1985 - Jan Wolter * */ #include "orville.h" #include #include #include #define TRUE 1 #define FALSE 0 char *mytty; /* my tty name in tty?? format */ long mypos; /* offset of my entry in wrttmp file */ struct wrttmp mywrt; /* my wrttmp entry */ struct utmp myutmp; /* A tmp buffer for reading utmp entries */ char silent= FALSE; /* generates no output if true */ int verbose= FALSE; /* generate whole table of output if true */ #define SMESG 0 #define SHELP 1 #define SRECO 2 #define SPREF 3 #define SMODE 4 #define SBELL 5 #define SEXCP 6 /* This must be last flag */ #define S_NUM 7 char *name[S_NUM]= {"mesg", "helper", "record", "preference", "mode", "bells", "exceptions"}; char *vname[S_NUM]= {"messages", "helper flag", "record", #ifdef WITH_TALK "preference (write/tel/talk)", #else "preference (write/tel)", #endif "mode (line/character)", "bells", "exceptions"}; /* Legal tag values for each type of setting. These must be listed in the * order of the corresponding numerical codes. nmap lists all legal flags, * smap lists only the flags that may be set by "mesg" and must have only * truncated versions of the nmap strings. */ char *nmap[S_NUM]= {"yn","ynY","yna","wtkan","lca","yn","yn"}; char *smap[S_NUM]= {"yn","ynY","yn","wtkan","lca","yn","yn"}; char *vmap[S_NUM][4]= { {"yes","no","yes (exceptions)", "no (exceptions)"}, {"yes","no","always (Y)",NULL}, {"yes","no","all",NULL}, {NULL}, /* not used */ {"line","character","any",NULL}, {"yes","no",NULL,NULL}, {"yes","no",NULL,NULL}}; int report= SMESG; /* which of the above to put in return code */ void set_perms(char new_mesg, int open_up); int report_status(void); int get_status(int rep); int find_me(void); int may_help(void); void do_disconnect(void); int window_warning(int newmode); char *myhomedir(void); int maywriteme(char *user, int mode); int main(int argc, char **argv) { int i,j; char new[S_NUM] = {'x', 'x', 'x', 0x00, 'x', 'x', 'x'}; char disconnect= FALSE; char open_up = FALSE; int setting= SMESG; int flip= 0; int update; char wassilent= FALSE; int lastset= -1; char flag; /* Check if I have a valid tty */ if (!(fcntl(2,F_GETFL,0) & O_RDWR) || !isatty(2)) { printf("%s: I/O stream 2 improperly redirected\n",argv[0]); exit(2); } /* Find my tty line */ if (getdevtty()) exit(1); mytty= mydevname+5; progname= leafname(argv[0]); /* Read configuration file */ readconfig(NULL); /* Parse options */ for(i=1;i= '0' && flag <= '9') { if (setting != SPREF) { if (flag < '0' + strlen(smap[setting])) flag= smap[setting][flag-'0']; } else { /* could be multi-digit number - add it up */ flag-= '0'; while (argv[i][j+1] >= '0' && argv[i][j+1] <= '9') { flag= 10*flag + argv[i][++j] - '0'; } if (flag > TELPREF_ALL || flag < 0) goto usage; new[SPREF]= flag; continue; } } else flag= argv[i][j]; switch (flag) { case '-': if (j != 0) goto usage; break; case 'v': verbose= TRUE; break; case 's': if (setting != SMESG) goto usage; wassilent= silent= TRUE; break; case 'm': if (setting != SMESG) report= setting; setting= SMODE; break; case 'b': if (setting != SMESG) report= setting; setting= SBELL; break; case 'r': if (setting != SMESG) report= setting; setting= SRECO; break; case 'p': if (setting != SMESG) report= setting; setting= SPREF; flip= 0; break; case 'x': if (setting != SMESG) report= setting; setting= SPREF; if (flip == 0) new[SPREF]= TELPREF_ALL; flip= 1; break; case 'h': if (!f_helpers) { printf("%s: Cannot use 'h' flag. Helpers not enabled " "on this system.\n", progname); exit(1); } if (setting != SMESG) report= setting; setting= SHELP; break; case 'E': case 'e': if (!f_exceptions) { printf("%s: Cannot use '%c' flag. Exceptions not enabled " "on this system.\n", progname, flag); exit(1); } if (lastset != SMESG) goto usage; new[SEXCP]= 'y'; break; case 'Y': if (setting == SMESG) { open_up= TRUE; new[SMESG]= 'y'; lastset= SMESG; break; } else if (setting != SHELP) goto usage; /* else drop through */ #ifdef WITH_TALK case 'k': #endif case 'y': case 'n': case 'l': case 'c': case 'w': case 't': case 'a': if (strchr(smap[setting],flag) == NULL) goto usage; if (setting == SPREF) { if (flip) { switch (flag) { case 'w': new[SPREF]&= ~TELPREF_WRITE; break; case 't': new[SPREF]&= ~TELPREF_TEL; break; #ifdef WITH_TALK case 'k': new[SPREF]&= ~TELPREF_TALK; break; #endif case 'n': new[SPREF]= TELPREF_ALL; break; case 'a': goto usage; } } else { switch (flag) { case 'w': new[SPREF]|= TELPREF_WRITE; break; case 't': new[SPREF]|= TELPREF_TEL; break; #ifdef WITH_TALK case 'k': new[SPREF]|= TELPREF_TALK; break; #endif case 'a': new[SPREF]= TELPREF_ALL; break; case 'n': goto usage; } } } else new[setting]= flag; lastset= setting; setting= SMESG; break; case 'N': lastset= SMESG; case 'd': if (setting != SMESG) goto usage; disconnect= TRUE; if (flag == 'N') new[SMESG]= 'n'; break; #ifndef WITH_TALK case 'k': printf("%s: Talk permissions cannot be separately set " "at this site\n",progname); goto usage; #endif default: goto usage; } } /* If we changed message perms, but didn't set exceptions, turn them off */ if (new[SMESG] != 'x' && new[SEXCP] == 'x') new[SEXCP]= 'n'; if (setting != SMESG) report= setting; else if (report == SMESG) report= ((lastset > SMESG) ? lastset : SMESG); /* Open the wrttmp file and find us in it */ if (init_wstream(O_RDWR)) exit(-1); find_me(); if ((new[SHELP] == 'y' || new[SHELP] == 'Y') && !may_help()) { printf("You are not on the helper list.\n"); exit(1); } /* Update permissions/helperness/preferences/bells */ update= 0; if (new[SMESG] != 'x') { set_perms(new[SMESG],open_up); update= 1; } if (f_helpers && new[SHELP] != 'x') { mywrt.wrt_help= new[SHELP]; update= 1; } if (f_exceptions && new[SEXCP] != 'x') { mywrt.wrt_except= new[SEXCP]; update= 1; } if (new[SRECO] != 'x') { mywrt.wrt_record= new[SRECO]; update= 1; } if (new[SMODE] != 'x') { mywrt.wrt_modepref= new[SMODE]; update= 1; } if (new[SPREF] != 0x00 && !flip) { mywrt.wrt_telpref= new[SPREF]; update= 1; } if (new[SPREF] != TELPREF_ALL && flip) { if (new[SPREF] == 0x00) set_perms('n',0); else mywrt.wrt_telpref= new[SPREF]; update= 1; } if (new[SBELL] != 'x') { mywrt.wrt_bells= new[SBELL]; update= 1; } /* Write out new settings */ if (update) { lseek(wstream,mypos,0); write(wstream,&mywrt,sizeof(struct wrttmp)); silent= TRUE; } /* Disconnect existing connections */ if (disconnect) { if (f_disconnect) do_disconnect(); else printf("Disconnect option not enabled on this system\n"); silent= TRUE; } /* Close the utmp file */ endutent(); if (f_wrthist != NULL && !wassilent && (new[SMESG] == 'n' || new[SEXCP] == 'y')) window_warning((new[SMESG]=='n')+2*(new[SEXCP]=='y')); exit(report_status()); usage: printf("usage: %s [-sv] [y|n", progname); if (f_disconnect) printf("|d"); if (f_exceptions) printf("|ye|ne"); printf("|Y"); if (f_disconnect) { printf("|N"); if (f_exceptions) printf("|NE"); } printf("] "); if (f_helpers) printf(" [-h[y|n|Y]]"); printf(" [-r[y|n]] [-m[l|c|a]] [-p[w|t|k|a]] [-x[w|t|k|n]] [-b[y|n]]\n"); exit(-1); } /* SET_PERMS: This sets the message permissions to "new_mesg" (which is * either 'y' or 'n'. It throws the tty permissions wide open as well if * "open_up" is true. */ void set_perms(char new_mesg, int open_up) { int mode; /* Change the device permissions */ if (open_up) mode= PERMS_OPEN; #ifdef TTYPERMS else if (new_mesg == 'y') mode= PERMS_ON; #endif /*TTYPERMS*/ else mode= PERMS_OFF; chmod(mydevname,mode); /* Change the wrttmp permissions */ #ifndef TTYPERMS mywrt.wrt_mesg= new_mesg; #endif /*TTYPERMS*/ } /* REPORT_PREF -- This prints a message reporting the perf setting, in * verbose or non-verbose format. The appropriate numeric return code is * returned. */ int report_pref(int verbose) { int val,n; if (!silent) { if (verbose) printf("%s: ",vname[SPREF]); else printf("%s is ",name[SPREF]); } val= mywrt.wrt_telpref; if (val & TELPREF_OLD) { switch (val) { case 'w': val= TELPREF_WRITE; break; case 't': val= TELPREF_TEL; break; #ifdef WITH_TALK case 'k': val= TELPREF_TALK; break; #endif case '-': case 'a': val= TELPREF_ALL; break; } } if (!silent) { if (val == TELPREF_ALL) { fputs(verbose ? "all\n":"a\n" ,stdout); return val; } n= 0; if (val & TELPREF_WRITE) { fputs(verbose ? "write":"w" ,stdout); n++; } if (val & TELPREF_TEL) { if (n > 0) putchar(','); fputs(verbose ? "tel":"t" ,stdout); n++; } #ifdef WITH_TALK if (val & TELPREF_TALK) { if (n > 0) putchar(','); fputs(verbose ? "talk":"k" ,stdout); } #endif putchar('\n'); } return val; } /* REPORT_STATUS -- This prints the current message permission settings and * returns the status code (0 = yes; 1 = no). If silent is true, it omits * the printing. If report is set to something other than SMESG it reports * on that other setting. If verbose is true, it reports on all settings. */ int report_status() { int code,rc,i; if (verbose) { for (i= 0; i < S_NUM; i++) { if (i == SEXCP) continue; if (!f_helpers && i == SHELP) continue; if (i == SPREF) {report_pref(1); continue; } code= get_status(i); printf("%s: %s\n",vname[i], vmap[i][code] != NULL ? vmap[i][code] : "strange"); if (i == report) rc= code; } } else { rc= get_status(report); if (!silent) { if (f_exceptions && report == SMESG) printf("%s is %c%s\n",name[report],nmap[report][rc%2], rc > 1 ? "e" : ""); else if (report == SPREF) report_pref(0); else printf("%s is %c\n",name[report],nmap[report][rc]); } } return rc; } /* GET_STATUS -- Get current index code of given switch */ int get_status(int rep) { struct stat stb; int code; switch (rep) { case SMESG: #ifdef TTYPERMS /* Stat my tty */ if (stat(mydevname,&stb)) { printf("%s: Error - can't stat %s\n",progname,mydevname); exit(-1); } code= ((stb.st_mode & 0020)==0); #else code= strchr(nmap[SMESG],mywrt.wrt_mesg) - nmap[SMESG]; #endif /* TTYPERMS */ if (f_exceptions) code+= 2 - 2*(strchr(nmap[SEXCP],mywrt.wrt_except) - nmap[SEXCP]); break; case SEXCP: code= strchr(nmap[SEXCP],mywrt.wrt_except) - nmap[SEXCP]; break; case SHELP: code= strchr(nmap[SHELP],mywrt.wrt_help) - nmap[SHELP]; break; case SRECO: code= strchr(nmap[SRECO],mywrt.wrt_record) - nmap[SRECO]; break; case SMODE: code= strchr(nmap[SMODE],mywrt.wrt_modepref) - nmap[SMODE]; break; case SBELL: code= strchr(nmap[SBELL],mywrt.wrt_bells) - nmap[SBELL]; break; } return code; } /* DO_DISCONNECT -- This does the disconnect, by searching the wrttmp file for * people who are writing you and sending a SIGTERM to each of the process * numbers listed there. This whole approach is a bit shady. */ void do_disconnect() { struct utmp *ut; /* A tmp buffer for reading utmp entries */ struct wrttmp hiswrt; /* Someone's wrttmp entry */ int slot= 0; /* Rewind utmp file */ setutent(); /* For each user who is writing me */ for (;;) { lseek(wstream, wrttmp_offset(slot++), 0); if (read(wstream, &hiswrt, sizeof(struct wrttmp)) != sizeof(struct wrttmp)) break; if (!strncmp(hiswrt.wrt_what, myutmp.ut_name, UT_NAMESIZE)) { setutent(); /* Check apparant writer against utmp file */ while ((ut= getutent()) != NULL) if ( #ifdef USER_PROCESS ut->ut_type == USER_PROCESS && #endif !strncmp(hiswrt.wrt_line, ut->ut_line, UT_LINESIZE)) { /* Writer is for real: bonk him one */ kill(hiswrt.wrt_pid, SIGTERM); break; } } } } /* FIND_ME -- This finds my wrttmp entry and loads it into "mywrt". */ int find_me() { struct utmp *ut; /* Find our entry in the Utmp file */ if ((ut= find_utmp(mytty)) == NULL || ut->ut_name[0] == '\0') { printf("%s: Unable to find your tty (%s) in utmp file\n", progname,mytty); exit(-1); } myutmp= *ut; /* Find the entry in the wrttmp file */ find_wrttmp(mytty,myutmp.ut_time,&mywrt,&mypos); } /* MAY_HELP -- Check if the user's name is anywhere to be found in the * f_helperlist file. If he is there, or the file doesn't exist at all, then # he may designate himself as a helper. */ int may_help() { #define BUFSZ 80 FILE *hfp; char buf[BUFSZ+1]; char myname[UT_NAMESIZE+2]; if (f_helperlist == NULL || (hfp= fopen(f_helperlist,"r")) == NULL) return TRUE; strncpy(myname,myutmp.ut_name,UT_NAMESIZE); myname[UT_NAMESIZE]= '\0'; strcat(myname,"\n"); while (fgets(buf,BUFSZ,hfp) != NULL) if (!strcmp(buf,myname)) { fclose(hfp); return TRUE; } fclose(hfp); return FALSE; } /* WINDOW_WARNING - If there are people who can still write you under the * four minute window rule, print a warning message. */ int window_warning(int newmode) { struct wrthist *hist; struct wrttmp w; struct utmp *u; long writer, writee; time_t now; int n, foundsome= 0; FILE *fp; if (newmode == 0) return; /* Compute my slot number from my offset */ if ((writer= (mypos - wt_head.hdr_size)/wt_head.tmp_size) > MAXSLOTS) return; if ((fp= fopen(f_wrthist,"r")) == NULL) return; fseek(fp,whindex(writer,0),0); hist= (struct wrthist *)malloc(MAXSLOTS*sizeof(struct wrthist)); n= fread(hist,sizeof(struct wrthist),MAXSLOTS,fp); fclose(fp); now= time((time_t *)0); for (writee= 0; writee < n; writee++) { if (hist[writee].tm > myutmp.ut_time && now - hist[writee].tm <= f_answertel) { /* Fetch "his" wrttmp entry - it may actually belong to a previous * user on that line, so only the wrt_line field is really to be * trusted. */ lseek(wstream,wrttmp_offset(writee),0); if (read(wstream, &w, sizeof(struct wrttmp)) != sizeof(struct wrttmp)) continue; /* Check times to ensure this is not from a later user */ if (hist[writee].tm < w.wrt_time) continue; /* Fetch his utmp entry, and confirm that the current user was * already logged in there when we sent our last telegram there. */ if ((u= find_utmp(w.wrt_line)) == NULL || u->ut_name[0] == '\0' || hist[writee].tm < u->ut_time) continue; /* Check if due to exceptions he may write us anyway */ if (f_exceptions && newmode > 1 && maywriteme(u->ut_name, newmode)) continue; if (!foundsome) { printf("Warning: Users to whom you recently sent messages may\n"); printf("still be able to write you for a few more minutes:\n"); foundsome= 1; } printf(" %-*.*s %-*.*s %4.1f more minutes\n", UT_NAMESIZE, UT_NAMESIZE, u->ut_name, UT_LINESIZE, UT_LINESIZE, u->ut_line, (float)(f_answertel - now + hist[writee].tm)/60.0); } } } /* MYHOMEDIR - Return my home directory. Speed counts over reliability here. * Return NULL if we can't find it. */ char *myhomedir() { char myname[UT_NAMESIZE+2]; struct passwd *pw; char *dir, *getenv(); /* Try environment variable first */ if ((dir= getenv("HOME")) != NULL) return dir; /* If that don't work, try passwd file */ strncpy(myname,myutmp.ut_name,UT_NAMESIZE); myname[UT_NAMESIZE]= '\0'; if ((pw= getpwnam(myname)) != NULL) return pw->pw_dir; /* If that don't work, give it up */ return NULL; } /* MAYWRITEME - can the named user write me? This checks exceptions. Does * some caching so that multiple successive calls are efficient. */ int maywriteme(char *user, int mode) { static int oldmode= -1; static char *list; struct stat st; char *dir,*fname, *p,*q; FILE *fp; int n, l, nl, sp; if (mode < 2) return (mode == 0); if (mode != oldmode) { list= NULL; oldmode= mode; /* Open the appropriate exception file */ if ((dir= myhomedir()) == NULL) return FALSE; fname= (char *)malloc(strlen(dir)+15); sprintf(fname,"%s/%s",dir, mode==2 ? ".nowrite" : ".yeswrite"); fp= fopen(fname,"r"); free(fname); /* Load the file into memory */ if (fp != NULL && !fstat(fileno(fp),&st)) { list= (char *)malloc(st.st_size+1); n= fread(list,1,st.st_size,fp); list[n]= '\0'; } if (list != NULL) { /* Compress list into login names separated by single spaces */ nl= 1; sp= 1; for (p= q= list; *p != '\0'; p++) { /* Skip lines starting with # */ if (nl && (*p == '#')) { p= strchr(p,'\n'); if (p == NULL) break; } nl= (*p == '\n'); if (strchr(" ,;:\t\n\r",*p)) { if (!sp) *(q++)= ' '; sp= 1; } else { sp= 0; *(q++)= *p; } } *q= '\0'; } } if (list != NULL) { /* Find length of user name */ for (l= 0; l < UT_NAMESIZE && user[l] != '\0'; l++) ; /* Search compressed list for the name */ p= list; for (;;) { if (!strncmp(p,user,l) && (p[l] == ' ' || p[l] == '\0')) return (mode != 2); if ((p= strchr(p,' ')) == NULL) break; p++; } } /* Not on list */ return (mode == 2); } orville-write-2.55/amin.c0100644000076500007650000001741610126436536013475 0ustar janjan/* AMIN.C * * Run a command, warning potential writers that you are in it. * * 8-24-86 Written by Jan Wolter * 8-27-86 Added code to make it work with shell scripts * 2-12-94 Fixed suspends. * 11-30-95 Added -p */ #include "orville.h" #include #include #include #ifdef HAVE_SYS_WAIT_H # include #endif #ifndef WEXITSTATUS #define WEXITSTATUS(x) ((unsigned)(x) >> 8) #endif #ifndef WIFEXITED #define WIFEXITED(x) (((x) & 255) == 0) #endif #include extern int errno; char *my_dir(void); RETSIGTYPE susp(void); void fix_modes(char *fullcmd); void restore_modes(void); int exec_cmd(int argc, char **argv); struct wrttmp mywrt; /* My old wrttmp entry, to be restored at exit time */ struct wrttmp newwrt; /* Space to build temporary wrttmp entry */ long mypos= -1; /* offset of my entry in the wrttmp file */ char tmp_mesg= 's'; /* Temporary setting of mesg during write */ int fixed_modes= 0; /* Have we fixed the wrttmp/tty modes? */ int postpone= 0; /* Should telegrams be postponed? */ int exceptions= 0; /* Should we allow exceptions on message permissions */ int main(int argc, char **argv) { char cmdbuf[280]; /* Space to build full command path name */ char lmfile[200]; /* Space to store full path name of .lastmesg file */ FILE *lmfp= NULL; int i,rc; char *c; progname= leafname(argv[0]); readconfig(NULL); for (i= 1; i \n",progname, f_exceptions ? "e" : ""); exit(1); } /* MY_DIR - Return name of my home directory, or NULL if I can't find it. */ char *my_dir() { struct passwd *pwd; char *r; /* Try the environment variable first */ if ((r= getenv("HOME")) != NULL) return(r); /* Try the password file */ setpwent(); pwd= getpwuid(getuid()); endpwent(); if (pwd != NULL) return(pwd->pw_dir); /* Give up */ return(NULL); } /* LOCATE_WRTTMP - find my entry in the wrttmp file. */ void locate_wrttmp(char *tty, struct wrttmp *wbuf, long *pos) { struct utmp *ut; /* Find utmp entry */ if ((ut= find_utmp(tty)) == NULL || ut->ut_name[0] == '\0') { printf("%s: Can't find your tty (%s) in utmp\n",progname,tty); exit(1); } find_wrttmp(tty, ut->ut_time, wbuf, pos); } /* FIX_MODES - modify wrttmp and tty permissions. */ void fix_modes(char *fullcmd) { char *mytty; /* my tty name in "tty##" format */ char *shortcmd; /* command without full pathname */ /* Find my tty line */ if (getdevtty()) exit(1); mytty= mydevname+5; /* Find my wrttmp entry */ locate_wrttmp(mytty,&mywrt,&mypos); if (mypos < 0) { printf("%s: Error - unable to locate %s in %s\n", progname, mytty, f_wrttmp); exit(1); } /* Close utmp file */ endutent(); /* Figure out name of program being exec'ed */ if ((shortcmd= strrchr(fullcmd,'/')) == NULL) shortcmd= fullcmd; else shortcmd++; /* Fix my entry in wrttmp */ newwrt= mywrt; newwrt.wrt_what[0]= '!'; strncpy(newwrt.wrt_what+1, shortcmd, UT_NAMESIZE-1); #ifndef TTYPERMS if (tmp_mesg != 's') newwrt.wrt_mesg= tmp_mesg; #endif if (tmp_mesg != 's') newwrt.wrt_except= (f_exceptions && exceptions) ? 'y' : 'n'; if (postpone) newwrt.wrt_record= 'a'; lseek(wstream,mypos,0); write(wstream,&newwrt,sizeof(struct wrttmp)); #ifdef TTYPERMS /* Fix my tty permissions */ if (tmp_mesg != 's') { if (saveperms()) exit(1); setperms(tmp_mesg); } #endif /*TTYPERMS*/ fixed_modes= 1; } /* RESTORE_MODES - Restore original modes. */ void restore_modes() { /* Restore old (or default) wrttmp entry */ lseek(wstream,mypos,0); write(wstream,&mywrt,sizeof(struct wrttmp)); close(wstream); #ifdef TTYPERMS if (tmp_mesg != 's') resetperms(); #endif /*TTYPERMS*/ } /* EXEC_CMD - Run the command as a child process */ int exec_cmd(int argc, char **argv) { int cpid,wpid; /* Child pid and pid returned by wait */ char **shargv; /* Arguements for running things with shell */ int status; /* Child's return status */ int i; if ((cpid= fork()) == 0) { /* Child process */ /* Use default interupts */ signal(SIGINT,SIG_DFL); signal(SIGQUIT,SIG_DFL); signal(SIGTERM,SIG_DFL); signal(SIGHUP,SIG_DFL); #ifdef SIGTSTP signal(SIGTSTP,SIG_DFL); #endif /*SIGTSTP*/ /* Close open file descriptors */ /* close(wstream); /* Don't need this, since set close-on-exec */ endutent(); /* Might or might not need this */ execvp(argv[0],argv); /* If wasn't executable, try running under a shell */ if (errno == ENOEXEC) { shargv= (char **)malloc((argc+3)*sizeof(char *)); shargv[0]= "sh"; shargv[1]= "-c"; for (i= 0; i < argc; i++) shargv[i+2]= argv[i]; shargv[i+2]= NULL; execv("/bin/sh",shargv); } printf("%s: command not found\n",argv[0]); exit(1); } /* Parent Process waits for child to exit */ while ((wpid= wait(&status)) != cpid && wpid != -1) ; return (WIFEXITED(status) ? WEXITSTATUS(status) : -2); } /* SUSP -- Suspend the process. Restore wrttmp entries first, since we can't * assume that stopped processes will be restarted in the reverse order in * which they were stopped. */ #ifdef SIGTSTP RETSIGTYPE susp() { int mask; /* Disable further signals */ mask= sigblock(sigmask(SIGTSTP)); /* Restore modes and make wrttmp look like we exited */ if (fixed_modes) { lseek(wstream,mypos,0); write(wstream,&mywrt,sizeof(struct wrttmp)); #ifdef TTYPERMS if (tmp_mesg != 's') resetperms(); #endif /*TTYPERMS*/ fixed_modes=0; } signal(SIGTSTP,SIG_DFL); sigsetmask(0); kill(getpid(),SIGTSTP); /* STOP HERE */ sigsetmask(mask); signal(SIGTSTP,(void (*)())susp); /* Reinstate wrttmp entry */ lseek(wstream,mypos,0); write(wstream,&newwrt,sizeof(struct wrttmp)); #ifdef TTYPERMS if (tmp_mesg != 's') { if (saveperms()) exit(1); setperms(tmp_mesg); } #endif /*TTYPERMS*/ } #endif /*SIGTSTP*/ orville-write-2.55/huh.c0100644000076500007650000000461307665675304013344 0ustar janjan#include "write.h" #include #include int keep= 0, silent= 0; /* MY_DIR - Return name of my home directory, or NULL if I can't find it. */ char *my_dir() { char *r; struct passwd *pwd; /* Try the environment variable first */ if ((r= getenv("HOME")) != NULL) return r; /* Try the password file */ setpwent(); pwd= getpwuid(getuid()); endpwent(); if (pwd != NULL) return pwd->pw_dir; /* Give up */ return NULL; } /* RECORD_ON -- return true if the user has his record flag on. We don't * really care, but we want to tell him about it if this is the reason he * hasn't any messages. */ int record_on() { struct utmp *ut; struct wrttmp wt; char *tty; long pos; /* Open the utmp file */ setutent(); /* Open the wrttmp file */ if (init_wstream(O_RDONLY)) return 1; /* Get tty name */ if (getdevtty()) exit(1); tty= mydevname+5; /* Find our entry in the utmp file */ if ((ut= find_utmp(tty)) == NULL || ut->ut_name[0] == '\0') return 1; /* Find the entry in the wrttmp file */ find_wrttmp(tty, ut->ut_time, &wt, &pos); /* Close utmp file */ endutent(); return (wt.wrt_record != 'n'); } int main(int argc, char **argv) { char fname[200]; char *dir; FILE *fp; int ch; int i,j; struct stat st; progname= leafname(argv[0]); readconfig(NULL); for (i= 1; i < argc; i++) { if (argv[i][0] == '-') for (j= 1; argv[i][j] != '\0'; j++) switch(argv[i][j]) { case 'k': keep= 1; break; case 's': silent= 1; default: goto usage; } else goto usage; } if ((dir= my_dir()) == NULL) { fprintf(stderr,"%s: cannot find your home directory\n",progname); exit(1); } sprintf(fname,"%.180s/.lastmesg",dir); if ((fp= fopen(fname,"r")) == NULL) { printf("No recorded messages%s.\n", (silent || record_on()) ? "": " (do \042mesg -r y\042 to record future messages)"); exit(0); } if (fstat(fileno(fp), &st) || st.st_uid != getuid()) { printf("Incorrect ownership of %s\n",fname); exit(1); } /* Unlink the file -- do it now to minimize conflicts with incoming * messages. */ if (!keep) unlink(fname); /* Display the file */ if (!silent) while ((ch= getc(fp)) != EOF) { if (ch != '\007') putchar(ch); } exit(0); usage: fprintf(stderr,"usage: %s [-ks]\n", progname); exit(1); } orville-write-2.55/amin.10100644000076500007650000000346507044101626013404 0ustar janjan.\" @(#)amin.1 2.41 (Wolter) 1/27/2000 .\" .TH AMIN 1 "July 1, 1991" .AT 3 .SH NAME amin \- notify writers that you are busy .SH SYNOPSIS .B amin [-ynesp] command [args...] .SH DESCRIPTION .I Amin is used when you don't want to be written while running a command. It runs the command given normally. If your message permissions (see .IR mesg (1)) are off, it does nothing much else. If your messages are on, people writing you with .IR write (1) will be warned that you are running that command and will be given the opportunity to change their minds about writing you. .PP The .B -n option may be used to turn your messages entirely off for the duration of the execution of command. People writing you will get "Permission denied". The .B -y option turns your message permissions on for the duration of the execution of the command. The .B -e may be used after either .B -n or .B -y to indicate that the logins listed in the .I .yeswrite or the .I .nowrite files respectively are exceptions to the message permissions set. The default is .B -s which leaves your message permissions in their original state. In any case, after the command is complete, your permissions will be restored to the original state. .PP The .B -p flag causes all telegrams sent to you while the command is running to be saved. They are displayed as soon as the command is complete. If used with the .B -n flag, writes are refused, but telegrams are still saved. .PP If you have designated yourself as a helper, you will still be marked on the .IR finger (1) output as a helper while you are running .I amin but people doing ``write help'' will not be connected to you, even if you have the helper flag set to ``Y''. .SH AUTHOR Jan Wolter .SH FILES /etc/wrttmp to find message permissions .br /etc/utmp to find user .SH "SEE ALSO" mesg(1), finger(1), write(1), huh(1). orville-write-2.55/write.10100644000076500007650000002756607665700751013637 0ustar janjan.\" @(#)write.1 2.41 .\" .TH WRITE 1 "Jan 20, 2000" .AT 3 .SH NAME write \- write to another user .SH SYNOPSIS .B write [-ctynsprfSv] [ user [ tty ] ] .br .B jot [-ltynsprfSv] [ user [ tty ] ] .br .B tel [-clynsprfSv] user [ tty ] [message...] .SH DESCRIPTION Note: This is "Orville write", an enhanced version of the standard Unix .I write program. .I Write copies lines from your terminal to that of another user. When first called, it sends the message: .PP Message from your-logname your-tty ... .PP The recipient of the message should write back at this point. Communication continues until an end of file is read from the terminal or an interrupt is sent. At that point, .I write writes "EOF (your-logname)" on the other terminal and exits. .PP The following protocol is strongly suggested for using .IR write : when you first write to another user, wait for him or her to write back before starting to type your message. Each party should end each message with a distinctive signal (\fBo\fR for ``over'' is conventional), indicating that the other may reply; .B oo for ``over and out'' is suggested when conversation is to be terminated. Avoid typing when it is the other person's turn, as your text will get all garbled with theirs. Anyway, it's rude. .PP The .I jot command is a variation of .I write which normally sends each character to the other user as you type it instead of waiting for you to finish a line before sending anything as write does. .PP The .I tel command sends one line ``telegrams'' and then immediately disconnects. The message may be given on the command lines (in which case it is usually best to quote it). If you don't put a message on the command line, you will be prompted for it. This is usually the preferable way to invoke .I tel. .PP All three commands are actually the same program, and share much of the same behavior. .PP Permission to write may be denied or granted by use of the .IR mesg (1) command. Your write permissions upon login are installation dependent. If you write a person who has permissions on, but is currently writing someone else, you will be warned of the fact and be given a chance to cancel your write request before interupting the other conversation. If you write a person who is running a command under .IR amin (1) you will be warned similarly. .PP You can always send messages to people who are currently writing to you, even if there message permissions are off. If you have sent a person a .I tel message, then that person can write or telegram to you for the next 4 minutes, even if your message permissions are off. This means that you won't be sitting around wondering why someone won't reply, just because you've forgotten to turn your permissions on. It also means that if you don't want someone to be able to talk to you, then you shouldn't talk to them. Root may write anyone. .PP If you invoke the .I write or .I jot command with no user name, they will write to whatever user is currently writing you. If no one is writing you, an error message is printed. .PP If you invoke the .IR write , .IR jot , or .I tel command with the user name '.', they will write again to whoever you wrote to last. If you haven't written to anyone in this login session, an error message is printed. This is especially useful when you are exchanging a series of messages back and forth with .IR tel . .PP If you want to write to a user who is logged in more than once, the tty argument may be used to indicate the appropriate terminal. If the tty argument is not given, the terminal from which you are being written will be written to, if there is one. If not, one of the lines you have write permission to will be chosen. If the tty argument is given, the user name can be given as "-", in which case it will write to whomever is on that tty, if anyone is. .PP On some systems there may be users designated as ``helpers''. If your system has helpers, then doing ``write help'' will write to some helper who is not busy. If more than one helper is available, one is selected at random to distribute the workload. Helpers designate themselves with the .IR mesg (1) command. They are considered busy if they are writing someone else, or if they are running a command under the .IR amin (1) program. .PP If the character ! , | , or & is found at the beginning of a line, .I write calls the shell to execute the rest of the line as a unix command. If the command began with a ! the output of the command will be sent only to your terminal. If it began with a |, output will be sent only to the other person's terminal. If it began with a & each of you will recieve a copy of the output. Note that .I write expands all strange control characters before sending them to the other person's terminal, but does not do so for characters echoed back to your terminal. .PP .I Write provides several command line options. Actually, the only difference between .IR write , .IR jot , and .I tel is what default values they have for these options: .TP .B \-c Send each character as it is typed. Actually, it will not begin doing so until after the other party has replied. Also, if you type a line starting with a ")" then the rest of the current line will be held until you hit return and the sent (minus the ")"). When this option used, typing a control-R will reprint the text of the line you are currently typing, and control-W will erase the last word you typed, even if your unix system doesn't usually support these. In the .I jot command this is the default. .TP .B \-l Send no characters until a full line has been entered. In the .I write command this is the default. .TP .B \-n During the duration of this conversation, temporarily turn off your message permissions, so as not to allow people other than the person being writen to write you. .TP .B \-y During the duration of this conversation, temporarily turn on your message permissions, allowing other people to write you after warning them that you are writing someone else. .TP .B \-p Postpone the receipt of telegrams during the duration of the conversation. All telegram received during the conversation will be saved in your .lastmesg file, and will be displayed when you are finished. The .IR huh (1) command can be used in a shell escape to check saved messages without leaving .IR write . .TP .B \-s During the duration of this conversation, leave your write permissions unchanged. This normally the default. .TP .B \-r This causes .I write to prompt for the root passwd. If it is given correctly, you will be able to write anyone, no matter how his message permissions are set, amd you can override his preference for .I write or .IR tel . .TP .B \-f Disallow piping input through .I write and disable the '&' and '|' shell escapes. This is mostly meant to be used on 'options' commands in the orville.conf file. It has been mostly obsoleted by the 'pipes' configuration command. .TP .B \-t Sends a one line message (called a telegram) and then disconnects immediately. The text of the message may be given on the command line, or, if it isn't, you will be prompted for it. Though write will attempt to blank out messages given on the command line so they cannot be seen by users running .IR w (1) or .IR ps (1), this will not always work, so secret messages should not be placed on the command line. This is the default in the .I tel command. .TP .B \-S Normally if you send a telegram to someone who has indicated a preference for writes, you get asked if you want to switch to writing, and vice versa. The -S flag suppresses this question, and just makes it quietly fail (unless you are root, in which case it quietly succeeds). .TP .B \-v print the version number. .PP The options selected by the writer may in some cases be overridden by the recipient. You can set your preferences for writes versus telegrams, and for line mode versus character mode with the .IR mesg (1) command. If the recipient has set write/telegram preferences, you will be asked if you want to use the other if you write him the wrong way. If you invoke .I Write with a .B \-S flag, then you will not be asked if you want to switch. Only root can actually override the recipient's preferences. For regular users, if you decline to switch, the command fails. .PP If the recipient has set character/line mode preferences, a message will be printed and you will be forced into his or her prefered mode. .SH CONFIGURATION The .I orville.conf file contains configuration information for Orville write and the associated utilities. Lines starting with '#' and blank lines are ignored. Other lines contain the commands listed below: .IP "answertel " 1i Normally you can send telegrams to a person for four minutes (240 seconds) after they sent you a telegram, even if their message permissions are off. This command can be used to set size of that window to other values. .IP "disconnect [y|n]" 1i If disconnect is enabled the 'mesg d' and 'mesg N' commands can be used by the writee to disconnect everyone currently writing them. (See .IR mesg (1)). It is enabled by default. .IP "exceptions [y|n]" 1i If exceptions are enabled the 'mesg ye' and 'mesg ne' commandsa can be used to limit which particular users can and cannot write you (See .IR mesg (1)). It is enabled by default. .IP "fromhost [y|n]" 1i If this flag is set, then message announcement banners will include the hostname of the sender's machine (and the reciever's since write does not allow interhost communications). It is disabled by default. .IP "helperlist " 1i If this flag is set, then only people whose logins appear in the given file may be helpers. Otherwise, anyone may be. It is disabled by default. .IP "helpername " 1i By default you get help by doing 'write help'. If you want to use some keyword other than 'help', use this command to define it. .IP "helpers [y|n]" 1i Can people designate themselves to be helpers, and should 'write help' work? By default, no. .IP "log " 1i What file should logging be done in? If not defined, or if it is defined and the file does not exist, then no logging will be done. .IP "loglevel " 1i How much logging should be done? Level 0 means none. Level 1 means only log help requests (with information about whether they succeeded or not). Level 2 means logging a one-line description of each write connection made. Of course, no logging is done if 'log' is not defined or does not exist. No content of any write conversation is ever logged. The default is 1. .IP "nohelp " 1i If someone does 'write help', but no helpers are found, this file is displayed. Normally it has information on other places to get help. If not defined, nothing is printed. .IP "pipes [y|n]" 1i If turned off, this disallows piping data through write, so you can't do 'cat /etc/termcap | write joe'. It also disables the '|' and '&' shell escapes. This may be necessary if many users are using write to annoy other users by sending large chunks of data. It defaults on. .IP "novicehelp " 1i If the environment variable NOVICE is defined, then print the contents of this file before running write. If not defined, nothing is printed. .IP "options -..." 1i Set default options for different links to the write program. For example, if you have the line 'options jot -c' and you make a link to the write program named 'jot', then jot will default to character mode instead of line mode. If command-name is '*', then all links (even ones created by users) get that option. .IP "wrthist " 1i This is the full pathname of the 'wrthist' file which maintains information about user's recent messages. It is used to limit telegram flooding attacks, and allow replies to telegrams during the four minute window. By default it is in the same directory as the 'orville.conf' file. .IP "wrttmp " 1i This is the full pathname of the 'wrttmp' file which maintains information about user's current state. By default it is in the same directory as the 'orville.conf' file. .SH AUTHOR Jan Wolter .SH "SEE ALSO" mail(1), mesg(1), who(1), huh(1), finger(1), amin(1), helpers(1). orville-write-2.55/mesg.10100644000076500007650000001601607044176376013425 0ustar janjan.\" @(#)mesg.1 2.41 .\" .TH MESG 1 "Jan 20, 2000" .AT 3 .SH NAME mesg \- permit or deny messages .SH SYNOPSIS .B mesg [-s] [-v] [y|n|ye|ne|Y|N|NE] [d] [-p[w|t|k|a]] [-x[w|t|k|n]] [-m[l|c|a]] [-h[Y|y|n]] [-r[y|n]] [-b[y|n]] .SH DESCRIPTION This is the "Orville write" verison of the standard Unix .I mesg command. .PP .I Mesg with argument .B n forbids messages via .IR write (1), .IR jot (1), .IR tel (1), and .IR talk (1) by revoking non-user write permission on the user's terminal. .I Mesg with argument .B y reinstates permission. All by itself, .I mesg reports the current state without changing it. .PP The .B ne and .B ye settings mean ``no with exceptions'' and ``yes with exceptions'' respectively. If .B ne is set, and there is file named .I .yeswrite in your home directory, then the users whose logins are listed there may still write you. If .B ye is set, and there is a file named .I .nowrite in your home directory, then the users whose logins are listed there may not write you. These files have no effect if the permissions are set to .B n or .BR y . The .I .nowrite and .I .yeswrite files do not need to be permitted to anyone else, and almost any plausible format will be understood (listing one login name per line is a good default). Lines may be commented out with a # sign in the first column. .PP The upper case .B Y and .B N do all that the lower case ones do, but may have some additional affects depending on the installation. .PP The .B N argument, if enabled, will attempt to disconnect any write sessions currently directed at your tty. This is meant to allow users to slam the door on unwelcome writers. Note that a simple ``mesg n'' will not stop anyone who is already writing you from continuing to do so, it only prevents new connections from being made. The .B NE setting also causes a disconnect, but turns your settings to .B ne instead of .BR n . The .B d argument causes a disconnect, just like ``mesg N'', but does not change your message permissions. .PP Normally .I mesg always depermits your tty device, so you can only be written through .I write and similar programs. This prevents arbitrary stuff from being redirected to your tty. When you do ``mesg Y'' your tty is write permitted to others. This is rarely necessary or desirable. .PP .I Mesg can also be used to set other switches that affect Orville .IR write (1). The .B -p flag lets you set preferences to (w) write, (t) telegrams, (k) talk, or (a) any. The default is ``any.'' If you set a preference to write, then people will not be able to send telegrams or talk requests to you. If they try to send telegrams, they will be asked if they want to write you instead. Similarly if you prefer telegrams, people will not be able to write or talk to you, and if you prefer talk, people will not be able to write or tel you. You can designate two preferences, like ``mesg -pt -pw'' to allow people to write or telegram you, but not make talk requests to you. Alternately, you can use the .B -x flag to block particular programs. Doing ``mesg -xk'' blocks only the talk program, and is equivalent to ``mesg -pt -pw''. Similarly the ``-xn'' flag excludes no programs and is equivalent to ``-pa''. Trying to block all programs just turns you permissions off. .PP The .B -m flag lets you set modes to (l) line, (c) character, or (a) any. The default is ``any.'' If you set a mode, then all writes to you will be done in that mode. If you leave it as ``any,'' the choice is left to the writer. This will not affect connections already in progress, only future ones. .PP The .B -r flag lets you turn on or off the recording to telegrams sent to you. If it is enabled, everytime you are sent a telegram (or a write with input taken from a file), the text of the messages is saved in a file named .lastmesg in your home directory. This allows you to redisplay the last message sent to you using the .IR huh (1) command. If a screen clear ate a telegram message before you had time to read it, then the .I huh command lets you see it again. Note that only the last message sent is stored. The file is permitted to be readable to you only. .PP The .B -b flag lets you tell the .I write and .I talk programs whether or not to beep when a person writes you or sends you a telegram. The default is to beep. .PP The .B -h flag lets you turn on or off your helper status. People who designate themselves as helpers are announcing their willingness to help out lost users. Their accounts will be marked on the output of the .IR finger (1) command, and if anyone does a .I write or .IR jot (1) to ``help'' they automatically get connected to someone who has a help flag set. Normally, turning your permissions off also turns your helper-status off, but if you set the .I -h flag to .IR Y , then you will remain a helper even when your message permissions are off. This means you can receive help requests, but not normal messages. .PP On some systems there is a restricted list of users who may be helpers. This is usually kept in the file /etc/helpers, one login name per line. If such a file exists then you will have to get the operators to add your name to it to be able to designate yourself as a helper. .PP If no new settings are given to .IR mesg , then it just reports on the current settings. Normally it prints the message permissions, but if a .BR -h , .BR -p , .BR -r , or .B -m flag was given without a new value after it, then the current status of that switch will be printed instead. If you use the .B -s flag, then this output will be suppressed. The command still reports the status of the selected switch with its numeric return code. .PP If you use the .B -v flag, all switch settings will be reported in a verbose mode. .PP The numeric values returned as return codes (see below) can also be used to set switches. Thus ``mesg 0 -m2'' sets permissions on, and the mode to any. This makes it easy for shell scripts to restore settings that were stored previously. .PP The argument syntax is actually a lot looser than mentioned above. The dashes before options may be omitted, Spaces may be added or omitted anywhere in the argument list. .SH FILES /dev/tty* .br /etc/wrttmp .br /etc/helpers .SH "SEE ALSO" write(1), amin(1), finger(1), huh(1), helpers(1), talk(1) .SH DIAGNOSTICS Exit status is -1 on an error. Otherwise a code is returned reporting the status of one of the settings. If the arguments included .BR -h , .BR -p , or .B -m flags without a new value after it, then the last of these listed will be reported. Otherwise, if any options were set, the last of those listed in the argument list will be reported. And if nothing was set, then message permissions are reported. .PP When message permissions, record settings, or helper settings are reported, 0 indicates 'y', and 1 indicates 'n'. When preferences are reported, 1 indicates 'w', 2 indicates 't', and 4 indicates 'k', and any combinations are returned as sums of these values. When modes are reported, 0 indicates 'l', 1 indicates 'c', and 2 indicates 'a'. .SH BUGS Turning off 'talk' permissions will only work if you have a talkd which has been modified to understand Orville write's permission. orville-write-2.55/huh.10100644000076500007650000000161507044101660013235 0ustar janjan.\" @(#)huh.1 2.41 .\" .TH HUH 1 "Jan 20, 2000" .AT 3 .SH NAME huh \- redisplay last telegram received. .SH SYNOPSIS .B huh [-sk] .SH DESCRIPTION .I Huh reprints the last telegram that was sent to you. It is intended for use when telegrams get garbled on your screen. .I Huh will only work if you had the ``record'' flag turned on when the telegram was received. This flag can be turned on with the .IR mesg (1) command. Normally, .I huh will delete each message immediately after displaying it. If the .B -k flag is given, the message is non deleted, and the next .I huh command will display it again. On the other hand, the .B -s flag suppresses the display of the message, so it will just be deleted. Normally, only the last message is retained, except when .IR amin (1) is run with the .B -p flag. .SH AUTHOR Jan Wolter .SH FILES ~/.lastmesg .br /etc/wrttmp .SH "SEE ALSO" mesg(1), write(1), amin(1) orville-write-2.55/wrttab0100644000076500007650000000004006673762531013625 0ustar janjan* chat -c tel -ct telegram -ct orville-write-2.55/wt.c0100644000076500007650000000337607044175042013200 0ustar janjan/* Dump WRTTMP file - This is a debugging command which prints out the current * contents of the wrttmp file in a human-readable format. Since it is rather * cryptic, I wouldn't recommend installing it for general use. */ #include "orville.h" /* Return a pointer to a string of n dashes. No more than MAXDASH allowed. */ char *dashes(n) int n; { #define MAXDASH 30 static char *d= "------------------------------"; /* Exactly MAXDASH -'s */ return(n<=MAXDASH ? d+(MAXDASH-n) : d); } main(int argc, char **argv) { FILE *fp; struct wrttmp w; struct wrthdr wt_head; int slot= 0; long x; progname= leafname(argv[0]); readconfig(NULL); if ((fp= fopen(f_wrttmp,"r")) == NULL) { printf("cannot open %s\n",f_wrttmp); exit(1); } if (!fread(&wt_head,sizeof(struct wrthdr),1,fp)) { printf("%s exists, but has no header\n",f_wrttmp); exit(1); } printf("HEAD SIZE = %ld ENTRY SIZE = %ld\n\n", wt_head.hdr_size, wt_head.tmp_size); printf("--line%s --what%s --last%s * E P M H R B --pid-- ---login time---\n", dashes(UT_LINESIZE-6), dashes(UT_NAMESIZE-6), dashes(UT_NAMESIZE-6)); for (;;) { x= wrttmp_offset(slot++); fseek(fp,x,0); if (!fread(&w,sizeof(struct wrttmp),1,fp)) break; printf("%-*.*s %-*.*s %-*.*s %c %c %2d %c %c %c %c %7d %15.15s\n", UT_LINESIZE,UT_LINESIZE,w.wrt_line, UT_NAMESIZE,UT_NAMESIZE,w.wrt_what, UT_NAMESIZE,UT_NAMESIZE,w.wrt_last, #ifndef TTYPERMS isprint(w.wrt_mesg) ? w.wrt_mesg : '#', #else ' ', #endif isprint(w.wrt_except) ? w.wrt_except : '#', w.wrt_telpref, isprint(w.wrt_modepref) ? w.wrt_modepref : '#', isprint(w.wrt_help) ? w.wrt_help : '#', isprint(w.wrt_modepref) ? w.wrt_record : '#', isprint(w.wrt_bells) ? w.wrt_bells : '#', w.wrt_pid, ctime(&w.wrt_time)+4); } } orville-write-2.55/helpers.c0100644000076500007650000000732607054022050014176 0ustar janjan/* HELPERS - List or count of current helpers. * * (C) Copyright, Nov 1995 - Jan Wolter */ #include "orville.h" #include /* Structure for list of ttys with helpers on them. */ struct hlp { time_t time; /* login time from wrttmp file */ char line[UT_LINESIZE]; /* ttyline occupied by a helper */ int busy; /* is he busy? */ struct hlp *next; /* next helper */ } *list= NULL; /* FINDLIST - search the list for the named tty. If found, remove it from the * list, and return a pointer to it. If not found, return NULL. */ struct hlp *findlist(char *tty) { struct hlp *curr, *prev; for (curr= list, prev= NULL; curr != NULL; prev= curr,curr= prev->next) { if (!strncmp(tty, curr->line, UT_LINESIZE)) { if (prev == NULL) list= curr->next; else prev->next= curr->next; return(curr); } } return(NULL); } /* PERMS_ON: Return true if permissions for the user whose wrttmp entry is * passed in are on. This doesn't test the exception files. */ int perms_on(struct wrttmp *w) { struct stat st; char devname[UT_LINESIZE+7]; #ifdef TTYPERMS #define MASK 022 #else #define MASK 002 if (w->wrt_mesg != 'n') return(1); #endif /*TTYPERMS*/ /* Is his tty physically writable? */ sprintf(devname,"/dev/%.*s",UT_LINESIZE,w->wrt_line); if (stat(devname,&st)) return(0); return ((st.st_mode & MASK) != 0); } main(int argc, char **argv) { FILE *fp; struct wrttmp w; struct wrthdr wt_head; struct utmp *u; struct hlp *tmp; int i, j; int slot= 0; int count= 0; int freeonly= 0; int listthem= 1; progname= leafname(argv[0]); readconfig(NULL); /* Parse command line options */ for (i= 1; i < argc; i++) { if (argv[i][0] != '-' || argv[i][1] == '\0') goto usage; for (j= 1; argv[i][j] != '\0'; j++) switch(argv[i][j]) { case 'f': freeonly= 1; break; case 'l': listthem= 1; break; case 'n': listthem= 0; break; default: goto usage; } } /* Open wrttmp file */ if ((fp= fopen(f_wrttmp,"r")) == NULL) { printf("cannot open %s\n", f_wrttmp); exit(1); } /* Scan through wrttmp file, looking for help */ if (fread(&wt_head,sizeof(struct wrthdr),1,fp)) { for (;;) { fseek(fp,wrttmp_offset(slot++),0); if (!fread(&w,sizeof(struct wrttmp),1,fp)) break; /* skip obvious non-helpers */ if ((w.wrt_help != 'y' && w.wrt_help != 'Y') || (freeonly && w.wrt_what[0] != '\0')) continue; /* check his permissions */ if (w.wrt_help != 'Y' && !perms_on(&w)) continue; /* Found an apparent helper - save in linked list */ tmp= (struct hlp *)malloc(sizeof(struct hlp)); strncpy(tmp->line,w.wrt_line,UT_LINESIZE); tmp->time= w.wrt_time; tmp->busy= (w.wrt_what[0] != '\0'); tmp->next= list; list= tmp; } } fclose(fp); /* Scan through utmp file, looking for ttys on our list */ if (list != NULL) { /* Do the scan */ while ((u= getutent()) != NULL) { #ifdef USER_PROCESS if (u->ut_type != USER_PROCESS) continue; #endif if ((tmp= findlist(u->ut_line)) != NULL) { /* If the time stamps don't match, this isn't a real helper */ if (u->ut_time == tmp->time) { /* Found a real helper -- count and print */ count++; if (listthem) printf("%-*.*s %-*.*s%s\n", UT_NAMESIZE, UT_NAMESIZE, u->ut_name, UT_LINESIZE, UT_LINESIZE, u->ut_line, tmp->busy ? " [busy]" : ""); } free(tmp); if (list == NULL) break; } } endutent(); } if (!listthem) printf("%d\n",count); else if (count == 0) printf("NONE\n"); exit(0); usage: printf("usage: %s [-fln]\n",argv[0]); exit(1); } orville-write-2.55/helpers.10100644000076500007650000000133307044101647014115 0ustar janjan.\" @(#)helpers.1 2.41 .\" .TH HUH 1 "Jan 20, 2000" .AT 3 .SH NAME helpers \- list or count helpers currently on the system. .SH SYNOPSIS .B helpers [-fln] .SH DESCRIPTION Helpers are users who volunteer to answer help requests by setting a help flag. For more information, see the manual pages for .IR mesg (1) and .IR write (1). .PP The .I helpers command lists or counts the people who currently have helper flags set on the system. It lists them by default, or if the .B -l flag is given. It prints a count to standard output if the .B -n flag is given. .PP If the .B -f flag is given, only the helpers who are currently free are listed or counted. .SH AUTHOR Jan Wolter .SH FILES /etc/wrttmp .SH "SEE ALSO" mesg(1), write(1) orville-write-2.55/say0100755000076500007650000000176206673762525013140 0ustar janjan#!/bin/sh # "SAY" SCRIPT - A cheap simulution of the Well/River "say" command using # Jan Wolter's "gate" and "write" programs. # # SYNOPSIS: # say [user|-|.] [tty] # # DESCRIPTION: # Say will prompt you to enter some text, and then send it in one burst # to the named user. It is essentially similar to "tel" except that # "tel" is limited to a single line of text. # # As with tel, the recipient must have message and telegram permissions # enabled. If he has the "mesg -r" flag set, he will be able to redisplay # the message with the "huh" command. # # Say will not work if system administrators have set the -f flag to be # the default on "write." # # The two lines below should be set to the paths of the "gate" and "write" # commands. "Red" could be used instead of "gate." # gate=/wolter/src/mnet/gate/gate write=/wolter/src/mnet/write/write rm=/bin/rm # file=/tmp/say$$ $gate --prompt="" --outdent=0 $file if ($write $* < $file) then echo DONE fi rm -f $file orville-write-2.55/Makefile.in0100644000076500007650000000676510126427216014452 0ustar janjanSHELL= /bin/sh srcdir= @srcdir@ VPATH= @srcdir@ CC= @CC@ INSTALL= @INSTALL@ LN= @LN_S@ prefix= @prefix@ exec_prefix= @exec_prefix@ bindir= @bindir@ mandir= @mandir@ datadir= @datadir@ sysconfdir= @sysconfdir@ localstatedir= @localstatedir@ groupid= @group_id@ CPPFLAGS= @CPPFLAGS@ CFLAGS= @CFLAGS@ LDFLAGS= @LDFLAGS@ LIB= @LIBS@ all: write mesg amin huh helpers WSRC= wrt_main.c wrt_type.c wrt_him.c wrt_me.c wrt_opt.c wrt_sig.c \ wrt_tty.c wrt_hist.c lib_common.c getutent.c WOBJ= wrt_main.o wrt_type.o wrt_him.o wrt_me.o wrt_opt.o wrt_sig.o \ wrt_tty.o wrt_hist.o lib_common.o getutent.o write: $(WOBJ) $(CC) $(CFLAGS) -o write $(WOBJ) $(LIB) wrt_main.o: wrt_main.c wrttmp.h write.h config.h orville.h wrt_type.o: wrt_type.c wrttmp.h write.h config.h orville.h wrt_him.o: wrt_him.c lib_common.h getutent.h wrttmp.h write.h config.h orville.h wrt_me.o: wrt_me.c lib_common.h getutent.h wrttmp.h write.h config.h orville.h wrt_opt.o: wrt_opt.c wrttmp.h write.h config.h orville.h wrt_sig.o: wrt_sig.c wrttmp.h write.h config.h orville.h wrt_tty.o: wrt_tty.c wrttmp.h write.h config.h orville.h wrt_hist.o: wrt_hist.c wrttmp.h write.h config.h orville.h lib_common.o:lib_common.c getutent.h lib_common.h wrttmp.h config.h orville.h getutent.o: getutent.c getutent.h wrttmp.h config.h orville.h mesg.o: mesg.c wrttmp.h lib_common.h config.h orville.h amin.o: amin.c wrttmp.h lib_common.h config.h orville.h huh.o: huh.c wrttmp.h lib_common.h config.h orville.h helpers.o: helpers.c wrttmp.h getutent.h config.h orville.h wt.o: wt.c wrttmp.h config.h orville.h mesg: mesg.o lib_common.o getutent.o $(CC) $(LDFLAGS) -o mesg mesg.o lib_common.o getutent.o amin: amin.o lib_common.o getutent.o $(CC) $(LDFLAGS) -o amin amin.o lib_common.o getutent.o huh: huh.o lib_common.o getutent.o $(CC) $(LDFLAGS) -o huh huh.o lib_common.o getutent.o helpers: helpers.o getutent.o $(CC) $(LDFLAGS) -o helpers helpers.o getutent.o lib_common.o wt: wt.o $(CC) $(LDFLAGS) -o wt wt.c lib_common.o getutent.o install: write mesg amin huh helpers ./install-sh -d $(bindir) $(INSTALL) -o root -g $(groupid) -m 6711 write $(bindir) -(cd $(bindir); $(LN) write jot; $(LN) write tel; $(LN) write telegram) $(INSTALL) -o root -m 4711 mesg $(bindir) $(INSTALL) -o root -m 4711 amin $(bindir) $(INSTALL) -o root -m 4711 huh $(bindir) $(INSTALL) -m 4711 helpers $(bindir) ./install-sh -d $(sysconfdir) $(INSTALL) -m 644 orville.conf $(sysconfdir) -rm -f $(sysconfdir)/wrttmp touch $(sysconfdir)/wrttmp chown root $(sysconfdir)/wrttmp chmod 600 $(sysconfdir)/wrttmp -rm -f $(sysconfdir)/wrthist touch $(sysconfdir)/wrthist chmod 600 $(sysconfdir)/wrthist ./install-sh -d $(mandir)/man1 $(INSTALL) -m 644 write.1 $(mandir)/man1 $(INSTALL) -m 644 mesg.1 $(mandir)/man1 $(INSTALL) -m 644 amin.1 $(mandir)/man1 $(INSTALL) -m 644 huh.1 $(mandir)/man1 $(INSTALL) -m 644 helpers.1 $(mandir)/man1 write.tar: README INSTALLATION CHANGES $(WSRC) wrttmp.h write.h orville.h \ lib_common.h getutent.h mesg.c amin.c huh.c amin.1 write.1 mesg.1 \ huh.1 wrttab wt.c say Makefile.in configure.in configure install-sh \ config.h.in orville.conf tar cvf write.tar README INSTALLATION CHANGES $(WSRC) write.h \ wrttmp.h orville.h lib_common.h getutent.h mesg.c amin.c huh.c amin.1 \ write.1 mesg.1 huh.1 wrttab wt.c helpers.c helpers.1 say \ Makefile.in configure.in configure install-sh config.h.in orville.conf clean: -rm -f wt core *.o distclean: -rm -f write mesg amin huh helpers wt core *.o config.h config.cache \ config.cache config.status Makefile write.tar orville-write-2.55/configure.in0100644000076500007650000000402507665676457014734 0ustar janjandnl Process this file with autoconf to produce a configure script. AC_INIT(orville.h) AC_CONFIG_HEADER(config.h) AC_SUBST(group_id) dnl Checks for programs. AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S dnl Checks for libraries. AC_CHECK_LIB(crypt, crypt) dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_HEADER_TIME AC_CHECK_HEADERS(fcntl.h paths.h sys/time.h unistd.h crypt.h) AC_CHECK_HEADERS(termios.h termio.h sgtty.h, [break]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_STRUCT_TM AC_STRUCT_TIMEZONE dnl Checks for library functions. AC_PROG_GCC_TRADITIONAL AC_TYPE_SIGNAL AC_CHECK_FUNCS(random getutent strchr) AC_CHECK_FUNCS(getuserpw) if test "$ac_cv_func_getuserpw" != "yes"; then AC_SEARCH_LIBS(getspnam, shadow, [ AC_DEFINE(HAVE_GETSPNAM) AC_SEARCH_LIBS(kg_pwhash,shadow, [ AC_DEFINE(HAVE_KG_PWHASH)], [ AC_SEARCH_LIBS(pw_encrpyt,shadow, [AC_DEFINE(HAVE_PW_ENCRYPT)])]) ]) fi dnl Checks for flags AC_ARG_WITH(slow_passwd, [ --with-slow-passwd looking up people in /etc/passwd is slow], [ if test "$enableval" != "no"; then AC_DEFINE(SLOWPASSWD) fi]) AC_ARG_WITH(talk, [ --with-talk you have a talkd hacked for orville compatibility], [ if test "$enableval" != "no"; then AC_DEFINE(WITH_TALK) fi]) dnl Unconditionally, for now. Later try to sense this. AC_DEFINE(TTY_GROUP) AC_CACHE_CHECK([for tty device group], ow_cv_tty_group_id, [dnl changequote(, )dnl tty=`tty` ow_cv_tty_group_id=`ls -lg $tty | sed 's/^.*-[^ ]* *[^ ]* *[^ ]* *\([^ ]*\).*$/\1/'` changequote([, ])dnl ]) group_id=$ow_cv_tty_group_id dnl Path name of orville.conf file. test "x$prefix" = xNONE && prefix=$ac_default_prefix oc=`eval echo "${sysconfdir}/orville.conf" | sed "s/\/\//\//g"` echo "Configuration file will be in $oc" AC_DEFINE_UNQUOTED(ORVILLE_CONF,"$oc") wt=`eval echo "${sysconfdir}/wrttmp" | sed "s/\/\//\//g"` AC_DEFINE_UNQUOTED(D_WRTTMP,"$wt") wh=`eval echo "${sysconfdir}/wrthist" | sed "s/\/\//\//g"` AC_DEFINE_UNQUOTED(D_WRTHIST,"$wh") AC_OUTPUT(Makefile) orville-write-2.55/configure0100755000076500007650000020367507665676463014343 0ustar janjan#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --with-slow-passwd looking up people in /etc/passwd is slow" ac_help="$ac_help --with-talk you have a talkd hacked for orville compatibility" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=orville.h # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:535: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:565: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:616: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:648: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 659 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:690: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:695: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:723: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break fi done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:785: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 echo "configure:838: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftestdata if ln -s X conftestdata 2>/dev/null then rm -f conftestdata ac_cv_prog_LN_S="ln -s" else ac_cv_prog_LN_S=ln fi fi LN_S="$ac_cv_prog_LN_S" if test "$ac_cv_prog_LN_S" = "ln -s"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 echo "configure:860: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lcrypt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_lib=HAVE_LIB`echo crypt | sed -e 's/[^a-zA-Z0-9_]/_/g' \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` cat >> confdefs.h <&6 fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:908: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:929: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:946: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 echo "configure:988: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1001: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "memchr" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "free" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF if { (eval echo configure:1068: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_header_stdc=no fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF #define STDC_HEADERS 1 EOF fi echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 echo "configure:1092: checking for sys/wait.h that is POSIX.1 compatible" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #ifndef WEXITSTATUS #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main() { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF if { (eval echo configure:1113: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_sys_wait_h=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 if test $ac_cv_header_sys_wait_h = yes; then cat >> confdefs.h <<\EOF #define HAVE_SYS_WAIT_H 1 EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 echo "configure:1134: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include int main() { struct tm *tp; ; return 0; } EOF if { (eval echo configure:1148: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_time=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_header_time" 1>&6 if test $ac_cv_header_time = yes; then cat >> confdefs.h <<\EOF #define TIME_WITH_SYS_TIME 1 EOF fi for ac_hdr in fcntl.h paths.h sys/time.h unistd.h crypt.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1172: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1182: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done for ac_hdr in termios.h termio.h sgtty.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1213: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1223: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done echo $ac_n "checking for working const""... $ac_c" 1>&6 echo "configure:1251: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } ; return 0; } EOF if { (eval echo configure:1305: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_c_const" 1>&6 if test $ac_cv_c_const = no; then cat >> confdefs.h <<\EOF #define const EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 echo "configure:1326: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF if { (eval echo configure:1339: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_tm=sys/time.h fi rm -f conftest* fi echo "$ac_t""$ac_cv_struct_tm" 1>&6 if test $ac_cv_struct_tm = sys/time.h; then cat >> confdefs.h <<\EOF #define TM_IN_SYS_TIME 1 EOF fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 echo "configure:1360: checking for tm_zone in struct tm" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_cv_struct_tm> int main() { struct tm tm; tm.tm_zone; ; return 0; } EOF if { (eval echo configure:1373: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_tm_zone=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6 if test "$ac_cv_struct_tm_zone" = yes; then cat >> confdefs.h <<\EOF #define HAVE_TM_ZONE 1 EOF else echo $ac_n "checking for tzname""... $ac_c" 1>&6 echo "configure:1393: checking for tzname" >&5 if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #ifndef tzname /* For SGI. */ extern char *tzname[]; /* RS6000 and others reject char **tzname. */ #endif int main() { atoi(*tzname); ; return 0; } EOF if { (eval echo configure:1408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_var_tzname=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_var_tzname=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_var_tzname" 1>&6 if test $ac_cv_var_tzname = yes; then cat >> confdefs.h <<\EOF #define HAVE_TZNAME 1 EOF fi fi if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 echo "configure:1432: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext < Autoconf TIOCGETP EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* ac_cv_prog_gcc_traditional=yes else rm -rf conftest* ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < Autoconf TCGETA EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 echo "configure:1478: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #ifdef signal #undef signal #endif #ifdef __cplusplus extern "C" void (*signal (int, void (*)(int)))(int); #else void (*signal ()) (); #endif int main() { int i; ; return 0; } EOF if { (eval echo configure:1500: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_type_signal=int fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_signal" 1>&6 cat >> confdefs.h <&6 echo "configure:1521: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:1549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done for ac_func in getuserpw do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:1576: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:1604: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done if test "$ac_cv_func_getuserpw" != "yes"; then echo $ac_n "checking for library containing getspnam""... $ac_c" 1>&6 echo "configure:1632: checking for library containing getspnam" >&5 if eval "test \"`echo '$''{'ac_cv_search_getspnam'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_getspnam="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_getspnam="none required" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* test "$ac_cv_search_getspnam" = "no" && for i in shadow; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_getspnam="-l$i" break else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* done LIBS="$ac_func_search_save_LIBS" fi echo "$ac_t""$ac_cv_search_getspnam" 1>&6 if test "$ac_cv_search_getspnam" != "no"; then test "$ac_cv_search_getspnam" = "none required" || LIBS="$ac_cv_search_getspnam $LIBS" cat >> confdefs.h <<\EOF #define HAVE_GETSPNAM 1 EOF echo $ac_n "checking for library containing kg_pwhash""... $ac_c" 1>&6 echo "configure:1694: checking for library containing kg_pwhash" >&5 if eval "test \"`echo '$''{'ac_cv_search_kg_pwhash'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_kg_pwhash="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_kg_pwhash="none required" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* test "$ac_cv_search_kg_pwhash" = "no" && for i in shadow; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_kg_pwhash="-l$i" break else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* done LIBS="$ac_func_search_save_LIBS" fi echo "$ac_t""$ac_cv_search_kg_pwhash" 1>&6 if test "$ac_cv_search_kg_pwhash" != "no"; then test "$ac_cv_search_kg_pwhash" = "none required" || LIBS="$ac_cv_search_kg_pwhash $LIBS" cat >> confdefs.h <<\EOF #define HAVE_KG_PWHASH 1 EOF else : echo $ac_n "checking for library containing pw_encrpyt""... $ac_c" 1>&6 echo "configure:1757: checking for library containing pw_encrpyt" >&5 if eval "test \"`echo '$''{'ac_cv_search_pw_encrpyt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_pw_encrpyt="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_pw_encrpyt="none required" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* test "$ac_cv_search_pw_encrpyt" = "no" && for i in shadow; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_pw_encrpyt="-l$i" break else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* done LIBS="$ac_func_search_save_LIBS" fi echo "$ac_t""$ac_cv_search_pw_encrpyt" 1>&6 if test "$ac_cv_search_pw_encrpyt" != "no"; then test "$ac_cv_search_pw_encrpyt" = "none required" || LIBS="$ac_cv_search_pw_encrpyt $LIBS" cat >> confdefs.h <<\EOF #define HAVE_PW_ENCRYPT 1 EOF else : fi fi else : fi fi # Check whether --with-slow_passwd or --without-slow_passwd was given. if test "${with_slow_passwd+set}" = set; then withval="$with_slow_passwd" if test "$enableval" != "no"; then cat >> confdefs.h <<\EOF #define SLOWPASSWD 1 EOF fi fi # Check whether --with-talk or --without-talk was given. if test "${with_talk+set}" = set; then withval="$with_talk" if test "$enableval" != "no"; then cat >> confdefs.h <<\EOF #define WITH_TALK 1 EOF fi fi cat >> confdefs.h <<\EOF #define TTY_GROUP 1 EOF echo $ac_n "checking for tty device group""... $ac_c" 1>&6 echo "configure:1858: checking for tty device group" >&5 if eval "test \"`echo '$''{'ow_cv_tty_group_id'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else tty=`tty` ow_cv_tty_group_id=`ls -lg $tty | sed 's/^.*-[^ ]* *[^ ]* *[^ ]* *\([^ ]*\).*$/\1/'` fi echo "$ac_t""$ow_cv_tty_group_id" 1>&6 group_id=$ow_cv_tty_group_id test "x$prefix" = xNONE && prefix=$ac_default_prefix oc=`eval echo "${sysconfdir}/orville.conf" | sed "s/\/\//\//g"` echo "Configuration file will be in $oc" cat >> confdefs.h <> confdefs.h <> confdefs.h < confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 DEFS=-DHAVE_CONFIG_H # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@group_id@%$group_id%g s%@CC@%$CC%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@LN_S@%$LN_S%g s%@CPP@%$CPP%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac case "$ac_given_INSTALL" in [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' ac_dC='\3' ac_dD='%g' # ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='\([ ]\)%\1#\2define\3' ac_uC=' ' ac_uD='\4%g' # ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' if test "${CONFIG_HEADERS+set}" != set; then EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac echo creating $ac_file rm -f conftest.frag conftest.in conftest.out ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` cat $ac_file_inputs > conftest.in EOF # Transform confdefs.h into a sed script conftest.vals that substitutes # the proper values into config.h.in to produce config.h. And first: # Protect against being on the right side of a sed subst in config.status. # Protect against being in an unquoted here document in config.status. rm -f conftest.vals cat > conftest.hdr <<\EOF s/[\\&%]/\\&/g s%[\\$`]%\\&%g s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp s%ac_d%ac_u%gp s%ac_u%ac_e%gp EOF sed -n -f conftest.hdr confdefs.h > conftest.vals rm -f conftest.hdr # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >> conftest.vals <<\EOF s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. rm -f conftest.tail while : do ac_lines=`grep -c . conftest.vals` # grep -c gives empty output for an empty file on some AIX systems. if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi # Write a limited-size here document to conftest.frag. echo ' cat > conftest.frag <> $CONFIG_STATUS sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS echo 'CEOF sed -f conftest.frag conftest.in > conftest.out rm -f conftest.in mv conftest.out conftest.in ' >> $CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail rm -f conftest.vals mv conftest.tail conftest.vals done rm -f conftest.vals cat >> $CONFIG_STATUS <<\EOF rm -f conftest.frag conftest.h echo "/* $ac_file. Generated automatically by configure. */" > conftest.h cat conftest.in >> conftest.h rm -f conftest.in if cmp -s $ac_file conftest.h 2>/dev/null; then echo "$ac_file is unchanged" rm -f conftest.h else # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi rm -f $ac_file mv conftest.h $ac_file fi fi; done EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 orville-write-2.55/install-sh0100755000076500007650000001273607042760056014411 0ustar janjan#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 orville-write-2.55/config.h.in0100644000076500007650000000462007665676751014444 0ustar janjan#ifndef CONFIG_H #define CONFIG_H /* Path name of configuration file. */ #undef ORVILLE_CONF /* Default location of wrttmp file. */ #undef D_WRTTMP /* Default location of wrthist file. */ #undef D_WRTHIST /* Define if we want to be talk compatible. */ #undef WITH_TALK /* Define if password file lookups are extremely slow on your system */ #undef SLOWPASSWD /* Define if tty devices are normally permitted only to group */ #undef TTY_GROUP /* Define if tty devices are normally permitted to others */ #undef TTY_OTHERS /* Define to empty if the keyword does not work. */ #undef const /* Define if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define as the return type of signal handlers (int or void). */ #undef RETSIGTYPE /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you do password lookups with the getuserpw() function. */ #undef HAVE_GETUSERPW /* Define if passwords in your shadow file are encrypted by pw_encrypt() */ #undef HAVE_PW_ENCRYPT /* Define if passwords in your shadow file are encrypted by kg_pwhash() */ #undef HAVE_KG_PWHASH /* Define if your declares struct tm. */ #undef TM_IN_SYS_TIME /* Define if you do password lookups with the getspnam() function. */ #undef HAVE_GETSPNAM /* Define if you have the random() function. */ #undef HAVE_RANDOM /* Define if you have the strchr() function. */ #undef HAVE_STRCHR /* Define if you have the getutent() function. */ #undef HAVE_GETUTENT /* Define if you have the header file. */ #undef HAVE_CRYPT_H /* Define if you have the header file. */ #undef HAVE_FCNTL_H /* Define if you have the header file. */ #undef HAVE_PATHS_H /* Define if you have the header file. */ #undef HAVE_SGTTY_H /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define if you may include both time.h and sys/time.h */ #undef TIME_WITH_SYS_TIME /* Define if you have the header file. */ #undef HAVE_TERMIO_H /* Define if you have the header file. */ #undef HAVE_TERMIOS_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H /* Define if you have the crypt library (-lcrypt). */ #undef HAVE_LIBCRYPT /* Define if 'struct tm' has a tm_zone member */ #undef HAVE_TM_ZONE /* Define if we have external array 'tzname' */ #undef HAVE_TZNAME #endif /* CONFIG_H */ orville-write-2.55/orville.conf0100644000076500007650000000641607044405013014715 0ustar janjan# ===== FILES ===== # Wrttmp File - Location of the file where all current user's write settings # are kept. If not defined, this defaults to being named 'wrttmp' and being # in the same directory as orville.conf. # wrttmp /etc/wrttmp # Wrthist File - Location of file where records of recent telgrams are saved. # are kept. If not defined, this defaults to being named 'wrthist' and being # in the same directory as orville.conf. # wrthist /etc/wrthist # Novice Help - If it is defined and exists, then contents of this file are # printed when help starts up if they have the NOVICE environment variable set. novicehelp /usr/local/share/write.help # ===== LOGGING ===== # Log file - Keeps a record of who wrote whom, whether the connection worked, # and what went wrong if it didn't. If loglevel is 0, or is not defined, or # the file does not exist, then no log is kept. log /var/log/write.log # Log Level - How much shall we log? Value should be: # 0 - nothing. # 1 - help requests only (good for monitoring how your help is doing) # 2 - all writes attempts. loglevel 1 # ===== OPTIONS ===== # Disconnect flag - Set to 'y' if you want people to be able to disconnect # all write sessions currently directed at them with 'mesg d' or 'mesg N'. # Default is 'y'. # disconnect y # Exceptions flag - Set to 'y' if you want people to be able to turn messages # on or off with the exception of a list of users named in the .nowrite or # .yeswrite files. Default is 'y'. # exceptions y # Helpers flag - Set to 'y' if you want 'write help' to connect people to a # helper. Default is 'n' # helpers n # Time to Answer Telegrams - After you send a telegram to a person, there # is a period of time during which that person may reply, even if your # permissions are off. The answertel command sets the length of that period # in seconds. Default is 240 seconds (4 minutes). # answertel 300 # Hostname on Message Banners - Many versions of write send banners like # "Message from user@hostname". This is nice if the recipient is in a telnet # connection to another Unix system, so the writes could be coming from either # of two systems. It defaults off because I have an irrational dislike for it. # fromhost n # Allow Piped Input - If 'pipes' is turned off, then standard input to write # must be a tty, not a pipe, and the '|' and '&' escapes are disabled. It # is useful if you have cretinous users who like sending large globs of data # to other users. # pipes y # ===== HELPERS ===== # Helper name - If instead of writing 'help' you'd like people to write to # some other name to get help, set that name here. Default is 'help'. # helpername help # Helpers file - If this is defined, and the file exists, then only people # named in this file can do 'mesg -h' and become helpers. If not, anyone can # designate themselves to be a helper. Just list one login id per line in # the file. helperlist /usr/local/etc/helplist # No Helper file - Contains a message to print when a person does 'write help' # but no helpers are found. Usually a description of alternate places to get # help. If not defined, no message is printed. nohelp /usr/local/share/write.nohelp # ===== LINKS ===== # Default options for various links to the Orville write program options jot -c options tel -t options telegram -t orville-write-2.55/config.log0100644000076500007650000001372710126432501014342 0ustar janjanThis file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. configure:535: checking for gcc configure:648: checking whether the C compiler (gcc ) works configure:664: gcc -o conftest conftest.c 1>&5 configure:690: checking whether the C compiler (gcc ) is a cross-compiler configure:695: checking whether we are using GNU C configure:704: gcc -E conftest.c configure:723: checking whether gcc accepts -g configure:785: checking for a BSD compatible install configure:838: checking whether ln -s works configure:860: checking for crypt in -lcrypt configure:879: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 configure:908: checking how to run the C preprocessor configure:929: gcc -E conftest.c >/dev/null 2>conftest.out configure:988: checking for ANSI C header files configure:1001: gcc -E conftest.c >/dev/null 2>conftest.out configure:1068: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 configure:1092: checking for sys/wait.h that is POSIX.1 compatible configure:1113: gcc -c -g -O2 conftest.c 1>&5 configure:1134: checking whether time.h and sys/time.h may both be included configure:1148: gcc -c -g -O2 conftest.c 1>&5 configure:1172: checking for fcntl.h configure:1182: gcc -E conftest.c >/dev/null 2>conftest.out configure:1172: checking for paths.h configure:1182: gcc -E conftest.c >/dev/null 2>conftest.out configure:1172: checking for sys/time.h configure:1182: gcc -E conftest.c >/dev/null 2>conftest.out configure:1172: checking for unistd.h configure:1182: gcc -E conftest.c >/dev/null 2>conftest.out configure:1172: checking for crypt.h configure:1182: gcc -E conftest.c >/dev/null 2>conftest.out configure:1213: checking for termios.h configure:1223: gcc -E conftest.c >/dev/null 2>conftest.out configure:1251: checking for working const configure:1305: gcc -c -g -O2 conftest.c 1>&5 configure:1326: checking whether struct tm is in sys/time.h or time.h configure:1339: gcc -c -g -O2 conftest.c 1>&5 configure:1360: checking for tm_zone in struct tm configure:1373: gcc -c -g -O2 conftest.c 1>&5 configure:1432: checking whether gcc needs -traditional configure:1478: checking return type of signal handlers configure:1500: gcc -c -g -O2 conftest.c 1>&5 configure:1521: checking for random configure:1549: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 configure:1521: checking for getutent configure:1549: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 configure:1521: checking for strchr configure:1549: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 configure:1533: warning: conflicting types for built-in function `strchr' configure:1576: checking for getuserpw configure:1604: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 /home/jan/tmp/ccSBSOVN.o(.text+0x9): In function `main': /home/jan/src/write/orville-write-2.55/configure:1598: undefined reference to `getuserpw' collect2: ld returned 1 exit status configure: failed program was: #line 1581 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getuserpw(); below. */ #include /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char getuserpw(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_getuserpw) || defined (__stub___getuserpw) choke me #else getuserpw(); #endif ; return 0; } configure:1632: checking for library containing getspnam configure:1650: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 configure:1694: checking for library containing kg_pwhash configure:1712: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 /home/jan/tmp/ccwck4vL.o(.text+0x9): In function `main': /home/jan/src/write/orville-write-2.55/configure:1708: undefined reference to `kg_pwhash' collect2: ld returned 1 exit status configure: failed program was: #line 1701 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char kg_pwhash(); int main() { kg_pwhash() ; return 0; } configure:1734: gcc -o conftest -g -O2 conftest.c -lshadow -lcrypt 1>&5 /usr/bin/ld: cannot find -lshadow collect2: ld returned 1 exit status configure: failed program was: #line 1723 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char kg_pwhash(); int main() { kg_pwhash() ; return 0; } configure:1757: checking for library containing pw_encrpyt configure:1775: gcc -o conftest -g -O2 conftest.c -lcrypt 1>&5 /home/jan/tmp/ccItJtKB.o(.text+0x9): In function `main': /home/jan/src/write/orville-write-2.55/configure:1771: undefined reference to `pw_encrpyt' collect2: ld returned 1 exit status configure: failed program was: #line 1764 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pw_encrpyt(); int main() { pw_encrpyt() ; return 0; } configure:1797: gcc -o conftest -g -O2 conftest.c -lshadow -lcrypt 1>&5 /usr/bin/ld: cannot find -lshadow collect2: ld returned 1 exit status configure: failed program was: #line 1786 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pw_encrpyt(); int main() { pw_encrpyt() ; return 0; } configure:1858: checking for tty device group