Newsgroups: comp.sources.unix From: thalerd@quip.eecs.umich.edu (Dave Thaler) Subject: v28i046: yapp - conferencing system (similar to PicoSpan), Part02/05 References: <1.770288965.8721@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: thalerd@quip.eecs.umich.edu (Dave Thaler) Posting-Number: Volume 28, Issue 46 Archive-Name: yapp/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'change.c' <<'END_OF_FILE' X/* CHANGE.C */ Xstatic char sccsid[] = "@(#)change.c 1.3 94/01/20 (c)1993 thalerd"; X/* PHASE 1: Conference Subsystem X Be able to enter/exit the program, and move between conferences X Commands: join, next, quit, source X Files: rc files, cflist, login, logout, bull X*/ X X#include X#include X#include X#include X#include X#include X#include X#include "config.h" X#include "struct.h" X#include "globals.h" X#include "conf.h" X#include "lib.h" X#include "joq.h" X#include "sum.h" X#include "item.h" X#include "range.h" X#include "macro.h" X#include "system.h" X#include "sep.h" X#include "xalloc.h" X#include "stats.h" /* for get_config */ X Xchar *cfiles[]={ "logi_n", "logo_ut", "in_dex", "b_ull", X "we_lcome", "rc", "sec_ret", "ul_ist", "" }; X X/******************************************************************************/ X/* CHANGE SYSTEM PARAMETERS */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xchange(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X char buff[MAX_LINE_LENGTH]; X char done; X short i,j; X char **config; X X if (argc<2) { X printf("Change what?\n"); X return 1; X } X X for (j=1; j=0) { X if (config = get_config(confidx)) X write_part(config[CF_PARTFILE]); X } X } else if (match(argv[j],"sum_mary")) { X if (!(st_glob.c_status & CS_FW)) { X wputs("Sorry, you can't do that!\n"); X return 1; X } X printf("Regenerating summary file; please wait\n"); X refresh_sum(0,confidx,sum,part,&st_glob); X save_sum(sum,(short)-1,confidx,&st_glob); X } else if (match(argv[j],"nosum_mary")) { X if (!(st_glob.c_status & CS_FW)) { X wputs("Sorry, you can't do that!\n"); X return 1; X } X sprintf(buff,"%s/sum",conflist[confidx].location); X rm(buff,SL_OWNER); X } else if (match(argv[j],"rel_oad")) { X if (confidx>=0) { X if (config = get_config(confidx)) X read_part(config[CF_PARTFILE],part,&st_glob,confidx); X } X st_glob.sumtime = 0; X } else { X for (i=0; cfiles[i][0]; i++) { X if (match(argv[j],cfiles[i])) { X char file[MAX_LINE_LENGTH],bufr[MAX_LINE_LENGTH]; X X if (!(st_glob.c_status & CS_FW)) { X printf("You aren't a fair-witness.\n"); X return 1; X } X sprintf(file,"%s/%s", X conflist[confidx].location,compress(cfiles[i])); X sprintf(bufr,"%s/cf.buffer",work); X X /* Copy file to cf.buffer owned by user */ X copy_file(file,bufr,SL_USER); X X if (!edit(bufr,(char*)0,0)) X printf("UNK Aborting...\n"); X else { X if (get_yes("Ok to install this? ")) X copy_file(bufr,file,SL_OWNER); X rm(bufr,SL_USER); X } X return 1; X } X } X printf("Bad parameters near \"%s\"\n",argv[j]); X return 2; X } X } X return 1; X} X X/******************************************************************************/ X/* DISPLAY SYSTEM PARAMETERS */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xdisplay(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X static time_t newmail=0; X time_t t; X char *noconferr="Not in a conference!\n",*var; X short i,done,j; X char **config; X X for (j=1; j\n"); X } else if (match(argv[j],"fro_zen")) { X int c=0; X X refresh_sum(0,confidx,sum,part,&st_glob); X printf("Items frozen:"); X for (i=0; i\n"); X } else if (match(argv[j],"f_orgotten")) { X int c=0; X printf("Items forgotten:"); X for (i=0; i\n"); X } else if (match(argv[j],"sup_eruser")) { X printf("fw superuser %s\n",(st_glob.c_status & CS_FW)?"yes":"no"); X } else if (match(argv[j],"fw_slist") X || match(argv[j],"fair_witnesslist") X || match(argv[j],"fair_witnesses")) { X if (confidx<0) wputs(noconferr); X else { X if (config = get_config(confidx)) X printf("fair witnesses: %s\n",config[CF_FWLIST]); X } X } else if (match(argv[j],"i_ndex") X || match(argv[j],"ag_enda")) { X sepinit(IS_START); X confsep("indxmsg",confidx,&st_glob,part,0); X } else if (match(argv[j],"li_st")) { X refresh_list(); X for (i=0; i" : " ",cflist[i]); X } else if (match(argv[j],"b_ulletin")) { X sepinit(IS_START); X confsep("bullmsg",confidx,&st_glob,part,0); X } else if (match(argv[j],"w_elcome")) { X sepinit(IS_START); X confsep("wellmsg",confidx,&st_glob,part,0); X } else if (match(argv[j],"logi_n")) { X sepinit(IS_START); X confsep("linmsg",confidx,&st_glob,part,0); X } else if (match(argv[j],"logo_ut")) { X sepinit(IS_START); X confsep("loutmsg",confidx,&st_glob,part,0); X } else if (match(argv[j],"ul_ist")) { X if (confidx<0) wputs(noconferr); X else more(conflist[confidx].location,"ulist"); X } else if (match(argv[j],"rc")) { X if (confidx<0) wputs(noconferr); X else more(conflist[confidx].location,"rc"); X } else if (match(argv[j],"log_messages")) { X if (confidx<0) wputs(noconferr); X else { X printf("login message:\n"); X more(conflist[confidx].location,"login"); X printf("logout message:\n"); X more(conflist[confidx].location,"logout"); X } X } else if (match(argv[j],"n_ew")) { X refresh_sum(0,confidx,sum,part,&st_glob); X sepinit(IS_ITEM); X open_pipe(); X confsep("linmsg",confidx,&st_glob,part,0); X check_mail(1); X } else if (match(argv[j],"n_ame") || match(argv[j],"u_ser")) X (void)printf("User: %s\n",st_glob.fullname); X else if (match(argv[j],"p_articipants")) { X participants(0,(char**)0); X } else if (match(argv[j],"s_een")) { X int c=0; X FILE *fp; X X refresh_sum(0,confidx,sum,part,&st_glob); X X /* Display seen item status */ X open_pipe(); X if (status & S_REDIRECT) fp = st_glob.outp; X else fp = stdout; X fprintf(fp,"item se re fl lastseen etime mtime\n\n"); X for (i=0; i'config.h' <<'END_OF_FILE' X/* CONFIG.H: @(#)config.h 1.5 93/06/07 Copyright (c)1993 thalerd */ X/* The following 3 defines are all that you should need to configure the bbs X * conferencing system for your machine: X * BBSDIR is the main subdirectory under which the whole system exists. On X * M-net it is /usr/bbs. The 'conflist' and main 'rc' files should exist there. X * HELPDIR is the subdirectory under which all the help files exist. On M-net X * it is /usr/bbs/help. X * MAILDIR should be set to the directory which contains the user mailbox files. X */ X#define BBSDIR "/usr/bbs" X#define HELPDIR "/usr/bbs/help" X#define MAILDIR "/usr/spool/mail" X#define NEWSDIR "/usr/spool/news" X X/* Define FREEZE_LINKED if you wish to allow fair-witnesses to freeze, X * thaw, retire, and unretire items that are linked to another conference. X */ X#undef FREEZE_LINKED X X/* Define BYTESWAP to be 1 if you want a consistent sum file format. This X * is useful on networks of machines of differing architectures. The only X * reason to change this is that on some machines, if you using YAPP with X * other programs that access the same files, the other programs may not X * do byteswapping (PicoSpan does). In this case, define BYTESWAP to be 0. X */ X#define BYTESWAP 1 X X/* Define NEWS if you wish to allow Usenet news conferences X */ X#define NEWS X X/* Do NOT return to SCCS without -k, or the %S% in LINMSG etc will go away! */ X X#ifdef __STDC__ X#define PROTO(x) x X#else X#define PROTO(x) () X#endif X#define CHAR char X#define U_CHAR unsigned char X#define SHORT short X#define U_SHORT unsigned short X X/* Defines for various OS's... */ X#ifdef ultrix X#define NOSTRDUP X#define NOSTRNICMP X#define NOEDATE X#define timelocal mktime X#endif X X#ifdef M_SYS3 X#define NOFLOCK X#define NOSTRNICMP X#endif X X#ifdef linux X#define NOFLOCK X#define NOSTRNICMP X#define timelocal mktime X#endif X X#ifdef hpux X#define NOEDATE X#define FLOCKF /* had lockf but not flock */ X#define NOSTRNICMP X#define timelocal mktime X#endif X X#ifdef NeXT X#define NOSTRNICMP X#define NOPUTENV X#define timelocal mktime X#define L_cuserid 9 X#define S_IRUSR 0400 X#define S_IWUSR 0200 X#define S_IXUSR 0100 X#include /* For X_OK */ X#undef CHAR X#define CHAR int X#undef U_CHAR X#define U_CHAR int X#undef SHORT X#define SHORT int X#undef U_SHORT X#define U_SHORT int X#endif X X#ifdef bsdi X#define NOSTRNICMP X#define timelocal mktime X#undef CHAR X#define CHAR int X#undef U_CHAR X#define U_CHAR int X#undef SHORT X#define SHORT int X#undef U_SHORT X#define U_SHORT int X#endif X X#define MAX_LINE_LENGTH 512 /* Buffer size for a line of text */ X#define MAX_FILE_NAME_LENGTH 80 /* Length of a file name */ X#define MAX_STRING_LENGTH 64 /* String length of our language */ X#define MAX_IDENT_LENGTH 32 /* Identifier length in our lang */ X#define DEFAULT_ON 1 /* Value of flag when on */ X#define DEFAULT_OFF 0 /* Value of flag when off */ X#define NIL (char *) 0 /* Empty string */ X#define CMD_DEPTH 20 X#define MAX_ARGS 128 X X#define MAX_LIST_LENGTH 300 /* # of conferences, help files */ X#define MAX_MACROS 200 /* # of aliases */ X#define MAX_RESPONSES 2000 /* # of responses/item */ X#define MAX_ITEMS 6000 /* # of items/conf */ X X/* Default variable values */ X#define PAGER "/usr/bin/more" X#define EDITOR "/bin/ed" X#define SHELL "/bin/sh" X#define PROMPT "\nYAPP: " X#define NOCONFP "\n\ XType HELP CONFERENCES for a list of conferences.\n\ XType JOIN to access a conference.\n\ XYAPP: " X#define RFPPROMPT "\n[%{curitem}/%l] Respond, forget, or pass? " X#define OBVPROMPT "\n[%{curitem}/%l] Can't respond, pass? " X#define JOQPROMPT "\nJoin, quit, or help? " X#define EDBPROMPT "Ok to enter this response? " X#define TEXT ">" /* No separators allowed for this prompt only */ X#define ESCAPE ":" X X/* : , / - ( ) + are used in dates */ X/* ! > | ` ~ are used for unix commands */ X/* < > % { } are used for separators */ X/* | & are reserved for future expansion for separators */ X/* . is used to specify responses */ X/* # is used for comments */ X/* _ is used for specifying commands */ X/* = ^ $ is used for range specs */ X/* " ' are used for strings */ X/* @ * ? [ ] ; are unused */ X#define CMDDEL ";" X#define BUFDEL "@" X X#define GECOS "," /* (char *)0 */ X#define NSEP "\n%(N%r new of %)%zn response%S total." X#define ISHORT "%(BItem Resps Subject\n\n%)%4i %5n %h" X#define ISEP "\nItem %i entered %d by %a (%l)\n %h" X#define RSEP "\n#%i.%r %a (%l) " X#define FSEP "%(R#%i.%r %a (%l)\n%)%7N: %L" X#define TXTSEP "%(L%(F%7N:%)%X%L%)" X#define ZSEP "%(T^L%)%c" X#define PRINTMSG "%QPrinted from conference %d (%s)" X#define MAILMSG "You have %(2xmore %)mail." X#define LINMSG "\ X%(1x%(2x\n%)%0g%)\ X%(2x%(3N%3g%)\ X%(1x\n%)%(n%(r%r newresponse item%S%)\ X%(b%(r and %)%b brandnew item%S%)\n%)\ X%(i%i item%S numbered %f-%l\n%)\ X%(sYou are a fairwitness in this conference.\n%)\ X%(lYou are an observer of this conference.\n%)\ X%(jYour name is \"%u\" in this conference.\n\ X%(~O%(4F\n%4g%E\n>>>> New users: type HELP for help.\n%)%)%)%)%c" X#define LOUTMSG "%(1x%1g%)%c" X#define INDXMSG "%(1x%2g%)%c" X#define BULLMSG "%(1x%3g%)%c" X#define WELLMSG "%(1x%4g%)%c" X#define PARTMSG "\ X%(2x%10v %o %u%)\ X%(4x\n%k participant%S total.%)\ X%(1x\n login last time on name\n%)" X#define CHECKMSG "%(1x\nNew resp items Conference name\n%)%(2x%(k--%E %)%(B>%E %)%4r %4b %s%(B (where you currently are!)%)%)" X#define CONFMSG "%Q\ XConference name : %s\n\ XDirectory : %d\n\ XParticipation file: %w/%p\n\ XSecurity type : %t\n\ X%(i%i item%S numbered %f-%l%ENo items yet.%)" X#define JOINMSG "Join: which conference?\n\ X%QYou are currently in the %s conference." X#define LISTMSG "\ X%(1x\nitems sec time conference\n%)\ X%(2x%(B>%E %)%4i %2t%(sF%E%(lR%E %)%) %m %s%)" X#define REPLYSEP "\ X%(1xIn #%i.%r of the %C conference, you write:%)\ X%(2x> %L%)\ X%(4x%)" X#ifdef NEWS X#define NEWSSEP "\ X%(1xIn article <%m>, %a writes:%)\ X%(2x> %L%)\ X%(4x%)" X#endif X X/* Option flags */ X#define NUM_OPTIONS 20 X#define O_DEBUG 0x0001 /* Turn all debugging options on */ X#define O_BUFFER 0x0002 /* Don't use a pager */ X#define O_DEFAULT 0x0004 /* Go to noconf mode at start */ X#define O_OBSERVE 0x0008 /* Force observer status */ X#define O_STRIP 0x0010 /* Turn strip flag on */ X#define O_SOURCE 0x0020 /* Don't source .cfrc and CONF/rc */ X#define O_FORGET 0x0040 /* */ X#define O_STAY 0x0080 /* Stay on curr item after resp */ X#define O_DOT 0x0100 /* '.' won't end text entry */ X#define O_EDALWAYS 0x0200 /* Go directly to editor for text */ X#define O_METOO 0x0400 /* */ X#define O_NUMBERED 0x0800 /* Number text in responses */ X#define O_DATE 0x1000 /* Display dates on items */ X#define O_UID 0x2000 /* Display uids on items */ X#define O_MAILTEXT 0x4000 /* Display uids on items */ X#define O_AUTOSAVE 0x8000 /* Display uids on items */ X#define O_VERBOSE 0x00010000 /* Display commands in rc files */ X#define O_SCRIBBLER 0x00020000 /* Display login of scribbler */ X#define O_SIGNITURE 0x00040000 /* Display signiture of authors */ X#define O_READONLY 0x00080000 /* Force noresponse status */ X X/* Status flags */ X#define S_INT 0x0001 /* Interrupt hit? */ X#define S_PIPE 0x0008 /* In a pipe? */ X#define S_QUIT 0x0010 /* Abort join */ X#define S_MAIL 0x0020 /* User has mail? */ X#define S_MOTIF 0x0040 /* Is this running under Motif? */ X#define S_MOREMAIL 0x0400 /* User has MORE mail? */ X#define S_EXECUTE 0x0800 /* Executing a `command` */ X#define S_REDIRECT 0x1000 /* Output is being redirected? */ X#define S_STOP 0x2000 /* Stop processing more ; cmds */ X X/* Conference status flags */ X#define CS_OBSERVER 0x0002 /* you're an observer in this cf */ X#define CS_FW 0x0004 /* you're a fairwitness of this cf */ X#define CS_NORESPONSE 0x0080 /* Response not possible */ X#define CS_OTHERCONF 0x0100 /* you were in another cf */ X#define CS_JUSTJOINED 0x0200 /* you just joined this cf */ X X/* Input Modes */ X#define M_MASK 63 X#define M_OK 0 /* Ok: */ X#define M_RFP 1 /* Respond or pass? */ X#define M_TEXT 2 /* > */ X#define M_JOQ 3 /* Join or quit */ X#define M_EDB 4 /* Ok to enter this response? */ X#define M_SUPERSANE 64 /* processing /usr/bbs/rc */ X#define M_SANE 128 /* processing CONF/rc */ X X/* Conference type flags */ X#define CT_OLDPUBLIC 0x00 /* 0000 */ X#define CT_PASSWORD 0x05 /* 0101 */ X#define CT_PRESELECT 0x04 /* 0100 */ X#define CT_PARANOID 0x06 /* 0110 */ X#define CT_PUBLIC 0x08 /* 1000 */ X#define CT_READONLY 0x10 /* 10000 */ X#define CT_BASIC 0x0F /* 01111 */ X#ifdef NEWS X#define CT_NEWS 0x20 /*100000 */ X#endif X X/* Config file fields */ X#define CF_MAGIC 0 X#define CF_PARTFILE 1 X#define CF_TIMELIMIT 2 X#define CF_FWLIST 3 X#define CF_SECURITY 4 X#ifdef NEWS X#define CF_NEWSGROUP 5 X#endif X X/* Item flags */ X#define IF_FORGOTTEN 0x0001 X#define IF_RETIRED 0x0002 X#define IF_ACTIVE 0x0030 X#define IF_FROZEN 0x0040 X#define IF_PARTY 0x0080 X#define IF_LINKED 0x0100 X#define IF_EXPIRED 0x0200 X#define IF_SAVEMASK 0xFFFE /* Save only these flags */ END_OF_FILE if test 10547 -ne `wc -c <'config.h'`; then echo shar: \"'config.h'\" unpacked with wrong size! fi # end of 'config.h' fi if test -f 'edbuf.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'edbuf.c'\" else echo shar: Extracting \"'edbuf.c'\" \(11292 characters\) sed "s/^X//" >'edbuf.c' <<'END_OF_FILE' X/* EDBUF.C */ Xstatic char sccsid[] = "@(#)edbuf.c 1.16 93/06/09 Copyright (c)1993 thalerd"; X#include X#include X#include X#include X#include "config.h" X#include "struct.h" X#include "globals.h" X#include "macro.h" X#include "driver.h" X#include "lib.h" X#include "item.h" X#include "edbuf.h" X#include "help.h" X#include "files.h" Xstatic FILE *file; Xstatic char post; Xstatic char oldmode; Xstatic int resp; X X/* Regarding mode: NOW USES oldmode X * Set mode back to RFP for respond command X * Enter command will set mode to OK itself X */ X X/******************************************************************************/ X/* MAIN TEXT ENTRY LOOP */ X/******************************************************************************/ Xchar /* RETURNS: 1 on success, 0 on failure */ Xcfbufr_open(flg) /* ARGUMENTS: */ Xshort flg; /* File open type (r,w, etc) */ X{ X char buff[MAX_LINE_LENGTH]; X X sprintf(buff,"%s/cf.buffer",work); X if ((file=mopen(buff,flg))==NULL) return 0; X printf("Type \".\" to exit or \":help\".\n"); X return 1; X} X X/******************************************************************************/ Xchar /* RETURNS: 1 on post, 0 on abort */ Xtext_loop(new,res) /* ARGUMENTS: (none) */ Xint new; Xint res; X{ X char ok=1,inbuff[MAX_LINE_LENGTH], X fromname[MAX_LINE_LENGTH],toname[MAX_LINE_LENGTH]; X register int cpid,wpid; X int statusp; X struct stat st; X X resp = res; X if ((status & S_MOTIF) || (flags & O_EDALWAYS)) X return edit(work,"cf.buffer",0); X X post=0; X X /* Fork & setuid down when creating cf.buffer */ X if (cpid=fork()) { /* parent */ X if (cpid<0) return -1; /* error: couldn't fork */ X while ((wpid = wait(&statusp)) != cpid && wpid != -1); X post = !statusp; X } else { /* child */ X if (setuid(getuid())) error("setuid",""); X setgid(getgid()); X X if (new) { X sprintf(fromname,"%s/cf.buffer",work); X if (!stat( fromname ,&st)) { /* cf.buffer exists */ X sprintf(toname,"%s/cbf.%d",work,getpid()); X if (rename(fromname,toname)) X error("renaming cf.buffer to ",toname); X } X } X X printf("%s your %s%s\n",(new) ? "Enter" : "(Continue", X (resp)? "response" : "text", X (new) ? ":" : " entry)" ); X if (!cfbufr_open((new)? O_WPLUS : O_APLUS)) return 0; /* "w+" */ X X oldmode = mode; X mode = M_TEXT; X while (mode==M_TEXT && ok) { X /* For optimization purposes, we do not allow seps in TEXT mode X * prompt. This could be changed back if confsep would dump X * out most strings quickly without accessing the disk. X */ X wputs(TEXT); X /* print_prompt(mode); */ X X ok = (ngets(inbuff,st_glob.inp)!=NULL); X if (ok && (status & S_INT)) { X status &= ~S_INT; /* Clear interrupt */ X ok = !get_yes((resp)? "Abort response? " : "Abort item? " ); X if (!ok) post= -1; X } X /* printf("ok=%d inbuff=%s\n",ok,inbuff); */ X if (!ok) { X printf("\n"); X mode = oldmode; /* Ctrl-D same as "." */ X post++; /* post on ^D or . don't post on ^C */ X } else if (inbuff[0]==':') { X if (inbuff[1]) ok = command(inbuff+1,0); X else ok = command("e",0); X } else if ((flags & O_DOT) && !strcmp(inbuff,".")) { X mode = oldmode; /* done */ X post = 1; X } else { /* Add to file buffer */ X if (fprintf(file,"%s\n",inbuff)<0) ok=0; X else fflush(file); X } X } X mclose(file); X exit(!post); X } /* ENDFORK */ X X return post; X} X X/* Commands available while in text entry mode */ Xstatic dispatch_t text_cmd[]={ X "q_uit", text_abort, X "c_ommand", text_done, X "ok", text_done, X "p_rint", text_print, X "e_dit", text_edit, X "v_isual", text_edit, X "h_elp", help, X "?", help, X "cl_ear", text_clear, X "em_pty", text_clear, X "r_ead", text_read, X "w_rite", text_write, X 0, 0 X}; X X/******************************************************************************/ X/* DISPATCH CONTROL TO APPROPRIATE TEXT COMMAND FUNCTION */ X/******************************************************************************/ Xchar /* RETURNS: 1 on abort, 0 else */ Xtext_cmd_dispatch(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X int i; X X for (i=0; text_cmd[i].name; i++) X if (match(argv[0],text_cmd[i].name)) X return text_cmd[i].func(argc,argv); X X /* Command dispatch */ X if (match(argv[0],"d_one") /* same as . on a new line */ X || match(argv[0],"st_op") /* ? */ X || match(argv[0],"ex_it"))/* ?*/{ X mode = oldmode; post = 1; /* mark as done */ X } else { X printf("Don't understand that!\n\n"); X text_abort(argc,argv); X } X return 1; X} X X/******************************************************************************/ X/* READ TEXT FROM A FILE INTO THE BUFFER */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_read(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X FILE *fp; X char buff[MAX_LINE_LENGTH]; X X /* PicoSpan puts spaces into the filename, we don't */ X if (argc!=2) { X printf("UNK Syntax: r filename\n"); X return 1; X } X X /* This is done inside the secure portion X * writing to the cf.buffer file, so it's already secure X */ X printf("Reading %s\n",argv[1]); X if ((fp=mopen(argv[1],O_R))==NULL) { X return 1; X } X while (ngets(buff,fp)) X fprintf(file,"%s\n",buff); X mclose(fp); X return 1; X} X X/******************************************************************************/ X/* WRITE TEXT IN BUFFER OUT TO A FILE */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_write(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X FILE *fp; X char buff[MAX_LINE_LENGTH]; X X /* PicoSpan puts spaces into the filename, we don't */ X if (argc!=2) { X printf("UNK Syntax: w filename\n"); X return 1; X } X X /* This is done inside the secure portion X * writing to the cf.buffer file, so is already secure X */ X printf("Writing %s\n",argv[1]); X if ((fp=mopen(argv[1],O_W))==NULL) { /* use normal umask */ X return 1; X } X fseek(file,0L,0); X while (ngets(buff,file)) X fprintf(fp,"%s\n",buff); X mclose(fp); X return 1; X} X X/******************************************************************************/ X/* DUMP TEXT IN BUFFER AND START OVER */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_clear(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X mclose(file); X printf("Enter your %s:\n",(oldmode==M_OK)? "text" : "response" ); X if (!cfbufr_open(O_WPLUS)) /* "w+" */ X mode = oldmode; /* abort */ X else X mode = M_TEXT; X return 1; X} X X/******************************************************************************/ X/* REPRINT CURRENT CONTENTS OF BUFFER */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_print(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X char buff[MAX_LINE_LENGTH]; X fseek(file,0L,0); X while (ngets(buff,file) && !(status & S_INT)) X printf(" %s\n",buff); X return 1; X} X X/******************************************************************************/ X/* INVOKE UNIX EDITOR ON THE BUFFER */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_edit(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X char buff[MAX_LINE_LENGTH]; X X mclose(file); X edit(work,"cf.buffer",(argv[0][0]=='v')); /* 'v_isual' check */ X printf("(Continue your %s entry)\n",(resp)? "response" : "text" ); X cfbufr_open(O_APLUS); /* a+ */ X return 1; X} X X/******************************************************************************/ X/* ABORT TEXT ENTRY MODE */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_abort(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X if (get_yes("Ok to abandon text? ")) X mode = oldmode; X return 1; X} X X/******************************************************************************/ X/* END TEXT ENTRY MODE AND POST IT */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xtext_done(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X /* Main EDB cmd loop */ X mode = M_EDB; X while (mode==M_EDB && get_command(NULL)); X return 1; X} X X/******************************************************************************/ X/* FIGURE OUT WHAT TO DO WHEN ESCAPING OUT OF TEXT MODE */ X/******************************************************************************/ Xchar Xedb_cmd_dispatch(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X /* Command dispatch */ X if (match(argv[0],"n_on") X || match(argv[0],"nop_e")) { X /* printf("Response aborted! Returning to current item.\n");*/ X mode = oldmode; X } else if (match(argv[0],"y_es") X || match(argv[0],"ok")) { post = 1; mode = oldmode; } X else if (match(argv[0],"ed_it")) text_edit(argc,argv); X else if (match(argv[0],"ag_ain") X || match(argv[0],"c_ontinue")) { X mode = M_TEXT; X printf("(Continue your text entry)\nType \".\" to exit or \":help\".\n"); X } else if (match(argv[0],"pr_int")) text_print(argc,argv); X else if (match(argv[0],"em_pty") X || match(argv[0],"cl_ear")) text_clear(argc,argv); X else return misc_cmd_dispatch(argc,argv); X return 1; X} END_OF_FILE if test 11292 -ne `wc -c <'edbuf.c'`; then echo shar: \"'edbuf.c'\" unpacked with wrong size! fi # end of 'edbuf.c' fi if test -f 'macro.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'macro.c'\" else echo shar: Extracting \"'macro.c'\" \(9096 characters\) sed "s/^X//" >'macro.c' <<'END_OF_FILE' X/* MACRO.C */ Xstatic char sccsid[] = "@(#)macro.c 1.19 93/06/07 Copyright (c)1993 thalerd"; X#include X#include X#include X#include X#include X#include "config.h" X#include "struct.h" X#include "globals.h" X#include "macro.h" X#include "lib.h" /* for ultrix where strdup() is defined */ X#include "xalloc.h" X Xstatic unsigned short num_macros=0; Xstatic macro_t macro[MAX_MACROS]; X Xchar * Xitostr(i) Xshort i; X{ Xstatic char buff[MAX_LINE_LENGTH]; X X sprintf(buff,"%d",i); X return buff; X} X X/******************************************************************************/ X/* EXPAND A MACRO */ X/* UNK Could put hashing in later to speed things up if needed */ X/******************************************************************************/ Xchar * /* RETURNS: string macro expands to */ Xexpand(mac,mask) /* ARGUMENTS: */ Xchar *mac; /* Macro name to expand */ Xunsigned short mask; /* Type of macro (see macro.h) */ X{ X unsigned short i; X X for (i=0; i=M_SUPERSANE) mask |= mode; X for (i=0; i'misc.c' <<'END_OF_FILE' X/* MISC.C */ Xstatic char sccsid[] = "@(#)misc.c 1.4 93/06/07 Copyright (c)1993 thalerd"; X#include X#include X#include X#include X#include X#ifndef NeXT X#include /* for X_OK */ X#endif X#include "config.h" X#include "struct.h" X#include "globals.h" X#include "misc.h" X#include "change.h" X#include "help.h" X#include "system.h" X#include "macro.h" X#include "range.h" X#include "item.h" X#include "sum.h" X#include "sep.h" X#include "files.h" X#include "arch.h" X#include "driver.h" /* for open_pipe */ X#include "lib.h" /* for noquote() */ X X/* Misc. commands available at all modes */ Xstatic dispatch_t misc_cmd[]={ X "c_hange", change, X "se_t", change, X "?", help, X "h_elp", help, X "exp_lain", help, X "al_ias", define, X "def_ine", define, X "una_lias", define, X "und_efine", define, X "ec_ho", echo, X "echoe", echo, X "echon", echo, X "echoen", echo, X "echone", echo, X "m_ail", mail, X "t_ransmit", mail, X "sen_dmail", mail, X "d_isplay", display, X "que_ry", display, X "sh_ow", display, X "t_est", test, X "cd", cd, X "chd_ir", cd, X "uma_sk", do_umask, X "cdate", date, X "da_te", date, X "clu_ster", cluster, X "cfdir", set_cfdir, X "eval_uate", eval, X "source", do_source, X/* ex_it q_uit st_op good_bye log_off log_out h_elp exp_lain sy_stem unix al_ias X * def_ine una_lias und_efine ec_ho echoe echon echoen echone so_urce m_ail X * t_ransmit sen_dmail chat write d_isplay que_ry p_articipants w_hoison X * am_superuser resign chd_ir uma_sk sh_ell f_iles dir_ectory ty_pe e_dit X * cdate da_te t_est clu_ster X */ X 0, 0 X}; X X/******************************************************************************/ X/* DISPATCH CONTROL TO APPROPRIATE MISC. COMMAND FUNCTION */ X/******************************************************************************/ Xchar /* RETURNS: 0 to quit, 1 else */ Xmisc_cmd_dispatch(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X int i; X X for (i=0; misc_cmd[i].name; i++) X if (match(argv[0],misc_cmd[i].name)) X return misc_cmd[i].func(argc,argv); X X /* Command dispatch */ X if (match(argv[0],"q_uit") X || match(argv[0],"st_op") X || match(argv[0],"ex_it")) { X status |= S_STOP; X return 0; X } else if (match(argv[0],"unix_cmd")) { X char buff[MAX_LINE_LENGTH],i; X if (argc<2) printf("syntax: unix_cmd \"command\"\n"); X else { X /* implode(buff,argv," ",1); */ X strcpy(buff,noquote(argv[1],0)); X for (i=2; i)? ",buff); X ngets(buff, st_glob.inp); X } X } X sprintf(buff,"%s/cf.buffer",work); X rm(buff,SL_USER); X } X return 1; X} X X/******************************************************************************/ X/* CHANGE CURRENT WORKING DIRECTORY */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xcd(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X if (argc>2) { X printf("Bad parameters near \"%s\"\n",argv[2]); X return 2; X } else if (chdir((argc>1)?argv[1]:home)) X error("cd'ing to ",argv[1]); X return 1; X} X X/******************************************************************************/ X/* ECHO ARGUMENTS TO OUTPUT */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xecho(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X short i; X FILE *fp; X X if (match(argv[0],"echoe") || match(argv[0],"echoen") X || match(argv[0],"echone")) X fp = stderr; X else { X open_pipe(); X fp = st_glob.outp; X if (!fp) fp = stdout; X } X X for (i=1; i1) /* Process argc */ X range(argc,argv,&fl,act,sum,&st_glob,0); X if (!(fl & OF_RANGE)) { X printf("Error, no item specified! (try HELP RANGE)\n"); X return 1; X } X X j = A_SKIP; X for (i=0; i1) /* Process argc */ X range(argc,argv,&st_glob.opt_flags,act,sum,&st_glob,0); X if (!st_glob.string[0]) { X printf("UNK usage: eval [range] \"string\"\n"); X return 1; X } X X open_pipe(); X if (!(st_glob.opt_flags & OF_RANGE)) { X X if (mode==M_OK || mode==M_SANE || mode==M_SUPERSANE) X confsep(st_glob.string,confidx,&st_glob,part,0); X else if (mode==M_RFP) X itemsep(st_glob.string,0); X else X printf("UNK bad mode\n"); X X } else { X X strcpy(buff,st_glob.string); X X if (mode==M_OK || mode==M_SANE || mode==M_SUPERSANE) { X X st_glob.string[0]='\0'; X if (st_glob.opt_flags & OF_REVERSE) { X i_s = st_glob.i_last; X i_i = -1; X } else { X i_s = st_glob.i_first; X i_i = 1; X } X X /* Process items */ X sepinit(IS_START); fp = NULL; X for (st_glob.i_current = i_s; X st_glob.i_current >= st_glob.i_first X && st_glob.i_current <= st_glob.i_last X && !(status & S_INT); X st_glob.i_current += i_i) { X if (cover(st_glob.i_current,confidx,st_glob.opt_flags, X act[st_glob.i_current-1],sum, part, &st_glob)) { X st_glob.r_first = rfirst; X itemsep(buff,0); X shown++; X } X } X if (!shown && (st_glob.opt_flags & (OF_BRANDNEW|OF_NEWRESP))) X wputs("No new items matched.\n"); X X } else if (mode==M_RFP) { X /* Open file */ X sprintf(buff,"%s/_%d",conflist[confidx].location,st_glob.i_current); X if (!(fp=mopen(buff,O_R))) return 1; X X i_lastseen = st_glob.i_current-1; X if (st_glob.opt_flags & (OF_NEWRESP|OF_NORESPONSE)) X st_glob.r_first = part[i_lastseen].nr; X else if (st_glob.since) { X st_glob.r_first=0; X while (st_glob.since > re[st_glob.r_first].date) { X st_glob.r_first++; X get_resp(fp,&(re[st_glob.r_first]),(short)GR_HEADER,st_glob.r_first); X if (st_glob.r_first>=sum[i_lastseen].nr) break; X } X } X st_glob.r_last = MAX_RESPONSES; X st_glob.r_max=sum[i_lastseen].nr-1; X X /* For each response */ X for (st_glob.r_current = st_glob.r_first; X st_glob.r_current<= st_glob.r_last X && st_glob.r_current<=st_glob.r_max X && !(status & S_INT); X st_glob.r_current++) { X get_resp(fp,&(re[st_glob.r_current]),(short)GR_HEADER,st_glob.r_current); X itemsep(st_glob.string,0); X } X X mclose(fp); X } else X printf("UNK bad mode\n"); X } X return 1; X} X X/* CHANGE CLUSTER */ Xint /* RETURNS: (nothing) */ Xcluster(argc,argv) /* ARGUMENTS: */ Xint argc; /* Number of arguments */ Xchar **argv; /* Argument list */ X{ X leave(0,(char**)0); X open_cluster(argv[1],HELPDIR); X return 1; X} END_OF_FILE if test 13253 -ne `wc -c <'misc.c'`; then echo shar: \"'misc.c'\" unpacked with wrong size! fi # end of 'misc.c' fi if test -f 'range.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'range.c'\" else echo shar: Extracting \"'range.c'\" \(12763 characters\) sed "s/^X//" >'range.c' <<'END_OF_FILE' X/* RANGE.C */ Xstatic char sccsid[] = "@(#)range.c 1.21 93/06/09 Copyright (c)1993 thalerd"; X#include X#include X#include X#include "config.h" X#include "struct.h" X#include "item.h" X#include "range.h" X#include "globals.h" X#include "dates.h" X#include "macro.h" X#include "lib.h" X#include "sum.h" X#include "stats.h" X#include "xalloc.h" /* for xfree */ X X/*****************************************************************************/ X/* TEST WHETHER ITEM IS COVERED BY THE SPECIFIED SUBSET PARAMETERS */ X/*****************************************************************************/ Xchar /* RETURNS: 1 if in subset, 0 else */ Xcover(i,idx,spec,act,sum,part,st) /* ARGUMENTS: */ Xshort i; /* Item number */ Xshort idx; Xshort spec; /* Specifiers */ Xshort act; /* Action flag */ Xsumentry_t *sum; /* Item summary */ Xpartentry_t *part; /* User participation info */ Xstatus_t *st; X{ X sumentry_t *s; X partentry_t *p; X X /* if (spec & OF_NONE) return 0; */ X if (act==A_SKIP) return 0; X refresh_sum(i,idx,sum,part,st); /* added for sno */ X s = &(sum[i-1]); X p = &(part[i-1]); X if (!s->flags) return 0; X if (st->string[0] && !strstr(get_subj(idx,i-1,sum),st->string)) X return 0; X if (st->author[0] && strcmp(get_auth(idx,i-1,sum),st->author)) X return 0; X if (st->since > s->last) return 0; X if (st->before < s->last && st->before>0) return 0; X if (st->rng_flags && !(s->flags & st->rng_flags)) return 0; X if (act==A_FORCE) return 1; /* force takes precedence over forgotten */ X/* Xif (s->flags & IF_FORGOTTEN) Xprintf("<%d:%d:%d:%d>",i,spec & (OF_NOFORGET|OF_FORGOTTEN|OF_RETIRED), X flags & O_FORGET, X s->flags & (IF_FORGOTTEN|IF_RETIRED)); X*/ X if (!(spec & (OF_NOFORGET|OF_FORGOTTEN)) && (flags & O_FORGET) X && (s->flags & IF_FORGOTTEN)) X return 0; X if (!(spec & (OF_NOFORGET|OF_RETIRED)) && (s->flags & IF_RETIRED)) X return 0; X if (!(spec & (OF_NOFORGET|OF_EXPIRED)) && (s->flags & IF_EXPIRED)) X return 0; X X /* Process NEW limitations */ X/* Changed per Russ's suggestion X if ((spec & OF_NEWRESP) && p->nr && (abs(p->nr) < s->nr)) return 1; X*/ X if ((spec & OF_NEWRESP) && p->nr && (p->last < s->last)) return 1; X if ((spec & OF_BRANDNEW) && (!p->nr && s->nr) X && (p->last < s->last)) return 1; X if (spec & (OF_NEWRESP|OF_BRANDNEW)) return 0; X if ((spec & OF_UNSEEN) && p->nr) return 0; X if ((spec & OF_FORGOTTEN) && !(s->flags & IF_FORGOTTEN)) return 0; X if ((spec & OF_RETIRED) && !(s->flags & IF_RETIRED)) return 0; X X /* if (spec & OF_NEXT) spec |= OF_NONE; */ X return 1; X} X X/*****************************************************************************/ X/* MARK A RANGE OF ITEMS TO BE ACTED UPON */ X/*****************************************************************************/ Xstatic void /* RETURNS: (nothing) */ Xmarkrange(bg,nd,act,sum,st,val) /* ARGUMENTS: */ Xshort bg; /* Beginning of range */ Xshort nd; /* End of range */ Xshort val; /* Action value to set */ Xchar act[MAX_ITEMS]; /* Action array to fill in */ Xsumentry_t sum[MAX_ITEMS]; /* Summary of item info */ Xstatus_t *st; /* Conference statistics */ X{ X short j; X X if (bgi_first) X printf("Item #%d is too small (first %d)\n",bg,st->i_first); X else if (nd>st->i_last) X printf("Item #%d is too big (last %d)\n",nd,st->i_last); X else { X for (j=bg; j<=nd; j++) X if (sum[j-1].flags) act[j-1]=val; X if (bg==nd && !sum[bg-1].flags) X printf("No such item!\n"); X } X} X X/*****************************************************************************/ X/* CONVERT A TOKEN TO AN INTEGER */ X/*****************************************************************************/ Xshort /* RETURNS: item number */ Xget_number(token,st) /* ARGUMENTS: */ Xchar *token; /* Field to process */ Xstatus_t *st; /* Conference statistics */ X{ X short a,b; X X if (match(token,"fi_rst") X || match(token,"^")) return st->i_first; X if (match(token,"l_ast") X || match(token,"$")) return st->i_last; X if (match(token,"th_is") X || match(token,"cu_rrent") X || match(token,".")) return st->i_current; X if (sscanf(token,"%hd.%hd",&a,&b)==2) { X if (b>=0 && br_first = b; X return a; X } X return atoi(token); X} X Xvoid Xrangearray(argv,argc,start,fl,act,sum,st) Xchar **argv; Xint argc,start; Xshort *fl; /* Flags to use */ Xchar act[MAX_ITEMS]; /* Action array to fill in */ Xsumentry_t sum[MAX_ITEMS]; /* Item summary info array */ Xstatus_t *st; /* Conference statistics */ X{ X short i; X X for (i=start; iauthor, argv[++i]); X } else if (!match(argv[i],"F=")) /* skip "F=" */ X rangetoken(argv[i],fl,act,sum,st); X } X} X X/*****************************************************************************/ X/* PARSE ONE FIELD OF A RANGE SPECIFICATION */ X/*****************************************************************************/ Xvoid /* RETURNS: (nothing) */ Xrangetoken(token,flg,act,sum,st) /* ARGUMENTS: */ Xchar *token; /* Field to process */ Xshort *flg; /* Flags to use */ Xchar act[MAX_ITEMS]; /* Action array to fill in */ Xsumentry_t sum[MAX_ITEMS]; /* Item summary info array */ Xstatus_t *st; /* Conference statistics */ X{ X short fl,a,b,c; X char buff[MAX_LINE_LENGTH],*bp,**arr; X X if (flags & O_DEBUG) X printf("rangetoken: '%s'\n",token); X if (bp=expand(token,DM_PARAM)) { X arr = explode(bp," "); X rangearray(arr,xsizeof(arr),0,flg,act,sum,st); X xfree(arr); X return; X } X fl = *flg; X X if (match(token,"a_ll") X || match(token,"*")) { X markrange(st->i_first, st->i_last,act,sum,st,A_COVER); X fl |= OF_RANGE; /* items specified */ X } else if (match(token,"nex_t")) { /* fl |= OF_NEXT; */ X markrange((short)(st->i_current+1),st->i_last,act,sum,st,A_COVER); X fl |= OF_RANGE; /* KKK */ X } else if (match(token,"pr_evious")) { fl |= /* OF_NEXT | */ OF_REVERSE; X markrange(st->i_first,(short)(st->i_current-1),act,sum,st,A_COVER); X fl |= OF_RANGE; /* KKK */ X } else if (match(token,"n_ew")) { fl |= OF_BRANDNEW | OF_NEWRESP; X } else if (match(token,"nof_orget")) { fl |= OF_NOFORGET; X } else if (match(token,"p_ass")) { fl |= OF_PASS; X } else if (match(token,"d_ate")) { fl |= OF_DATE; X } else if (match(token,"nor_esponse")) { fl |= OF_NORESPONSE; X } else if (match(token,"u_id")) { fl |= OF_UID; X } else if (match(token,"nod_ate")) { fl &= ~OF_DATE; X } else if (match(token,"nou_id")) { fl &= ~OF_UID; X } else if (match(token,"bra_ndnew")) { fl |= OF_BRANDNEW; X } else if (match(token,"newr_esponse")) { fl |= OF_NEWRESP; X } else if (match(token,"r_everse")) { fl |= OF_REVERSE; X } else if (match(token,"s_hort")) { fl |= OF_SHORT; X } else if (match(token,"nop_ass")) { fl &= ~OF_PASS; X } else if (match(token,"nu_mbered")) { fl |= OF_NUMBERED; X } else if (match(token,"nonu_mbered")) { fl &= ~OF_NUMBERED; X } else if (match(token,"unn_umbered")) { fl &= ~OF_NUMBERED; X } else if (match(token,"o_ld")) { /* KKK */ X } else if (match(token,"exp_ired")) { fl |= OF_EXPIRED; X } else if (match(token,"ret_ired")) { fl |= OF_RETIRED; X } else if (match(token,"for_gotten")) { fl |= OF_FORGOTTEN; X } else if (match(token,"un_seen")) { fl |= OF_UNSEEN; X } else if (match(token,"linked")) { st->rng_flags |= IF_LINKED; X } else if (match(token,"frozen")) { st->rng_flags |= IF_FROZEN; X } else if (match(token,"force_response") X || match(token,"force_respond")){ /* KKK */ X } else if (match(token,"respond")) { /* KKK */ X } else if (match(token,"form_feed") X || match(token,"ff")) { /* KKK */ X } else if (match(token,"lo_ng")) { fl &= ~OF_SHORT; X } else if (token[0]=='"') { /* "string" */ X strcpy(st->string,token+1); X st->string[ strlen(token)-2 ]='\0'; X } else if (strchr(token,',')) { X arr = explode(token,","); X rangearray(arr,xsizeof(arr),0,flg,act,sum,st); X xfree(arr); X return; X } else if (token[0]=='-') { X a = get_number(token+1,st); X markrange(st->i_first,a,act,sum,st,A_COVER); X fl |= OF_RANGE; /* range specified */ X } else if (token[strlen(token)-1]=='-') { X strcpy(buff,token); X buff[strlen(buff)-1]='\0'; X a = get_number(buff,st); X markrange(a,st->i_last,act,sum,st,A_COVER); X fl |= OF_RANGE; X } else if (bp=strchr(token,'-')) { X strncpy(buff,token,bp-token); X buff[bp-token]='\0'; X a = get_number(buff,st); X b = get_number(bp+1,st); X if (bi_first,a,act,sum,st,A_COVER); X fl |= OF_RANGE; X } else if (sscanf(token,"%hd-%hd",&a,&b)==2) { X if (bi_last,act,sum,st,A_COVER); X fl |= OF_RANGE; X } else if (sscanf(token,"%hd",&a)==1) { X markrange(a,a,act,sum,st,A_FORCE); X fl |= OF_RANGE; X*/ X } else if (a=get_number(token,st)) { X markrange(a,a,act,sum,st,A_FORCE); X fl |= OF_RANGE; X } else { X strcpy(st->string,token); X/* KKK printf("Bad token type in getrange\n"); */ X } X *flg = fl; X} X Xtime_t Xsince(argc,argv,ip) Xint argc; Xchar **argv; Xshort *ip; X{ X short i,j,start=0; X char buff[MAX_LINE_LENGTH],*ptr; X int where[MAX_ARGS]; X time_t t; X X i = *ip + 1; X if (i>=argc) { X printf("Bad date near \"\"\n"); X return LONG_MAX; /* process nothing */ X } X /* if (!strnicmp(argv[i],"S=",2) || !strnicmp(argv[i],"B=",2)) start+=2; */ X if (argv[i][start]=='"') { X if (argv[i][ strlen(argv[i])-1 ]=='"') X argv[i][ strlen(argv[i])-1 ]='\0'; X getdate(&t,argv[i]+start+1); X } else { X where[i]=0; X strcpy(buff,argv[i]+start); X for (j=i+1; j where[i] && istring[0]= st->author[0] = '\0'; X st->since = st->before = st->opt_flags = 0; X st->rng_flags = 0; X/* flags |= O_FORGET; commented out 8/18 since it breaks 'set noforget;r' */ X for (i=0; i'system.c' <<'END_OF_FILE' X/* SYSTEM.C - Dave Thaler 3/1/93 X * This file does secure replacements for popen and system calls X */ Xstatic char sccsid[] = "@(#)system.c 1.17 93/06/09 Copyright (c)1993 thalerd"; X#include X#include X#include X#include X#include X#include X/* X#include X#include X*/ X#include "config.h" X#include "struct.h" X#include "lib.h" X#include "xalloc.h" X#include "macro.h" X#include "globals.h" X#include "files.h" X X/******************************************************************************/ X/* SECURE popen() - OPEN A PIPE TO A PROCESS */ X/******************************************************************************/ XFILE * /* RETURNS: file pointer of pipe */ Xspopen(cmd) /* ARGUMENTS: */ Xchar *cmd; /* Command to pipe to */ X{ X int fd[2],s; X char **argv; X FILE *fp; X X if (status & S_REDIRECT) { X printf("UNK Error, pipe already open\n"); X } X X if (pipe(fd)<0) return NULL; X if ((fp=fdopen(fd[1],"w"))==NULL) return NULL; X X /* The following two lines are not necessary, and even slow the program X * down, but make seen be more accurate in some cases, since less info is X * buffered by the pager. X */ X/* fcntl(fd[1], F_SETFL, O_SYNC); X setsockopt(fd[1],SOL_SOCKET, SO_SNDBUF, 4, 1); X */ X X if (s=fork()) { /* parent */ X if (s<0) return NULL; /* error: couldn't fork */ X close(fd[0]); X status |= S_PIPE|S_REDIRECT; X madd(fd[1],cmd,O_PIPE); X return fp; X } else { /* child */ X setuid(getuid()); X setgid(getgid()); X signal(SIGINT,SIG_DFL); X signal(SIGPIPE,SIG_DFL); X close(0); X dup(fd[0]); X close(fd[1]); X X if (strpbrk(cmd,"<>*?|![]{}~`$&';\\\"") == NULL) { X argv = explode(cmd," "); X s = xsizeof(argv); X argv = xrealloc(argv, (short)(s+1)); X argv[s]=0; X execvp(argv[0],argv); X printf("oops: Can't execute \"%s\"!\n",cmd); X } else { X char *shpath,*sh; X X shpath = expand("shell",DM_VAR); X sh = strrchr(shpath,'/'); X if (!sh) sh = shpath; X else sh++; X execl(shpath,sh,"-c",cmd,(char *)NULL); X } X exit(1); X } X return NULL; X} X X/******************************************************************************/ X/* DUMP A STRING TO A SECURE PIPE */ X/******************************************************************************/ Xint /* RETURNS: # bytes written */ Xspout(fd,buff) /* ARGUMENTS: */ Xint fd; /* File descriptor of pipe */ Xchar *buff; /* String to dump */ X{ X return write(fd,buff,strlen(buff)); X} X X/******************************************************************************/ X/* CLOSE A SECURE PIPE */ X/******************************************************************************/ Xint /* RETURNS: error code */ Xspclose(pp) /* ARGUMENTS: */ XFILE *pp; /* File pointer to close */ X{ X int i; X int statusp; X X if (!(status & S_REDIRECT)) { X printf("UNK Error, pipe not open\n"); X } X X i=mclose(pp); X if (status & S_PIPE) X wait(&statusp); X status &= ~(S_PIPE|S_REDIRECT|S_INT); X return i; X} X X/******************************************************************************/ X/* SECURE system() - EXECUTE A UNIX COMMAND */ X/******************************************************************************/ Xint /* RETURNS: exit status of command */ Xunix_cmd(cmd) /* ARGUMENTS: */ Xchar *cmd; /* Command to execute */ X{ X char **argv; X short s; X register int cpid,wpid; X int statusp; X X if (cpid=fork()) { /* parent */ X if (cpid<0) return -1; /* error: couldn't fork */ X while ((wpid = wait(&statusp)) != cpid && wpid != -1); X } else { /* child */ X setuid(getuid()); X setgid(getgid()); X signal(SIGINT,SIG_DFL); X signal(SIGPIPE,SIG_DFL); X if (strpbrk(cmd,"<>*?|![]{}~`$&';\\\"") == NULL) { X argv = explode(cmd," "); X s = xsizeof(argv); X argv = xrealloc(argv, (short)(s+1)); X argv[s]=0; X execvp(argv[0],argv); X printf("oops: Can't execute \"%s\"!\n",cmd); X } else { X char *shpath,*sh; X X shpath = expand("shell",DM_VAR); X sh = strrchr(shpath,'/'); X if (!sh) sh = shpath; X else sh++; X execl(shpath,sh,"-c",cmd,(char *)NULL); X } X exit(1); X } X return statusp; X} X X/******************************************************************************/ X/* REMOVE A FILE */ X/******************************************************************************/ Xint /* RETURNS: error code */ Xrm(file,sec) /* ARGUMENTS: */ Xchar *file; Xint sec; /* As owner(0) or user(1)? */ X{ X int c; X register int cpid,wpid; X int statusp; X X if (!sec) { X statusp=unlink(file); X } else { X if (cpid=fork()) { /* parent */ X if (cpid<0) return -1; /* error: couldn't fork */ X while ((wpid = wait(&statusp)) != cpid && wpid != -1); X } else { /* child */ X setuid(getuid()); X setgid(getgid()); X exit(unlink(file)); X } X } X if (statusp) error("removing ",file); X return statusp; X} X X/******************************************************************************/ X/* SECURELY COPY ONE FILE TO ANOTHER */ X/******************************************************************************/ Xint /* RETURNS: error code */ Xcopy_file(src,dest,sec) /* ARGUMENTS: */ Xchar *src; /* Source file */ Xchar *dest; /* Destination file */ Xint sec; /* As owner(0) or user(1)? */ X{ X FILE *fsrc,*fdest; X int c; X register int cpid,wpid; X int statusp; X long mod; X X if (cpid=fork()) { /* parent */ X if (cpid<0) return -1; /* error: couldn't fork */ X while ((wpid = wait(&statusp)) != cpid && wpid != -1); X } else { /* child */ X X mod = O_W; X if (!sec && (st_glob.c_security & CT_BASIC)) mod |= O_PRIVATE; X X if (sec) { /* cfadm to user */ X if ((fsrc=mopen(src,O_R))==NULL) exit(1); X setuid(getuid()); X setgid(getgid()); X if ((fdest=mopen(dest,mod))==NULL) { X mclose(fsrc); X exit(1); X } X } else { /* user to cfadm */ X if ((fdest=mopen(dest,mod))==NULL) exit(1); X setuid(getuid()); X setgid(getgid()); X if ((fsrc=mopen(src,O_R))==NULL) { X mclose(fdest); X exit(1); X } X } X X while ((c=fgetc(fsrc))!=EOF) X fputc(c,fdest); X mclose(fdest); X mclose(fsrc); X exit(0); X } X return statusp; X} X X/******************************************************************************/ X/* INVOKE EDITOR ON A FILE */ X/******************************************************************************/ Xint /* RETURNS: (nothing) */ Xedit(dir,file,visual) /* ARGUMENTS: */ Xchar *dir; /* Directory containing file */ Xchar *file; /* Filename to edit */ Xint visual; /* Flag: visual editor? */ X{ X char buff[MAX_LINE_LENGTH]; X char buff2[MAX_LINE_LENGTH]; X char buff3[MAX_LINE_LENGTH]; X struct stat st; X X if (file) X sprintf(buff3,"%s/%s",dir,file); X else X strcpy(buff3,dir); X X if (status & S_MOTIF) X sprintf(buff2,"xterm -j -s -sb -sl 1024 -fn 9x15 -e "); X else X buff2[0]=0; X sprintf(buff,"%s%s %s", buff2, expand((visual)? "visual":"editor", DM_VAR), X buff3); X unix_cmd(buff); X return !stat(buff3,&st); X} END_OF_FILE if test 7865 -ne `wc -c <'system.c'`; then echo shar: \"'system.c'\" unpacked with wrong size! fi # end of 'system.c' fi echo shar: End of archive 2 \(of 5\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0