/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available Software. */ /* \ 1011 / */ /* ------ */ /* */ /* (C) Copyright 1987-90, Bit Bucket Software Co., a Delaware Corporation. */ /* */ /* */ /* This module was written by Vince Perriello */ /* */ /* */ /* BinkleyTerm Configuration File Parser */ /* */ /* */ /* For complete details of the licensing restrictions, please refer */ /* to the License agreement, which is published in its entirety in */ /* the MAKEFILE and BT.C, and also contained in the file LICENSE.240. */ /* */ /* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */ /* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */ /* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */ /* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */ /* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */ /* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */ /* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */ /* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */ /* */ /* */ /* You can contact Bit Bucket Software Co. at any one of the following */ /* addresses: */ /* */ /* Bit Bucket Software Co. FidoNet 1:104/501, 1:132/491, 1:141/491 */ /* P.O. Box 460398 AlterNet 7:491/0 */ /* Aurora, CO 80046 BBS-Net 86:2030/1 */ /* Internet f491.n132.z1.fidonet.org */ /* */ /* Please feel free to contact us at any time to share your comments about */ /* our software and/or licensing policies. */ /* */ /*--------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #ifdef OS_2 #define INCL_DOS #include #endif #ifdef __TURBOC__ #include #include #else #include #endif #include "com.h" #include "xfer.h" #include "zmodem.h" #include "keybd.h" #include "sbuf.h" #include "sched.h" #include "externs.h" #include "prototyp.h" static char *ctl_slash_string (char *); static int Zone = 1; void parse_config (config_file) char *config_file; { FILE *stream; char temp[256]; #ifdef Snoop char temp2[80]; #endif char *c; int i; unsigned temp_num; char *p, *p1, *p2; PN_TRNS *tpn; MDM_TRNS *tmm; J_TYPES *tjt; (void) sprintf (temp, "%s%s", BINKpath, config_file); if ((stream = fopen (temp, "rt")) == NULL) /* OK, let's open the file */ return; /* no file, no work to do */ while ((fgets (temp, 255, stream)) != NULL) /* Now we parse the file ... */ { c = temp; /* Check out the first char */ if ((*c == '%') || (*c == ';')) /* See if it's a comment * line */ continue; i = (int) strlen (temp); /* how long this line is */ if (i < 3) continue; /* If too short, ignore it */ c = &temp[--i]; /* point at last character */ if (*c == '\n') /* if it's a newline, */ *c = '\0'; /* strip it off */ switch (parse (temp, config_lines)) { case 1: /* "SameRing" */ modemring = 1; break; case 2: /* "NewNodeList" */ newnodelist = 1; break; case 3: /* "QuickNodeList" */ nodefunc = QuickLookup; break; case 4: /* "Answerback" */ answerback = ctl_string (&temp[10]); break; case 5: /* "Macro" */ c = skip_blanks (&temp[5]); i = atoi (c); if ((i <= 0) || (i > 9)) { (void) printf ("%s %d %s\n", msgtxt[M_MACRO_NUMBER], i, msgtxt[M_OUT_OF_RANGE]); break; } c = skip_to_blank (c); c = skip_blanks (c); keys[i - 1] = malloc (strlen (c) + 1); p = keys[i - 1]; while (*c && (*c != '\n')) { if (*c == '|') *p++ = '\r'; else *p++ = *c; ++c; } *p = '\0'; break; case 6: /* "Shell" */ c = skip_blanks (&temp[5]); i = atoi (c); if ((i <= 0) || (i > 9)) { (void) printf ("%s %d %s\n", msgtxt[M_SHELL_NUMBER], i, msgtxt[M_OUT_OF_RANGE]); break; } c = skip_to_blank (c); c = skip_blanks (c); shells[i - 1] = malloc (strlen (c) + 1); (void) strcpy (shells[i - 1], c); (void) strupr (shells[i - 1]); break; case 7: /* "Dial" */ p = &temp[4]; while ((*p) && (isspace (*p))) ++p; if ((*p == ';') || (*p == '\0')) { break; } tpn = (PN_TRNS *) malloc (sizeof (PN_TRNS)); p1 = tpn->num; while ((*p) && (!isspace (*p))) { *p1++ = *p++; } *p1 = '\0'; while ((*p) && (isspace (*p))) { ++p; } p1 = tpn->pre; while ((*p) && (*p != '/') && (!isspace (*p))) { *p1++ = *p++; } *p1 = '\0'; p1 = tpn->suf; if ((*p == '\0') || (isspace (*p))) { *p1 = '\0'; } else { ++p; while ((*p) && (!isspace (*p))) { *p1++ = *p++; } *p1 = '\0'; } tpn->len = (int) strlen (tpn->num); tpn->next = NULL; if (pn_head == NULL) { pn_head = tpn; } else { pn->next = tpn; } pn = tpn; break; case 8: /* "Event" */ c = skip_blanks (&temp[5]); (void) parse_event (c); break; case 9: /* "Zone" */ c = skip_blanks (&temp[4]); Zone = atoi (c); if (!Zone) /* if we didn't find a zone */ (void) printf (msgtxt[M_ILLEGAL_ZONE], &temp[4]); break; case 10: /* "MaxReq" */ c = skip_blanks (&temp[6]); DEFAULT.rq_Limit = atoi (c); if (!DEFAULT.rq_Limit) /* No requests??? */ (void) printf ("0 %s\n", msgtxt[M_REQUESTS_ALLOWED]); break; case 11: /* "LogLevel" */ c = skip_blanks (&temp[8]); i = atoi (c); if ((i <= 5) && (i > 0)) { loglevel = i; } else { (void) printf (msgtxt[M_BAD_LOGLEVEL], &temp[8]); } break; case 12: /* "Baud" */ temp_num = (unsigned int) atoi (&temp[4]); max_baud.rate_value = 0; for (i = 0; btypes[i].rate_value; i++) { if (btypes[i].rate_value == temp_num) { max_baud.rate_mask = btypes[i].rate_mask; max_baud.rate_value = temp_num; break; } } if (!max_baud.rate_value) goto bad_line; break; case 13: /* "MaxPort" */ c = skip_blanks (&temp[7]); i = atoi (c); /* make it binary */ if ((i > 0) && (i < 33)) /* if range is reasonable, */ MAXport = i; /* Make it the max value */ else (void) printf (msgtxt[M_BAD_MAXPORT], &temp[7]); break; case 14: /* "Port" */ c = skip_blanks (&temp[4]); i = atoi (c); /* make it binary */ if ((i > 0) || (i < 33)) /* see if it's OK */ { port_ptr = i - 1; /* store it if so */ if (MAXport < i) /* See if MAXport is less */ MAXport = i; /* If so, increase MAXport */ original_port = port_ptr; } else (void) printf (msgtxt[M_ILLEGAL_PORT], &temp[4]); break; case 15: /* "Carrier" */ c = skip_blanks (&temp[7]); i = 0; (void) sscanf (c, "%x", &i); /* convert it to binary */ if (i != 0) /* if we got anything */ carrier_mask = (unsigned int) i; else (void) printf (msgtxt[M_ILLEGAL_CARRIER], &temp[7]); break; case 16: /* "StatusLog" */ log_name = ctl_string (&temp[9]); if ((status_log = fopen (log_name, "at")) == NULL) { free (log_name); log_name = NULL; } else { (void) fprintf (status_log, "\n"); (void) fflush (status_log); (void) real_flush (fileno (status_log)); } break; case 17: /* "Reader" */ BBSreader = ctl_string (&temp[6]); break; case 18: /* "BossPhone" */ BOSSphone = ctl_string (&temp[9]); break; case 19: /* "BossPwd" */ BOSSpwd = ctl_string (&temp[7]); break; case 20: /* "Protocol" */ if (extern_index == 5) break; protocols[extern_index++] = ctl_string (&temp[8]); break; case 21: /* "System" */ system_name = ctl_string (&temp[6]); break; case 22: /* "Sysop" */ sysop = ctl_string (&temp[5]); break; case 23: /* "Boss" */ c = skip_blanks (&temp[4]); (void) parse_address (c, &boss_addr); break; case 24: /* "Point" */ i = 5; goto address; case 25: /* "Aka" */ i = 3; goto address; case 94: /* "Address" */ i = 7; address: c = skip_blanks (&temp[i]); if (num_addrs == 0) alias[0].Zone = Zone; (void) parse_address (c, &(alias[num_addrs])); Zone = (int) alias[0].Zone; /* First is real default */ ++num_addrs; break; case 26: /* "Hold" */ hold_area = ctl_slash_string (&temp[4]); domain_area = strdup (hold_area); domain_area[strlen (domain_area) - 1] = '\0'; p = strrchr (domain_area, '\\'); if (p == NULL) { p = strrchr (domain_area, '/'); if (p == NULL) { p = strrchr (domain_area, ':'); if (p == NULL) p = domain_area; } } if (p != domain_area) ++p; domain_loc = p; *p = '\0'; break; case 27: /* "DownLoads" */ download_path = ctl_slash_string (&temp[9]); break; case 28: /* "NetFile" */ DEFAULT.sc_Inbound = ctl_slash_string (&temp[7]); break; case 29: /* "Init" */ modem_init = ctl_string (&temp[4]); break; case 30: /* "Busy" */ modem_busy = ctl_string (&temp[4]); break; case 31: /* "Prefix" */ predial = ctl_string (&temp[6]); normprefix = predial; break; case 32: /* "NodeList" */ net_info = ctl_slash_string (&temp[8]); break; case 33: /* "Avail" */ DEFAULT.rq_FILES = ctl_string (&temp[5]); break; case 34: /* "OKFile" */ DEFAULT.rq_OKFile = ctl_string (&temp[6]); break; case 35: /* "About" */ DEFAULT.rq_About = ctl_string (&temp[5]); break; case 36: /* "MAILnote" */ MAILnote = ctl_string (&temp[8]); break; case 37: /* "Banner" */ BBSbanner = ctl_string (&temp[6]); break; case 38: /* "UnAttended" */ un_attended = 1; command_line_un = 1; break; case 39: /* "OverWrite" */ overwrite = 1; break; case 40: /* "Rev3" */ rev3 = 1; break; case 41: /* "ReqOnUs" */ on_our_nickel = 1; break; case 42: /* "LockBaud" */ c = skip_blanks (&temp[8]); /* Skip to baud */ if (*c) lock_baud = (unsigned) (atoi (c)); if (!lock_baud) /* If none, */ lock_baud = 1; /* Use a small no.*/ break; case 43: /* "TimeOut" */ c = skip_blanks (&temp[7]); BBStimeout = (unsigned) (atoi (c) * 100); if (BBStimeout < 2000) BBStimeout = 2000; break; case 44: /* "NoSLO" */ no_overdrive = 1; break; case 45: /* "SlowModem" */ slowmodem = 1; break; case 46: /* "SmallWindow" */ small_window = 1; break; case 47: /* "NoPickup" */ no_pickup = 1; break; case 48: /* "NoRequests" */ no_requests = 1; break; case 49: /* "NetMail" */ break; /* for BTCTL & MAIL.SYS */ case 50: /* "Suffix" */ postdial = ctl_string (&temp[6]); normsuffix = postdial; break; case 51: /* "NoFullScreen" */ fullscreen = 0; break; case 52: /* "AutoBaud" */ autobaud = 1; break; case 53: /* "Gong" */ gong_allowed = 1; break; case 54: /* "NoCollide" */ no_collide = 1; break; case 55: /* "TBBSlist" */ nodefunc = TBBSLookup; break; case 56: /* "TaskView" */ case 57: /* "TopView" */ have_tv = 1; break; case 58: /* "ExtrnMail" */ c = skip_blanks (&temp[9]); if (isdigit (*c)) { lev_ext_mail[num_ext_mail] = atoi (c); while ((*c) && (!isspace (*c))) ++c; } else { lev_ext_mail[num_ext_mail] = 99; } ext_mail_string[num_ext_mail++] = ctl_string (c); break; case 59: /* "BBSnote" */ BBSnote = ctl_string (&temp[7]); break; case 60: /* "BBS" */ BBSopt = ctl_string (&temp[3]); break; case 61: /* "ScriptPath" */ script_path = ctl_slash_string (&temp[10]); break; case 62: /* "BoxType" */ c = skip_blanks (&temp[7]); boxtype = atoi (c); if ((boxtype > 4) || (boxtype < 0)) boxtype = 1; break; case 63: /* "MultiLink" */ have_ml = 1; break; case 64: /* "Include" */ c = skip_blanks (&temp[7]); parse_config (c); break; case 65: /* "CaptureFile" */ logptr = ctl_string (&temp[11]); break; case 66: /* "CursorCol" */ c = skip_blanks (&temp[9]); cursor_col = atoi (c) - 1; if ((cursor_col < 0) || (cursor_col > 79)) cursor_col = 79; break; case 67: /* "CursorRow" */ c = skip_blanks (&temp[9]); cursor_row = atoi (c) - 1; if ((cursor_row < 0) || (cursor_row > 23)) cursor_row = 22; break; case 68: /* "DoingMail" */ c = skip_blanks (&temp[9]); (void) sprintf (junk, "\r\r%s\r\r", c); noBBS = malloc (strlen (junk) + 1); (void) strcpy (noBBS, junk); break; case 69: /* "EnterBBS" */ c = skip_blanks (&temp[8]); (void) sprintf (junk, "\r%s\r", c); BBSesc = malloc (strlen (junk) + 1); (void) strcpy (BBSesc, junk); break; case 70: /* "PrivateNet" */ c = skip_blanks (&temp[10]); pvtnet = atoi (c); break; case 71: /* "Packer" */ packer = ctl_string (&temp[6]); break; case 72: /* "Cleanup" */ cleanup = ctl_string (&temp[7]); break; case 73: /* "AfterMail" */ aftermail = ctl_string (&temp[9]); break; case 74: /* "Colors" */ c = skip_blanks (&temp[6]); colors.background = (unsigned char) (atoi (c) & 0xff); c = skip_to_blank (c); colors.settings = (unsigned char) (atoi (c) & 0xff); c = skip_blanks (c); c = skip_to_blank (c); colors.history = (unsigned char) (atoi (c) & 0xff); c = skip_blanks (c); c = skip_to_blank (c); colors.hold = (unsigned char) (atoi (c) & 0xff); c = skip_blanks (c); c = skip_to_blank (c); colors.call = (unsigned char) (atoi (c) & 0xff); c = skip_blanks (c); c = skip_to_blank (c); colors.file = (unsigned char) (atoi (c) & 0xff); c = skip_blanks (c); c = skip_to_blank (c); colors.calling = (unsigned char) (atoi (c) & 0xff); c = skip_blanks (c); c = skip_to_blank (c); colors.popup = (unsigned char) (atoi (c) & 0xff); break; case 75: /* "JanusBaud" */ c = skip_blanks (&temp[9]); janus_baud = (unsigned) atoi(c); break; case 76: /* "ReqTemplate" */ DEFAULT.rq_Template = ctl_string (&temp[11]); break; case 77: /* "KnownAvail" */ KNOWN.rq_FILES = ctl_string(&temp[10]); break; case 78: /* "KnownReqList" */ KNOWN.rq_OKFile = ctl_string(&temp[12]); break; case 79: /* "KnownAbout" */ KNOWN.rq_About = ctl_string (&temp[10]); break; case 80: /* "KnownInbound" */ KNOWN.sc_Inbound = ctl_slash_string (&temp[12]); break; case 81: /* "KnownReqLim" */ c = skip_blanks (&temp[11]); KNOWN.rq_Limit = atoi (c); break; case 82: /* "KnownReqTpl" */ KNOWN.rq_Template = ctl_string (&temp[11]); break; case 83: /* "ProtAvail" */ PROT.rq_FILES = ctl_string(&temp[9]); break; case 84: /* "ProtReqList" */ PROT.rq_OKFile = ctl_string(&temp[11]); break; case 85: /* "ProtAbout" */ PROT.rq_About = ctl_string (&temp[9]); break; case 86: /* "ProtInbound" */ PROT.sc_Inbound = ctl_slash_string (&temp[11]); break; case 87: /* "ProtReqLim" */ c = skip_blanks (&temp[10]); PROT.rq_Limit = atoi (c); break; case 88: /* "ProtReqTpl" */ PROT.rq_Template = ctl_string (&temp[10]); break; case 89: /* "Application" */ break; case 90: /* "NoZones" */ no_zones = 1; break; case 91: /* "Answer" */ ans_str = ctl_string (&temp[6]); break; case 92: /* "PollTries" */ c = skip_blanks (&temp[9]); poll_tries = atoi (c); break; case 93: /* "SwapDir" */ c = skip_blanks (&temp[7]); i = (int) strlen (c); swapdir = malloc ((unsigned int) (i + 15)); (void) strcpy (swapdir, c); (void) add_backslash (swapdir); (void) strcat (swapdir, "BTXXXXXX"); (void) mktemp (swapdir); break; case 95: /* "Curmudgeon" */ ++curmudgeon; /* Do it like Randy */ break; case 96: /* "NoWaZOO" */ ++no_WaZOO; /* FTSC sessions */ break; case 97: /* "ScreenBlank" */ do_screen_blank = 1; p = skip_blanks (&temp[11]); if (strnicmp (p, msgtxt[M_KEY], 3) == 0) { blank_on_key = 1; } else if (strnicmp (p, msgtxt[M_CALL], 4) == 0) { blank_on_key = 0; } break; case 98: /* "Mark_Kromm" */ /* These colors from Mark Kromm, Fidonet 1:261/1034 */ colors.background = 112; /* The */ colors.settings = 9; /* Great */ colors.history = 10; /* BinkleyTerm */ colors.hold = 11; /* Colors */ colors.call = 14; /* Contest */ colors.file = 12; /* Winner!!!! */ colors.calling = 56; colors.popup = 15; break; case 99: /* "Server" */ server_mode = 1; break; case 100: /* "ModemTrans" */ p = &temp[10]; while ((*p) && (isspace (*p))) ++p; if ((*p == ';') || (*p == '\0')) { break; } tmm = (MDM_TRNS *) malloc (sizeof (MDM_TRNS)); tmm->mdm = (byte) atoi (p); while ((*p) && (!isspace (*p))) { p++; } while ((*p) && (isspace (*p))) { ++p; } p1 = tmm->pre; while ((*p) && (*p != '/') && (!isspace (*p))) { *p1++ = *p++; } *p1 = '\0'; p1 = tmm->suf; if ((*p == '\0') || (isspace (*p))) { *p1 = '\0'; } else { ++p; while ((*p) && (!isspace (*p))) { *p1++ = *p++; } *p1 = '\0'; } tmm->next = NULL; if (mm_head == NULL) { mm_head = tmm; } else { mm->next = tmm; } mm = tmm; break; case 101: /* "PreDial" */ dial_setup = ctl_string (&temp[7]); break; case 102: /* "PreInit" */ init_setup = ctl_string (&temp[7]); break; case 103: /* "DTRHigh" */ leave_dtr_high = 1; break; case 104: /* "Debug" */ debugging_log = !debugging_log; break; case 105: /* "NoZedZap" */ no_zapzed = !no_zapzed; break; case 106: /* "NoResync" */ no_resync = !no_resync; break; case 107: /* "NoSEAlink" */ no_sealink = !no_sealink; break; case 108: /* "FTS-0001" */ no_sealink = 1; no_resync = 1; no_overdrive = 1; ++no_WaZOO; /* FTSC sessions */ break; case 109: /* "LineUpdate" */ immed_update = !immed_update; break; case 110: /* "JanusOK" */ p = &temp[7]; while ((*p) && (isspace (*p))) ++p; if ((*p == ';') || (*p == '\0')) { break; } tjt = (J_TYPES *) malloc (sizeof (J_TYPES)); p1 = tjt->j_match; while ((*p) && (!isspace (*p))) { *p1++ = *p++; } *p1 = '\0'; tjt->next = NULL; if (j_top == NULL) { j_top = tjt; } else { j_next->next = tjt; } j_next = tjt; break; case 111: /* "TermInit" */ term_init = ctl_string (&temp[8]); break; case 112: /* "Domain" */ p = skip_blanks (&temp[6]); p = strtok (p, "; \t\r\n"); if (p != NULL) { /* Have the domain name, now get the abbreviated name */ p2 = strtok (NULL, "; \t\r\n"); if (strlen (p2) > 8) *(p2 + 8) = '\0'; if (p2 != NULL) { /* Have the domain name and abbreviated, now get the list name */ p1 = strtok (NULL, "; \t\r\n"); if (p1 == NULL) p1 = p2; /* Have the list name and the domain name, now use them */ for (i = 0; domain_name[i] != NULL; i++) { if (strnicmp (domain_name[i], p, strlen (domain_name[i])) == 0) { domain_nodelist[i] = strdup (p1); domain_abbrev[i] = strdup (p2); break; } } if ((domain_name[i] == NULL) && (i < 49)) { domain_name[i] = strdup (p); domain_abbrev[i] = strdup (p2); domain_nodelist[i] = strdup (p1); } } } break; case 113: /* "Snoop" */ #ifdef Snoop if (getenv("SNOOPPIPE") == NULL) { snoop_open(skip_blanks(&temp[5])); strcpy(temp2, "SNOOPPIPE="); strcat(temp2, skip_blanks(&temp[5])); putenv(strdup(temp2)); } else snoop_open(getenv("SNOOPPIPE")); #endif /* Snoop */ break; case 114: /* "Flags" */ flag_dir = ctl_slash_string (&temp[5]); break; case 115: /* "Tasknumber" */ c = skip_blanks (&temp[10]); TaskNumber = atoi (c); break; case 116: /* "MaxBytes" */ c = skip_blanks (&temp[8]); DEFAULT.byte_Limit = atol (c); break; case 117: /* "KnownMaxBytes"*/ c = skip_blanks (&temp[13]); KNOWN.byte_Limit = atol (c); break; case 118: /* "ProtMaxBytes" */ c = skip_blanks (&temp[12]); PROT.byte_Limit = atol (c); break; bad_line: default: (void) printf (msgtxt[M_UNKNOWN_LINE], temp); } } (void) fclose (stream); /* close input file */ if (debugging_log) loglevel = 6; } char *ctl_string (source) /* malloc & copy to ctl */ char *source; { char *dest, *c; int i; c = skip_blanks (source); /* get over the blanks */ i = (int) strlen (c); /* get length of remainder */ if (i < 1) /* must have at least 1 */ return (NULL); /* if not, return NULL */ dest = malloc ((unsigned int) (++i)); /* allocate space for string */ if (dest == NULL) /* If we failed to get it, */ return (NULL); /* Just return NULL */ (void) strcpy (dest, c); /* copy the stuff over */ return (dest); /* and return the address */ } static char *ctl_slash_string (source) /* malloc & copy to ctl */ char *source; { char *dest, *c; int i; struct stat buffer; c = skip_blanks (source); /* get over the blanks */ i = (int) strlen (c); /* get length of remainder */ if (i < 1) /* must have at least 1 */ return (NULL); /* if not, return NULL */ dest = malloc ((unsigned int) (i+2)); /* allocate space for string */ if (dest == NULL) /* If we failed to get it, */ return (NULL); /* Just return NULL */ (void) strcpy (dest, c); /* copy the stuff over */ (void) delete_backslash (dest); /* get rid of trailing stuff */ /* Check to see if the directory exists */ i = stat (dest, &buffer); if (i || (!(buffer.st_mode & S_IFDIR))) { (void) printf (msgtxt[M_BAD_DIR], dest); (void) printf (msgtxt[M_FAIL_EXEC]); return(NULL); } (void) add_backslash (dest); /* add the backslash */ return (dest); /* return the directory name */ } char *add_backslash (str) char *str; { char *p; p = str + strlen (str) - 1; if (p >= str) { /* Strip off the trailing blanks */ while ((p >= str) && (isspace (*p))) { *p = '\0'; --p; } /* Put a backslash if there isn't one */ if ((p >=str) && (*p != '\\') && (*p != '/')) { *(++p) = '\\'; *(++p) = '\0'; } } return (fancy_str (str)); } char *delete_backslash (str) char *str; { char *p; p = str + strlen (str) - 1; if (p >= str) { /* Strip off the trailing blanks */ while ((p >= str) && (isspace (*p))) { *p = '\0'; --p; } /* Get rid of backslash if there is one */ if ((p >=str) && ((*p == '\\') || (*p == '/'))) { if ((p > str) && (*(p-1) != ':')) /* Don't delete on root */ *p = '\0'; } } return (fancy_str (str)); }