/******************************************************************** * $Author: lindner $ * $Revision: 1.10 $ * $Date: 1993/01/17 04:30:38 $ * $Source: /home/mudhoney/GopherSrc/gopher1.12/gopher/RCS/ourutils.c,v $ * $State: Rel $ * * Paul Lindner, University of Minnesota CIS. * * Copyright 1991, 1992 by the Regents of the University of Minnesota * see the file "Copyright" in the distribution for conditions of use. ********************************************************************* * MODULE: ourutils.c * stuff that doesn't really fit anywhere else. ********************************************************************* * Revision History: * $Log: ourutils.c,v $ * Revision 1.10 1993/01/17 04:30:38 lindner * VMSfile() truncates to a legal VMS filename length. * * Revision 1.9 1993/01/14 21:16:58 lindner * New routines to make nice filenames for Unix and VMS. * Add return to make screen look nice for VMS pagers. * * Revision 1.8 1993/01/12 21:45:17 lindner * Removed \n from system() calls. * Added filter to Save_file for directories and searches * * Revision 1.7 1993/01/12 18:19:32 lindner * Fixed Save_file call in display_file * * Revision 1.6 1993/01/09 01:37:32 lindner * Changed Save_file so that it takes a default filename. * Removed some dead code... * * Revision 1.5 1992/12/31 05:50:03 lindner * Added mods for VMS * * Revision 1.4 1992/12/11 21:19:51 lindner * Really fixed RealName this time.. Gotta test these things.. * * Revision 1.3 1992/12/11 20:59:48 lindner * Fixed problem with syntax error RealName, grrr * * Revision 1.2 1992/12/11 20:54:38 lindner * Mailing items with quotes in their name now works, added fflush(stdin) * everywhere to fix some input processing problems. * * Revision 1.1 1992/12/10 23:32:16 lindner * gopher 1.1 release * *********************************************************************/ #include "gopher.h" #ifndef VMS #include #endif #ifdef mips char *getenv(); #endif int outchar(c) char c; { /** output the given character. From tputs... **/ /** Note: this CANNOT be a macro! **/ putc(c, stdout); return(c); } display_image(Filename, Realname) char *Filename, *Realname; { char imagecmd[512]; strcpy(imagecmd, STRget(ImageCommand)); strcat(imagecmd, " "); strcat(imagecmd, Filename); CURexit(CursesScreen); system(imagecmd); CURenter(CursesScreen); printf("Press any key to return to gopher: "); fflush(stdin); fflush(stdout); getchar(); } display_mime(Filename, Realname) char *Filename, *Realname; { char metamailcmd[512]; strcpy(metamailcmd, STRget(MIMECommand)); strcat(metamailcmd, " "); strcat(metamailcmd, Filename); CURexit(CursesScreen); system(metamailcmd); CURenter(CursesScreen); printf("Press any key to return to gopher: "); fflush(stdin); fflush(stdout); getchar(); } /* ** This procedure sends a file through the mail. */ void mail_file(Filename, Realname) char *Filename, *Realname; { static char *SaveName = NULL; char command[512]; if (SaveName==NULL) { if ((SaveName = (char *) malloc(sizeof(char)*256)) == NULL) perror("Out of memory!"); *SaveName = '\0'; } if (CURGetOneOption(CursesScreen, "Mail current document to:", SaveName)<0) return; if (*SaveName == '\0') return; #define ACHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%.@!-_" if (SecureMode) if ( strspn(SaveName, ACHARS) != strlen(SaveName)) { puts(CURgetBell(CursesScreen)); fflush(stdout); Draw_Status("Address syntax rejected..."); refresh(); return; } if (strchr(Realname, '\"') != NULL) Realname = "Gopher File"; Draw_Status("Mailing File..."); refresh(); #ifdef VMS sprintf(command, "%s/subject=\"%s\" %s %s", STRget(MailCommand), Realname, Filename, SaveName); #else sprintf(command, "%s -s \"%s\" %s < %s", STRget(MailCommand), Realname, SaveName, Filename); #endif system(command); } /* * This fcn transfers a file from a gopher server into f. */ boolean GStoFile(gs, f) GopherObj *gs; FILE *f; { int numread, sockfd; boolean success = TRUE; char buf[1024]; int line = 0; if ((sockfd = GSconnect(gs)) <0) { check_sock(sockfd, GSgetHost(gs), GSgetPort(gs)); return(FALSE); } /** Send out the request **/ writestring(sockfd, GSgetPath(gs)); writestring(sockfd, "\r\n"); Draw_Status("Receiving file..."); refresh(); switch (GSgetType(gs)) { case A_FILE: case A_MACHEX: while (readline(sockfd, buf, sizeof(buf)) > 0) { ZapCRLF(buf); line ++; if (*buf == '.' && *(buf+1) == '\0') break; fputs(buf, f); putc('\n', f); if ((line % 25) == 0) twirl(); } break; case A_SOUND: case A_IMAGE: case A_GIF: case A_UNIXBIN: case A_PCBIN: while ((numread = readn(sockfd, buf, sizeof buf)) > 0) { if (fwrite(buf, numread, 1, f) == 0) { CursesErrorMsg("Problems Writing"); closenet(sockfd); return(FALSE); } twirl(); } break; } closenet(sockfd); return(TRUE); } /* * This function makes a nice vms filename. */ void VMSfile(fname) char *fname; { #ifndef VMS return; #else char *cp, *dot; int i, j; /**** Further tweek VMS names ****/ /*** Replace illegal characters with dashes ***/ for (cp = fname; *cp != '\0'; cp++) { switch (*cp) { case ':': case ',': case '\'': case '\"': case '/': case ' ': *cp = '-'; } } /** Replace all but last dot with _'s, or **/ /** second to last if last char is Z or z **/ /** e.g., converts foo.tar.Z to foo.tar_Z **/ dot = fname; j = strlen(fname) - 1; if ( (dot =strrchr(dot, '.')) != 0) { if (((fname[j] != '.') && (*(dot+1) == 'Z' || *(dot+1) == 'z')) && (((cp =strchr(fname, '.')) != NULL) && cp < dot)) { *dot = '_'; dot = strrchr(fname, '.'); } cp = fname; while ((cp =strchr(cp, '.')) != NULL && cp < dot) { *cp = '_'; } } /** If the filename is longer than 39 characters, truncate, keep the extension though.. **/ if ((j=strlen(fname)) > 37) { fname[39] = '\0'; } /** If there isn't an extension, add a '.', assume we have some space to *$^%& around with **/ if (strrchr(fname, '.') == NULL) { cp = fname +strlen(fname); *cp = '.'; *(cp+1) = '\0'; } #endif } void UNIXfile(fname) char *fname; { char *cp; for (cp = fname; *cp != '\0'; cp++) { switch (*cp) { case '\'': case '\"': case '/': case ' ': *cp = '-'; } } } /* * This procedure prompts the user for a name, checks for pipe characters * and ~ characters in the filename and saves the file to disk. * * If infile is NULL then contact the server and get the file. * * If saveto is non-NULL then don't prompt the user for a filename * to save into, just "do it". */ void Save_file(gs, infile, saveto) GopherObj *gs; char *infile; char *saveto; { char Userfilename[128]; char *cp; int sockfd; char buf[1024]; boolean Openpipe = FALSE; FILE *f; switch (GSgetType(gs)) { case A_DIRECTORY: case A_INDEX: if (infile == NULL) return; } /*** Construct a nice default filename ***/ if (saveto == NULL) { /*** Let them use the Title ***/ strcpy(Userfilename, GSgetTitle(gs)); #ifdef VMS VMSfile(Userfilename); #else UNIXfile(Userfilename); #endif if (CURGetOneOption(CursesScreen, "Save in file: ", Userfilename)<0) return; saveto = Userfilename; } if (*saveto == '\0') return; #ifndef VMS if (*saveto == '|') { /** Open a pipe! **/ Openpipe = TRUE; saveto++; } if (*saveto == '~') { /*** Save in our home directory ***/ if (*(saveto + 1) == '/' && (cp = getenv("HOME")) != NULL) { /*** Expand ~ to the home directory ***/ strcpy(buf,cp); buf[strlen(cp)]='/'; strcpy(buf+strlen(cp) +1, saveto+2); strcpy(saveto, buf); } else { /*** Save in someone else's home directory ***/ struct passwd *pass; cp = strchr(saveto,'/'); *cp = '\0'; pass = getpwnam(saveto+1); if (pass != NULL) { /** align in prep for the home dir **/ strcpy(buf,pass->pw_dir); buf[strlen(pass->pw_dir)]='/'; strcpy(buf+strlen(pass->pw_dir)+1,cp+1); strcpy(saveto,buf); } else { char tmpstr[256]; sprintf(tmpstr, "No such user '%s'", saveto+1); CursesErrorMsg(tmpstr); return; } } } #endif if (Openpipe) f = popen(saveto, "w+"); else f = fopen(saveto, "w+"); if (f == NULL) { char tempstr[128]; sprintf(tempstr, "Couldn't create '%s'", saveto); /** Should give better error messages here **/ CursesErrorMsg(tempstr); return; } if (infile != NULL) { /** We've already retrieved it, copy it over... **/ int oldfd, cc; oldfd = open(infile, O_RDONLY); if (oldfd <0) { CursesErrorMsg("Can't open old file.."); if (Openpipe) pclose(f); else fclose(f); return; } while ( (cc=read(oldfd, buf, sizeof buf)) > 0) { if (fwrite(buf, cc, 1, f) <= 0) CursesErrorMsg("Problems Writing"); twirl(); } if (Openpipe) pclose(f); else fclose(f); close(oldfd); return; } else { /** We don't have the file yet, let's get it... **/ GStoFile(gs, f); if (Openpipe) pclose(f); else fclose(f); } } /* ** This procedure exits out of the curses environment and ** displays the file indicated by pathname to the screen ** using a pager command of some sort */ void display_file(Filename,gs) char *Filename; GopherObj *gs; { static char command[MAXSTR]; static char SaveName[MAXSTR]; int ch; int c; strcpy(command, STRget(PagerCommand)); CURexit(CursesScreen); /** Execute the PAGER command **/ strcat(command, " "); strcat(command, Filename); if (strcmp(STRget(PagerCommand), "builtin") != 0) system(command); else Ourpager(Filename); printf("\nPress to continue"); if (!SecureMode) printf(", to mail, to save, or

to print:"); else printf(", to mail:"); fflush(stdin); fflush(stdout); noecho(); cbreak(); #ifdef mips raw(); #endif ch = 0; while (ch == 0) { ch=getchar(); if (SecureMode) { switch (ch) { case '\n': case '\r': case KEY_ENTER: case ' ': break; case 'm': #ifdef VMS (void) getchar(); #endif CURenter(CursesScreen); mail_file(Filename, GSgetTitle(gs)); break; default: puts(CURgetBell(CursesScreen)); fflush(stdout); ch=0; break; } } else { switch(ch) { case '\n': case '\r': case ' ' : break; case 's': #ifdef VMS (void) getchar(); #endif CURenter(CursesScreen); Draw_Status("Saving File..."); refresh(); Save_file(gs, Filename,NULL); break; case 'p': #ifdef VMS (void) getchar(); #endif sprintf(command, "%s %s", STRget(PrinterCommand), Filename); system(command); break; case 'm': #ifdef VMS (void) getchar(); #endif CURenter(CursesScreen); mail_file(Filename, GSgetTitle(gs)); break; default: puts(CURgetBell(CursesScreen)); fflush(stdout); ch=0; break; } } } tputs(CURgetCLS(CursesScreen),1,outchar); fflush(stdout); } /* ** This mini pager is intended for people worried about shell escapes from ** more or less or whatever */ /*Ourpager(filename) char *filename; { FILE *InFile; int i; char inputline[512], *cp; int Done = FALSE; char ZeTypedChar; if ((InFile = fopen(filename, "r")) == NULL) return; while (Done == FALSE) { tputs(CURgetCLS(CursesScreen),1,outchar); for (i=0 ; i < LINES-1; i++) { cp = fgets(inputline, 512, InFile); ZapCRLF(inputline); puts(inputline); } printf("----Press for next page, q to exit------"); cbreak(); ZeTypedChar = getchar(); if ((ZeTypedChar == 'q') || (cp == NULL)) { printf("\n"); Done = TRUE; } } cbreak(); fclose(InFile); } */ /* * This allows the user to add or change data in a form. * * It returns true if the user wants to keep the changes * It returns false if the user wants to abort * */ BOOLEAN NewForm(ZeForm) Form *ZeForm; { static char printstring[WHOLELINE]; int i; /** Acme Buggy whips and integers **/ char ch; while (1) { DisplayForm(ZeForm); sprintf(printstring, "Press to accept fields and continue"); CURcenterline(CursesScreen,"Press to accept fields and continue", LINES-3); CURcenterline(CursesScreen,"or press to abort", LINES-2); refresh(); /*** Now get some user input ***/ for (i=0; i< ZeForm->numfields; i++) { move(ZeForm->yloc[i],ZeForm->xloc[i] + strlen(ZeForm->tags[i])+2); refresh(); echo(); ch = CURwgetstr(CursesScreen, stdscr, ZeForm->values[i],80); /*** ESC key ***/ if (ch == '\033') { noecho(); return(TRUE); } /*** CTRL-A ***/ else if (ch == '\001') { noecho(); return(FALSE); } noecho(); } } } /* * This Displays a form and a "menu". It displays the Form * and then it waits for a keypress. It returns the value of the * key that is pressed. */ void DisplayForm(ZeForm) Form *ZeForm; { int availlines; int optionlen; int i; /** Acme Buggy whips and integers **/ clear(); Draw_Banner(); CURcenterline(CursesScreen, ZeForm->Title, 2); availlines = LINES - 6; /*** Print out the options according to the Form structure ***/ for (i=0; inumfields; i++) { optionlen = strlen((ZeForm->tags)[i]); mvaddstr(ZeForm->yloc[i],ZeForm->xloc[i], ZeForm->tags[i]); addch(':'); addch(' '); /*** Now add the current value ***/ addstr((ZeForm->values)[i]); } } void CursesMsg(Message, title) char *Message; char *title; { char *mess[2]; mess[0] = Message; mess[1] = NULL; CURBeep(CursesScreen); CURDialog(CursesScreen, title,mess); return; } void CursesErrorMsg(Message) char *Message; { CursesMsg(Message, "Gopher Error"); }