/* ****************************************************************************** ****************************************************************************** * * Licensed Materials - Property of IBM * * IBM TCP/IP for OS/2. * Copyright (c) IBM Corp. 1990, 1993. All rights reserved. * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule contract with IBM Corp. * ****************************************************************************** * ****************************************************************************** ****************************************************************************** */ #define INCL_PM #define INCL_DOS #define INCL_BASE #define INCL_DOSMEMMGR #define INCL_DOSMODULEMGR #define INCL_WINSHELLDATA #include #include #include #include #include #include #include #include "glo.h" #include "ver.h" #include "lpdport.h" #define NUMCARDS 40 /* max # of control cards accepted */ #define MAXCARD 275 /* max length of a control card */ #define isparm(s) (*(s) == '-' || *(s) == '/') /* global variables */ CHAR LpdPipeFmt[] = "\\PIPE\\LPD%d"; CHAR LprPortDriver[] = "LPRPDRVR"; CHAR PMPortDriver[] = "PM_PORT_DRIVER"; int Debug; /* local functions */ static void fatal(int rc, char *msg, ...); static int findports(void); static int findtcp(char *dest); static void write_debug(char *msg, ...); static int install_ports(PSZ base_path, int nport); static int parse(char *fname); static char *gettok(char *dest, register char *src); static char *getstr(char *dest, register char *src); static int valid(LPDPORT *port, char cards[NUMCARDS][MAXCARD], int *nextcard, char *kw, char *value); static int define(LPDPORT *port, char cards[NUMCARDS][MAXCARD], int nextcard); static void reset(LPDPORT *port, char cards[NUMCARDS][MAXCARD]); static void copy(register char *dest, register int destsize, register char *src); static int LpdSetPort(PLPDPORT LpdPort); static BOOL IniWriteStr(HINI hini, PSZ app, PSZ key, ULONG len, PSZ format, ...); main(int argc, char *argv[]) { char tcppath[256]; int numports; int rc, args; printf("LPINST Version %s\n\n", Version); Debug = 0; tcppath[0] = '\0'; numports = 0; for (args = 1; (args < argc) && isparm(argv[args]); ++args) { switch (argv[args][1]) { case '#': numports = atoi(argv[++args]); if ((numports < 0) || (numports > 64)) fatal(ERR_BADPORT, "legal number of ports: 0 <= ports <= 64"); break; case 'd': Debug = 1; break; case 't': strcpy(tcppath, argv[++args]); break; default: printf("usage: lpinst [-# number] [-d] [-t path] [filename]\n\n"); printf(" -# Specify number of ports to install.\n"); printf(" -d Enable debugging information.\n"); printf(" -t Specify path to TCP/IP product.\n"); exit(ERR_USAGE); } } if ((rc = findtcp(tcppath))) fatal(ERR_NOTCP, "Can't find the TCPIP product directories."); /* how many ports are being installed? */ if ((numports == 0) && ((numports = findports()) == 0)) numports = 8; /* install the ports */ if ((rc = install_ports(tcppath, numports))) fatal(rc, "Port installation failed."); /* now, define the setting's pages */ if (args < argc) rc = parse(argv[args]); exit(rc); } /* findports(void) - Lookup the number of ports in the INI file. */ static int findports(void) { int rc; rc = PrfQueryProfileInt(HINI_SYSTEM, LprPortDriver, "MAXPORTS", 0); if ((rc < 0) || (rc > 64)) rc = 0; return rc; } /* findtcp(dest) - If the path to TCP/IP hasn't been specified, try to find the product. Returns 0 on success, -1 on error. On success, `dest' contains the product's path. */ static int findtcp(char *dest) { char fullpath[256]; HMODULE hmod; int rc; rc = -1; if (strlen(dest) < 1) { /* the user didn't specify a path, try to find TCP/IP */ if ((rc = DosSearchPath(SEARCH_ENVIRONMENT, "PATH", "LPRPORTD.EXE", fullpath, sizeof(fullpath))) == 0) { register char *fp; write_debug("findtcp(): found LPRPORTD.EXE in PATH: %s\n", fullpath); /* fullpath = "\\LPRPORTD.EXE", strip off "\\LPRPORTD.EXE" */ fp = fullpath + strlen(fullpath) - strlen("LPRPORTD.EXE") - 1; if (fp >= fullpath) { *fp = '\0'; /* fullpath = \\BIN", strip off "\\BIN" */ for (fp = fullpath + strlen(fullpath); fp > fullpath; --fp) if (*fp == '\\') break; if (*fp == '\\') *fp = '\0'; } write_debug("findtcp(): setting dest to (%s)\n", fullpath); strcpy(dest, fullpath); } } if (strlen(dest) < 1) /* the TCPIP product directories can't be located */ rc = -1; else { /* verify `dest' by loading LPRPDRVR.PDR */ if (*(dest + strlen(dest) - 1) == '\\') *(dest + strlen(dest) - 1) = '\0'; sprintf(fullpath, "%s\\DLL\\%s.PDR", dest, LprPortDriver); write_debug("findtcp(): verifying path (%s)\n", fullpath); if ((rc = DosLoadModule(NULL, 0, fullpath, &hmod))) printf("The path \"%s\" is invalid.\n", dest); else { printf("Found TCP/IP in: %s\n", dest); DosFreeModule(hmod); } } return rc; } static void fatal(int rc, char *msg, ...) { va_list args; va_start(args, msg); vprintf(msg, args); va_end(args); fflush(stdout); exit(rc); } static void write_debug(char *msg, ...) { va_list args; if (Debug) { va_start(args, msg); vprintf(msg, args); va_end(args); fflush(stdout); } } /* ------------------------------------------------------------------------ */ /* Install Ports */ /* ------------------------------------------------------------------------ */ static int install_ports(char *base_path, int nport) { CHAR fullpath[256]; long lpd_ports; int rc = 0; printf("Creating %d \\PIPE\\LPDx ports...\n", nport); write_debug("install(%s, %d): called\n", base_path, nport); lpd_ports = PrfQueryProfileInt(HINI_SYSTEM, LprPortDriver, "MAXPORTS", 0); write_debug(" INI file reports %d ports\n", lpd_ports); if (!IniWriteStr(HINI_SYSTEM, LprPortDriver, "MAXPORTS", 10, "%lu", nport)) rc = ERR_PORTS; else { write_debug(" updated LPRPDRVR MAXPORTS OK\n"); if (*(base_path + strlen(base_path) - 1) == '\\') *(base_path + strlen(base_path) - 1) = '\0'; sprintf(fullpath, "%s\\DLL\\%s.PDR", base_path, LprPortDriver); strupr(fullpath); write_debug(" fullpath = %s\n", fullpath); if (!IniWriteStr(HINI_SYSTEM, PMPortDriver, LprPortDriver, strlen(fullpath)+2, "%s", fullpath)) { IniWriteStr(HINI_SYSTEM, LprPortDriver, "MAXPORTS", 0, 0); rc = ERR_PDRVR; } else { HMODULE hmod = (HMODULE)0; PFN SplPdInstallPort; PFN SplPdRemovePort; write_debug(" Updated PM_PORT_DRIVER field.\n"); if ((rc = DosLoadModule(NULL, 0, fullpath, &hmod))) { printf("DosLoadModule(%s) failed, rc = %d.\n", fullpath, rc); rc = ERR_LOADMOD; } else if ((rc = DosQueryProcAddr(hmod, 0, "SPLPDINSTALLPORT", &SplPdInstallPort))) { printf("DosQueryProcAddr(SPLPDINSTALLPORT) failed, rc = %d.\n", rc); rc = ERR_BADPROC; } else if ((rc = DosQueryProcAddr(hmod, 0, "SPLPDREMOVEPORT", &SplPdRemovePort))) { printf("DosQueryProcAddr(SPLPDREMOVEPORT) failed, rc = %d.\n", rc); rc = ERR_BADPROC; } else { CHAR cBuf[256]; int i; for (i=0; !rc && i=0; i--) { sprintf(cBuf, LpdPipeFmt, i); write_debug(" uninstalling port %s\n", cBuf); (SplPdRemovePort)(0, cBuf); } break; } } /* Disable all other ports above the number specified. * Unlike SplPdRemovePort(), this only removes the port from the * list, it does NOT destroy any port specific configuration data! */ if (!rc) { for (; i = line */ if (*lp == '[') { /* defining a new port */ if (skip) /* some error caused us to start skipping the previous port */ skip = 0; else { /* define the previous port */ if (define(&port, cards, nextcard)) fatal(ERR_CANTDEFINE, "Unable to define port %s.\n", port.PortName); } if (!done) { /* reset */ reset(&port, cards); nextcard = 0; /* get the port name */ if ((lp = gettok(kw, ++lp)) == NULL) { printf("\"%s\", line %d: Expected a port name\n", fname, lineno); rc = ERR_BADDEF; skip = 1; } copy(port.PortName, sizeof(port.PortName), kw); strupr(port.PortName); /* verify the port */ if (strncmp(port.PortName, "\\PIPE\\LPD", 9)) { printf("\"%s\", line %d: Illegal port name \"%s\"", fname, lineno, port.PortName); skip = 1; } } } /* not defining a new printer, look for a keyword */ else if ((lp = gettok(kw, lp)) == NULL) { printf("\"%s\", line %d: Expected a keyword\n", fname, lineno); rc = ERR_BADDEF; skip = 1; } else { /* not skipping => the following has been parsed correctly: * [printer_name] * keyword * '=' is next, followed by the string value */ while (*lp && isspace(*lp)) ++lp; if (*lp != '=') { printf("\"%s\", line %d: Expected '=' to follow \"%s\"\n", fname, lineno, kw); rc = ERR_BADDEF; skip = 1; } /* parsed the equals sign, parse string */ else if ((lp = getstr(str, ++lp)) == NULL) { printf("\"%s\", line %d: Expected a string to follow '='\n", fname, lineno); rc = ERR_BADDEF; skip = 1; } /* everything parsed correctly, process the keyword and value */ else if (valid(&port, cards, &nextcard, kw, str)) { printf("\"%s\", line %d: '%s' is an unrecognized keyword\n", fname, lineno); rc = ERR_BADDEF; skip = 1; } } } fclose(fp); if (rc == 0) printf(" The ports were defined correctly.\n"); return rc; } static char *gettok(char *dest, register char *src) { register char *d; d = dest; while (*src && !isspace(*src) && (*src != ']') && (*src != '=')) *d++ = *src++; *d = '\0'; return (*dest ? src : NULL); } static char *getstr(char *dest, register char *src) { register char *d; /* skip leading whitespace on src */ while (*src && isspace(*src)) ++src; if (*src != '"') *dest = '\0'; else { /* copy src to dest */ ++src; d = dest; while (*src && *src != '"') { if (*src == '\\') ++src; *d++ = *src++; } /* strip trailing blanks on dest */ --d; while (d >= dest && isspace(*d)) --d; ++d; *d = '\0'; } return (*dest ? src : NULL); } /* valid(port, cards[][], nextcard, keyword, value) - A valid line of the def file has been read and parsed. */ static int valid(LPDPORT *port, char cards[NUMCARDS][MAXCARD], int *nextcard, char *kw, char *value) { int rc; rc = 0; if (stricmp(kw, "SERVER") == 0) copy(port->Server, sizeof(port->Server), value); else if (stricmp(kw, "PRINTER") == 0) copy(port->Printer, sizeof(port->Printer), value); else if (stricmp(kw, "HOST") == 0) copy(port->Source, sizeof(port->Source), value); else if (stricmp(kw, "USER") == 0) copy(port->User, sizeof(port->User), value); else if (stricmp(kw, "SPOOLER") == 0) port->SpoolerParamPrefix = strdup(value); else if (stricmp(kw, "QUEUE") == 0) port->QueueParamPrefix = strdup(value); else if (stricmp(kw, "NETWORK") == 0) port->NetworkParamPrefix = strdup(value); else if (stricmp(kw, "SETTINGS") == 0) { if ((stricmp(value, "YES") == 0) || (stricmp(value, "Y") == 0) || (stricmp(value, "TRUE") == 0) || (stricmp(value, "T") == 0)) port->Flags |= PORTFLGS_DIALOGONPRINT; } else if (stricmp(kw, "FILTER") == 0) copy(port->DataFilter, sizeof(port->DataFilter), value); else if (stricmp(kw, "MAILTO") == 0) copy(port->MailTo, sizeof(port->MailTo), value); else if (stricmp(kw, "CLASS") == 0) copy(port->Class, sizeof(port->Class), value); else if (stricmp(kw, "CARD") == 0) { copy(cards[*nextcard], MAXCARD, value); *nextcard += 1; } else rc = ERR_BADDEF; return rc; } /* define(port, cards[]) - Given a port and a set of control cards, define the setting's page in the INI file. */ static int define(LPDPORT *port, char cards[NUMCARDS][MAXCARD], int nextcard) { int card, cfilelen; char *cptr; int rc; rc = 0; printf(" Defining \"%s\"...\n", port->PortName); /* make sure the port name is upper-case */ strupr(port->PortName); if (port->SpoolerParamPrefix) port->Flags |= PORTFLGS_PASS_SPARAMS; if (port->QueueParamPrefix) port->Flags |= PORTFLGS_PASS_QPARAMS; if (port->NetworkParamPrefix) port->Flags |= PORTFLGS_PASS_NPARAMS; if (strlen(port->MailTo)) port->Flags |= PORTFLGS_MAIL; if (strlen(port->Class)) port->Flags |= PORTFLGS_BANNER; if (strlen(port->DataFilter)) port->Flags |= PORTFLGS_DATAFILTER; /* we have to build the control file */ cfilelen = 0; for (card = 0; card < nextcard; ++card) cfilelen += strlen(cards[card]) + 1; if (cfilelen) { cfilelen += 100; if ((port->ControlFile = malloc(cfilelen)) == NULL) fatal(ERR_NOMEM, "Out of memory"); cptr = port->ControlFile; for (card = 0; card < nextcard; ++card) cptr += sprintf(cptr, "%s\n", cards[card]); } write_debug("defining port %s", port->PortName); write_debug(" Server : %s\n", port->Server); write_debug(" Printer : %s\n", port->Printer); write_debug(" Source : %s\n", port->Source); write_debug(" User : %s\n", port->User); write_debug(" MailTo : %s\n", port->MailTo); write_debug(" Class : %s\n", port->Class); write_debug(" DataFilter: %s\n", port->DataFilter); write_debug(" Flags : %x\n", port->Flags); write_debug(" Control File: %s\n", (port->ControlFile ? port->ControlFile : "(none)")); write_debug(" Spooler Pfx : %s\n", (port->SpoolerParamPrefix ? port->SpoolerParamPrefix : "(none)")); write_debug(" Queue Prefix: %s\n", (port->QueueParamPrefix ? port->QueueParamPrefix : "(none)")); write_debug(" Network Pfx : %s\n", (port->NetworkParamPrefix ? port->NetworkParamPrefix : "(none)")); write_debug("\n"); rc = LpdSetPort(port); if (port->ControlFile) free(port->ControlFile); if (port->SpoolerParamPrefix) free(port->SpoolerParamPrefix); if (port->QueueParamPrefix) free(port->QueueParamPrefix); if (port->NetworkParamPrefix) free(port->NetworkParamPrefix); return rc; } /* reset(port, cards) */ static void reset(LPDPORT *port, char cards[NUMCARDS][MAXCARD]) { register int i; memset(port, 0, sizeof(LPDPORT)); for (i = 0; i < NUMCARDS; ++i) cards[i][0] = '\0'; } /* copy(dest, destsize, src) - Copy `src' into `dest' ensuring that `src' fits into `dest'. */ static void copy(register char *dest, register int destsize, register char *src) { if (strlen(src) >= destsize) *(src + destsize - 1) = '\0'; strcpy(dest, src); } /* ------------------------------------------------------------------------ */ /* INI file support */ /* ------------------------------------------------------------------------ */ #define SYSPRO HINI_SYSTEMPROFILE #define MEMBITS (PAG_READ|PAG_WRITE|PAG_COMMIT) static int LpdSetPort(PLPDPORT LpdPort) { static CHAR PrfPortPrefix[] = "PM_"; CHAR AppName[16]; APIRET rc; rc = 0; strcpy(AppName, PrfPortPrefix); strcat(AppName, LpdPort->PortName); if(!PrfWriteProfileData(SYSPRO, AppName, "LPDDATA", LpdPort, sizeof(*LpdPort))) { rc = ERROR_NO_ITEMS; } else { if (LpdPort->ControlFile) IniWriteStr(SYSPRO, AppName, "CONTROLFILE", strlen(LpdPort->ControlFile)+1, "%s", LpdPort->ControlFile); else IniWriteStr(SYSPRO, AppName, "CONTROLFILE", 0, (PSZ)NULL); if (LpdPort->SpoolerParamPrefix) IniWriteStr(SYSPRO, AppName, "SPARAMPREFIX", strlen(LpdPort->SpoolerParamPrefix)+1, "%s", LpdPort->SpoolerParamPrefix); else IniWriteStr(SYSPRO, AppName, "SPARAMPREFIX", 0, (PSZ)NULL); if(LpdPort->QueueParamPrefix) IniWriteStr(SYSPRO, AppName, "QPARAMPREFIX", strlen(LpdPort->QueueParamPrefix)+1, "%s", LpdPort->QueueParamPrefix); else IniWriteStr(SYSPRO, AppName, "QPARAMPREFIX", 0, (PSZ)NULL); if (LpdPort->NetworkParamPrefix) IniWriteStr(SYSPRO, AppName, "NPARAMPREFIX", strlen(LpdPort->NetworkParamPrefix)+1, "%s", LpdPort->NetworkParamPrefix); else IniWriteStr(SYSPRO, AppName, "NPARAMPREFIX", 0, (PSZ)NULL); } return rc; } static BOOL IniWriteStr(HINI hini, PSZ app, PSZ key, ULONG len, PSZ format, ...) { BOOL success; if (len && key && format) { va_list marker; CHAR *pBuf = NULL; if(DosAllocMem((PPVOID)&pBuf, len, MEMBITS)) return(FALSE); va_start(marker, format); vsprintf(pBuf, format, marker); va_end(marker); success = PrfWriteProfileString(hini, app, key, pBuf); DosFreeMem((PVOID)pBuf); } else success = PrfWriteProfileString(hini, app, key, (PSZ)NULL); return success; }