From 51b8e807745a78147f6b0efd0fd24feae4cdcbc2 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sun, 13 Nov 2011 00:38:59 +0100 Subject: [PATCH] mars_nwe-0.99.pl01 --- debmask.h | 4 + doc/BUGS | 5 +- doc/CHANGES | 13 +- doc/CREDITS | 6 + doc/FAQS | 4 + doc/INSTALL.ger | 51 +- doc/NEWS | 4 + doc/mars_nwe.lsm | 4 +- examples/nw.ini | 62 ++- extpipe.c | 166 +++++++ extpipe.h | 16 + makefile.unx | 15 +- nameos2.c | 2 +- namspace.c | 220 +++++++-- namspace.h | 3 +- nwbind.c | 355 ++++++++++---- nwbind.h | 28 ++ nwconn.c | 218 +++++---- nwconn.h | 19 +- nwdbm.c | 413 +++++++++++----- nwdbm.h | 12 +- nwfile.c | 114 +++-- nwfile.h | 2 +- nwqconn.c | 317 +++++++++++++ nwqconn.h | 23 + nwqueue.c | 1166 ++++++++++++++++++++++++++++++---------------- nwqueue.h | 111 ++--- nwvolume.c | 9 +- nwvolume.h | 3 +- queuedef.h | 78 ++++ sema.c | 259 ++++++++++ sema.h | 9 + tools.c | 53 ++- 33 files changed, 2833 insertions(+), 931 deletions(-) create mode 100644 extpipe.c create mode 100644 extpipe.h create mode 100644 nwbind.h create mode 100644 nwqconn.c create mode 100644 nwqconn.h create mode 100644 queuedef.h create mode 100644 sema.c create mode 100644 sema.h 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);