diff --git a/debmask.h b/debmask.h index 25e059d..47ba9b0 100644 --- a/debmask.h +++ b/debmask.h @@ -15,5 +15,9 @@ #define D_FN_NAMES 8 #define D_FN_SEARCH 0x10 /* file search */ + +/* NWBIND */ +#define D_BIND_REQ 0x8000 /* all Requests */ + #endif diff --git a/doc/BUGS b/doc/BUGS index 9016c63..be9e01c 100644 --- a/doc/BUGS +++ b/doc/BUGS @@ -10,6 +10,7 @@ If you have problems. Section 1: volumes Section 3: Number of the internal network Section 4: IPX-devices + Section 5: device flags Section 6: version-"spoofing" Section 12: supervisor-login If you do not have success, please make one try with @@ -23,8 +24,8 @@ If you have problems. some short notes for problem- or bug-reports. --------------------------------------------- - report your running environment - full mars_nwe version, example: 0.98.pl5 - linux-kernel, 2.0.23 + full mars_nwe version, example: 0.99.pl0 + linux-kernel, 2.0.29 exact typ of client (NCPFS, DOS (NETX,VLM), OS/2, Win .. ) changes you made into nwserv.conf(nw.ini), config.h. - if you send nwserv.conf, please remove the comments first. diff --git a/doc/CHANGES b/doc/CHANGES index 4c44e09..a617ff5 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,6 +1,6 @@ Sorry, this is in German only. User important notes are in the NEWS file. -Aenderungen in mars_nwe bis zum : 14-Jul-97 +Aenderungen in mars_nwe bis zum : 08-Aug-97 -------------------------------- Erste 'oeffentliche' Version ^^^^^^^^^^ VERSION 0.94 ^^^^^^^^ @@ -349,3 +349,14 @@ Erste 'oeffentliche' Version - Internen Router Code fuer SAP Anfragen des internen Netzes (slist usw.) korrigiert. <----- ^^^^^^^^^^ pl0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- namespace routine delete file/dir um wildcardhandling erweitert fuer + client32. (W95) +- einfache Semaphore Routinen eingebaut. +- Routine 0x16,0x2f eingebaut. (fuer Pete) +- Quota Support wieder zum Laufen gebracht. + Durch Bindery Security Fixes funktionierte Quota Support + nicht mehr. +- im MAIL Verzeichnis werden nun im Unterverzeichnis user symbolische Links + der Login Namen erzeugt. +<----- ^^^^^^^^^^ pl1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/doc/CREDITS b/doc/CREDITS index 210488a..0758575 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -6,6 +6,9 @@ Michael Beddow Thomas Behr testings, wrote syslog stuff +Peter Beno + testings+bugfixes + Guntram Blohm testing router code on token ring wrote the 'crypted change password' routines ! @@ -46,6 +49,9 @@ Volker Lendecke Ambrose Li gave hints, patches, docs +Andreas Liebmann + docs + James B. MacLean many testings+notes diff --git a/doc/FAQS b/doc/FAQS index dc601f6..9373afa 100644 --- a/doc/FAQS +++ b/doc/FAQS @@ -49,6 +49,10 @@ A: Give the volume the 'O' flag. [HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\NWREDIR] "SupportLFN"=hex:02 +A: Pascal Haible reported that he had to set system.ini, too. + [nwredir] + SupportLFN=2 + Q: I have 2 Eth-devices (one for IP/IPX and one for IPX only) and after starting mars_nwe I have strange problems with my IP-net. A: Make sure that all Eth-devices have an assigned IP address, even if diff --git a/doc/INSTALL.ger b/doc/INSTALL.ger index 13ed763..9d0e4ab 100644 --- a/doc/INSTALL.ger +++ b/doc/INSTALL.ger @@ -4,7 +4,7 @@ Mars_nwe kann auf 2 Arten konfiguriert werden. die IPX-Interfaces per ini/conf Datei konfigurieren und als RIP/SAP Router arbeiten. Dieses ist der default Modus. Es werden keine weiteren - Programme wie ipx-configure oder IPX rip/sap Daemons + Programme wie ipx-interface, ipx-configure oder IPX rip/sap Daemons benoetigt. In diesem Modus wurde das korrekte Zusammenspiel mit dosemu, ncpfs oder Caldera's nwclient getestet. @@ -21,7 +21,7 @@ Mars_nwe kann auf 2 Arten konfiguriert werden. Netwerknummer erhalten. Es muss ein Eintrag '4' mit Netzwerk Nummer = 0, Device = '*' und Frame = 'auto' fuer ein 'autodetect' Interface - vorhanden sein. + vorhanden sein und Eintrag '5' muss flag 2 enthalten. Beispiel fuer conf/ini Datei: (siehe auch: examples/nw.ini) 3 0x0 # verwende IP Nummer als Internal Net. 4 0x0 * AUTO # autodetect interfaces. @@ -38,8 +38,8 @@ Mars_nwe kann auf 2 Arten konfiguriert werden. 2. Mars_nwe soll nur als File Server Verwendung finden, d.h. Routing usw. soll von anderen Programmen erledigt werden. -> Die IPX-Interfaces muessen durch andere Programme/Tools - wie 'ipx-configure' oder aehnliche eingerichtet werden - und es muss ein rip/sap router/daemon eingerichtet sein. + wie 'ipx-interface, ipx-configure' oder aehnliche eingerichtet + werden und es muss ein rip/sap router/daemon eingerichtet sein. In mars_nwe/config.h muss folgende Zeile vorhanden sein. #define INTERNAL_RIP_SAP 0 @@ -72,5 +72,46 @@ sind. Falls nwserv nicht daemonisiert wurde, kann der Server mit ^C wieder gestoppt werden, ansonsten muss nwserv per Dos Client (fconsole server down) gestoppt werden (Supervisor) oder per -'kill' Befehl. Je nach Eintrag 210 in der nw.ini Datei kann +'nwserv -k' Befehl. Je nach Eintrag 210 in der nw.ini Datei kann das einige Sekunden dauern. + + +Erlaeuterungen zu Punkt 1 in /etc/nwserv.conf : + +Wenn der NetAdmin die Homeverzeichnisse des LINUX-Servers dem einzelnen +Usern durch das MAP Kommando bereitstellt, kann er das auf +zwei verschiedene Arten zustandebringen: + +Angenommen, der User test2 hat sich am NWE angemeldet. Er hat bereits Dateien +in seinem Verzeichnis /home/test2 gespeichert. + +Je nachdem welcher Eintrag 1 in der Datei /etc/nwserv.conf (natuerlich +neben anderen) vorgenommen worden ist, hat das MAP-Kommando ein +anderes Ergebnis: + + Variante 1 Variante2 + +Befehl DOS + MAP H:=MARS\HOMEDIR: MAP H:=MARS\HOMEDIR: + +Eintrag in /etc/nwserv.conf + 1 HOMEDIR ~ k 1 HOMEDIR /home k + +Resultat DIR *.* + Der Inhalt des Verzeichnisses Es werden alle unter /home + /home/test2 erscheint unter auf dem LINUX-Server enthaltenen + Laufwerk H. Verzeichnisse angezeigt. Der + D.h. die bereits vom User User test2 muesste also noch ein + test2 gespeicherten zwei cd /test2 machen, um seine + Dateien. Dateien anschauen zu koennen. + +Achtung ! +Ein Eintrag in /etc/nwserv.conf + + 1 HOMEDIR /home/~ k + +macht bestimmt nicht das was erwartet wird. +Nur ein "~" ohne vorlaufenden Pfad hat die besondere Bedeutung +des Homedirs, ein "/home/~" als Verzeichnis gilt als 'normales' Volume +das den 'normalen' Pfad "/home/~" exportiert. + diff --git a/doc/NEWS b/doc/NEWS index 16a9252..62ff597 100644 --- a/doc/NEWS +++ b/doc/NEWS @@ -1,3 +1,7 @@ +------16-Aug-97--- 0.99.pl1 --------- +- print queue handling changed. (please look into examples/nw.ini) +- simple semaphore calls added. +- in mail directory subdirectory 'user' added with symlinks to mail/user-id's. ------31-Jul-97--- 0.99.pl0 --------- - Client-32 from Novell should now work. (added vol/dev/inode/path cache) The cache directory '/var/spool/nwserv/.volcache' should/can be controlled diff --git a/doc/mars_nwe.lsm b/doc/mars_nwe.lsm index 3129ae4..080cbbc 100644 --- a/doc/mars_nwe.lsm +++ b/doc/mars_nwe.lsm @@ -1,6 +1,6 @@ Begin3 Title: mars_nwe -Version: 0.99.pl0 +Version: 0.99.pl1 Entered-date: 31-Jul-97 Description: Full netware-emulator (src), beta. Supports file-services, bindery-services, @@ -9,7 +9,7 @@ Keywords: novell, netware, server, ipx, ncp, tli Author: mstover@stover.f.eunet.de (Martin Stover) Maintained-by: mstover@stover.f.eunet.de (Martin Stover) Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs - 240kB mars_nwe-0.99.pl0.tgz + 240kB mars_nwe-0.99.pl1.tgz Alternate-site: sunsite.unc.edu:/pub/Linux/system/filesystems/ncpfs Platforms: Linux (1.2.xx, 1.3.xx, 2.xx), UnixWare (2.xx) Copying-policy: GNU diff --git a/examples/nw.ini b/examples/nw.ini index 255e2d1..b69ca5e 100644 --- a/examples/nw.ini +++ b/examples/nw.ini @@ -2,12 +2,14 @@ # This is the configuration-file for "mars_nwe", a free netware-emulator # for Linux. # -# last changed: 20-Jul-97 +# last changed: 30-Aug-97 +# # !! section 4 : automatic creation of ipx-interfaces changed in 0.98.pl9 !! # # since version 0.98.pl11: # the most important options in config.h can now be altered in # this file begin at section 60. +# # This file specifies which Linux-resources (printers, users, directories) @@ -68,6 +70,31 @@ # volume; use the special name "~" to refer to the users # individual home-directory # +# Attention ! A directory entry like "/home/~" +# do not work. Only is simple "~" as directory name +# has this special meaning. +# +# If the netadmin wants to map the homedirectories with the MAP-Command to +# every user, he can do it in two variants: +# We suppose that the user test2 is logged in MARS_NWE. He has files +# earlier stored in his homedirectory /home/test2. +# In case of entry 1 in /etc/nwserv.conf (naturally amongst other entries) +# there are other results of the MAP-command. +# +# Variant 1 Variant 2 +# +#DOS-Command MAP H:=MARS\HOMEDIR: MAP H:=MARS\HOMEDIR: +# +#Entry in /etc/nwserv.conf +# 1 HOMEDIR ~ k 1 HOMEDIR /home k +# +#Result of DIR *.* All files stored in All homedirs of the +# /home/test2 will shown. users will shown. +# Showing his own files +# it is a command like +# CD test2 and then +# dir *.* necessary. +# # OPTIONS: none or some of the following characters (without a seperator) # # Next two options control DOS and OS/2 namespace. @@ -193,7 +220,7 @@ # # Under Linux, it is possible to let the kernel creat all ipx-devices # automatically for you. This is only possible (and only makes sense then) -# if there are other IXP/NCP servers on the same net which are setup +# if there are other IPX/NCP servers on the same net which are setup # correctly. It can be switched on in section '5'. # ------------------------------------------------------------------------- # Syntax: @@ -561,31 +588,50 @@ # # ------------------------------------------------------------------------- # Syntax: -# 21 QUEUE_NAME QUEUE_DIR PRINT_COMMAND +# 21 QUEUE_NAME [QUEUE_DIR] [PRINT_COMMAND] # # QUEUE_NAME: the name of the print queue on client-side (to make it # perfectly clear: _not_ the Linux-queue) # QUEUE_DIR: spooling directory for the print-jobs. # The name is the DOS (not Unix) name of this # directory. -# It should be placed on the first defined volume. +# It must be placed on the first defined volume. # (standard name is SYS volume). # Then it will be created at starttime of mars_nwe. # It must exist before printing. # (_not_ the spooling-directories of the Linux-lpd) +# NOTE ! +# A '-' sign as QUEUE_DIR has special meaning of +# 'standard' queuedir name. ( SYS:\SYSTEM\queueid.QDR ) +# # PRINT_COMMAND: command used for serving the print-jobs under Linux # (see "man lpr" and "man magicfilter" for details) # if the '!' is last parameter of command then # the queue-packet fields 'banner_user_name' # and 'banner_file_name' will be added to the # command as last parameters. +# NOTE ! +# If a print command is not specified the job can/must be +# printed by any print server. +# (e.g. pserver (ncpfs utils) or external printserver) # # Examples: -# 21 LASER SYS:/PRINT/L lpr -Plaser -# 21 OCTOPUSS SYS:/PRINT/O lpr -Php_deskjet +# 21 LASER - lpr -Plaser +# 21 OCTOPUSS # ------------------------------------------------------------------------- +# ========================================================================= +# Section 22: print server entries (optional) +# adds printserver entries into bindery +# e.g. to enable printing with ncpfs pserver +# ------------------------------------------------------------------------- +# Syntax: +# 22 PSERVER_NAME QUEUE_NAME +# Examples: +# 22 PS1 OCTOPUSS + + # ========================================================================= # Section 30: Burst mode values (optional) # @@ -605,10 +651,12 @@ 40 /var/spool/nwserv/.volcache # 41 = path for share/lock files 41 /var/spool/nwserv/.locks +# 42 = path for spool dir +42 /var/spool/nwserv +# # # 45 = path for bindery file's 45 /etc - # ========================================================================= # Section 50: Conversion tables by Victor Khimenko # Tables for DOS->Unix names translation & upper/lowercase translations diff --git a/extpipe.c b/extpipe.c new file mode 100644 index 0000000..402b4a8 --- /dev/null +++ b/extpipe.c @@ -0,0 +1,166 @@ +/* extpipe.c 08-Aug-97 */ +/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "net.h" +#include "extpipe.h" + +static char **build_argv(char *buf, int bufsize, char *command) +/* routine returns **argv for use with execv routines */ +/* buf will contain the path component */ +{ + int len = strlen(command); + int offset = ((len+4) / 4) * 4; /* aligned offset for **argv */ + int components = (bufsize - offset) / 4; + if (components > 1) { /* minimal argv[0] + NULL */ + char **argv = (char **)(buf+offset); + char **pp = argv; + char *p = buf; + char c; + int i=0; + --components; + memcpy(buf, command, len); + memset(buf+len, 0, bufsize - len); + *pp = p; + while ((0 != (c = *p++)) && i < components) { + if (c == 32 || c == '\t') { + *(p-1) = '\0'; + if (*p != 32 && *p != '\t') { + *(++pp)=p; + i++; + } + } else if (!i && c == '/') { /* here i must get argv[0] */ + *pp=p; + } + } + XDPRINTF((5, 0, "build_argv, path='%s'", buf)); + pp=argv; + while (*pp) { + XDPRINTF((5, 0, "build_argv, argv='%s'", *pp)); + pp++; + } + return(argv); + } + return(NULL); +} + + +static void close_piped(int piped[3][2]) +{ + int j=3; + while (j--) { + int k=2; + while (k--) { + if (piped[j][k] > -1){ + close(piped[j][k]); + piped[j][k] = -1; + } + } + } +} + +static int x_popen(char *command, int uid, int gid, FILE_PIPE *fp) +{ + int piped[3][2]; + int lpid=-1; + int j=3; + char buf[300]; + char **argv=build_argv(buf, sizeof(buf), command); + if (argv == NULL) return(-1); + while (j--){ + int k=2; + while(k--) piped[j][k] = -1; + } + if (! (pipe(&piped[0][0]) > -1 && pipe(&piped[1][0]) > -1 + && pipe(&piped[2][0]) > -1 && (lpid=fork()) > -1)) { + close_piped(piped); + return(-1); + } + if (lpid == 0) { /* Child */ + signal(SIGTERM, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + signal(SIGHUP, SIG_DFL); + j=3; + while(j--) close(j); + j=3; + while(j--) { + int x = (j) ? 0 : 1; + int x_ = (j) ? 1 : 0; + close(piped[j][x] ); + dup2( piped[j][x_], j); + close(piped[j][x_] ); + } + if (uid > -1 || gid > -1) { + seteuid(0); + if (gid > -1) setgid(gid); + if (uid > -1) setuid(uid); + if (gid > -1) setegid(gid); + if (uid > -1) seteuid(uid); + } + execvp(buf, argv); + exit(1); /* Never reached I hope */ + } + j=-1; + while (++j < 3) { + int x = (j) ? 0 : 1; + int x_ = (j) ? 1 : 0; + close(piped[j][x_]); + piped [j][x_] = -1; + fp->fds[j] = piped[j][x]; + } + return(lpid); +} + +int ext_pclose(FILE_PIPE *fp) +{ + int status=-1; + void (*intsave) (int) = signal(SIGINT, SIG_IGN); + void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN); + void (*hupsave) (int) = signal(SIGHUP, SIG_IGN); + int j = 3; + while (j--) close(fp->fds[j]); + if (fp->command_pid != waitpid(fp->command_pid, &status, 0)) { + kill(fp->command_pid, SIGTERM); + waitpid(fp->command_pid, &status, 0); + } + kill(fp->command_pid, SIGKILL); + signal(SIGINT, intsave); + signal(SIGQUIT, quitsave); + signal(SIGHUP, hupsave); + xfree(fp); + return(status); +} + +FILE_PIPE *ext_popen(char *command, int uid, int gid) +{ + FILE_PIPE *fp=(FILE_PIPE*) xcmalloc(sizeof(FILE_PIPE)); + void (*intsave) (int) = signal(SIGINT, SIG_IGN); + void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN); + void (*hupsave) (int) = signal(SIGHUP, SIG_IGN); + if ((fp->command_pid = x_popen(command, uid, gid, fp)) < 0) { + xfree(fp); + fp=NULL; + XDPRINTF((1, 0x10, "ext_popen failed:uid=%d, gid=%d,command='%s'", + uid, gid, command)); + } + signal(SIGINT, intsave); + signal(SIGQUIT, quitsave); + signal(SIGHUP, hupsave); + return(fp); +} diff --git a/extpipe.h b/extpipe.h new file mode 100644 index 0000000..3d1faf8 --- /dev/null +++ b/extpipe.h @@ -0,0 +1,16 @@ +/* extpipe.h 08-Aug-97 */ + +#ifndef _EXTPIPE_H_ +#define _EXTPIPE_H_ + +/* enhanced pipe handling */ +typedef struct { + int fds[3]; /* filedescriptor to 0,1,2 of new process */ + int command_pid; /* pid of piped command */ + int flags; /* special flags */ +} FILE_PIPE; + +extern int ext_pclose(FILE_PIPE *fp); +extern FILE_PIPE *ext_popen(char *command, int uid, int gid); + +#endif diff --git a/makefile.unx b/makefile.unx index 7f24d27..487d821 100644 --- a/makefile.unx +++ b/makefile.unx @@ -1,5 +1,5 @@ #if 0 -#makefile.unx 09-Jul-97 +#makefile.unx 09-Aug-97 #endif VPATH=$(V_VPATH) @@ -9,7 +9,7 @@ C=.c V_H=0 V_L=99 -P_L=0 +P_L=1 #define D_P_L 1 DISTRIB=mars_nwe @@ -113,24 +113,26 @@ PROGS=$(INSTALLPROGS) $(PROG8) OBJ1= $(EMUTLIOBJ) net1$(O) tools$(O) OBJ2= $(OBJ1) $(EMUTLIOBJ1) $(NWROUTE_O) OBJ3= $(OBJ1) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) unxfile$(O) \ -nwqueue$(O) nameos2$(O) nwfname$(O) nwshare$(O) +nwqconn$(O) nameos2$(O) nwfname$(O) nwshare$(O) extpipe$(O) OBJ4= $(OBJ1) OBJ5= $(OBJ1) -OBJ6= $(OBJ1) nwdbm$(O) nwcrypt$(O) unxlog$(O) +OBJ6= $(OBJ1) nwdbm$(O) nwcrypt$(O) unxlog$(O) sema$(O) nwqueue$(O) OBJ7= $(OBJ1) $(EMUTLIOBJ1) OBJ8= $(OBJ6) OBJS= $(EMUTLIOBJ) net1$(O) tools$(O) \ $(EMUTLIOBJ1) $(NWROUTE_O) \ connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) unxfile$(O)\ - nwqueue$(O) nameos2$(O) \ - nwdbm$(O) nwcrypt$(O) unxlog$(O) \ + nwqconn$(O) nameos2$(O) nwfname$(O) nwshare$(O) extpipe$(O) \ + nwdbm$(O) nwcrypt$(O) unxlog$(O) sema$(O) nwqueue$(O) \ $(PROG2)$(O) $(PROG3)$(O) $(PROG4)$(O) $(PROG5)$(O) $(PROG6)$(O) \ $(PROG7)$(O) $(PROG8)$(O) HOBJ3= $(PROG3)$(O) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) \ unxfile$(O) +HOBJ6= $(PROG6)$(O) sema$(O) + #if 0 #$(PROG1): $(PROG1)$(O) $(OBJ1) # $(CC) -o $(VPATH)/$(PROG1) $(PROG1)$(O) $(OBJ1) $(CRYPTLIB) $(NSLLIB) @@ -162,6 +164,7 @@ $(PROG8): $(PROG8)$(O) $(OBJ8) $(CC) -o $(VPATH)/$(PROG8) $(PROG8)$(O) $(OBJ8) $(NDBMLIB) $(CRYPTLIB) $(NSLLIB) $(HOBJ3): namspace.h connect.h nwvolume.h nwfile.h +$(HOBJ6): nwbind.h sema.h $(OBJS): net.h config.h $(PROG7)$(O): nwserv.c nwroute.c tools$(O): $(DESTMAKEFILE) diff --git a/nameos2.c b/nameos2.c index 046eadc..c0c5f10 100644 --- a/nameos2.c +++ b/nameos2.c @@ -249,7 +249,7 @@ int fn_os2_match(uint8 *s, uint8 *p, int soptions) continue; default : if (soptions & VOL_OPTION_IGNCASE) { - if (!dfn_imatch(*s, *p)) + if (!dfn_imatch(*s, pc)) return(0); } else if (pc != *s) return(0); ++s; diff --git a/namspace.c b/namspace.c index 040a0b2..9b8cc57 100644 --- a/namspace.c +++ b/namspace.c @@ -1,4 +1,4 @@ -/* namspace.c 30-Jul-97 : NameSpace Services, mars_nwe */ +/* namspace.c 12-Aug-97 : NameSpace Services, mars_nwe */ /* !!!!!!!!!!!! NOTE !!!!!!!!!! */ /* Its still dirty, but it should work fairly well */ @@ -967,15 +967,24 @@ static int build_dir_info(DIR_BASE_ENTRY *dbe, memset(p, 0, result+2); + if ( (!S_ISDIR(stb->st_mode)) + && (voloptions & VOL_OPTION_IS_PIPE) ) { + (void)time(&(stb->st_mtime)); + stb->st_size = 0x70000000|(stb->st_mtime&0xfffffff); + stb->st_atime = stb->st_mtime; + } + + if (infomask & INFO_MSK_DATA_STREAM_SPACE) { U32_TO_32(stb->st_size, p); } p += 4; if (infomask & INFO_MSK_ATTRIBUTE_INFO) { - uint32 attrib = (voloptions & VOL_OPTION_IS_PIPE) - ? (uint32) FILE_ATTR_SHARE - : (uint32) un_nw_attrib(stb, 0, 0); + uint32 attrib = ( (!S_ISDIR(stb->st_mode)) + && (voloptions & VOL_OPTION_IS_PIPE) ) + ? (uint32) FILE_ATTR_SHARE|FILE_ATTR_A + : (uint32) un_nw_attrib(stb, 0, 0); U32_TO_32(attrib, p); p += 4; U16_TO_16((uint16)(attrib & 0xFFFF), p); @@ -1517,7 +1526,8 @@ static int nw_open_creat_file_or_dir( int exist = result; uint8 last_part[258]; *last_part='\0'; - if (result < 0 && (opencreatmode & OPC_MODE_CREAT)) { /* do not exist */ + if (result < 0 && (opencreatmode & (OPC_MODE_CREAT|OPC_MODE_REPLACE))) { + /* do not exist */ result = build_base(namespace, nwp, pathes, 1, last_part); XDPRINTF((5, 0, "nw_open_c... result=%d, last_part='%s'", result, last_part)); @@ -1533,7 +1543,7 @@ static int nw_open_creat_file_or_dir( if (!(creatattrib & FILE_ATTR_DIR)) { int creatmode=0; /* open */ int attrib=0; - if (opencreatmode & (OPC_MODE_OPEN | OPC_MODE_CREAT) ) { + if (opencreatmode & (OPC_MODE_OPEN | OPC_MODE_CREAT| OPC_MODE_REPLACE) ) { if (opencreatmode & OPC_MODE_CREAT) { #if 0 if (exist > -1 && !(opencreatmode & OPC_MODE_REPLACE)) @@ -1547,7 +1557,7 @@ static int nw_open_creat_file_or_dir( nwpath_2_unix(&dbe->nwpath, 2), &(dbe->nwpath.statb), attrib, access_rights, creatmode, task)) > -1) { fhandle = (uint32) result; -#if 0 +#if 1 /* should be ok, 31-Jul-97 0.99.pl1 */ actionresult |= OPC_ACTION_OPEN; /* FILE OPEN */ #endif if (exist > -1 && (opencreatmode & OPC_MODE_REPLACE)) @@ -1572,32 +1582,136 @@ static int nw_open_creat_file_or_dir( return(result); } +typedef struct { + int searchattrib; + uint8 *ubuf; /* userbuff */ +} FUNC_SEARCH; + +static int func_search_entry(DIR_BASE_ENTRY *dbe, int namespace, + uint8 *path, int len, int searchattrib, + int (*fs_func)(DIR_BASE_ENTRY *dbe, FUNC_SEARCH *fs), FUNC_SEARCH *fs) +{ + int result=-0xff; + FUNC_SEARCH fs_local; + DIR_SEARCH_STRUCT *ds=(DIR_SEARCH_STRUCT*) xcmalloc(sizeof(DIR_SEARCH_STRUCT)); + if (!fs) { + fs = &fs_local; + fs->ubuf = NULL; + } + fs->searchattrib = searchattrib; + ds->unixname = (uint8*)nwpath_2_unix1(&(dbe->nwpath), 2, 258); + if (NULL != (ds->fdir = opendir(ds->unixname)) ) { + uint8 entry[257]; + uint8 *pe=entry; + int have_wild = 0; /* do we have a wildcard entry */ + int inode_search = 0; + uint8 *is_ap = NULL; /* one after point */ + struct dirent *dirbuff = NULL; + int vol_options = get_volume_options(dbe->nwpath.volume); + ds->kpath = ds->unixname+strlen(ds->unixname); + *(ds->kpath) = '/'; + *(++(ds->kpath)) = '\0'; + dbe->locked++; /* lock dbe */ + + while (len--) { + uint8 c=*path++; + *pe++=c; + if (!have_wild) { + if (c==0xff) { + if (*path == '?' || *path == '*' + || *path == 0xae || *path == 0xbf || *path==0xaa) + have_wild++; + } else if (c == '.') is_ap=pe; + } + } + *pe='\0'; + + if ((!have_wild) && is_ap && pe - is_ap == 3 && *is_ap== '_' + && *(is_ap+1) == '_' && *(is_ap+2) == '_') { + *(is_ap -1) = '\0'; + inode_search=atoi(entry); + *(is_ap -1) = '.'; + } + + if ( (namespace == NAME_DOS || namespace == NAME_OS2) + && !(vol_options & VOL_OPTION_IGNCASE) ) { + if (vol_options & VOL_OPTION_DOWNSHIFT) { + down_fn(entry); + } else { + up_fn(entry); + } + } + + while (NULL != (dirbuff=readdir(ds->fdir))) { + uint8 dname[257]; + if (search_match( dirbuff, + vol_options, + namespace, + inode_search, + entry, + searchattrib, + dname, + ds)) { + int dest_entry = get_add_new_entry(dbe, namespace, dname, 0); + if (dest_entry > -1) { + int res = (*fs_func)(dir_base[dest_entry], fs); + if (res < 0) { + result=res; + break; + } else + result=0; + } else { + XDPRINTF((2, 0, "func_search_entry:Cannot add entry '%s'", entry)); + } + } + } /* while */ + *(ds->kpath) = '\0'; + dbe->locked=0; + closedir(ds->fdir); + } else { /* if NULL != ds->fdir */ + XDPRINTF((5, 0, "func_search_entry:could not opendir=`%s`", ds->unixname)); + } + xfree(ds->unixname); + xfree(ds); + return(result); +} + +static int delete_file_dir(DIR_BASE_ENTRY *dbe, FUNC_SEARCH *fs) +/* callbackroutine */ +{ + uint8 *unname=(uint8*)nwpath_2_unix(&(dbe->nwpath), 2); + int result; + if (S_ISDIR(dbe->nwpath.statb.st_mode)) { + result = rmdir(unname); + if (result < 0) { + switch (errno) { + case EEXIST: result=-0xa0; /* dir not empty */ + default: result=-0x8a; /* No privilegs */ + } + } else { + result = 0; + free_dbe_p(dbe); + } + } else { + if (-1 < (result = nw_unlink(dbe->nwpath.volume, unname))) + free_dbe_p(dbe); + } + return(result); +} + + static int nw_delete_file_dir(int namespace, int searchattrib, NW_HPATH *nwp) { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + uint8 search_entry[258]; + int result = build_base(namespace, nwp, nwp->pathes, 1, search_entry); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; - uint8 *unname=(uint8*)nwpath_2_unix(&(dbe->nwpath), 2); if (get_volume_options(dbe->nwpath.volume) & - VOL_OPTION_READONLY) result = -0x8a; - else { - if (S_ISDIR(dbe->nwpath.statb.st_mode)) { - result = rmdir(unname); - if (result < 0) { - switch (errno) { - case EEXIST: result=-0xa0; /* dir not empty */ - default: result=-0x8a; /* No privilegs */ - } - } else { - result = 0; - free_dbe_p(dbe); - } - } else { - if (-1 < (result = nw_unlink(dbe->nwpath.volume, unname))) - free_dbe_p(dbe); - } - } + VOL_OPTION_READONLY) result = -0x8a; + else result=func_search_entry(dbe, namespace, + search_entry, strlen(search_entry), searchattrib, + delete_file_dir, NULL); } return(result); } @@ -1674,6 +1788,8 @@ static int nw_get_full_path_cookies(int namespace, *(p++) = (uint8)l; memcpy(p, pp, l); *(p+l)='\0'; + if (!namespace) + up_fn(p); k++; XDPRINTF((5, 0, "component=%d, path=`%s`", k ,p)); p+=l; @@ -2137,6 +2253,56 @@ static int code = 0; } +int fill_namespace_buffer(int volume, uint8 *rdata) +{ + if (volume < used_nw_volumes) { + int voloptions=get_volume_options(volume); + uint8 *p=rdata; + int count=0; + + *p++=5; /* we say 5 known namespaces (index 0=DOS .. 4=OS2 */ + + /* names */ + *p++=3; memcpy(p,"DOS", 3); p+=3; + *p++=9; memcpy(p,"MACINTOSH", 9); p+=9; + *p++=3; memcpy(p,"NFS", 3); p+=3; + *p++=4; memcpy(p,"FTAM", 4); p+=4; + *p++=3; memcpy(p,"OS2", 3); p+=3; + + /* datastreams */ + *p++=3; /* we say 3 datastreams here */ + + *p++=NAME_DOS; + *p++=19; memcpy(p,"Primary Data Stream", 19); p+=19; + + *p++=NAME_MAC; + *p++=23; memcpy(p,"Macintosh Resource Fork", 23); p+=23; + + *p++=NAME_FTAM; + *p++=20; memcpy(p,"FTAM Extra Data Fork", 20); p+=20; + + if (loaded_namespaces & VOL_NAMESPACE_DOS) ++count; + if (loaded_namespaces & VOL_NAMESPACE_OS2) ++count; + if (loaded_namespaces & VOL_NAMESPACE_NFS) ++count; + *p++ = count; /* loaded namespaces */ + if (loaded_namespaces & VOL_NAMESPACE_DOS) *p++ = NAME_DOS; + if (loaded_namespaces & VOL_NAMESPACE_OS2) *p++ = NAME_OS2; + if (loaded_namespaces & VOL_NAMESPACE_NFS) *p++ = NAME_NFS; + + count=0; + if (voloptions & VOL_NAMESPACE_DOS) ++count; + if (voloptions & VOL_NAMESPACE_OS2) ++count; + if (voloptions & VOL_NAMESPACE_NFS) ++count; + *p++ = count; /* volume namespaces */ + if (voloptions & VOL_NAMESPACE_DOS) *p++ = NAME_DOS; + if (voloptions & VOL_NAMESPACE_OS2) *p++ = NAME_OS2; + if (voloptions & VOL_NAMESPACE_NFS) *p++ = NAME_NFS; + *p++ = 1; /* only one datastream */ + *p++ = 0; /* DOS datastream */ + return((int)(p-rdata)); + } else return(-0x98); +} + int get_namespace_dir_entry(int volume, uint32 basehandle, int namspace, uint8 *rdata) { diff --git a/namspace.h b/namspace.h index 70adba3..5334014 100644 --- a/namspace.h +++ b/namspace.h @@ -1,4 +1,4 @@ -/* namspace.h 09-Nov-96 : NameSpace Services, mars_nwe */ +/* namspace.h 01-Aug-97 : NameSpace Services, mars_nwe */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * @@ -108,6 +108,7 @@ typedef struct { extern int handle_func_0x57(uint8 *p, uint8 *responsedata, int task); extern int handle_func_0x56(uint8 *p, uint8 *responsedata, int task); +extern int fill_namespace_buffer(int volume, uint8 *rdata); extern int get_namespace_dir_entry(int volume, uint32 basehandle, int namspace, uint8 *rdata); diff --git a/nwbind.c b/nwbind.c index 23b3c45..f6587a9 100644 --- a/nwbind.c +++ b/nwbind.c @@ -1,5 +1,5 @@ /* nwbind.c */ -#define REVISION_DATE "22-Jul-97" +#define REVISION_DATE "26-Aug-97" /* NCP Bindery SUB-SERVER */ /* authentification and some message handling */ @@ -22,6 +22,9 @@ #include "net.h" #include "nwdbm.h" #include "unxlog.h" +#include "nwbind.h" +#include "nwqueue.h" +#include "sema.h" /* next should be '1', is for testing only */ #define USE_PERMANENT_OUT_SOCKET 1 @@ -64,17 +67,6 @@ static void write_to_nwserv(int what, int connection, int mode, #define nwserv_down_server() \ write_to_nwserv(0xffff, 0, 0, NULL, 0) -typedef struct { - ipxAddr_t client_adr; /* address remote client */ - uint32 object_id; /* logged object */ - /* 0 = not logged in */ - uint8 crypt_key[8]; /* password generation */ - time_t t_login; /* login time */ - uint8 message[60]; /* saved BCastmessage */ - int active; /* 0=closed, 1= active */ - int send_to_sock; /* this is the receiving sock */ - int pid_nwconn; /* pid of user process nwconn */ -} CONNECTION; static int max_nw_vols=MAX_NW_VOLS; static int max_connections=MAX_CONNECTIONS; @@ -163,13 +155,17 @@ static void open_clear_connection(int conn, int activate, uint8 *addr) c->active = activate; c->message[0] = '\0'; c->t_login = 0; + if (activate && addr) { memcpy(&(c->client_adr), addr, sizeof(ipxAddr_t)); c->send_to_sock = GET_BE16(addr+sizeof(ipxAddr_t)); c->pid_nwconn = GET_BE32(addr+sizeof(ipxAddr_t)+sizeof(uint16)); - } else { + } else { /* down connection */ if (c->object_id) write_utmp(0, conn+1, c->pid_nwconn, &(c->client_adr), NULL); + if (c->count_semas) { + clear_conn_semas(c); + } } c->object_id = 0; } @@ -221,29 +217,38 @@ static void handle_fxx(int gelen, int func) uint8 len = *(requestdata+1); #endif - uint8 ufunc = *(requestdata+2); - uint8 *rdata = requestdata+3; + uint8 ufunc; + uint8 *rdata; uint8 completition = 0; uint8 connect_status= 0; int data_len = 0; - if (nw_debug > 1){ - int j = gelen - sizeof(NCPREQUEST); - if (nw_debug){ - if (func == 0x19) ufunc=0; - XDPRINTF((1, 0, "NCP 0x%x REQUEST:ufunc:0x%x", func, ufunc)); - if (j > 0){ - uint8 *p=requestdata; - XDPRINTF((1, 2, "len %d, DATA:", j)); - while (j--) { - int c = *p++; - if (c > 32 && c < 127) XDPRINTF((1, 3, ",\'%c\'", (char) c)); - else XDPRINTF((1, 3, ",0x%x", c)); - } - XDPRINTF((1, 1, NULL)); - } - } + if (func==0x19) { + ufunc = 0; + rdata = requestdata; + } else if (func==0x20) { + ufunc = *requestdata; + rdata = requestdata+1; + } else { + ufunc = *(requestdata+2); + rdata = requestdata+3; } + + MDEBUG(D_BIND_REQ, { + int j = gelen - sizeof(NCPREQUEST); + XDPRINTF((1, 0, "NCP 0x%x REQUEST:ufunc:0x%x", func, ufunc)); + if (j > 0){ + uint8 *p=requestdata; + XDPRINTF((1, 2, "len %d, DATA:", j)); + while (j--) { + int c = *p++; + if (c > 32 && c < 127) XDPRINTF((1, 3, ",\'%c\'", (char) c)); + else XDPRINTF((1, 3, ",0x%x", c)); + } + XDPRINTF((1, 1, NULL)); + } + }) + if (0x15 == func) { switch (ufunc) { /* Messages */ case 0x0 : { /* Send Broadcast Message (old) */ @@ -307,11 +312,13 @@ static void handle_fxx(int gelen, int func) case 0x29 : { /* Read volume restrictions */ /* Returns 3 integers, uid, gid, 0=OK/1=Permission denied */ uint32 id = GET_BE32(rdata+1); + internal_act=1; if (get_guid((int*) responsedata, (int*)(responsedata+sizeof(int)), id, (char *) NULL) != 0) { completition = 0xff; XDPRINTF((2, 0, "quota id-uid mapping failure %d 0x%x", ufunc, id)); } + internal_act=0; /* OK if supervisor or trying to read (0x29) own limits */ if (act_c->object_id == 1 || (act_c->object_id == id && ufunc == 0x29)) @@ -446,16 +453,20 @@ static void handle_fxx(int gelen, int func) ? (int) *rdata : act_connection) : GET_32(rdata); - if (conn && --conn < max_connections - && connections[conn].active ) { - CONNECTION *cx=&(connections[conn]); + if (conn >0 && conn <= max_connections + && connections[conn-1].active ) { + CONNECTION *cx=&(connections[conn-1]); data_len = sizeof(ipxAddr_t); memcpy(responsedata, (char*)&(cx->client_adr), data_len); if (ufunc==0x1a) { *(responsedata+data_len)=0x02; /* NCP connection */ data_len++; } - } else completition = 0xff; + } else { + XDPRINTF((1, 0, "Get Connection Internet Adress, Conn:%d of %d failed", + conn, max_connections)); + completition = 0xff; + } } break; case 0x14 : { /* Login Objekt, unencrypted passwords */ @@ -1087,94 +1098,178 @@ static void handle_fxx(int gelen, int func) completition=0xfb; } break; - - case 0x66 : { /* Read Queue Current Status,old */ - /* !!!!!! TO DO */ - NETOBJ obj; + case 0x66 : { /* Read Queue Current Status,old */ struct XDATA { - uint8 queue_id[4]; + uint8 id[4]; uint8 status; uint8 entries; uint8 servers; - uint8 data[1]; /* server_id + server_station list */ + uint8 data[1]; } *xdata = (struct XDATA*) responsedata; - obj.id = GET_BE32(rdata); - memset(xdata, 0, sizeof(struct XDATA)); - U32_TO_BE32(obj.id, xdata->queue_id); - data_len = sizeof(struct XDATA); - XDPRINTF((1, 0, "TODO:READ QUEUE STATUS,old of Q=0x%lx", obj.id)); + uint32 q_id = GET_BE32(rdata); + int status; + int entries; + int servers; + int server_ids[25]; + int server_conns[25]; + int result=nw_get_queue_status(q_id, &status, &entries, + &servers, server_ids, server_conns); + if (result>-1) { + int k; + uint8 *p=&(xdata->data[0]); + U32_TO_BE32(q_id, xdata->id); + xdata->status=status; + xdata->entries=entries; + xdata->servers=servers; + k=-1; + while (++k < servers) { + U32_TO_BE32(server_ids[k], p); + p+=4; + } + k=-1; + while (++k < servers) { + *p=(uint8) server_conns[k]; + ++p; + } + data_len=sizeof(struct XDATA)-1+5*servers; + } else + completition=(uint8)-result; } break; case 0x6A : /* Remove Job from Queue OLD */ case 0x80 : { /* Remove Job from Queue NEW */ - NETOBJ obj; - uint32 jobnr = (ufunc == 0x6A) + uint32 q_id = GET_BE32(rdata); + uint32 job_id = (ufunc == 0x6A) ? GET_BE16(rdata+4) : GET_BE32(rdata+4); - obj.id = GET_BE32(rdata); - XDPRINTF((1, 0, "TODO:Remove Job=%ld from Queue Q=0x%lx", jobnr, obj.id)); - completition=0xd5; /* no Queue Job */ - }break; - - case 0x6B : { /* Get Queue Job List, old */ - /* !!!!!! TO DO */ - NETOBJ obj; - obj.id = GET_BE32(rdata); - XDPRINTF((1, 0, "TODO:GET QUEUE JOB LIST,old of Q=0x%lx", obj.id)); - memset(responsedata, 0, 2); - data_len = 2; -#if 0 - completition=0xd5; /* no Queue Job */ -#endif + int result=nw_remove_job_from_queue( + act_c->object_id, + q_id, job_id); + if (result < 0) + completition=(uint8)-result; } break; - case 0x6C : { /* Get Queue Job Entry */ - /* !!!!!! TODO */ - NETOBJ obj; - obj.id = GET_BE32(rdata); - XDPRINTF((1, 0, "TODO: GET QUEUE JOB ENTRY of Q=0x%lx", obj.id)); + case 0x6B : { /* Get Queue Job List, old */ + uint32 q_id=GET_BE32(rdata); + int result=nw_get_queue_job_list_old(q_id, responsedata); + if (result > -1) + data_len=result; + else + completition=(uint8)-result; + } + break; - completition=0xd5; /* no Queue Job */ + case 0x6C : { /* Get Queue Job Entry old */ + uint32 q_id = GET_BE32(rdata); + int job_id = GET_BE16(rdata+4); + int result=nw_get_q_job_entry(q_id, job_id, + responsedata, 1); + if (result > -1) + data_len=result; + else completition=(uint8)-result; } break; case 0x68: /* creat queue job and file old */ case 0x79: { /* creat queue job and file new */ - uint32 q_id = GET_BE32(rdata); - uint8 *dir_name = responsedata+1; - int result = nw_get_q_dirname(q_id, dir_name); - if (result > -1) { - *(dir_name-1) = result; - data_len = result+1; - } else { - /* - static int re=0x96; - */ - completition = (uint8) 0xd3; /* err no queue rights */ - /* - if (re == 0x96) re=0xd0; - else if (re < 0xff) ++re; - */ - } + uint32 q_id = GET_BE32(rdata); + uint8 *q_job = rdata+4; /* jobsize = 256(old) or 280 */ + int result = nw_creat_queue_job( + act_connection, ncprequest->task, + act_c->object_id, + q_id, q_job, + responsedata, + ufunc==0x68); + if (result > -1) + data_len=result; + else + completition = (uint8) -result; + /*0xd3 err no queue rights */ } break; case 0x69: /* close file and start queue old ?? */ case 0x7f: { /* close file and start queue */ uint32 q_id = GET_BE32(rdata); - uint8 *prc = responsedata+1; - int result = nw_get_q_prcommand(q_id, prc); - if (result > -1) { - *(prc-1) = result; - data_len = result+1; - } else completition = (uint8) 0xff; + uint32 job_id = (ufunc==0x69) + ? GET_BE16(rdata+4) + : GET_BE32(rdata+4); + int result = nw_close_queue_job(q_id, job_id, + responsedata); + if (result > -1) + data_len=result; + else + completition = (uint8) -result; } break; + case 0x6f : { /* attach server to queue */ + /* from pserver */ + uint32 q_id = GET_BE32(rdata); + int result=nw_attach_server_to_queue( + act_c->object_id, + act_connection, + q_id); + if (result < 0) + completition = (uint8) -result; + /* NO REPLY */ + } + break; + + case 0x70 : { /* detach server from queue */ + /* from pserver */ + uint32 q_id = GET_BE32(rdata); + int result=nw_detach_server_from_queue( + act_c->object_id, + act_connection, + q_id); + if (result < 0) + completition = (uint8) -result; + /* NO REPLY */ + } + break; + + case 0x78: /* Get Queue Job File Size (old) */ + case 0x87: /* Get Queue Job File Size */ + { + uint32 q_id = GET_BE32(rdata); + uint32 job_id = (ufunc==0x78) + ? GET_BE16(rdata+4) + : GET_BE32(rdata+4); + int result = nw_get_queue_job_file_size(q_id, job_id); + if (result > -1) { + uint8 *p=responsedata; + U32_TO_BE32(q_id, p); p+=4; + if (ufunc==0x78) { + U16_TO_BE16(job_id, p); p+=2; + } else { + U32_TO_BE32(job_id, p); p+=4; + } + U32_TO_BE32(result, p); p+=4; + data_len=(int)(p-responsedata); + } else + completition = (uint8) -result; + } + break; + + case 0x7c : { /* service queue job */ + uint32 q_id = GET_BE32(rdata); + int type = GET_BE16(rdata+4); + int result=nw_service_queue_job( + act_c->object_id, + act_connection, ncprequest->task, + q_id, type, responsedata, 0); + if (result > -1) + data_len=result; + else + completition=(uint8)-result; + } + break; + + case 0x7d : { /* Read Queue Current Status, new */ - NETOBJ obj; struct XDATA { uint8 id[4]; /* queue id */ uint8 status[4]; /* &1 no station allowed */ @@ -1183,11 +1278,34 @@ static void handle_fxx(int gelen, int func) uint8 entries[4]; /* current entries */ uint8 servers[4]; /* current servers */ } *xdata = (struct XDATA*) responsedata; - obj.id = GET_BE32(rdata); - XDPRINTF((1, 0, "TODO:READ QUEUE STATUS NEW of Q=0x%lx", obj.id)); - memset(xdata, 0, sizeof(*xdata)); - U32_TO_BE32(obj.id, xdata->id); - data_len=sizeof(struct XDATA); + uint32 q_id = GET_BE32(rdata); + int status; + int entries; + int servers; + int server_ids[25]; + int server_conns[25]; + int result=nw_get_queue_status(q_id, &status, &entries, + &servers, server_ids, server_conns); + if (result>-1) { + int k; + uint8 *p=responsedata+sizeof(*xdata); + U32_TO_BE32(q_id, xdata->id); + U32_TO_32(status, xdata->status); + U32_TO_32(entries, xdata->entries); + U32_TO_32(servers, xdata->servers); + k=-1; + while (++k < servers) { + U32_TO_BE32(server_ids[k], p); + p+=4; + } + k=-1; + while (++k < servers) { + U32_TO_32(server_conns[k], p); + p+=4; + } + data_len=sizeof(struct XDATA)+8*servers; + } else + completition=(uint8)-result; } break; case 0x81 : { /* Get Queue Job List */ @@ -1203,6 +1321,37 @@ static void handle_fxx(int gelen, int func) data_len=sizeof(struct XDATA); }break; + case 0x83: { /* finish servicing queue job */ + uint32 q_id = GET_BE32(rdata); + uint32 job_id = GET_BE32(rdata+4); +#if 0 + uint32 chargeinfo = GET_BE32(rdata+8); +#endif + int result = nw_finish_abort_queue_job(0, + act_c->object_id, + act_connection, + q_id, job_id); + if (result <0) + completition=(uint8) -result; + }break; + + case 0x84: { /* abort servicing queue job */ + uint32 q_id = GET_BE32(rdata); + uint32 job_id = GET_BE32(rdata+4); + int result = nw_finish_abort_queue_job(1, + act_c->object_id, + act_connection, + q_id, job_id); + if (result <0) + completition=(uint8) -result; + else { + memset(responsedata, 0, 2); + data_len=2; + } + }break; + + + case 0xc8 : { /* CHECK CONSOLE PRIVILEGES */ XDPRINTF((1, 0, "TODO: CHECK CONSOLE PRIV")); /* !!!!!! TODO completition=0xc6 (no rights) */ @@ -1283,14 +1432,18 @@ static void handle_fxx(int gelen, int func) #if 0 case 0xfd : /* Send Console Broadcast (new) */ return(-1); /* nicht erkannt */ - break; #endif default : completition = 0xfb; /* not known here */ + break; } /* switch */ } else if (func == 0x19) { /* logout */ write_utmp(0, act_connection, act_c->pid_nwconn, &(act_c->client_adr), NULL); act_c->object_id = 0; /* not LOGIN */ + } else if (0x20 == func) { /* Semaphore */ + int result = handle_func_0x20(act_c, rdata, ufunc, responsedata); + if (result > -1) data_len = result; + else completition=(uint8)-result; } else completition = 0xfb; U16_TO_BE16(0x3333, ncpresponse->type); @@ -1346,8 +1499,11 @@ static void handle_bind_calls(uint8 *p) static void reinit_nwbind(void) { + int org_internal_act=internal_act; get_ini_debug(NWBIND); + internal_act=1; (void)nw_fill_standard(NULL, NULL); + internal_act=org_internal_act; sync_dbm(); } @@ -1561,7 +1717,8 @@ int main(int argc, char *argv[]) t_close(ipx_out_fd); } } - sync_dbm(); + internal_act=1; + nw_exit_dbm(); xfree(connections); XDPRINTF((2,0, "LEAVE nwbind")); return(0); diff --git a/nwbind.h b/nwbind.h new file mode 100644 index 0000000..e568382 --- /dev/null +++ b/nwbind.h @@ -0,0 +1,28 @@ +/* nwbind.h 07-Aug-97 */ + +#ifndef _NWBIND_H_ +#define _NWBIND_H_ + +#define MAX_SEMA_CONN 10 /* 10 Semaphore pre connection */ + + +typedef struct { + int handle; /* semahore handle */ + int opencount; /* times open */ +} SEMA_CONN; + +typedef struct { + ipxAddr_t client_adr; /* address remote client */ + uint32 object_id; /* logged object */ + /* 0 = not logged in */ + uint8 crypt_key[8]; /* password generation */ + time_t t_login; /* login time */ + uint8 message[60]; /* saved BCastmessage */ + int active; /* 0=closed, 1= active */ + int send_to_sock; /* this is the receiving sock */ + int pid_nwconn; /* pid of user process nwconn */ + int count_semas; /* open semahores */ + SEMA_CONN semas[MAX_SEMA_CONN]; +} CONNECTION; + +#endif diff --git a/nwconn.c b/nwconn.c index 0184402..94a734b 100644 --- a/nwconn.c +++ b/nwconn.c @@ -1,4 +1,4 @@ -/* nwconn.c 20-Jul-97 */ +/* nwconn.c 14-Aug-97 */ /* one process / connection */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany @@ -28,13 +28,10 @@ #include "nwvolume.h" #include "nwfile.h" #include "connect.h" -#include "nwqueue.h" +#include "nwqconn.h" #include "namspace.h" #include "nwconn.h" -IPX_IO_RW ipx_io; -int use_ipx_io=0; - int act_connection = 0; int act_pid = 0; @@ -92,8 +89,8 @@ typedef struct { struct t_unitdata ud; ipxAddr_t to_addr; - uint8 *recv_buf; /* complete data buf for burst read requests - * must be 24 byte more allocated + uint8 *recv_buf; /* complete data buf for burst read requests + * must be 24 byte more allocated * than max_recv_size ! */ @@ -108,9 +105,9 @@ static BURST_W *burst_w=NULL; static void set_program_title(char *s) { memset(prog_title, 0, 49); - if (s&&*s) + if (s&&*s) strmaxcpy(prog_title, s, 48); - else + else strcpy(prog_title, "()"); } @@ -541,8 +538,8 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', } } completition = (uint8)-result; - } else if (*p == 0x19){ - /* Set Directory Information + } else if (*p == 0x19){ + /* Set Directory Information * Modifies basic directory information as creation date and * directory rights mask. DOS namespace. */ @@ -550,8 +547,8 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', struct INPUT { uint8 header[7]; /* Requestheader */ uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; - uint8 creation_date[2]; + uint8 dir_handle; + uint8 creation_date[2]; uint8 creation_time[2]; uint8 owner_id[4]; uint8 new_max_rights; @@ -633,17 +630,17 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', /* remove Vol restrictions for Obj */ XDPRINTF((5, 0, "Remove vol restrictions")); return(-2); /* nwbind must do prehandling */ - } else if (*p == 0x25){ - /* Set Entry, Set Directory File Information + } else if (*p == 0x25){ + /* Set Entry, Set Directory File Information * sets or changes the file or directory information to the * values entered in 'Change Bits'. */ /* NO REPLY */ /* ncopy use this call */ /* TODO !!!!!!!!!!!!!!!!!!!! */ - + do_druck++; - + } else if (*p == 0x26) { /* Scan file or Dir for ext trustees */ int sequenz = (int)*(p+2); /* trustee sequenz */ struct XDATA { @@ -806,10 +803,18 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', } else completition = (uint8) -result; } else if (*p == 0x2e){ /* RENAME DATEI */ completition = 0xfb; /* TODO: !!! */ - } else if (*p == 0x2f){ /* Fill namespace buffer */ - completition = 0xfb; /* TODO: !!! */ - /* ncopy use this call */ + #if WITH_NAME_SPACE_CALLS + } else if (*p == 0x2f){ + /* Fill namespace buffer */ + /* ncopy use this call */ + int volume = (int) *(p+1); + /* (p+2) == 0xe4 or 0xe2 sometimes ???? */ + int result=fill_namespace_buffer( + volume, responsedata); + if (result > -1) { + data_len = result; + } else completition = (uint8) -result; } else if (*p == 0x30){ /* Get Name Space Directory Entry */ int volume = (int) *(p+1); @@ -929,11 +934,54 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', break; case 0x68: /* create queue job and file old */ - case 0x69: /* close file and start queue old ?? */ case 0x79: /* create queue job and file */ - case 0x7f: /* close file and start queue */ return(-2); /* nwbind must do prehandling */ + case 0x69: /* close file and start queue old ?? */ + case 0x7f: { /* close file and start queue */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 packetlen[2]; /* low high */ + uint8 func; /* 0x7f or 0x69 */ + uint8 queue_id[4]; /* Queue ID */ + uint8 job_id[4]; /* result from creat queue */ + /* if 0x69 then only first 2 byte ! */ + } *input = (struct INPUT *) (ncprequest); + uint32 q_id = GET_BE32(input->queue_id); + int job_id = (ufunc==0x69) ? GET_BE16(input->job_id) + : GET_BE32(input->job_id); + int result = close_queue_job(q_id, job_id); + if (result < 0) { + completition = (uint8)-result; + } else { + return(-2); /* nwbind must do next */ + } + } + break; + + case 0x7c : /* service queue job */ + return(-2); /* nwbind must do prehandling */ + + case 0x83 : /* finish queue job */ + case 0x84 : { /* abort queue job */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 packetlen[2]; /* low high */ + uint8 func; /* 0x7f or 0x69 */ + uint8 queue_id[4]; /* Queue ID */ + uint8 job_id[4]; /* result from creat queue */ + /* if 0x69 then only first 2 byte ! */ + } *input = (struct INPUT *) (ncprequest); + uint32 q_id = GET_BE32(input->queue_id); + int job_id = GET_BE32(input->job_id); + int result = finish_abort_queue_job(q_id, job_id); + if (result <0) + completition=(uint8) -result; + else + return(-1); /* nwbind must do the rest */ + } + break; + case 0xf3: { /* Map Direktory Number TO PATH */ XDPRINTF((2,0, "TODO: Map Directory Number TO PATH")); completition = 0xff; @@ -957,6 +1005,7 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', break; case 0x19 : /* logout, some of this call is handled in ncpserv. */ + free_queue_jobs(); nw_free_handles(-1); set_default_guid(); nw_setup_home_vol(-1, NULL); @@ -965,6 +1014,9 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', return(-1); /* nwbind must do a little rest */ break; + case 0x20 : /* Semaphore */ + return(-1); /* handled by nwbind */ + case 0x1a : /* lock file */ case 0x1e : /* unlock file */ { @@ -1583,23 +1635,21 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', burst_w->max_send_size= min(max_burst_send_size, GET_BE32(input->max_recv_size)); - -#if 1 /* MUST BE REMOVED LATER !!! */ - /* we don't want fragment send packets */ - if (burst_w->max_send_size > - burst_w->max_burst_data_size-8) - burst_w->max_send_size - =burst_w->max_burst_data_size-8; -#endif - burst_w->send_buf=xcmalloc(burst_w->max_send_size+8); burst_w->max_recv_size= min(max_burst_recv_size, GET_BE32(input->max_send_size)); +#if 1 /* MUST BE REMOVED LATER !!! */ + /* we don't want fragmented receive packets */ + if (burst_w->max_recv_size > + burst_w->max_burst_data_size-24) + burst_w->max_recv_size + =burst_w->max_burst_data_size-24; +#endif burst_w->recv_buf=xcmalloc(burst_w->max_recv_size+24); -#if 0 - U32_TO_BE32(0x1600, burst_w->sendburst->delaytime); +#if 1 + U32_TO_BE32(0x5ff22, burst_w->sendburst->delaytime); #endif U32_TO_BE32(burst_w->max_recv_size, xdata->max_recv_size); U32_TO_BE32(burst_w->max_send_size, xdata->max_send_size); @@ -1635,6 +1685,7 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', } /* switch function */ } else if (ncp_type == 0x1111) { + free_queue_jobs(); (void) nw_init_connect(); last_sequence = -9999; } else { @@ -1771,7 +1822,7 @@ static void handle_after_bind() case 0x68: /* create queue job and file old */ case 0x79: { /* create queue job and file */ - /* nwbind must do prehandling */ + /* nwbind made prehandling */ struct INPUT { uint8 header[7]; /* Requestheader */ uint8 packetlen[2]; /* low high */ @@ -1779,22 +1830,15 @@ static void handle_after_bind() uint8 queue_id[4]; /* Queue ID */ uint8 queue_job[280]; /* oldsize is 256 */ } *input = (struct INPUT *) (ncprequest); - struct RINPUT { - uint8 dir_nam_len; /* len of dirname */ - uint8 dir_name[1]; - } *rinput = (struct RINPUT *) (bindresponse); - int result = nw_creat_queue( - (int)ncpresponse->connection - | (((int)ncpresponse->high_connection) << 8), - input->queue_id, - input->queue_job, - rinput->dir_name, - (int)rinput->dir_nam_len, - (ufunc == 0x68) ); - if (!result) { - data_len = (ufunc == 0x68) ? 54 : 78; - memcpy(responsedata, input->queue_job, data_len); - } else completition= (uint8)-result; + uint32 q_id = GET_BE32(input->queue_id); + uint8 *qjob = bindresponse; + int result = creat_queue_job(q_id, qjob, + responsedata, + (ufunc == 0x68) ); + if (result > -1) + data_len=result; + else + completition = (uint8) -result; } break; @@ -1803,22 +1847,47 @@ static void handle_after_bind() struct INPUT { uint8 header[7]; /* Requestheader */ uint8 packetlen[2]; /* low high */ - uint8 func; /* 0x7f or 0x6f */ + uint8 func; /* 0x7f or 0x69 */ uint8 queue_id[4]; /* Queue ID */ uint8 job_id[4]; /* result from creat queue */ /* if 0x69 then only 2 byte ! */ } *input = (struct INPUT *) (ncprequest); struct RINPUT { + uint8 client_area[152]; uint8 prc_len; /* len of printcommand */ uint8 prc[1]; /* printcommand */ } *rinput = (struct RINPUT *) (bindresponse); - int result = nw_close_file_queue(input->queue_id, - input->job_id, + uint32 q_id = GET_BE32(input->queue_id); + int job_id = (ufunc==0x69) ? GET_BE16(input->job_id) + : GET_BE32(input->job_id); + + int result = close_queue_job2(q_id, job_id, + rinput->client_area, rinput->prc, rinput->prc_len); if (result < 0) completition = (uint8)-result; } break; + + case 0x7c : { /* service queue job */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 packetlen[2]; /* low high */ + uint8 func; /* 0x7c */ + uint8 queue_id[4]; /* Queue ID */ + uint8 job_typ[2]; /* service typ */ + } *input = (struct INPUT *) (ncprequest); + uint32 q_id = GET_BE32(input->queue_id); + uint8 *qjob = bindresponse; + int result = service_queue_job(q_id, qjob, + responsedata, 0); + if (result > -1) + data_len=result; + else + completition = (uint8) -result; + } + break; + default : completition = 0xfb; } } @@ -1864,7 +1933,7 @@ static void handle_burst_response(uint32 offset, int size) U16_TO_BE16(burst_w->burst_sequence, sb->burst_seq); U16_TO_BE16(burst_w->burst_sequence+1, sb->ack_seq); U32_TO_BE32(size, sb->burstsize); - + while (size) { int sendsize=min(size, burst_w->max_burst_data_size); int flags=0; @@ -1901,8 +1970,8 @@ static void handle_burst(BURSTPACKET *bp, int len) struct REQ { uint8 function[4]; /* lo-hi 1=READ, 2=WRITE */ uint8 fhandle[4]; /* from open file */ - uint8 reserved1[6]; /* all zero */ - uint8 reserved2[2]; /* ??? c8,0 od. c9,f0 */ + uint8 reserved1[4]; /* all zero */ + uint8 reserved2[4]; /* ??? c8,0 od. c9,f0 */ uint8 file_offset[4]; /* HI-LO */ uint8 file_size [4]; /* HI-LO */ uint8 data[2]; /* only Write */ @@ -1923,9 +1992,13 @@ static void handle_burst(BURSTPACKET *bp, int len) */ uint8 readbytes[4]; /* hi-lo */ } *xdata= (struct XDATA*)burst_w->send_buf; - int size = nw_read_file(fhandle, + int zusatz = 0; /* (foffset & 1) ? 1 : 0; */ + int size = nw_read_file(fhandle, burst_w->send_buf+sizeof(struct XDATA), fsize, foffset); + if (zusatz) { + XDPRINTF((1, 0, "foffset=%d, fsize=%d", foffset, fsize)); + } if (size > -1) { U32_TO_32(0, xdata->resultcode); U32_TO_BE32(size, xdata->readbytes); @@ -1948,7 +2021,10 @@ static void handle_burst(BURSTPACKET *bp, int len) burst_w->burst_sequence = burstsequence; handle_burst_response(0, sizeof(struct XDATA)); } + } else { + XDPRINTF((1, 0, "burst unknow function=0x%x", function)); } + req->function[0]=0; } else if (bp->flags & 0x80) { /* System Flag */ int missing=GET_BE16(bp->missing); uint8 *p=(uint8*)(bp+1); @@ -2013,11 +2089,11 @@ static void set_sig(void) int main(int argc, char **argv) { - if (argc != 4 || 3!=sscanf(argv[3], "()INIT-:%x,%x,%x-", + if (argc != 4 || 3!=sscanf(argv[3], "()INIT-:%x,%x,%x-", &father_pid, &sock_nwbind, &sock_echo)) { fprintf(stderr, "usage nwconn connid FROM_ADDR ()INIT-:pid,nwbindsock,echosock-\n"); exit(1); - } + } prog_title=argv[3]; setuid(0); setgid(0); @@ -2027,7 +2103,7 @@ int main(int argc, char **argv) XDPRINTF((2, 0, "FATHER PID=%d, ADDR=%s CON:%d", father_pid, *(argv+2), act_connection)); adr_to_ipx_addr(&from_addr, *(argv+2)); - + if (nw_init_connect()) exit(1); act_pid = getpid(); @@ -2044,9 +2120,6 @@ int main(int argc, char **argv) int conn = act_connection; int result = ioctl(0, SIOCIPXNCPCONN, &conn); XDPRINTF((2, 0, "ioctl:SIOCIPXNCPCONN result=%d", result)); -#if 0 - if (result == 1) use_ipx_io++; -#endif } # endif # endif @@ -2069,27 +2142,10 @@ int main(int argc, char **argv) ncpresponse->connection = (uint8)act_connection; ncpresponse->high_connection = (uint8)(act_connection >> 8); - ipx_io.ubuf = readbuff; - ipx_io.size = sizeof(readbuff); - ipx_io.ncp_resp = (char*)&ipxdata; - ipx_io.resp_size= sizeof(ipxdata); - - ipx_io.fh_r = 0; - ipx_io.fd_r = -1; - ipx_io.fh_w = 0; - ipx_io.fd_w = -1; - set_sig(); while (fl_get_int >= 0) { - int data_len ; -#ifdef SIOCIPXNCPCONN - if (use_ipx_io) - data_len = ioctl(0, SIOCIPXNCPCONN+1, &ipx_io); - else -#endif - data_len = read(0, readbuff, sizeof(readbuff)); - + int data_len = read(0, readbuff, sizeof(readbuff)); /* this read is a pipe or a socket read, * depending on CALL_NWCONN_OVER_SOCKET */ diff --git a/nwconn.h b/nwconn.h index 5dc6584..7d9a613 100644 --- a/nwconn.h +++ b/nwconn.h @@ -1,23 +1,6 @@ +/* nwconn.h 01-Aug-97 */ #ifndef _NWCONN_H_ #define _NWCONN_H_ - -typedef struct { - int size; /* max. read size or write size */ - char *ubuf; /* readbuf */ - /* ------------------------------*/ - char *ncp_resp; /* response packet */ - int resp_size; /* max. size of response packet */ - /* ------------------------------*/ - int fh_r; /* NCP-Filehandle, read */ - int fd_r; /* file-descriptor, read */ - - int fh_w; /* NCP-Filehandle, write */ - int fd_w; /* file-descriptor, write */ -} IPX_IO_RW; - -extern IPX_IO_RW ipx_io; -extern int use_ipx_io; - extern int act_connection; extern int act_pid; #endif diff --git a/nwdbm.c b/nwdbm.c index 84719b6..79b473d 100644 --- a/nwdbm.c +++ b/nwdbm.c @@ -1,4 +1,4 @@ -/* nwdbm.c 24-Jul-97 data base for mars_nwe */ +/* nwdbm.c 16-Aug-97 data base for mars_nwe */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -24,6 +24,7 @@ #include "net.h" #include "nwdbm.h" #include "nwcrypt.h" +#include "nwqueue.h" #include "dirent.h" #ifdef LINUX @@ -60,7 +61,7 @@ uint32 network_serial_nmbr=(uint32)NETWORK_SERIAL_NMBR; uint16 network_appl_nmbr=(uint16)NETWORK_APPL_NMBR; static int entry8_flags = 0; -static uint8 *sys_unixname=NULL; /* Unixname of SYS: */ +static uint8 *sys_unixname=NULL; /* Unixname of SYS: ends with '/' */ static int sys_unixnamlen=0; /* len of unixname */ static int sys_downshift=0; /* is SYS downshift */ @@ -153,10 +154,33 @@ void sync_dbm() #ifdef USE_GDBM -# define firstkey() gdbm_firstkey(my_dbm) -# define nextkey(key) gdbm_nextkey(my_dbm, key) +static datum firstkey(void) +{ + static char *last_dptr=NULL; + datum result=gdbm_firstkey(my_dbm); + if (last_dptr) free(last_dptr); + last_dptr=result.dptr; + return(result); +} + +static datum nextkey(datum key) +{ + static char *last_dptr=NULL; + datum result=gdbm_nextkey(my_dbm, key); + if (last_dptr) free(last_dptr); + last_dptr=result.dptr; + return(result); +} + +static datum fetch(datum key) +{ + static char *last_dptr=NULL; + datum result=gdbm_fetch(my_dbm, key); + if (last_dptr) free(last_dptr); + last_dptr=result.dptr; + return(result); +} # define delete(key) gdbm_delete(my_dbm, key) -# define fetch(key) gdbm_fetch(my_dbm, key) # define store(key, content) gdbm_store(my_dbm, key, content, GDBM_REPLACE) #else # define firstkey() dbm_firstkey(my_dbm) @@ -218,11 +242,11 @@ int find_obj_id(NETOBJ *o) int result; XDPRINTF((2, 0,"findobj_id OBJ=%s, type=0x%x", o->name,(int)o->type)); if ((result=handle_iobj(0, o)) == 0) { + result = -0xff; if (!dbminit(FNOBJ)){ key.dsize = NETOBJ_KEY_SIZE; key.dptr = (char*)o; data = fetch(key); - result = -0xff; if (data.dptr != NULL){ NETOBJ *obj=(NETOBJ*)data.dptr; XDPRINTF((3,0, "got OBJ name=%s, id = 0x%x", obj->name, (int)obj->id)); @@ -239,7 +263,7 @@ int find_obj_id(NETOBJ *o) XDPRINTF((1,0, "OBJ Index '%s',0x%x, id=0x%x not found in OBJ data", o->name, (int)o->type, o->id)); } - } else result = -0xff; + } dbmclose(); if (!result) return(0); @@ -827,6 +851,17 @@ int nw_delete_property(int object_type, return(result); } +int nw_is_member_in_set(uint32 obj_id, char *propname, uint32 member_id) +{ + NETPROP prop; + int result; + strmaxcpy(prop.name, propname, sizeof(prop.name)); + result=find_first_prop_id(&prop, obj_id); + if (!result) + result = prop_find_member(obj_id, (int)prop.id, prop.security, member_id); + return(result); +} + int nw_is_obj_in_set(int object_type, uint8 *object_name, int object_namlen, uint8 *prop_name, int prop_namlen, @@ -998,8 +1033,9 @@ int nw_get_prop_val_str(uint32 q_id, char *propname, uint8 *buff) if (result > -1) { result=strlen(buff); XDPRINTF((5,0, "nw_get_prop_val_str:%s strlen=%d", propname, result)); - } else + } else { XDPRINTF((5,0, "nw_get_prop_val_str:%s, result=-0x%x", propname, -result)); + } return(result); } @@ -1078,6 +1114,19 @@ static int nw_create_obj_prop(uint32 obj_id, NETPROP *prop) prop->id = p->id; prop->obj_id = obj_id; result = -0xed; /* Property exists */ + if (p->security != prop->security || + p->flags != prop->flags) { + /* added 16-Aug-97 0.99.pl1 */ + XDPRINTF((1, 0, "prop '%s' got new security/flag=0x%x / %d", + p->name, p->security, p->flags)); + p->security=prop->security; + p->flags=prop->flags; + key.dsize = NETPROP_KEY_SIZE; + key.dptr = (char *)p; + data.dsize = sizeof(NETPROP); + data.dptr = (char *)p; + if (store(key, data)) result = -0xff; + } break; } else founds[p->id]++; } @@ -1515,6 +1564,7 @@ int nw_test_adr_time_access(uint32 obj_id, ipxAddr_t *client_adr) return(result); } + static int nw_new_add_prop_member(uint32 obj_id, char *propname, int propflags, int propsecurity, uint32 member_id) @@ -1534,13 +1584,19 @@ static int nw_new_add_prop_member(uint32 obj_id, char *propname, return(result); } -static int xmkdir(char *unixname, int mode) +int nwdbm_mkdir(char *unixname, int mode, int flags) +/* flags & 1 = set x permiss flag in upper dirs */ { char *p=unixname; while (NULL != (p=strchr(p+1, '/'))) { *p = '\0'; if (!mkdir(unixname, mode)) chmod(unixname, mode); + else if (flags&1){ + struct stat stb; + if (!stat(unixname, &stb)) + chmod(unixname, stb.st_mode|0111); + } *p='/'; } if (!mkdir(unixname, mode)) { @@ -1557,7 +1613,7 @@ static void create_nw_db(char *fn, int always) (void)get_div_pathes(fname, fn, 1, ".dir"); if (stat(fname, &stbuff)){ (void)get_div_pathes(fname, NULL, 1, NULL); - xmkdir(fname, 0700); + nwdbm_mkdir(fname, 0700, 0); (void)get_div_pathes(fname, fn, 1, ".dir"); } if (always || stat(fname, &stbuff)){ @@ -1573,30 +1629,54 @@ static void create_nw_db(char *fn, int always) chmod(fname, 0600); } - static void add_pr_queue(uint32 q_id, char *q_name, char *q_directory, char *q_command, uint32 su_id, uint32 ge_id) { + uint8 buf[300]; + nw_new_obj(&q_id, q_name, 0x3, O_FL_STAT, 0x31); + + if (!q_directory || !*q_directory) { + q_directory=buf; + sprintf(q_directory, "SYS:/SYSTEM/%08lX.QDR", q_id); + } XDPRINTF((2,0, "ADD Q=%s, V=%s, C=%s", q_name, q_directory, q_command)); - q_id = - nw_new_obj_prop(q_id, q_name, 0x3, O_FL_DYNA, 0x31, + nw_new_obj_prop(q_id, NULL, 0, 0, 0, "Q_DIRECTORY", P_FL_ITEM, 0x31, q_directory, strlen(q_directory), 1); - /* this is mars_nwe own property to handle the print job !!! */ - nw_new_obj_prop(q_id ,NULL, 0 , 0 , 0 , + /* this is mars_nwe own property to handle the print job direct !!! */ + if (q_command && *q_command) { + nw_new_obj_prop(q_id ,NULL, 0 , 0 , 0 , "Q_UNIX_PRINT", P_FL_ITEM| P_FL_DYNA, 0x31, q_command, strlen(q_command), 1); - + } nw_new_add_prop_member(q_id, "Q_USERS", P_FL_STAT, 0x31, ge_id); nw_new_add_prop_member(q_id, "Q_OPERATORS", P_FL_STAT, 0x31, su_id); -#if 0 nw_new_obj_prop(q_id , NULL, 0 , 0 , 0 , "Q_SERVERS", P_FL_SET, 0x31, NULL, 0, 0); -#endif +} + +static void add_pr_server(uint32 ps_id, + char *ps_name, + char *ps_queue, + uint32 su_id, uint32 ge_id) +{ + XDPRINTF((2,0, "ADD PS=%s, Q=%s", ps_name, ps_queue)); + nw_new_obj(&ps_id, ps_name, 0x7, O_FL_STAT, 0x31); + nw_new_add_prop_member(ps_id, "PS_OPERATORS", P_FL_STAT, 0x31, su_id); + nw_new_add_prop_member(ps_id, "PS_USERS", P_FL_STAT, 0x31, ge_id); + + if (ps_queue && *ps_queue) { + NETOBJ obj; + strmaxcpy((char*)obj.name, (char*)ps_queue, 47); + obj.type = 0x3; /* QUEUE */ + if (!find_obj_id(&obj)) + nw_new_add_prop_member(obj.id, "Q_SERVERS", P_FL_STAT, 0x31, ps_id); + } + } static void add_user_to_group(uint32 u_id, uint32 g_id) @@ -1610,7 +1690,7 @@ static void add_user_2_unx(uint32 u_id, char *unname) { if (unname && *unname) nw_new_obj_prop(u_id, NULL, 0 , 0 , 0 , - pn_unix_user, P_FL_ITEM, 0x33, + pn_unix_user, P_FL_ITEM, 0x30, (char*)unname, strlen(unname), 1); } @@ -1703,7 +1783,7 @@ static int get_sys_unixname(uint8 *unixname, uint8 *sysname, uint8 *sysentry) *(pp+1) = '\0'; if (stat(unixname, &statb) < 0) - xmkdir(unixname, 0777); + nwdbm_mkdir(unixname, 0777, 1); if (stat(unixname, &statb) < 0 || !S_ISDIR(statb.st_mode)) { errorp(1, "No good SYS", "unix name='%s'", unixname); @@ -1720,13 +1800,14 @@ static uint8 *test_add_dir(uint8 *unixname, uint8 *pp, int flags, /* flags & 1 = fn will be appended to unixname */ /* flags & 2 = always modify uid/gid, permission */ +/* flags & 4 = always add x flag to upper dirs */ { struct stat stb; strcpy((char*)pp, fn); if (downshift) downstr(pp); else upstr(pp); if (stat(unixname, &stb) < 0) { - if (xmkdir(unixname, permiss)< 0) + if (nwdbm_mkdir(unixname, permiss, (flags&4) ? 1 : 0)< 0) errorp(1, "mkdir error", "fname='%s'", unixname); else { chmod(unixname, permiss); @@ -1734,10 +1815,22 @@ static uint8 *test_add_dir(uint8 *unixname, uint8 *pp, int flags, chown(unixname, uid, gid); XDPRINTF((1, 0, "Created dir '%s'", unixname)); } - } else if (flags&2) { - chmod(unixname, permiss); - if (uid >-1 && gid > -1) - chown(unixname, uid, gid); + } else { + if (flags&4) { /* add 'x' flag */ + char *p=unixname; + while (NULL != (p=strchr(p+1, '/'))) { + struct stat stb; + *p = '\0'; + if (!stat(unixname, &stb)) + chmod(unixname, stb.st_mode|0111); + *p='/'; + } + } + if (flags&2) { + chmod(unixname, permiss); + if (uid >-1 && gid > -1) + chown(unixname, uid, gid); + } } if (flags&1) { pp += strlen(pp); @@ -1748,24 +1841,30 @@ static uint8 *test_add_dir(uint8 *unixname, uint8 *pp, int flags, return(pp); } -static void correct_user_dirs(uint32 objid, int uid, int gid) +static void correct_user_dirs(uint32 objid, uint8 *objname, int uid, int gid) { uint8 fndir[512]; + uint8 buf1[20]; uint8 *p = fndir+sys_unixnamlen; uint8 *pp; + uint8 *p1; int l; DIR *f; memcpy(fndir, sys_unixname, sys_unixnamlen); - /* SYS/MAIL */ - l=sprintf(p,"/mail/%x", (int)objid); - pp=p+l; - if (!sys_downshift) + memcpy(p,"/mail/", 6); + p1=p+6; + l=sprintf(buf1,"../%x", (int)objid)-3; + memcpy(p1, buf1+3, l+1); + pp=p1+l; + *pp='\0'; + if (!sys_downshift) { upstr(p); + upstr(buf1); + } (void)mkdir(fndir, 0733); (void)chmod(fndir, 0733); (void)chown(fndir, uid, gid); - if ((f=opendir(fndir)) != (DIR*)NULL) { struct dirent* dirbuff; *pp='/'; @@ -1778,24 +1877,35 @@ static void correct_user_dirs(uint32 objid, int uid, int gid) } } } - *pp='\0'; closedir(f); } + memcpy(p1, "user/", 5); + strmaxcpy(p1+5, objname, 47); + if (!sys_downshift) + upstr(p1); + else + downstr(p1+5); + symlink(buf1, fndir); } void test_ins_unx_user(uint32 id) { NETOBJ obj; obj.id = id; - if ((MYPASSWD*)NULL == nw_getpwnam(id) && !nw_get_obj(&obj)){ - struct passwd *pw; - uint8 unxname[50]; - xstrcpy(unxname, obj.name); - downstr(unxname); - pw = getpwnam(unxname); - if (NULL != pw && pw->pw_uid) { /* only non root user */ - add_user_2_unx(id, unxname); - correct_user_dirs(id, pw->pw_uid, pw->pw_gid); + if (!nw_get_obj(&obj)){ + MYPASSWD *mpw=nw_getpwnam(id); + if ((MYPASSWD*)NULL == mpw){ + struct passwd *pw; + uint8 unxname[50]; + xstrcpy(unxname, obj.name); + downstr(unxname); + pw = getpwnam(unxname); + if (NULL != pw && pw->pw_uid) { /* only non root user */ + add_user_2_unx(id, unxname); + correct_user_dirs(id, obj.name, pw->pw_uid, pw->pw_gid); + } + } else if (mpw->pw_uid){ + correct_user_dirs(id, obj.name, mpw->pw_uid, mpw->pw_gid); } } } @@ -1806,12 +1916,10 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) char serverna[MAX_SERVER_NAME+2]; uint32 su_id = 0x00000001; uint32 ge_id = 0x01000001; - uint32 serv_id = 0x03000001; + uint32 server_id= 0x03000001; uint32 q1_id = 0x0E000001; -#ifdef _MAR_TESTS_1 - uint32 pserv_id = 0L; -#endif - FILE *f = open_nw_ini(); + uint32 ps1_id = 0x0F000001; + FILE *f = open_nw_ini(); int auto_ins_user = 0; char auto_ins_passwd[100]; int make_tests = 1; @@ -1844,13 +1952,16 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) } else if (8 == what) { /* entry8_flags */ entry8_flags = hextoi((char*)buff); } else if (21 == what) { /* QUEUES */ - char name[100]; + char name[200]; char directory[200]; char command[200]; char *p=buff; char *pp=name; char c; int state=0; + name[0]='\0'; + directory[0]='\0'; + command[0]='\0'; while (0 != (c = *p++)) { if (c == 32 || c == '\t') { if (!(state & 1)) { @@ -1862,21 +1973,59 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) if (state == 1) { pp=directory; state++; - } else { + } else if (state==3) { strcpy(command, p-1); - if (*command) state++; break; - } + } } *pp++ = c; } } *pp='\0'; - if (state == 4) { + if (*name) { upstr(name); + if (directory[0]=='-' && directory[1]=='\0') + directory[0]='\0'; + if (command[0]=='-' && command[1]=='\0') + command[0]='\0'; add_pr_queue(q1_id, name, directory, command, su_id, ge_id); q1_id++; } + } else if (22 == what) { /* PSERVER */ + char name[200]; + char queue[200]; + char *p=buff; + char *pp=name; + char c; + int state=0; + name[0]='\0'; + queue[0]='\0'; + + while (0 != (c = *p++)) { + if (c == 32 || c == '\t') { + if (!(state & 1)) { + *pp = '\0'; + state++; + } + } else { + if (state & 1){ + if (state == 1) { + pp=queue; + state++; + } else break; + } + *pp++ = c; + } + } + *pp='\0'; + + if (*name) { + upstr(name); + upstr(queue); + add_pr_server(ps1_id, name, queue, su_id, ge_id); + ps1_id++; + } + } else if (12 == what || 13 == what || 14 == what) { /* SUPERVISOR, OTHERS and GROUPS*/ char nname[100]; @@ -1927,10 +2076,12 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) fclose(f); } + + if (servername && adr) { strmaxcpy(serverna, servername, MAX_SERVER_NAME); upstr(serverna); - nw_new_obj_prop(serv_id, serverna, 0x4, O_FL_DYNA, 0x40, + nw_new_obj_prop(server_id, serverna, 0x4, O_FL_DYNA, 0x40, "NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40, (char*)adr, sizeof(ipxAddr_t), 1); @@ -1940,6 +2091,7 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) (char*)adr, sizeof(ipxAddr_t), 1); #endif } + if (auto_ins_user) { /* here Unix users will be inserted automaticly as mars_nwe users */ struct passwd *pw; @@ -1989,83 +2141,90 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) memset(auto_ins_passwd, 0, sizeof(auto_ins_passwd)); if (*sysentry) { - int result = 0; + uint8 unixname[512]; + uint8 sysname[256]; + int result = get_sys_unixname(unixname, sysname, sysentry); + int downshift = (result & 1); + int unlen = strlen(unixname); + if (result < 0) return(-1); + new_str(sys_unixname, unixname); + sys_downshift = downshift; + sys_unixnamlen = unlen; + if (make_tests) { - uint8 unixname[512]; - uint8 maildir[512]; - uint8 sysname[256]; - result = get_sys_unixname(unixname, sysname, sysentry); - if (result > -1) { - uint32 objs[2000]; /* max. 2000 User should be enough :) */ - int ocount=0; - int downshift = (result & 1); - int unlen = strlen(unixname); - uint8 *pp = unixname+unlen; - uint8 *ppp = maildir+unlen; - memcpy(maildir, unixname, unlen+1); + uint32 objs[LOC_MAX_OBJS]; + uint8 maildir[512]; + int ocount=0; + uint8 *pp = unixname+unlen; + uint8 *ppp = maildir+unlen; + memcpy(maildir, unixname, unlen+1); - new_str(sys_unixname, unixname); - sys_downshift=downshift; - sys_unixnamlen=unlen; + test_add_dir(unixname, pp, 4, downshift,0755, 0,0, "LOGIN"); + test_add_dir(unixname, pp, 0, downshift,0755, 0,0, "SYSTEM"); + test_add_dir(unixname, pp, 0, downshift,0755, 0,0, "PUBLIC"); + /* ----- */ + ppp=test_add_dir(maildir, ppp, 1, downshift,0755, 0,0, "MAIL"); + test_add_dir(maildir, ppp, 0, downshift,0755, 0,0, "USER"); - test_add_dir(unixname, pp, 0, downshift,0777, 0,0, "LOGIN"); - test_add_dir(unixname, pp, 0, downshift,0777, 0,0, "SYSTEM"); - test_add_dir(unixname, pp, 0, downshift,0777, 0,0, "PUBLIC"); - ppp=test_add_dir(maildir, ppp, 1, downshift,0777, 0,0, "MAIL"); - - if (!dbminit(FNOBJ)){ - for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { - data = fetch(key); - if (data.dptr) { - NETOBJ *obj=(NETOBJ*)data.dptr; - if (obj->type == 1 || obj->type == 3) { - objs[ocount++] = obj->id; - if (ocount == 2000) break; - } + if (!dbminit(FNOBJ)){ + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETOBJ *obj=(NETOBJ*)data.dptr; + if (obj->type == 1 || obj->type == 3) { + objs[ocount++] = obj->id; + if (ocount == LOC_MAX_OBJS) break; } } } - dbmclose(); + } + dbmclose(); - while (ocount--) { - NETOBJ obj; - obj.id = objs[ocount]; - nw_get_obj(&obj); - if (obj.type == 1) { - char sx[20]; - int gid; - int uid; - sprintf(sx, "%x", (int)obj.id); - if (!get_guid(&gid, &uid, obj.id, NULL)) - test_add_dir(maildir, ppp, 2, downshift, 0733, gid, uid, sx); - else - errorp(0, "Cannot get unix uid/gid", "User=`%s`", obj.name); + while (ocount--) { + NETOBJ obj; + obj.id = objs[ocount]; + nw_get_obj(&obj); + if (obj.type == 1) { + char sx[20]; + int gid; + int uid; + sprintf(sx, "../%x", (int)obj.id); + if (!get_guid(&gid, &uid, obj.id, NULL)) { + test_add_dir(maildir, ppp, 2, downshift, 0733, gid, uid, sx+3); + memcpy(ppp, "user/", 5); + strmaxcpy(ppp+5, obj.name, 47); + if (downshift) downstr(ppp+5); + else upstr(ppp); + unlink(maildir); + symlink(sx, maildir); + *ppp='\0'; + } else + errorp(0, "Cannot get unix uid/gid", "User=`%s`", obj.name); - } else if (obj.type == 3) { /* print queue */ - uint8 buff[300]; - char *p; - int result=nw_get_q_dirname(obj.id, buff); - upstr(buff); - if (result > -1 && NULL != (p=strchr(buff, ':')) ) { - *p++='\0'; - if (!strcmp(buff, sysname)) { - test_add_dir(unixname, pp, 2, downshift, 0770, 0, 0, p); - } else - errorp(0, "Warning:queue dir not on first SYS", - "Queue=%s, Volume=%s", obj.name, sysname); + } else if (obj.type == 3) { /* print queue */ + uint8 buff[300]; + char *p; + result=nw_get_q_dirname(obj.id, buff); + upstr(buff); + if (result > -1 && NULL != (p=strchr(buff, ':')) ) { + *p++='\0'; + if (!strcmp(buff, sysname)) { + test_add_dir(unixname, pp, 2|4, downshift, 0775, 0, 0, p); } else - errorp(0, "Cannot get queue dir", "Queue=%s", obj.name); - } + errorp(0, "queue dir not on SYS", + "Queue=%s, Volume=%s", obj.name, sysname); + } else + errorp(0, "Cannot get queue dir", "Queue=%s", obj.name); } - result = 0; } } - return(result); + init_queues(sys_unixname, sys_unixnamlen, sys_downshift, sysname); /* nwqueue.c */ + return(0); } return(-1); } -int nw_init_dbm(char *servername, ipxAddr_t *adr) +static void nw_init_dbm_1(char *servername, ipxAddr_t *adr) /* * routine inits bindery * all dynamic objects and properties will be deleted. @@ -2122,11 +2281,22 @@ int nw_init_dbm(char *servername, ipxAddr_t *adr) dbmclose(); while (anz--) /* now delete dynamic properties */ loc_delete_property(objs[anz], (char*)NULL, props[anz], 1); - anz = nw_fill_standard(servername, adr); - sync_dbm(); - return(anz); } +int nw_init_dbm(char *servername, ipxAddr_t *adr) +{ + int result; + nw_init_dbm_1(servername, adr); + result = nw_fill_standard(servername, adr); + sync_dbm(); + return(result); +} + +void nw_exit_dbm(void) +{ + exit_queues(); + sync_dbm(); +} #if 0 #define MAX_OBJ_IDS 100000 /* should be enough */ @@ -2392,14 +2562,3 @@ int do_import_dbm(char *path) return(result); } -/* ============> this should becomes queue.c or similar < ============== */ - -int nw_get_q_dirname(uint32 q_id, uint8 *buff) -{ - return(nw_get_prop_val_str(q_id, "Q_DIRECTORY", buff)); -} - -int nw_get_q_prcommand(uint32 q_id, uint8 *buff) -{ - return(nw_get_prop_val_str(q_id, "Q_UNIX_PRINT", buff)); -} diff --git a/nwdbm.h b/nwdbm.h index 1dd7a26..ea189be 100644 --- a/nwdbm.h +++ b/nwdbm.h @@ -1,4 +1,4 @@ -/* nwdbm.h 17-Apr-97 */ +/* nwdbm.h 24-Aug-97 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -120,6 +120,8 @@ extern int nw_delete_property(int object_type, uint8 *object_name, int object_namlen, uint8 *prop_name, int prop_namlen); +extern int nw_is_member_in_set(uint32 obj_id, char *propname, + uint32 member_id); extern int nw_is_obj_in_set(int object_type, uint8 *object_name, int object_namlen, @@ -162,6 +164,8 @@ extern int nw_scan_property(NETPROP *prop, int prop_namlen, uint32 *last_scan); +extern int nw_get_prop_val_str(uint32 q_id, char *propname, uint8 *buff); + extern int nw_create_obj(NETOBJ *obj, uint32 wanted_id); @@ -193,15 +197,17 @@ extern int nw_keychange_passwd(uint32 obj_id, extern int nw_test_adr_time_access(uint32 obj_id, ipxAddr_t *client_adr); -extern int nw_get_q_dirname(uint32 q_id, uint8 *buff); -extern int nw_get_q_prcommand(uint32 q_id, uint8 *buff); +extern int nwdbm_mkdir(char *unixname, int mode, int flags); extern void test_ins_unx_user(uint32 id); extern int test_allow_password_change(uint32 id); extern int nw_fill_standard(char *servername, ipxAddr_t *adr); extern int nw_init_dbm(char *servername, ipxAddr_t *adr); +extern void nw_exit_dbm(void); + extern int do_export_dbm(char *path); extern int do_import_dbm(char *path); + #endif diff --git a/nwfile.c b/nwfile.c index fe525f2..d759cbb 100644 --- a/nwfile.c +++ b/nwfile.c @@ -1,4 +1,4 @@ -/* nwfile.c 25-Jul-97 */ +/* nwfile.c 26-Aug-97 */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -41,11 +41,20 @@ void sig_bus_mmap(int rsig) static FILE_HANDLE file_handles[MAX_FILE_HANDLES_CONN]; #define HOFFS 0 +#define USE_NEW_FD 1 static int count_fhandles=0; +#if USE_NEW_FD +static int last_fhandle=HOFFS; +#endif + static int new_file_handle(uint8 *unixname, int task) { - int fhandle = HOFFS -1; +#if USE_NEW_FD + int fhandle= -1 + last_fhandle++; +#else + int fhandle=HOFFS-1; +#endif FILE_HANDLE *fh=NULL; while (++fhandle < count_fhandles) { fh=&(file_handles[fhandle]); @@ -54,13 +63,27 @@ static int new_file_handle(uint8 *unixname, int task) break; } else fh=NULL; } + if (fh == NULL) { if (count_fhandles < MAX_FILE_HANDLES_CONN) { fh=&(file_handles[count_fhandles]); fhandle = ++count_fhandles; } else { - XDPRINTF((1, 0, "No more free file handles")); - return(0); /* no free handle anymore */ +#if USE_NEW_FD + last_fhandle=HOFFS+1; + fhandle=HOFFS-1; + while (++fhandle < count_fhandles) { + fh=&(file_handles[fhandle]); + if (fh->fd == -1 && !(fh->fh_flags & FH_DO_NOT_REUSE)) { /* empty slot */ + fhandle++; + break; + } else fh=NULL; + } +#endif + if (fh == NULL) { + XDPRINTF((1, 0, "No more free file handles")); + return(0); /* no free handle anymore */ + } } } /* init handle */ @@ -74,31 +97,12 @@ static int new_file_handle(uint8 *unixname, int task) fh->f = NULL; XDPRINTF((5, 0, "new_file_handle=%d, count_fhandles=%d, fn=%s", fhandle, count_fhandles, unixname)); - - if (fhandle == ipx_io.fh_r){ - ipx_io.fh_r= 0; - ipx_io.fd_r=-1; - } - if (fhandle == ipx_io.fh_w){ - ipx_io.fh_w= 0; - ipx_io.fd_w=-1; - } return(fhandle); } static int free_file_handle(int fhandle) { int result=-0x88; - - if (fhandle == ipx_io.fh_r){ - ipx_io.fh_r= 0; - ipx_io.fd_r=-1; - } - if (fhandle == ipx_io.fh_w){ - ipx_io.fh_w= 0; - ipx_io.fd_w=-1; - } - if (fhandle > HOFFS && (fhandle <= count_fhandles)) { FILE_HANDLE *fh=&(file_handles[fhandle-1]); if (fh->fd > -1) { @@ -125,11 +129,13 @@ static int free_file_handle(int fhandle) } } fh->fd = -1; +#if !USE_NEW_FD while (count_fhandles > fhandle && file_handles[count_fhandles-1].fd == -1 && !(file_handles[count_fhandles-1].fh_flags & FH_DO_NOT_REUSE) ) { count_fhandles--; } +#endif result=0; } XDPRINTF((5, 0, "free_file_handle=%d, count_fhandles=%d, result=%d", @@ -148,6 +154,9 @@ void init_file_module(int task) while (k++ < count_fhandles) free_file_handle(k); count_fhandles = HOFFS; +#if USE_NEW_FD + last_fhandle = HOFFS; +#endif } else { /* I hope next is ok, added 20-Oct-96 ( 0.98.pl5 ) */ while (k++ < count_fhandles) { @@ -157,10 +166,6 @@ void init_file_module(int task) } } } - ipx_io.fh_r= 0; - ipx_io.fd_r=-1; - ipx_io.fh_w= 0; - ipx_io.fd_w=-1; } static int xsetegid(gid_t gid) @@ -185,8 +190,9 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, * creatmode: 0 = open * | 1 = creat (ever) * | 2 = creatnew ( creat if not exist ) - * & 4 == save handle (creat) - * & 8 == ignore rights (create ever) + * --------- + * & 4 == save handle (not reuse) + * & 8 == ignore rights (try to open as root) * attrib ?? * * access: 0x1=read, @@ -210,7 +216,7 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, */ { int fhandle = new_file_handle(unixname, task); - int dowrite = ((access & 2) || creatmode) ? 1 : 0; + int dowrite = ((access & 2) || (creatmode & 3) ) ? 1 : 0; if (fhandle > HOFFS){ FILE_HANDLE *fh=&(file_handles[fhandle-1]); int completition = 0; /* first ok */ @@ -220,7 +226,7 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, int did_grpchange = 0; if (dowrite && (voloptions & VOL_OPTION_READONLY)) { - completition = (creatmode) ? -0x84 : -0x94; + completition = (creatmode&3) ? -0x84 : -0x94; } else if (acc > -1) { /* do exist */ if (!S_ISDIR(stbuff->st_mode)) { @@ -238,9 +244,9 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, XDPRINTF((1, 0, "Uses strange open comp. mode for file `%s`", fh->fname)); } else - completition = (creatmode) ? -0x84 : -0x94; + completition = (creatmode&3) ? -0x84 : -0x94; } else - completition = (creatmode) ? -0x84 : -0x94; + completition = (creatmode&3) ? -0x84 : -0x94; } else if (!(acc & R_OK) && !(creatmode & 0x8) ) completition = -0x93; @@ -267,7 +273,7 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, } } else completition= -0xff; - } else if ( (voloptions & VOL_OPTION_IS_PIPE) || !creatmode) { + } else if ( (voloptions & VOL_OPTION_IS_PIPE) || !(creatmode&3) ) { /* must exist, but don't */ completition=-0xff; } else { @@ -326,7 +332,7 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, } } else { /* <========= this is NOT a PIPE Volume ====================> */ - if (creatmode) { /* creat File */ + if (creatmode&0x3) { /* creat File */ if (creatmode & 0x2) { /* creatnew */ XDPRINTF((5,0,"CREAT FILE:%s: Handle=%d", fh->fname, fhandle)); fh->fd = creat(fh->fname, 0777); @@ -369,6 +375,15 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, stbuff->st_atime = stbuff->st_mtime; } fh->fd = open(fh->fname, acm); + if (fh->fd < 0 && (creatmode&8)) { + if (did_grpchange) { + xsetegid(act_gid); + did_grpchange=0; + } + seteuid(0); + fh->fd = open(fh->fname, acm); + reset_guid(); + } XDPRINTF((5,0, "OPEN FILE:fd=%d, attrib:0x%x, access:0x%x, fh->fname:%s:fhandle=%d", fh->fd, attrib, access, fh->fname, fhandle)); if (fh->fd < 0) @@ -601,7 +616,7 @@ static void open_pipe_command(FILE_HANDLE *fh, int dowrite) act_connection, act_pid); fh->f = ext_popen(pipecommand, geteuid(), getegid()); } - fh->fd = (fh->f) ? fileno(fh->f->fildes[dowrite ? 0 : 1]) : -3; + fh->fd = (fh->f) ? fh->f->fds[dowrite ? 0 : 1] : -3; } int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) @@ -613,6 +628,7 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) if (fh->fd > -1) { if (fh->fh_flags & FH_IS_PIPE) { /* PIPE */ int readsize=size; +#if 1 if (-1 == (size = read(fh->fd, data, readsize)) ) { int k=2; do { @@ -620,10 +636,24 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) } while(k-- && -1 == (size = read(fh->fd, data, readsize))); if (size == -1) size=0; } +#else + int offset=0; + int k=2; + while ((size = read(fh->fd, data+offset, readsize)) < readsize) { + if (size>0) { + readsize-=size; + offset+=size; + } else if (!k-- || ((!size)&&readsize)) break; + else sleep(1); + } + size=offset; +#endif +#if 1 if (!size) { if (fh->f->flags & 1) return(-0x57); fh->f->flags |= 1; } +#endif } else if (use_mmap && fh->p_mmap) { while (1) { if (offset < fh->size_mmap) { @@ -641,7 +671,7 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) } } /* while */ } else { - if (use_ipx_io || fh->offd != (long)offset) { + if (fh->offd != (long)offset) { fh->offd=lseek(fh->fd, offset, SEEK_SET); if (fh->offd < 0) { XDPRINTF((5,0,"read-file failed in lseek")); @@ -650,10 +680,6 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) if (fh->offd > -1L) { if ((size = read(fh->fd, data, size)) > -1) { fh->offd+=(long)size; - if (use_ipx_io) { - ipx_io.fh_r=fhandle+1; - ipx_io.fd_r=fh->fd; - } } else { XDPRINTF((5,0,"read-file failed in read")); } @@ -699,16 +725,12 @@ int nw_write_file(int fhandle, uint8 *data, int size, uint32 offset) if (fh->fh_flags & FH_IS_PIPE) { /* PIPE */ return(size ? write(fh->fd, data, size) : 0); } else { - if (use_ipx_io || fh->offd != (long)offset) + if (fh->offd != (long)offset) fh->offd = lseek(fh->fd, offset, SEEK_SET); if (size) { if (fh->offd > -1L) { size = write(fh->fd, data, size); fh->offd+=(long)size; - if (use_ipx_io&&size>0) { - ipx_io.fh_w=fhandle+1; - ipx_io.fd_w=fh->fd; - } } else size = -1; return(size); } else { /* truncate FILE */ diff --git a/nwfile.h b/nwfile.h index 0dd9ffc..535b4ff 100644 --- a/nwfile.h +++ b/nwfile.h @@ -1,7 +1,7 @@ /* nwfile.h 21-Jul-97 */ #ifndef _NWFILE_H_ #define _NWFILE_H_ -#include "nwqueue.h" +#include "extpipe.h" typedef struct { int task; /* for which task */ diff --git a/nwqconn.c b/nwqconn.c new file mode 100644 index 0000000..2448eec --- /dev/null +++ b/nwqconn.c @@ -0,0 +1,317 @@ +/* nwqconn.c 26-Aug-97 */ +/* (C)opyright (C) 1997 Martin Stover, Marburg, Germany + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "net.h" +#include + +#include "nwvolume.h" +#include "nwfile.h" +#include "connect.h" +#include "nwqconn.h" + +typedef struct S_INT_QUEUE_JOB { + uint32 queue_id; + int job_id; + int fhandle; + struct S_INT_QUEUE_JOB *next; +} INT_QUEUE_JOB; + +INT_QUEUE_JOB *queue_jobs=NULL; + +static INT_QUEUE_JOB *new_queue_job(uint32 queue_id, int job_id) +{ + INT_QUEUE_JOB *p=(INT_QUEUE_JOB*)xcmalloc(sizeof(INT_QUEUE_JOB)); + if (!queue_jobs) { + queue_jobs=p; + } else { + INT_QUEUE_JOB *qj=queue_jobs; + while (qj->next != NULL) qj=qj->next; + qj->next=p; + } + p->next=NULL; + p->queue_id=queue_id; + p->job_id=job_id; + return(p); +} + +static void free_queue_job(uint32 queue_id, int job_id) +{ + INT_QUEUE_JOB *qj=queue_jobs; + if (!qj) return; + if (qj->queue_id==queue_id && qj->job_id == job_id){ + queue_jobs=qj->next; + xfree(qj); + return; + } + while (qj->next) { + if (qj->next->queue_id == queue_id && qj->next->job_id == job_id) { + INT_QUEUE_JOB *tmp=qj->next; + qj->next=tmp->next; + xfree(tmp); + return; + } else qj=qj->next; + } + /* not found */ +} + +static INT_QUEUE_JOB *find_queue_job(uint32 queue_id, int job_id) +{ + INT_QUEUE_JOB *qj=queue_jobs; + while (qj) { + if (qj->queue_id==queue_id && qj->job_id == job_id) + return(qj); + qj=qj->next; + } + return(NULL); +} + +static int open_creat_queue_file(int mode, uint8 + *file_name, int file_name_len, + uint8 *dirname, int dirname_len) + /* modes: + * 0 : creat + * 1 : open ro (as root) + * 2 : open rw (as root) + */ +{ + int result; + result=nw_alloc_dir_handle(0, dirname, dirname_len, 99, 2, 1); + if (result > -1) { + char unixname[300]; + + result=conn_get_kpl_unxname(unixname, result, file_name, file_name_len); + if (result > -1) { + struct stat stbuff; + if (mode == 0) { /* creat */ + result=file_creat_open(result, (uint8*)unixname, + &stbuff, 0x6, 0x6, 1|4|8, 0); + if (result > -1) + chmod(unixname, 0600); + } else if (mode == 1) { /* open ro */ + result=file_creat_open(result, (uint8*)unixname, + &stbuff, 0x6, 0x9, 4|8, 0); + } else if (mode == 2) { /* open rw */ + result=file_creat_open(result, (uint8*)unixname, + &stbuff, 0x6, 0x6, 4|8, 0); + } else result=-1; + } + } + if (result < 0) { + uint8 dn[300]; + uint8 fn[300]; + strmaxcpy(dn, dirname, dirname_len); + strmaxcpy(fn, file_name, file_name_len); + XDPRINTF((1, 0, "open_creat_queue_file, mode=%d,result=-0x%x, dn='%s', fn='%s'", + mode, -result, dn, fn)); + result=-0xff; + } + return(result); +} + +int creat_queue_job(uint32 q_id, + uint8 *queue_job, + uint8 *responsedata, + uint8 old_call) +{ + uint8 *dirname = (old_call) ? queue_job+sizeof(QUEUE_JOB_OLD) + : queue_job+sizeof(QUEUE_JOB); + int job_id; + INT_QUEUE_JOB *jo; + int result; + memcpy(responsedata, queue_job, (old_call) ? sizeof(QUEUE_JOB_OLD) + : sizeof(QUEUE_JOB)); + if (old_call) { + QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; /* before 3.11 */ + job_id = GET_BE16(job->job_id); + jo = new_queue_job(q_id, job_id); + result = open_creat_queue_file(0, job->job_file_name+1, *(job->job_file_name), + dirname+1, *dirname); + if (result > -1) { + jo->fhandle = (uint32) result; + U16_TO_BE16(0, job->job_file_handle); + U32_TO_32(jo->fhandle, job->job_file_handle+2); + result = sizeof(QUEUE_JOB_OLD) - 202; + } + } else { + QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + job_id=GET_BE32(job->job_id); + jo = new_queue_job(q_id, job_id); + result = open_creat_queue_file(0, job->job_file_name+1, *(job->job_file_name), + dirname+1, *dirname); + if (result > -1) { + jo->fhandle = (uint32) result; + U32_TO_32(jo->fhandle, job->job_file_handle); + result = sizeof(QUEUE_JOB) - 202; + } + } + if (result < 0) + free_queue_job(q_id, job_id); + return(result); +} + +int close_queue_job(uint32 q_id, int job_id) +{ + int result = -0xff; + INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id); + if (jo) { + nw_close_file(jo->fhandle, 0); + result=0; + } + XDPRINTF((5,0,"close_queue_job Q=0x%x, job=%d, result=%d", + q_id, job_id, result)); + return(result); +} + +int close_queue_job2(uint32 q_id, int job_id, + uint8 *client_area, + uint8 *prc, int prc_len) +{ + int result = -0xff; + INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id); + XDPRINTF((5,0,"close_queue_job2, Q=0x%x, job=%d", q_id, job_id)); + if (jo) { + if (prc_len) { + char unixname[300]; + QUEUE_PRINT_AREA qpa; + memcpy(&qpa, client_area, sizeof(QUEUE_PRINT_AREA)); + strmaxcpy((uint8*)unixname, + (uint8*)file_get_unix_name(jo->fhandle), sizeof(unixname)-1); + XDPRINTF((5,0,"nw_close_file_queue fhandle=%d", jo->fhandle)); + if (*unixname) { + char buff[1024]; + char printcommand[300]; + FILE *f=NULL; + if (prc_len && *(prc+prc_len-1)=='!'){ + strmaxcpy((uint8*)buff, prc, prc_len-1); + sprintf(printcommand, "%s %s %s", buff, + qpa.banner_user_name, qpa.banner_file_name); + } else + strmaxcpy((uint8*)printcommand, prc, prc_len); + nw_close_file(jo->fhandle, 1); + jo->fhandle = 0L; + if (NULL == (f = fopen(unixname, "r"))) { + /* OK now we try the open as root */ + seteuid(0); + f = fopen(unixname, "r"); + reset_guid(); + } + if (NULL != f) { + int is_ok = 0; + FILE_PIPE *fp = ext_popen(printcommand, geteuid(), getegid()); + if (fp) { + int k; + is_ok++; + while (is_ok && (k = fread(buff, 1, sizeof(buff), f)) > 0) { + if (k != write(fp->fds[0], buff, k)) { + XDPRINTF((1,0x10,"Cannot write to pipe `%s`", printcommand)); + if ((k=read(fp->fds[2], buff, sizeof(buff)-1)) > 0 ) { + buff[k]='\0'; + XDPRINTF((1,0x0,"err='%s'", buff)); + } + is_ok=0; + } + } + if (0 != (k=ext_pclose(fp))) { + XDPRINTF((1,0,"Errorresult = %d by closing print pipe", k)); + } + } + fclose(f); + if (is_ok) { + seteuid(0); + unlink(unixname); + reset_guid(); + result=0; + } + } else XDPRINTF((1,0,"Cannot open queue-file `%s`", unixname)); + } + } else { + nw_close_file(jo->fhandle, 1); + } + free_queue_job(q_id, job_id); + } + return(result); +} + +int service_queue_job(uint32 q_id, + uint8 *queue_job, + uint8 *responsedata, + uint8 old_call) +{ + uint8 *dirname = (old_call) ? queue_job+sizeof(QUEUE_JOB_OLD) + : queue_job+sizeof(QUEUE_JOB); + int job_id; + INT_QUEUE_JOB *jo; + int result; + memcpy(responsedata, queue_job, (old_call) ? sizeof(QUEUE_JOB_OLD) + : sizeof(QUEUE_JOB)); + if (old_call) { + QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; /* before 3.11 */ + job_id = GET_BE16(job->job_id); + jo = new_queue_job(q_id, job_id); + result = open_creat_queue_file(1, + job->job_file_name+1, *(job->job_file_name), + dirname+1, *dirname); + if (result > -1) { + jo->fhandle = (uint32) result; + U16_TO_BE16(0, job->job_file_handle); + U32_TO_32(jo->fhandle, job->job_file_handle+2); + result = sizeof(QUEUE_JOB_OLD) - 202; + } + } else { + QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + job_id=GET_BE32(job->job_id); + jo = new_queue_job(q_id, job_id); + result = open_creat_queue_file(1, + job->job_file_name+1, *(job->job_file_name), + dirname+1, *dirname); + if (result > -1) { + jo->fhandle = (uint32) result; + U32_TO_32(jo->fhandle, job->job_file_handle); + result = sizeof(QUEUE_JOB) - 202; + } + } + if (result < 0) + free_queue_job(q_id, job_id); + return(result); +} + +int finish_abort_queue_job(uint32 q_id, int job_id) +{ + int result = -0xff; + INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id); + if (jo) { + nw_close_file(jo->fhandle, 0); + free_queue_job(q_id, job_id); + result=0; + } + XDPRINTF((5,0,"finish_abort_queue_job Q=0x%x, job=%d, result=%d", + q_id, job_id, result)); + return(result); +} + +void free_queue_jobs(void) +{ + INT_QUEUE_JOB *qj=queue_jobs; + while(qj){ + INT_QUEUE_JOB *tmp=qj; + qj=qj->next; + xfree(tmp); + } + queue_jobs=NULL; +} + diff --git a/nwqconn.h b/nwqconn.h new file mode 100644 index 0000000..519e016 --- /dev/null +++ b/nwqconn.h @@ -0,0 +1,23 @@ +/* nwqconn.h 26-Aug-97 */ +#ifndef _NWQCONN_H_ +#define _NWQCONN_H_ +#include "queuedef.h" +extern int creat_queue_job(uint32 q_id, + uint8 *queue_job, + uint8 *responsedata, + uint8 old_call); + +extern int close_queue_job(uint32 q_id, int job_id); +extern int close_queue_job2(uint32 q_id, int job_id, + uint8 *client_area, + uint8 *prc, int prc_len); + +extern int service_queue_job(uint32 q_id, + uint8 *queue_job, + uint8 *responsedata, + uint8 old_call); + +extern int finish_abort_queue_job(uint32 q_id, int job_id); + +extern void free_queue_jobs(void); +#endif diff --git a/nwqueue.c b/nwqueue.c index 891a017..44da388 100644 --- a/nwqueue.c +++ b/nwqueue.c @@ -1,4 +1,4 @@ -/* nwconn.c 19-Oct-96 */ +/* nwqueue.c 24-Aug-97 */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -17,432 +17,778 @@ */ #include "net.h" -#include - -#include "nwvolume.h" -#include "nwfile.h" -#include "connect.h" +#include "nwdbm.h" +#include "nwbind.h" #include "nwqueue.h" -static char **build_argv(char *buf, int bufsize, char *command) -/* routine returns **argv for use with execv routines */ -/* buf will contain the path component */ -{ - int len = strlen(command); - int offset = ((len+4) / 4) * 4; /* aligned offset for **argv */ - int components = (bufsize - offset) / 4; - if (components > 1) { /* minimal argv[0] + NULL */ - char **argv = (char **)(buf+offset); - char **pp = argv; - char *p = buf; - char c; - int i=0; - --components; - memcpy(buf, command, len); - memset(buf+len, 0, bufsize - len); - *pp = p; - while ((0 != (c = *p++)) && i < components) { - if (c == 32 || c == '\t') { - *(p-1) = '\0'; - if (*p != 32 && *p != '\t') { - *(++pp)=p; - i++; - } - } else if (!i && c == '/') { /* here i must get argv[0] */ - *pp=p; - } - } - XDPRINTF((5, 0, "build_argv, path='%s'", buf)); - pp=argv; - while (*pp) { - XDPRINTF((5, 0, "build_argv, argv='%s'", *pp)); - pp++; - } - return(argv); - } - return(NULL); -} +/* + * the bindery/global queue handling is in this modul. + * The running process is nwbind. + * the connection based queue stuff is in nwqconn.c +*/ - -static void close_piped(int piped[3][2]) -{ - int j=3; - while (j--) { - int k=2; - while (k--) { - if (piped[j][k] > -1){ - close(piped[j][k]); - piped[j][k] = -1; - } - } - } -} - -static void err_close_pipe(FILE_PIPE *fp, int lpid, int j, int piped[3][2]) -{ - while (j--) if (fp->fildes[j]) fclose(fp->fildes[j]); - close_piped(piped); - kill(lpid, SIGTERM); - kill(lpid, SIGQUIT); - waitpid(lpid, NULL, 0); - kill(lpid, SIGKILL); -} - -static int x_popen(char *command, int uid, int gid, FILE_PIPE *fp) -{ - int piped[3][2]; - int lpid=-1; - int j=3; - char buf[300]; - char **argv=build_argv(buf, sizeof(buf), command); - if (argv == NULL) return(-1); - while (j--){ - int k=2; - while(k--) piped[j][k] = -1; - } - if (! (pipe(&piped[0][0]) > -1 && pipe(&piped[1][0]) > -1 - && pipe(&piped[2][0]) > -1 && (lpid=fork()) > -1)) { - close_piped(piped); - return(-1); - } - if (lpid == 0) { /* Child */ - signal(SIGTERM, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGPIPE, SIG_DFL); - signal(SIGHUP, SIG_DFL); - j=3; - while(j--) close(j); - j=3; - while(j--) { - int x = (j) ? 0 : 1; - int x_ = (j) ? 1 : 0; - close(piped[j][x] ); - dup2( piped[j][x_], j); - close(piped[j][x_] ); - } - if (uid > -1 || gid > -1) { - seteuid(0); - if (gid > -1) setgid(gid); - if (uid > -1) setuid(uid); - if (gid > -1) setegid(gid); - if (uid > -1) seteuid(uid); - } - execvp(buf, argv); - exit(1); /* Never reached I hope */ - } - j=-1; - while (++j < 3) { - int x = (j) ? 0 : 1; - int x_ = (j) ? 1 : 0; - close(piped[j][x_]); - piped [j][x_] = -1; - - fp->fildes [j] = fdopen(piped[j][x], ( (j) ? "r" : "w") ); - if (NULL == fp->fildes[j]){ - err_close_pipe(fp, lpid, j+1, piped); - return(-1); - } - } - return(lpid); -} - -int ext_pclose(FILE_PIPE *fp) -{ - int status=-1; - void (*intsave) (int) = signal(SIGINT, SIG_IGN); - void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN); - void (*hupsave) (int) = signal(SIGHUP, SIG_IGN); - int j = 3; - while (j--) if (fp->fildes[j]) fclose(fp->fildes[j]); - if (fp->command_pid != waitpid(fp->command_pid, &status, 0)) { - kill(fp->command_pid, SIGTERM); - waitpid(fp->command_pid, &status, 0); - } - kill(fp->command_pid, SIGKILL); - signal(SIGINT, intsave); - signal(SIGQUIT, quitsave); - signal(SIGHUP, hupsave); - xfree(fp); - return(status); -} - -FILE_PIPE *ext_popen(char *command, int uid, int gid) -{ - FILE_PIPE *fp=(FILE_PIPE*) xcmalloc(sizeof(FILE_PIPE)); - void (*intsave) (int) = signal(SIGINT, SIG_IGN); - void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN); - void (*hupsave) (int) = signal(SIGHUP, SIG_IGN); - if ((fp->command_pid = x_popen(command, uid, gid, fp)) < 0) { - xfree(fp); - fp=NULL; - XDPRINTF((1, 0, "ext_popen failed:command='%s'", command)); - } - signal(SIGINT, intsave); - signal(SIGQUIT, quitsave); - signal(SIGHUP, hupsave); - return(fp); -} - -/* minimal queue handling to enable simple printing */ - -#define MAX_JOBS 5 /* max. open queue jobs for one connection */ -static int anz_jobs=0; - -typedef struct { - uint32 fhandle; - int old_job; /* is old structure */ - union { - QUEUE_JOB n; - QUEUE_JOB_OLD o; - } q; +typedef struct S_INT_QUEUE_JOB { + int client_connection; + int client_task; + uint32 client_id; + time_t entry_time; + uint32 target_id; /* if 0xffffffff then all q-servers allowed */ + time_t execute_time; /* if -1 then at once */ + int job_id; /* 1 ... 999 */ + int job_typ; + int job_position; + int job_control_flags; /* if | 0x20 then job is actually queued */ + int server_station; + int server_task; + uint32 server_id; + uint8 job_description[50]; + uint8 client_area[152]; + time_t file_entry_time; /* for filenamehandling */ + struct S_INT_QUEUE_JOB *next; } INT_QUEUE_JOB; -INT_QUEUE_JOB *queue_jobs[MAX_JOBS]; +typedef struct S_QUEUE_SERVER { + int connection; /* actual connection */ + uint32 user_id; + uint8 status_record[64]; /* for free queue server use */ +} QUEUE_SERVER; -static INT_QUEUE_JOB *give_new_queue_job(int old_job) +typedef struct S_NWE_QUEUE { + uint32 id; + int last_job_id; /* job id 1 .. 999 */ + int count_jobs; + INT_QUEUE_JOB *queue_jobs; + int status; /* 0x1 = stations not allow to insert in queue + * 0x2 = no more queue servers allowed to login. + * 0x4 = queue servers not allowed to handle queue. + */ + int changed; /* needs flush */ + + uint8 *queuedir; + int queuedir_len; + int queuedir_downshift; /* is downshift volume */ + QUEUE_SERVER *qserver; + struct S_NWE_QUEUE *next; +} NWE_QUEUE; + +NWE_QUEUE *nwe_queues=NULL; + +static NWE_QUEUE *new_queue(uint32 id) { - int k=-1; - while (++k < anz_jobs) { - INT_QUEUE_JOB *p=queue_jobs[k]; - if (!p->fhandle) { /* free slot */ - memset(p, 0, sizeof(INT_QUEUE_JOB)); - p->old_job = old_job; - if (old_job) - p->q.o.job_id[0] = k+1; - else - p->q.n.job_id[0] = k+1; - return(p); - } + NWE_QUEUE *p=(NWE_QUEUE*)xcmalloc(sizeof(NWE_QUEUE)); + if (!nwe_queues) { + nwe_queues=p; + } else { + NWE_QUEUE *q=nwe_queues; + while (q->next != NULL) q=q->next; + q->next=p; } - if (anz_jobs < MAX_JOBS) { - INT_QUEUE_JOB **pp=&(queue_jobs[anz_jobs++]); - *pp = (INT_QUEUE_JOB *) xmalloc(sizeof(INT_QUEUE_JOB)); - memset(*pp, 0, sizeof(INT_QUEUE_JOB)); - (*pp)->old_job = old_job; - if (old_job) - (*pp)->q.o.job_id[0] = anz_jobs; - else - (*pp)->q.n.job_id[0] = anz_jobs; - return(*pp); + p->next=NULL; + p->id=id; + return(p); +} + +static void free_queue_p(NWE_QUEUE *q) +{ + if (!q) return; + xfree(q->qserver); + xfree(q->queuedir); + xfree(q); +} + +static void free_queue(uint32 id) +{ + NWE_QUEUE *q=nwe_queues; + if (!q) return; + if (q->id==id){ + nwe_queues=q->next; + free_queue_p(q); + return; + } + while (q->next) { + if (q->next->id == id) { + NWE_QUEUE *tmp=q->next; + q->next=tmp->next; + free_queue_p(tmp); + return; + } else q=q->next; + } + /* not found */ +} + +static NWE_QUEUE *find_queue(uint32 id) +{ + NWE_QUEUE *q=(NWE_QUEUE*)nwe_queues; + while (q) { + if (q->id==id) return(q); + q=q->next; } return(NULL); } -static void free_queue_job(int q_id) +static INT_QUEUE_JOB *add_queue_job(NWE_QUEUE *que, INT_QUEUE_JOB *p) { - if (q_id > 0 && q_id <= anz_jobs) { - INT_QUEUE_JOB **pp=&(queue_jobs[q_id-1]); - uint32 fhandle = (*pp)->fhandle; - if (fhandle > 0) nw_close_file(fhandle, 1); - if (q_id == anz_jobs) { - xfree(*pp); - --anz_jobs; - } else (*pp)->fhandle=0L; - } -} - -static void set_entry_time(uint8 *entry_time) -{ - struct tm *s_tm; - time_t timer; - time(&timer); - s_tm = localtime(&timer); - entry_time[0] = (uint8) s_tm->tm_year; - entry_time[1] = (uint8) s_tm->tm_mon+1; - entry_time[2] = (uint8) s_tm->tm_mday; - entry_time[3] = (uint8) s_tm->tm_hour; - entry_time[4] = (uint8) s_tm->tm_min; - entry_time[5] = (uint8) s_tm->tm_sec; -} - -static int create_queue_file(uint8 *job_file_name, - uint32 q_id, - int jo_id, - int connection, - uint8 *dirname, - int dir_nam_len, - uint8 *job_bez) - -{ - int result; - *job_file_name - = sprintf((char*)job_file_name+1, "%07lX%d.%03d", q_id, jo_id, connection); - - seteuid(0); - result=nw_alloc_dir_handle(0, dirname, dir_nam_len, 99, 2, 1); - if (result > -1) { - char unixname[300]; - result=conn_get_kpl_unxname(unixname, result, - job_file_name+1, (int) *job_file_name); - if (result > -1) { - struct stat stbuff; - result=file_creat_open(result, (uint8*)unixname, - &stbuff, 0x6, 0x6, 1|4|8, 0); - if (result > -1) { - chown(unixname, act_uid, act_gid); - chmod(unixname, 0660); - } - } - } - reset_guid(); - XDPRINTF((5,0,"creat queue file bez=`%s` handle=%d", - job_bez, result)); - return(result); -} - - -int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job, - uint8 *dirname, int dir_nam_len, int old_call) -{ - INT_QUEUE_JOB *jo = give_new_queue_job(old_call); - uint32 q_id = GET_BE32(queue_id); - int result = -0xff; - XDPRINTF((5,0,"NW_CREAT_Q:dlen=%d, dirname=%s", dir_nam_len, dirname)); - - if (NULL != jo) { - int jo_id = 0; - if (jo->old_job) { - jo_id = (int) jo->q.o.job_id[0]; - memcpy(&(jo->q.o), queue_job, sizeof(QUEUE_JOB_OLD)); - jo->q.o.job_id[0] = (uint8) jo_id; - jo->q.o.client_connection = (uint8)connection; - - jo->q.o.client_task = (uint8)0xfe; /* ?? */ - U32_TO_BE32(1, jo->q.o.client_id); /* SU */ - set_entry_time(jo->q.o.job_entry_time); - jo->q.o.job_typ[0] = 0x0; /* 0xd0;*/ - jo->q.o.job_typ[1] = 0x0; - jo->q.o.job_position = 0x1; - jo->q.o.job_control_flags |= 0x20; - - result = create_queue_file(jo->q.o.job_file_name, - q_id, jo_id, connection, - dirname, dir_nam_len, - jo->q.o.job_bez); - - if (result > -1) { - jo->fhandle = (uint32) result; - U16_TO_BE16(0, jo->q.o.job_file_handle); - U32_TO_32(jo->fhandle, jo->q.o.job_file_handle+2); - result = 0; - } - jo->q.o.server_station = 0; - jo->q.o.server_task = 0; - U32_TO_BE32(0, jo->q.o.server_id); - if (!result) memcpy(queue_job, &(jo->q.o), sizeof(QUEUE_JOB_OLD)); + if (que) { + if (!que->queue_jobs) { + que->queue_jobs=p; + p->job_position=1; + que->last_job_id=1; } else { - jo_id = (int) jo->q.n.job_id[0]; - memcpy(&(jo->q.n), queue_job, sizeof(QUEUE_JOB)); - jo->q.n.job_id[0] = (uint8) jo_id; - - U16_TO_BE16(0xffff, jo->q.n.record_in_use); - U32_TO_BE32(0x0, jo->q.n.record_previous); - U32_TO_BE32(0x0, jo->q.n.record_next); - jo->q.n.client_connection[2] = 0; - jo->q.n.client_connection[3] = 0; - U16_TO_16(connection, jo->q.n.client_connection); - - memset(jo->q.n.client_task, 0, 4); - jo->q.n.client_task[0] = (uint8)0xfe; /* ?? */ - U32_TO_BE32(1, jo->q.n.client_id); /* SU */ - set_entry_time(jo->q.n.job_entry_time); - - jo->q.n.job_typ[0] = 0x0; /* 0xd0;*/ - jo->q.n.job_typ[1] = 0x0; - jo->q.n.job_position[0] = 0x1; - jo->q.n.job_position[1] = 0x0; - jo->q.n.job_control_flags[0] |= 0x20; - jo->q.n.job_control_flags[1] = 0x0; - - result = create_queue_file(jo->q.n.job_file_name, - q_id, jo_id, connection, - dirname, dir_nam_len, - jo->q.n.job_bez); - - if (result > -1) { - jo->fhandle = (uint32) result; - U32_TO_32(jo->fhandle, jo->q.n.job_file_handle); - result = 0; - } - U32_TO_BE32(0, jo->q.n.server_station); - U32_TO_BE32(0, jo->q.n.server_task); - U32_TO_BE32(0, jo->q.n.server_id); - if (!result) memcpy(queue_job, &(jo->q.n), sizeof(QUEUE_JOB)); - } - if (result) free_queue_job(jo_id); - } - return(result); -} - -int nw_close_file_queue(uint8 *queue_id, - uint8 *job_id, - uint8 *prc, int prc_len) -{ - int result = -0xff; - int jo_id = (int) *job_id; /* ever only the first byte */ - XDPRINTF((5,0,"nw_close_file_queue JOB=%d", jo_id)); - if (jo_id > 0 && jo_id <= anz_jobs){ - INT_QUEUE_JOB *jo=queue_jobs[jo_id-1]; - int fhandle = (int)jo->fhandle; - char unixname[300]; - QUEUE_PRINT_AREA qpa; - if (jo->old_job) { - memcpy(&qpa, jo->q.o.client_area, sizeof(QUEUE_PRINT_AREA)); - } else { - memcpy(&qpa, jo->q.n.client_area, sizeof(QUEUE_PRINT_AREA)); - } - strmaxcpy((uint8*)unixname, (uint8*)file_get_unix_name(fhandle), sizeof(unixname)-1); - XDPRINTF((5,0,"nw_close_file_queue fhandle=%d", fhandle)); - if (*unixname) { - char buff[1024]; - char printcommand[300]; - FILE *f=NULL; - if (prc_len && *(prc+prc_len-1)=='!'){ - strmaxcpy((uint8*)buff, prc, prc_len-1); - sprintf(printcommand, "%s %s %s", buff, - qpa.banner_user_name, qpa.banner_file_name); - } else - strmaxcpy((uint8*)printcommand, prc, prc_len); - nw_close_file(fhandle, 1); - jo->fhandle = 0L; - if (NULL == (f = fopen(unixname, "r"))) { - /* OK now we try the open as root */ - seteuid(0); - f = fopen(unixname, "r"); - reset_guid(); - } - if (NULL != f) { - int is_ok = 0; - FILE_PIPE *fp = ext_popen(printcommand, geteuid(), getegid()); - if (fp) { - int k; - is_ok++; - while ((k = fread(buff, 1, sizeof(buff), f)) > 0) { - /* - if (1 != fwrite(buff, k, 1, fp->fildes[0])) { - */ - if (k != write(fileno(fp->fildes[0]), buff, k)) { - XDPRINTF((1,0,"Cannot write to pipe `%s`", printcommand)); - is_ok=0; - } + int flag; + INT_QUEUE_JOB *qj; + int verylastjobid=que->last_job_id?que->last_job_id:1; + do { + qj=que->queue_jobs; + flag=1; + do { + if (++(que->last_job_id)>999) que->last_job_id=1; + if (que->last_job_id==verylastjobid) { + xfree(p); + return(NULL); } - if (0 != (k=ext_pclose(fp))) { - XDPRINTF((1,0,"Errorresult = %d by closing print pipe", k)); + } while (que->last_job_id==qj->job_id); + while (qj->next != NULL) { + qj=qj->next; + if (qj->job_id==que->last_job_id) { + flag=0; + break; } - } else - XDPRINTF((1,0,"Cannot open pipe `%s`", printcommand)); - fclose(f); - if (is_ok) { - seteuid(0); - unlink(unixname); - reset_guid(); - result=0; } - } else XDPRINTF((1,0,"Cannot open queue-file `%s`", unixname)); - } else - XDPRINTF((2,0,"fhandle=%d NOT OK !", fhandle)); - free_queue_job(jo_id); + } while (!flag); + qj->next=p; + p->job_position=qj->job_position+1; + } + if (!p->job_id) + p->job_id=que->last_job_id; + p->next=NULL; + que->changed++; + que->count_jobs++; + return(p); + } + return(NULL); +} + +static INT_QUEUE_JOB *new_queue_job(NWE_QUEUE*que, int connection, int task, uint32 id) +{ + if (que) { + INT_QUEUE_JOB *p=(INT_QUEUE_JOB*)xcmalloc(sizeof(INT_QUEUE_JOB)); + time(&(p->entry_time)); + p->file_entry_time=p->entry_time; + p->client_connection=connection; + p->client_task=task; + p->client_id=id; + p->next=NULL; + p->job_id=0; + return(add_queue_job(que, p)); + } + return(NULL); +} + +static void free_queue_job(NWE_QUEUE *que, int job_id) +{ + INT_QUEUE_JOB *qj=(que) ? que->queue_jobs : NULL; + if (!qj) return; + if (qj->job_id==job_id){ + int pos=1; + que->queue_jobs=qj->next; + xfree(qj); + qj=que->queue_jobs; + while(qj) { + qj->job_position=pos++; + qj=qj->next; + } + que->changed++; + que->count_jobs--; + return; + } + while (qj->next) { + if (qj->next->job_id == job_id) { + INT_QUEUE_JOB *tmp=qj->next; + int pos=tmp->job_position; + qj->next=tmp->next; + xfree(tmp); + tmp=qj->next; + while(tmp) { + tmp->job_position=pos++; + tmp=tmp->next; + } + que->changed++; + que->count_jobs--; + return; + } else qj=qj->next; + } + /* not found */ +} + +static INT_QUEUE_JOB *find_queue_job(NWE_QUEUE *que, uint32 job_id) +{ + if (que) { + INT_QUEUE_JOB *qj=que->queue_jobs; + while (qj) { + if (qj->job_id==job_id) return(qj); + qj=qj->next; + } + } + return(NULL); +} + +static void r_w_queue_jobs(NWE_QUEUE *q, int mode) +/* mode == 0 read, 1 = write if changed, 2 = write always */ +{ + if (q && (q->changed || !mode || mode == 2)) { + uint8 path[300]; + int fd=open(get_div_pathes(path, NULL, 4, "%x/queue", q->id), + mode ? O_RDWR|O_TRUNC|O_CREAT:O_RDONLY); + if (fd>-1) { + int i; + if (!mode) { /* read */ + if (read(fd, &i, sizeof(i))==sizeof(i) && i==sizeof(INT_QUEUE_JOB)){ + INT_QUEUE_JOB *qj=(INT_QUEUE_JOB*)xmalloc(sizeof(INT_QUEUE_JOB)); + while (i == read(fd, qj, i)){ + if (i < sizeof(INT_QUEUE_JOB)) + memset(((uint8*)qj)+i, 0, sizeof(INT_QUEUE_JOB)-i); + /* correct some possible wrong values */ + qj->server_station=0; + qj->server_id=0; + add_queue_job(q, qj); + qj=(INT_QUEUE_JOB*)xmalloc(sizeof(INT_QUEUE_JOB)); + } + xfree(qj); + } + } else { + INT_QUEUE_JOB *qj=q->queue_jobs; + if (qj) { + i=sizeof(INT_QUEUE_JOB); + i=(sizeof(i)==write(fd, &i, sizeof(i))) ? 0: -1; + while (!i&&qj) { + if(sizeof(INT_QUEUE_JOB) != write(fd, qj, sizeof(INT_QUEUE_JOB))) + --i; + qj=qj->next; + } + } + } + close(fd); + } else if (mode || errno != 2) { + XDPRINTF((1,0x10, "Cannot open '%s'", path)); + } + q->changed=0; + } +} + +static void set_time_field(uint8 *timef, time_t ptime) +{ + if ((int)ptime == -1) { + memset(timef, 0xff, 6); + } else { + struct tm *s_tm = localtime(&ptime); + timef[0] = (uint8) s_tm->tm_year; + timef[1] = (uint8) s_tm->tm_mon+1; + timef[2] = (uint8) s_tm->tm_mday; + timef[3] = (uint8) s_tm->tm_hour; + timef[4] = (uint8) s_tm->tm_min; + timef[5] = (uint8) s_tm->tm_sec; + } +} + +static time_t get_time_field(uint8 *timef) +{ + struct tm s_tm; + if (0xff==timef[0]) return((time_t)-1); + s_tm.tm_year = timef[0]; + s_tm.tm_mon = timef[1]-1; + s_tm.tm_mday = timef[2]; + s_tm.tm_hour = timef[3]; + s_tm.tm_min = timef[4]; + s_tm.tm_sec = timef[5]; + s_tm.tm_isdst = -1; + return(mktime(&s_tm)); +} + +static void build_queue_file_name(uint8 *job_file_name, INT_QUEUE_JOB *jo) +{ + *job_file_name = (uint8) sprintf((char*)job_file_name+1, + "%08lX.%03d", jo->file_entry_time, jo->job_id); +} + +static void build_unix_queue_file(uint8 *buf, NWE_QUEUE *q, INT_QUEUE_JOB *jo) +{ + if (q->queuedir_len) { + memcpy(buf, q->queuedir, q->queuedir_len); + sprintf(buf+q->queuedir_len, "/%08lX.%03d", jo->file_entry_time, jo->job_id); + if (q->queuedir_downshift) + downstr(buf+q->queuedir_len+1); + } else *buf='\0'; + XDPRINTF((3,0, "build_unix_queue_file=`%s`", buf)); +} + +int nw_get_q_dirname(uint32 q_id, uint8 *buff) +{ + return(nw_get_prop_val_str(q_id, "Q_DIRECTORY", buff)); +} + +static int nw_get_q_prcommand(uint32 q_id, uint8 *buff) +{ + return(nw_get_prop_val_str(q_id, "Q_UNIX_PRINT", buff)); +} + +static int fill_q_job_entry_old(INT_QUEUE_JOB *jo, + QUEUE_JOB_OLD *job, + int full) +{ + job->client_connection = (uint8)jo->client_connection; + job->client_task = (uint8)jo->client_task; + U32_TO_BE32(jo->client_id, job->client_id); + U32_TO_BE32(jo->target_id, job->target_id); + + set_time_field(job->target_execute_time, jo->execute_time); + set_time_field(job->job_entry_time, jo->entry_time); + + U16_TO_BE16(jo->job_id, job->job_id); + U16_TO_BE16(jo->job_typ, job->job_typ); + + job->job_position = (uint8)jo->job_position; + job->job_control_flags = (uint8)jo->job_control_flags; + + build_queue_file_name(job->job_file_name, jo); + /* file handle is not filled here */ + job->server_station = (uint8)jo->server_station; + job->server_task = (uint8)jo->server_task; + U32_TO_BE32(jo->server_id, job->server_id); + if (full) { + memcpy(job->job_description, jo->job_description, + sizeof(job->job_description)); + memcpy(job->client_area, jo->client_area, + sizeof(job->client_area)); + return(sizeof(QUEUE_JOB_OLD)); + } + return(54); +} + +static int fill_q_job_entry(INT_QUEUE_JOB *jo, + QUEUE_JOB *job, + int full) +{ + memset(job->record_in_use, 0xff, 2); + memset(job->record_previous, 0, 4); + memset(job->record_next, 0, 4); + + U32_TO_32(jo->client_connection, job->client_connection); + U32_TO_32(jo->client_task, job->client_task); + U32_TO_BE32(jo->client_id, job->client_id); + U32_TO_BE32(jo->target_id, job->target_id); + + set_time_field(job->target_execute_time, jo->execute_time); + set_time_field(job->job_entry_time, jo->entry_time); + + U32_TO_BE32(jo->job_id, job->job_id); + U16_TO_BE16(jo->job_typ, job->job_typ); + + U16_TO_16(jo->job_position, job->job_position); + U16_TO_16(jo->job_control_flags, job->job_control_flags); + + build_queue_file_name(job->job_file_name, jo); + /* file handle is not filled here */ + U32_TO_32(jo->server_station, job->server_station); + U32_TO_32(jo->server_task, job->server_task); + U32_TO_BE32(jo->server_id, job->server_id); + if (full) { + memcpy(job->job_description, jo->job_description, + sizeof(job->job_description)); + memcpy(job->client_area, jo->client_area, + sizeof(job->client_area)); + return(sizeof(QUEUE_JOB)); + } + return(78); +} + +int nw_creat_queue_job(int connection, int task, uint32 object_id, + uint32 q_id, uint8 *q_job, uint8 *responsedata, + int old_call) +{ + uint8 *fulldirname = (old_call) ? responsedata+sizeof(QUEUE_JOB_OLD) + : responsedata+sizeof(QUEUE_JOB); + int result = nw_get_q_dirname(q_id, fulldirname+1); + NWE_QUEUE *que=find_queue(q_id); + if (result > 0 && que) { + INT_QUEUE_JOB *jo = new_queue_job(que, connection, task, object_id); + *fulldirname=(uint8) result++; + if (jo == NULL) return(-0xd4); /* queue full */ + if (old_call) { /* before 3.11 */ + QUEUE_JOB_OLD *job = (QUEUE_JOB_OLD*)q_job; + memcpy(jo->job_description, job->job_description, + sizeof(jo->job_description)); + memcpy(jo->client_area, job->client_area, + sizeof(jo->client_area)); + jo->target_id = GET_BE32(job->target_id); + jo->execute_time = get_time_field(job->target_execute_time); + jo->job_typ = GET_BE16(job->job_typ); + jo->job_control_flags = job->job_control_flags|0x20; + result+=fill_q_job_entry_old(jo, (QUEUE_JOB_OLD*)responsedata, 1); + } else { + QUEUE_JOB *job = (QUEUE_JOB*)q_job; + memcpy(jo->job_description, job->job_description, + sizeof(jo->job_description)); + memcpy(jo->client_area, job->client_area, + sizeof(jo->client_area)); + jo->target_id = GET_BE32(job->target_id); + jo->execute_time = get_time_field(job->target_execute_time); + jo->job_typ = GET_BE16(job->job_typ); + jo->job_control_flags = GET_16(job->job_control_flags) | 0x20; + result+=fill_q_job_entry(jo, (QUEUE_JOB*)responsedata, 1); + } + } else { + result=-0xd3; /* no rights */ } return(result); } + +int nw_close_queue_job(uint32 q_id, int job_id, + uint8 *responsedata) +{ + NWE_QUEUE *que=find_queue(q_id); + if (que) { + INT_QUEUE_JOB *jo=find_queue_job(que, job_id); + if (jo) { + int result=sizeof(jo->client_area); + int i; + jo->job_control_flags &= ~0x20; + memcpy(responsedata, jo->client_area, result); + i = nw_get_q_prcommand(q_id, responsedata+result+1); + if (i > -1) { /* this job is handled directly by client */ + *(responsedata+result)=(uint8)i; + result+=i; + free_queue_job(que, job_id); + } else + *(responsedata+result)=0; + ++result; + return(result); + } + return(-0xff); + } + return(-0xd8); /* queue not active */ +} + +int nw_get_queue_status(uint32 q_id, int *status, int *entries, + int *servers, int server_ids[], int server_conns[]) +{ + NWE_QUEUE *q=find_queue(q_id); + if (q) { + *status=q->status; + *entries=q->count_jobs; + if (q->qserver) { + *servers=1; + server_ids[0] = q->qserver->user_id; + server_conns[0] = q->qserver->connection; + } else + *servers=0; + return(0); + } + return(-0xff); +} + +int nw_get_q_job_entry(uint32 q_id, int job_id, + uint8 *responsedata, int old_call) +{ + int result=-0xd5; + NWE_QUEUE *q = find_queue(q_id); + INT_QUEUE_JOB *qj = find_queue_job(q, job_id); + if (qj) { + if (old_call) { + QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; + result=fill_q_job_entry_old(qj, job, 1); + } else { + QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + result=fill_q_job_entry(qj, job, 1); + } + } + return(result); +} + +int nw_get_queue_job_list_old(uint32 q_id, uint8 *responsedata) +{ + int result = -0xff; + NWE_QUEUE *q = find_queue(q_id); + if (q) { + INT_QUEUE_JOB *qj=q->queue_jobs; + uint8 *p=responsedata+2; + int count=0; + while (qj && count < 255) { + U16_TO_BE16(qj->job_id, p); + p+=2; + ++count; + qj=qj->next; + } + U16_TO_BE16(count, responsedata); /* Hi-Lo !! */ + result=2+count*2; + } + return(result); +} + +int nw_get_queue_job_file_size(uint32 q_id, int job_id) +{ + int result=-0xd5; + NWE_QUEUE *q = find_queue(q_id); + INT_QUEUE_JOB *qj = find_queue_job(q, job_id); + if (qj) { + struct stat stb; + uint8 buf[300]; + build_unix_queue_file(buf, q, qj); + if (!stat(buf, &stb)) + return(stb.st_size); + return(0); + } + return(result); +} + +static int remove_queue_job_file(NWE_QUEUE *q, INT_QUEUE_JOB *qj) +{ + struct stat stb; + uint8 buf[300]; + build_unix_queue_file(buf, q, qj); + if (!stat(buf, &stb)) + return(unlink(buf)); + return(0); +} + +int nw_remove_job_from_queue(uint32 user_id, uint32 q_id, int job_id) +{ + int result=-0xff; + NWE_QUEUE *q = find_queue(q_id); + INT_QUEUE_JOB *qj = find_queue_job(q, job_id); + if (qj) { + if (user_id==1 || user_id == qj->client_id) { + result=remove_queue_job_file(q, qj); + if (!result) + free_queue_job(q, job_id); + else result=-0xd6; + } else result=-0xd6; /* no queue user rights */ + } + return(result); +} + +/* ------------------ for queue servers ------------------- */ +static QUEUE_SERVER *new_qserver(uint32 user_id, int connection) +{ + QUEUE_SERVER *qs=(QUEUE_SERVER*)xcmalloc(sizeof(QUEUE_SERVER)); + qs->user_id=user_id; + qs->connection=connection; + return(qs); +} + +static void free_qserver(QUEUE_SERVER *qs) +{ + if (qs) { + xfree(qs); + } +} + +int nw_attach_server_to_queue(uint32 user_id, + int connection, + uint32 q_id) +{ + int result=-0xff; + NWE_QUEUE *q = find_queue(q_id); + if (q) { + if (!(result=nw_is_member_in_set(q_id, "Q_SERVERS", user_id))){ + if (!q->qserver) { + q->qserver=new_qserver(user_id, connection); + } else result=-0xdb; /* too max queue servers */ + /* we only allow 1 qserver/queue in this version */ + } + } + return(result); +} + +int nw_detach_server_from_queue(uint32 user_id, + int connection, + uint32 q_id) +{ + int result=-0xff; + NWE_QUEUE *q = find_queue(q_id); + if (q && q->qserver + && q->qserver->user_id == user_id + && q->qserver->connection == connection) { + free_qserver(q->qserver); + q->qserver=NULL; + result=0; + } + return(result); +} + + +int nw_service_queue_job(uint32 user_id, int connection, int task, + uint32 q_id, int job_typ, + uint8 *responsedata, int old_call) +{ + int result=-0xd5; /* no job */ + NWE_QUEUE *q = find_queue(q_id); + if (q && q->qserver + && q->qserver->user_id == user_id + && q->qserver->connection == connection) { + uint8 *fulldirname = (old_call) ? responsedata+sizeof(QUEUE_JOB_OLD) + : responsedata+sizeof(QUEUE_JOB); + int len = nw_get_q_dirname(q_id, fulldirname+1); + + if (len > 0) { + INT_QUEUE_JOB *qj=q->queue_jobs; + INT_QUEUE_JOB *fqj=NULL; + time_t acttime=time(NULL); + *fulldirname=(uint8) len++; + while(qj) { + if ( (!qj->server_id) + && !(qj->job_control_flags&0x20) /* not actual queued */ + && qj->execute_time <= acttime + && (qj->target_id == MAX_U32 || qj->target_id == user_id) + && (qj->job_typ == MAX_U16 || job_typ==MAX_U16 + || qj->job_typ == job_typ)) { + + fqj=qj; + break; + } else { + XDPRINTF((6, 0, "Queue job ignored: station=%d, target_id=0x%x,job_typ=0x%x, %s", + qj->server_station, qj->target_id, qj->job_typ, + (qj->execute_time > acttime) ? "execute time not reached" : "")); + } + qj=qj->next; + } + if (fqj) { + fqj->server_id = user_id; + fqj->server_station = connection; + fqj->server_task = task; + if (old_call) { + QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; + result=fill_q_job_entry_old(fqj, job, 1); + } else { + QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + result=fill_q_job_entry(fqj, job, 1); + } + result+=len; + } else { + XDPRINTF((3, 0, "No queue job found for q_id=0x%x, user_id=0x%x,job_typ=0x%x", + q_id, user_id, job_typ)); + } + } else { + XDPRINTF((1, 0, "Could not get queuedir of q_id=0x%x", q_id)); + } + } else { + XDPRINTF((1, 0, "Could not find qserver q_id=0x%x, user_id=0x%x, connect=%d", + q_id, user_id, connection)); + } + return(result); +} + +int nw_finish_abort_queue_job(int mode, uint32 user_id, int connection, + uint32 q_id, int job_id) +/* modes + * 0 = finish, + * 1 = abort +*/ +{ + NWE_QUEUE *que=find_queue(q_id); + if (que) { + INT_QUEUE_JOB *jo=find_queue_job(que, job_id); + if (jo && jo->server_id == user_id + && jo->server_station == connection) { + if (mode && (jo->job_control_flags&0x10) ) { /* restart job */ + jo->server_id=0; + jo->server_station=0; + } else { + if (!remove_queue_job_file(que, jo)) + free_queue_job(que, job_id); + else return(-0xd6); + } + return(0); + } + return(-0xff); + } + return(-0xd8); /* queue not active */ +} + +void exit_queues(void) +{ + if (nwe_queues) { + NWE_QUEUE *q=(NWE_QUEUE*)nwe_queues; + while (q) { + INT_QUEUE_JOB *qj=q->queue_jobs; + uint32 qid=q->id; + r_w_queue_jobs(q, 2); + while(qj) { + int job_id=qj->job_id; + qj=qj->next; + free_queue_job(q, job_id); + } + q=q->next; + + free_queue(qid); + } + nwe_queues=NULL; + } +} + +int build_unix_queue_dir(uint8 *buf, + uint8 *unixname, + int unixname_len, + int downshift, + uint8 *sysname, + uint32 q_id) +{ + int result = -0xff; + uint8 buf1[300]; + uint8 *p; + memcpy(buf, unixname, unixname_len); + result=nw_get_q_dirname(q_id, buf1); + upstr(buf1); + if (result > -1 && NULL != (p=strchr(buf1, ':')) ) { + *p++='\0'; + result -= (int)(p - buf1); + if (!strcmp(buf1, sysname)) { + memcpy(buf+unixname_len, p, result); + result+=unixname_len; + if (buf[result-1]=='/') + --result; + buf[result]='\0'; + if (downshift) + downstr(buf+unixname_len); + } + } + XDPRINTF((3,0, "build_unix_queue_dir=`%s`, len=%d", buf, result)); + return(result); +} + +void init_queues(uint8 *unixname, int unixname_len, + int downshift, uint8 *sysname) +{ + NETOBJ obj; + uint8 buf[300]; + int result; + uint8 *wild="*"; + uint32 last_obj_id=MAX_U32; + exit_queues(); + strmaxcpy(buf, unixname, unixname_len); + XDPRINTF((3,0, "init_queues:unixname='%s'", buf)); + obj.type = 3; /* queue */ + strcpy(obj.name, wild); + result = scan_for_obj(&obj, last_obj_id); + while (!result) { + NWE_QUEUE *que; + nwdbm_mkdir(get_div_pathes(buf, NULL, 4, "%x", obj.id), + 0700, 0); + strmaxcpy(buf, obj.name, 47); + XDPRINTF((3, 0, "init queue, id=0x%x, '%s'", + obj.id, buf)); + + result=build_unix_queue_dir(buf, unixname, unixname_len, + downshift, sysname, obj.id); + if (result > 0) { + que=new_queue(obj.id); + new_str(que->queuedir, buf); + que->queuedir_len=result; + que->queuedir_downshift=downshift; + r_w_queue_jobs(que, 0); + } + last_obj_id=obj.id; + strcpy(obj.name, wild); + result = scan_for_obj(&obj, last_obj_id); + } +} + diff --git a/nwqueue.h b/nwqueue.h index 5a72371..d6082a3 100644 --- a/nwqueue.h +++ b/nwqueue.h @@ -1,93 +1,44 @@ -/* nwqueue.h 04-May-96 */ +/* nwqueue.h 18-Aug-97 */ #ifndef _NWQUEUE_H_ #define _NWQUEUE_H_ +#include "queuedef.h" -/* enhanced pipe handling */ -typedef struct { - FILE *fildes[3]; /* filedescriptor to 0,1,2 of new process */ - int command_pid; /* pid of piped command */ - int flags; /* special flags */ -} FILE_PIPE; +extern int nw_get_q_dirname(uint32 q_id, uint8 *buff); -extern int ext_pclose(FILE_PIPE *fp); -extern FILE_PIPE *ext_popen(char *command, int uid, int gid); +extern int nw_creat_queue_job(int connection, int task, uint32 object_id, + uint32 q_id, uint8 *q_job, uint8 *responsedata, + int old_call); -/* queues */ -typedef struct { - uint8 record_in_use[2]; - uint8 record_previous[4]; - uint8 record_next[4]; - uint8 client_connection[4]; - uint8 client_task[4]; - uint8 client_id[4]; +extern int nw_close_queue_job(uint32 q_id, int job_id, + uint8 *responsedata); - uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */ - uint8 target_execute_time[6]; /* all 0xff */ - uint8 job_entry_time[6]; /* all zero */ - uint8 job_id[4]; /* ?? alles 0 HI-LOW */ - uint8 job_typ[2]; /* z.B. Printform HI-LOW */ - uint8 job_position[2]; /* ?? alles 0 low-high ? */ - uint8 job_control_flags[2]; /* z.B 0x10, 0x00 */ - /* 0x80 operator hold flag */ - /* 0x40 user hold flag */ - /* 0x20 entry open flag */ - /* 0x10 service restart flag */ - /* 0x08 autostart flag */ +extern int nw_get_queue_status(uint32 q_id, int *status, int *entries, + int *servers, int server_ids[], int server_conns[]); - uint8 job_file_name[14]; /* len + DOS filename */ - uint8 job_file_handle[4]; - uint8 server_station[4]; - uint8 server_task[4]; - uint8 server_id[4]; - uint8 job_bez[50]; /* "LPT1 Catch" */ - uint8 client_area[152]; -} QUEUE_JOB; +extern int nw_get_q_job_entry(uint32 q_id, int job_id, + uint8 *responsedata, int old_call); +extern int nw_get_queue_job_list_old(uint32 q_id, uint8 *responsedata); +extern int nw_get_queue_job_file_size(uint32 q_id, int job_id); -typedef struct { - uint8 client_connection; - uint8 client_task; - uint8 client_id[4]; - uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */ - uint8 target_execute_time[6]; /* all 0xff */ - uint8 job_entry_time[6]; /* all zero */ - uint8 job_id[2]; /* ?? alles 0 HI-LOW */ - uint8 job_typ[2]; /* z.B. Printform HI-LOW */ - uint8 job_position; /* zero */ - uint8 job_control_flags; /* z.B 0x10 */ - /* 0x80 operator hold flag */ - /* 0x40 user hold flag */ - /* 0x20 entry open flag */ - /* 0x10 service restart flag */ - /* 0x08 autostart flag */ +extern int nw_remove_job_from_queue(uint32 user_id, uint32 q_id, int job_id); - uint8 job_file_name[14]; /* len + DOS filename */ - uint8 job_file_handle[6]; - uint8 server_station; - uint8 server_task; - uint8 server_id[4]; - uint8 job_bez[50]; /* "LPT1 Catch" */ - uint8 client_area[152]; -} QUEUE_JOB_OLD; /* before 3.11 */ +/* ------------------ for queue servers ------------------- */ +extern int nw_attach_server_to_queue(uint32 user_id, + int connection, + uint32 q_id); -typedef struct { - uint8 version; /* normal 0x0 */ - uint8 tabsize; /* normal 0x8 */ - uint8 anz_copies[2]; /* copies 0x0, 0x01 */ - uint8 print_flags[2]; /* 0x0, 0xc0 z.B. with banner */ - uint8 max_lines[2]; /* 0x0, 0x42 */ - uint8 max_chars[2]; /* 0x0, 0x84 */ - uint8 form_name[16]; /* "UNKNOWN" */ - uint8 reserved[6]; /* all zero */ - uint8 banner_user_name[13]; /* "SUPERVISOR" */ - uint8 banner_file_name[13]; /* "LST:" */ - uint8 banner_header_file_name[14]; /* all zero */ - uint8 file_path_name[80]; /* all zero */ -} QUEUE_PRINT_AREA; +extern int nw_detach_server_from_queue(uint32 user_id, + int connection, + uint32 q_id); -extern int nw_creat_queue(int connection, uint8 *queue_id, uint8 *queue_job, - uint8 *dirname, int dir_nam_len, int old_call); +extern int nw_service_queue_job(uint32 user_id, int connection, int task, + uint32 q_id, int job_typ, + uint8 *responsedata, int old_call); -extern int nw_close_file_queue(uint8 *queue_id, - uint8 *job_id, - uint8 *prc, int prc_len); +extern int nw_finish_abort_queue_job(int mode, uint32 user_id, int connection, + uint32 q_id, int job_id); + +extern void exit_queues(void); +extern void init_queues(uint8 *unixname, int unixname_len, + int downshift, uint8 *sysname); #endif diff --git a/nwvolume.c b/nwvolume.c index 1665a7e..895f5c8 100644 --- a/nwvolume.c +++ b/nwvolume.c @@ -1,4 +1,4 @@ -/* nwvolume.c 20-Jul-97 */ +/* nwvolume.c 02-Aug-97 */ /* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -34,6 +34,7 @@ NW_VOL *nw_volumes=NULL; int used_nw_volumes=0; +int loaded_namespaces=0; uint8 *home_dir=NULL; int home_dir_len=0; char *path_vol_inodes_cache=NULL; @@ -78,7 +79,8 @@ void nw_init_volumes(FILE *f) } } rewind(f); - used_nw_volumes = 0; + used_nw_volumes = 0; + loaded_namespaces = 0; new_str(path_vol_inodes_cache, "/var/spool/nwserv/.volcache"); while (0 != (what = get_ini_entry(f, 0, buff, sizeof(buff)))) { if ( what == 1 && used_nw_volumes < max_nw_vols && strlen((char*)buff) > 3){ @@ -91,6 +93,7 @@ void nw_init_volumes(FILE *f) if (founds > 1) { NW_VOL *vol=&(nw_volumes[used_nw_volumes]); vol->options = VOL_NAMESPACE_DOS; + loaded_namespaces |= VOL_NAMESPACE_DOS; up_fn(sysname); new_str(vol->sysname, sysname); if (1 == (len = strlen((char*)unixname)) && unixname[0] == '~') { @@ -133,10 +136,12 @@ void nw_init_volumes(FILE *f) case 'O' : vol->options |= VOL_NAMESPACE_OS2; + loaded_namespaces |= VOL_NAMESPACE_OS2; break; case 'N' : vol->options |= VOL_NAMESPACE_NFS; + loaded_namespaces |= VOL_NAMESPACE_NFS; break; default : break; diff --git a/nwvolume.h b/nwvolume.h index 693d457..748cb3d 100644 --- a/nwvolume.h +++ b/nwvolume.h @@ -1,4 +1,4 @@ -/* nwvolume.h 20-Jul-97 */ +/* nwvolume.h 02-Aug-97 */ /* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany * * This program is free software; you can redistribute it and/or modify @@ -69,6 +69,7 @@ struct fs_usage { extern NW_VOL *nw_volumes; extern int used_nw_volumes; +extern int loaded_namespaces; extern uint8 *home_dir; extern int home_dir_len; extern char *path_vol_inodes_cache; /* for namespace routines */ diff --git a/queuedef.h b/queuedef.h new file mode 100644 index 0000000..0a05ad4 --- /dev/null +++ b/queuedef.h @@ -0,0 +1,78 @@ +/* queuedef.h 09-Aug-97 */ + +#ifndef _QUEUEDEF_H_ +#define _QUEUEDEF_H_ +typedef struct { + uint8 record_in_use[2]; + uint8 record_previous[4]; + uint8 record_next[4]; + + uint8 client_connection[4]; /* Lo-Hi */ + uint8 client_task[4]; /* Lo-Hi */ + uint8 client_id[4]; /* Hi-Lo */ + + uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */ + uint8 target_execute_time[6]; /* all 0xff */ + uint8 job_entry_time[6]; /* all zero */ + uint8 job_id[4]; /* Hi-Lo */ + uint8 job_typ[2]; /* Hi-Lo */ + uint8 job_position[2]; /* Lo-Hi, e.g. 0x01, 0x00 */ + uint8 job_control_flags[2]; /* Lo-Hi, e.g. 0x10, 0x00 */ + /* 0x80 operator hold flag */ + /* 0x40 user hold flag */ + /* 0x20 entry open flag */ + /* 0x10 service restart flag */ + /* 0x08 autostart flag */ + + uint8 job_file_name[14]; /* len + DOS filename */ + uint8 job_file_handle[4]; + uint8 server_station[4]; + uint8 server_task[4]; + uint8 server_id[4]; + /* offset 78 */ + uint8 job_description[50]; /* "LPT1 Catch" */ + uint8 client_area[152]; +} QUEUE_JOB; + +typedef struct { + uint8 client_connection; + uint8 client_task; + uint8 client_id[4]; + uint8 target_id[4]; /* 0xff, 0xff, 0xff, 0xff */ + uint8 target_execute_time[6]; /* all 0xff */ + uint8 job_entry_time[6]; /* all zero */ + uint8 job_id[2]; /* Hi-Lo */ + uint8 job_typ[2]; /* Hi-Lo */ + uint8 job_position; /* zero */ + uint8 job_control_flags; + /* 0x80 operator hold flag */ + /* 0x40 user hold flag */ + /* 0x20 entry open flag */ + /* 0x10 service restart flag */ + /* 0x08 autostart flag */ + + uint8 job_file_name[14]; /* len + DOS filename */ + uint8 job_file_handle[6]; + uint8 server_station; + uint8 server_task; + uint8 server_id[4]; + /* offset 54 */ + uint8 job_description[50]; /* "LPT1 Catch" */ + uint8 client_area[152]; +} QUEUE_JOB_OLD; /* before 3.11 */ + +typedef struct { + uint8 version; /* normal 0x0 */ + uint8 tabsize; /* normal 0x8 */ + uint8 count_copies[2]; /* copies 0x0, 0x01 */ + uint8 print_flags[2]; /* 0x0, 0xc0 e.g. with banner */ + uint8 max_lines[2]; /* 0x0, 0x42 */ + uint8 max_chars[2]; /* 0x0, 0x84 */ + uint8 form_name[16]; /* "UNKNOWN" */ + uint8 reserved[6]; /* all zero */ + uint8 banner_user_name[13]; /* "SUPERVISOR" */ + uint8 banner_file_name[13]; /* "LST:" */ + uint8 banner_header_file_name[14]; /* all zero */ + uint8 file_path_name[80]; /* all zero */ +} QUEUE_PRINT_AREA; +#endif diff --git a/sema.c b/sema.c new file mode 100644 index 0000000..43a1eab --- /dev/null +++ b/sema.c @@ -0,0 +1,259 @@ +/* sema.c :07-Aug-97 */ + +/* simple semaphore emulation, needs more work */ + +/* (C)opyright (C) 1997 Martin Stover, Marburg, Germany + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "net.h" +#include "nwbind.h" +#include "sema.h" + +#define MAX_SEMAPHORES 100 + +typedef struct { + int namlen; + uint8 *name; + int opencount; + int value; +} SEMA; + +static int count_semas=0; +static SEMA *semas[MAX_SEMAPHORES]; + +static int open_sema(int namlen, uint8 *name, int value, int *opencount) +{ + int k=-1; + int isfree=-1; + SEMA *se; + while (++k < count_semas){ + se=semas[k]; + if (se) { + if (se->namlen==namlen && !memcmp(se->name, name, namlen)) { + *opencount=++(se->opencount); + return(++k); + } + } else if (isfree<0) isfree=k; + } + if (isfree<0 && count_semas < MAX_SEMAPHORES) + isfree=count_semas++; + if (isfree < 0) return(-0x96); /* out of mem */ + se=semas[isfree]=(SEMA*)xcmalloc(sizeof(SEMA)); + se->namlen=namlen; + se->name=xmalloc(namlen); + memcpy(se->name, name, namlen); + se->value=value; + *opencount=se->opencount=1; + return(++isfree); +} + +static int close_sema(int handle) +{ + SEMA *se; + if (handle > 0 && --handle < count_semas && NULL != (se=semas[handle])){ + if (!(--se->opencount)) { + xfree(se->name); + xfree(se); + semas[handle]=NULL; + while (handle == count_semas-1) { + --count_semas; + if (!handle || semas[--handle]) break; + } + } + return(0); + } + return(-0xff); /* wrong handle */ +} + +static int wait_sema(int handle, int timeout) +{ + SEMA *se; + if (handle > 0 && --handle < count_semas && NULL != (se=semas[handle])){ + if (se->value < 1) return(-0xfe); /* timeout */ + --se->value; + return(0); + } + return(-0xff); /* wrong handle */ +} + +static int signal_sema(int handle) +{ + SEMA *se; + if (handle > 0 && --handle < count_semas && NULL != (se=semas[handle])){ + ++se->value; + return(0); + } + return(-0xff); /* wrong handle */ +} + +static int examine_sema(int handle, int *value, int *opencount) +{ + SEMA *se; + if (handle > 0 && --handle < count_semas && NULL != (se=semas[handle])){ + *value=se->value; + *opencount=se->opencount; + return(0); + } + return(-0xff); /* wrong handle */ +} + +static int open_conn_sema(CONNECTION *c, int handle) +{ + int k=c->count_semas; + int is_free=-1; + SEMA_CONN *sem; + while (k--) { + sem=&(c->semas[k]); + if (sem->handle==handle) { + sem->opencount++; + return(handle); + } else if (!sem->handle) is_free=k; + } + if (is_free < 0 && c->count_semas < MAX_SEMA_CONN) + is_free=c->count_semas++; + if (is_free < 0) + return(-0x96); /* we say out of mem here */ + sem=&(c->semas[is_free]); + sem->handle=handle; + sem->opencount=1; + return(handle); +} + +static int close_conn_sema(CONNECTION *c, int handle) +{ + int k=c->count_semas; + SEMA_CONN *sem; + while (k--) { + sem=&(c->semas[k]); + if (sem->handle==handle) { + if (!--sem->opencount) { + sem->handle=0; + if (k==c->count_semas-1) { + while(c->count_semas > 0 + && !(c->semas[c->count_semas-1].handle) ) + --c->count_semas; + } + } + return(0); + } + } + return(-0xff); /* wrong handle */ +} + +void clear_conn_semas(CONNECTION *c) +/* removes semas which are opened by this connection */ +{ + while (c->count_semas--) { + SEMA_CONN *sem=&(c->semas[c->count_semas]); + if (sem->handle>0&&sem->opencount>0) { + while (sem->opencount--) + close_sema(sem->handle); + } + } + c->count_semas=0; +} + +int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata) +{ + int result = -0xfb; /* unknown request */ + XDPRINTF((3, 0, "0x20 call ufunc=0x%x", ufunc)); + switch (ufunc) { + case 0x0 : { /* open semaphore */ + int value = *p; + int namlen = *(p+1); + uint8 *name = (p+2); + struct XDATA { + uint8 handle[4]; + uint8 opencount; + } *xdata = (struct XDATA*) responsedata; + int opencount; + if (namlen < 1 || namlen > 127) return(-0xfe); + if (value > 127) return(-0xff); + result=open_sema(namlen, name, value, &opencount); + if (result > -1) { + result=open_conn_sema(c, result); + if (result < 0){ + close_sema(result); + } + } + if (nw_debug>1){ + name[namlen]=0; + XDPRINTF((2, 0, "open_sem:`%s` value=%d, count=%d, handle=%d", + name, value, opencount, result)); + } + if (result > -1) { + U32_TO_BE32(result, xdata->handle); + xdata->opencount=(uint8)opencount; + result=sizeof(*xdata); + } + } + break; + + case 0x1 : { /* examine semaphore */ + int handle = GET_BE32(p); + struct XDATA { + char value; + uint8 opencount; + } *xdata = (struct XDATA*) responsedata; + int value; + int opencount; + result=examine_sema(handle, &value, &opencount); + XDPRINTF((2, 0, "examine_sem:%d, value=%d, opcount=%d, result=%d", + handle, value, opencount, result)); + if (result > -1) { + xdata->value=(char)value; + xdata->opencount=(uint8)opencount; + result=sizeof(*xdata); + } + } + break; + + + case 0x2 : { /* wait on semaphore */ + int handle = GET_BE32(p); + int timeout = GET_BE16(p+4); + result=wait_sema(handle, timeout); + XDPRINTF((2, 0, "wait_sem:%d, timeout=%d, result=%d", + handle, timeout, result)); + } + break; + + case 0x3 : { /* signal sema */ + int handle = GET_BE32(p); + result=signal_sema(handle); + XDPRINTF((2, 0, "signal_sem:%d, result=%d", + handle, result)); + } + break; + + + case 0x4 : { /* close semaphore */ + int handle = GET_BE32(p); + result=close_conn_sema(c, handle); + if (!result) + result=close_sema(handle); + XDPRINTF((2, 0, "close_sem:%d, result=%d", + handle, result)); + } + break; + + default : break; + } + return(result); +} + + diff --git a/sema.h b/sema.h new file mode 100644 index 0000000..16b5325 --- /dev/null +++ b/sema.h @@ -0,0 +1,9 @@ +/* sema.h: 07-Aug-97 */ + +#ifndef _SEMA_H_ +#define _SEMA_H_ + +extern void clear_conn_semas(CONNECTION *c); +extern int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata); + +#endif diff --git a/tools.c b/tools.c index 2c7fa94..f5cf4c4 100644 --- a/tools.c +++ b/tools.c @@ -115,12 +115,14 @@ static char *buffered=NULL; int errnum = errno; if (nw_debug >= dlevel) { if (use_syslog==1) { - char buf[2048]; /* should be ever big enough */ - char *pb=buf; + char *buf; + char *pb; if (buffered) { - strcpy(buf, buffered); - xfree(buffered); - pb+=strlen(buf); + buf=buffered; + pb=buf+strlen(buffered); + buffered=NULL; + } else { + pb=buf=xmalloc(2048); } if (p) { int l; @@ -143,9 +145,10 @@ static char *buffered=NULL; closelog(); } else { int l=strlen(buf); - buffered=xmalloc(l+1); - strcpy(buffered, buf); + buffered=xmalloc(l+2048); + memcpy(buffered, buf, l+1); } + xfree(buf); } else { if (!(mode & 1)) fprintf(logfile, "%-8s %d:", get_modstr(), connection); @@ -288,6 +291,7 @@ int get_ini_entry(FILE *f, int entry, uint8 *str, int strsize) } static uint8 *path_bindery=NULL; +static uint8 *path_spool=NULL; char *get_div_pathes(char *buff, char *name, int what, char *p, ... ) { @@ -297,15 +301,29 @@ char *get_div_pathes(char *buff, char *name, int what, char *p, ... ) switch (what) { case 0 : wpath = PATHNAME_PROGS; break; case 1 : if (path_bindery==NULL) { - if (get_ini_entry(NULL, 45, locbuf, sizeof(locbuf)) + if (get_ini_entry(NULL, 45, locbuf, sizeof(locbuf)) && *locbuf) { new_str(path_bindery, locbuf); } else new_str(path_bindery, PATHNAME_BINDERY); } - wpath = path_bindery; + wpath = path_bindery; break; case 2 : wpath = PATHNAME_PIDFILES; break; + + case 3 : + case 4 : if (path_spool==NULL) { + if (get_ini_entry(NULL, 42, locbuf, sizeof(locbuf)) + && *locbuf) { + new_str(path_spool, locbuf); + } else + new_str(path_spool, "/var/spool/nwserv"); + } + wpath = path_spool; + if (what==4) name="queues/"; + break; + + default : buff[0]='\0'; return(buff); } @@ -375,7 +393,7 @@ void get_debug_level(uint8 *buf) char dummy; if (sscanf(buf2, "%ld%c", &debug_mask, &dummy) != 1) sscanf(buf2, "%lx", &debug_mask); - } + } } } @@ -390,7 +408,7 @@ void get_ini_debug(int module) */ { uint8 buff[300]; - if (get_ini_entry(NULL, 100+module, buff, sizeof(buff))) + if (get_ini_entry(NULL, 100+module, buff, sizeof(buff))) get_debug_level(buff); } @@ -466,6 +484,19 @@ void init_tools(int module, int options) if (!strcmp(logfilename, "syslog")) use_syslog=1; + if (NWSERV == module) { + fprintf(stdout, "\n\nMars_nwe V%d.%02dpl%d started using %s.\n", + _VERS_H_, _VERS_L_, _VERS_P_, FILENAME_NW_INI); + fprintf(stdout, "If you have problems, please read mars_nwe/doc/BUGS !\n"); + if (use_syslog==1) { + fprintf(stdout, "Errors/warnings will be reported in syslog\n"); + } else { + fprintf(stdout, "Errors/warnings will be reported in %s\n", logfilename); + } + fprintf(stdout, "\n\n"); + fflush(stdout); + } + if (NWSERV == module || NWROUTED == module) { /* now make daemon */ int fd=fork(); if (fd) exit((fd > 0) ? 0 : 1);