/* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** Copyright (C) 1993 by ** DIGITAL EQUIPMENT CORPORATION, Maynard, MA. ** ** This software is furnished under a license and may be used and copied ** only in accordance with the terms of such license and with the inclusion ** of the above copyright notice. This software or any other copies there- ** of may not be provided or otherwise made available to any other person. ** No title to and ownership of the software is hereby transferred. ** ** The information in this software is subject to change without notice ** and should not be construed as a commitment by DIGITAL EQUIPMENT ** CORPORATION. ** ** DIGITAL assumes no responsibility for the use or reliability of its ** software on equipment which is not supplied by DIGITAL. **------------------------------------------------------------------------ */ /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FACILITY: DISKMOUNT_CHILD ** ** MODULE DESCRIPTION: ** ** Diskmount child (sub-)process. This module receives disk-mount ** data from the parent process, and attempts to perform all of the ** appropriate mount-related actions specified in the data. Success ** and error messages are returned to the parent process. This process ** will terminate when it receives an "EOF" QIO from the parent. ** ** AUTHORS: ** ** Philip Dickerson (with much assistance from the VAXC Notes ** conference and individuals within Digital) ** ** CREATION DATE: March, 1992 ** ** MODIFICATION HISTORY: ** ** March,1992 P. Dickerson ** ** X-5 Joseph A. Dziedzic 21-Sep-1993 ** Final cleanup, change local-area disk conditional assembly ** switch from "LAT" to "LAD". Local-area disks are NOT ** supported in this version. ** ** X-4 Joseph Dziedzic 13-Sep-1993 ** Fix bug in read_homeblock_label. ** ** X-3 Joseph A. Dziedzic 6-Jul-1993 ** Clean up comments, etc. ** ** X-2 Joseph Dziedzic 24-May-1993 ** Rename main program entry point to eliminate confusion ** in UTIL32.OLB. ** **------------------------------------------------------------------------ */ /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** ** INCLUDE FILES ** **------------------------------------------------------------------------ */ #include "src$:diskmount.h" /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** ** GLOBAL DECLARATIONS ** **------------------------------------------------------------------------ */ char *ddata_ptr, *dcurr_ptr; /* pointers to disk name data */ char *pdata_ptr, *pcurr_ptr; /* pointers to preferred path data */ char *ldata_ptr, *lcurr_ptr; /* pointers to disk label data */ unsigned int action, mnt_type, /* 0-nomnt, 1-normal mnt, 2-DFS mnt */ i, itm_nbr, debugx, status; int msg_len; char output_data[OUT_MBX_MAXMSG], status_msg[128], msg_text[133]; ITMDSC mnt_itmlst[MAX_ITEMS]; $DESCRIPTOR (message_desc, msg_text); /* Function prototype definitions */ void add_status_msg (); void obtain_label (); int read_homeblock_label (); int set_pref_path (); build_phys_device_items (); #ifdef LAD dad_bind_service (); #endif /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function main ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** **------------------------------------------------------------------------ */ diskmount_child_main () MAIN_PROGRAM { static $DESCRIPTOR (input_dev_desc, "SYS$INPUT"); static $DESCRIPTOR (output_dev_desc, "SYS$OUTPUT"); char severity; char action_str[12]; int in_mbx_iosb[2]; int out_mbx_iosb[2]; short in_mbx_chan; short out_mbx_chan; char input_data[1024]; char temp[12]; char tempstr[256]; long flags; int j, count; char name[80], disk[512], label[256], logical[256], prf_path[32], add_log[256], qual[256], dfs_access[256]; int paren_open; count = 0; /* Assign channels to input and output mailbox created by parent */ status = sys$assign ( &output_dev_desc, /* Device name descriptor */ &out_mbx_chan, /* I/O channel */ 0, /* Access mode */ 0); /* Mailbox name */ if ( !(status & STS$M_SUCCESS) ) return status; status = sys$assign ( &input_dev_desc, /* Device name descriptor */ &in_mbx_chan, /* I/O channel */ 0, /* Access mode */ 0); /* Mailbox name */ if ( !(status & STS$M_SUCCESS) ) { sys$dassgn (out_mbx_chan); return status; } /* Loop forever, reading disk data sent to mailbox by parent, performing mount, and sending mount status back to parent. End (by terminating subprocess) when parent sends "EOF" to mailbox. */ while (1) /* START of main loop */ { status = sys$qiow ( 0, /* EFN */ in_mbx_chan, /* I/O channel */ IO$_READVBLK, /* I/O function */ &in_mbx_iosb, /* I/O status block */ 0, /* Completion AST routine */ 0, /* Completion AST parameter */ input_data, /* P1 - buffer address */ sizeof input_data, /* P2 - buffer length */ 0, /* P3 - Not used */ 0, /* P4 - Not used */ 0, /* P5 - Not used */ 0); /* P6 - Not used */ if ( !(status & STS$M_SUCCESS) ) { sys$dassgn (in_mbx_chan); sys$dassgn (out_mbx_chan); return status; } /* When parent sends EOF, send informational message back to parent and terminate this subprocess. */ if (in_mbx_iosb[0] == SS$_ENDOFFILE) { sprintf (output_data, "\3 terminating - attempted/performed %d mount(s)\0", count); status = sys$qiow ( 0, /* EFN */ out_mbx_chan, /* I/O channel */ IO$_WRITEVBLK | IO$M_NOW, /* I/O function */ &out_mbx_iosb, /* I/O status block */ 0, /* Completion AST routine */ 0, /* Completion AST parameter */ output_data, /* P1 - buffer address */ sizeof output_data, /* P2 - buffer length */ 0, /* P3 - Not used */ 0, /* P4 - Not used */ 0, /* P5 - Not used */ 0); /* P6 - Not used */ sys$dassgn (in_mbx_chan); sys$dassgn (out_mbx_chan); sys$delprc (0, 0); /* Delete this subprocess */ } /* Initialize variables each time through the loop */ status_msg[0] = '\0'; mnt_type = 1; /* Assume normal mount */ name[0] = '\0'; disk[0] = '\0'; label[0] = '\0'; logical[0] = '\0'; prf_path[0] = '\0'; add_log[0] = '\0'; qual[0] = '\0'; dfs_access[0] = '\0'; /* Separate input data string into separate elements */ sscanf (input_data, "%s %s %s %s %s %s %s %s %s", action_str, name, disk, label, logical, add_log, prf_path, qual, dfs_access); action = atoi (action_str); output_data[0] = STS$K_SUCCESS ; /* Preset null status */ output_data[1] = '\0'; /* Preset null string */ strcat (output_data, name); strcat (output_data, "\n"); if (prf_path[0] == '-') prf_path[0] = '\0'; ldata_ptr = &label[0]; lcurr_ptr = &label[0]; ddata_ptr = &disk[0]; dcurr_ptr = &disk[0]; pdata_ptr = &prf_path[0]; pcurr_ptr = &prf_path[0]; paren_open = 0; itm_nbr = 0; /* Construct item list with item(s) for each field in input data */ /* Item for logical name (only 1 allowed by MOUNT) */ if (logical[0] != '-') { ITM_RET0_INIT (mnt_itmlst[itm_nbr], MNT$_LOGNAM, strlen (logical), &logical); itm_nbr++; } /* Mount flags are bit-encoded in MNT$_FLAGS item */ flags = 0; if (strstr (qual, "NOASSI") != NULL) flags = flags | MNT$M_NOASSIST; if (strstr (qual, "NODISK") != NULL) flags = flags | MNT$M_NODISKQ; if (strstr (qual, "NOWRIT") != NULL) flags = flags | MNT$M_NOWRITE; if (strstr (qual, "SYSTEM") != NULL) flags = flags | MNT$M_SYSTEM; if (strstr (qual, "NOREBU") != NULL) flags = flags | MNT$M_NOREBUILD; if (strstr (qual, "NOMNTV") != NULL) flags = flags | MNT$M_NOMNTVER; if (strstr (qual, "CLUSTE") != NULL) flags = flags | MNT$M_CLUSTER ; if (strstr (qual, "NOUNLO") != NULL) flags = flags | MNT$M_NOUNLOAD ; /* Future qualifiers for the "MOUNT command" if (strstr (qual, "NOCACH") != NULL) flags = flags | MNT$M_NOCACHE ; if (strstr (qual, "READCH") != NULL) flags = flags | MNT$M_READCHECK ; if (strstr (qual, "SHARE ") != NULL) flags = flags | MNT$M_SHARE ; if (strstr (qual, "MESSAG") != NULL) flags = flags | MNT$M_MESSAGE ; if (strstr (qual, "WRITEC") != NULL) flags = flags | MNT$M_WRITECHECK ; if (strstr (qual, "WRITET") != NULL) flags = flags | MNT$M_WRITETHRU ; if (strstr (qual, "NOCOPY") != NULL) flags = flags | MNT$M_NOCOPY ; if (strstr (qual, "NOAUTO") != NULL) flags = flags | MNT$M_NOAUTO ; if (strstr (qual, "OVR_SH") != NULL) flags = flags | MNT$M_OVR_SHAMEM ; */ ITM_RET0_INIT (mnt_itmlst[itm_nbr], MNT$_FLAGS, sizeof (flags), &flags); itm_nbr++; /* Disk device name is most complex because it must allow for shadow sets and/or volume sets, and build items for each appropriate element of the disk field. */ do /* Do loop for "disk" data */ { if ((dcurr_ptr[0] == '\0') && (dcurr_ptr > ddata_ptr)) /* End of string without ",()" - must be device name */ { build_phys_device_items (MNT$_DEVNAM, 1); ddata_ptr = dcurr_ptr; } if (dcurr_ptr[0] == '(') { /* "(" - previous data is shadow-set name, following is member */ dcurr_ptr[0] = '\0'; paren_open = 1; ITM_RET0_INIT (mnt_itmlst[itm_nbr], MNT$_SHANAM, strlen (ddata_ptr), ddata_ptr); itm_nbr++; ddata_ptr = dcurr_ptr + 1; } if (dcurr_ptr[0] == ')') { /* ")" - previous data is shadow member name */ dcurr_ptr[0] = '\0'; paren_open = 0; build_phys_device_items (MNT$_SHAMEM, 1); ddata_ptr = dcurr_ptr + 1; } if ((dcurr_ptr[0] == ',') && (dcurr_ptr > ddata_ptr)) { /* "comma" - may be within parentheses or outside */ dcurr_ptr[0] = '\0'; if (paren_open == 1) { /* inside parentheses - shadow member name */ build_phys_device_items (MNT$_SHAMEM, 0); ddata_ptr = dcurr_ptr + 1; } else { /* outside parentheses - physical device name */ build_phys_device_items (MNT$_DEVNAM, 1); ddata_ptr = dcurr_ptr + 1; } } if ((dcurr_ptr[0] == ',') && (dcurr_ptr == ddata_ptr)) { dcurr_ptr[0] = '\0'; ddata_ptr = dcurr_ptr + 1; } dcurr_ptr++; } while (ddata_ptr[0] != '\0'); /* End of do-loop for "disk" */ /* Terminate item list */ ITM_TERM (mnt_itmlst[itm_nbr]); /* Call SYS$MOUNT with the completed item list */ /* Debugging aid sprintf (temp, "Count: %d\0", i); */ debugx++; switch (mnt_type) { case 0: status = STS$K_SEVERE; break; case 1: status = SYS$MOUNT (&mnt_itmlst); break; /* DFS mount not yet supported case 2: status = DFS$MOUNT (&mnt_itmlst); break; */ } count++; if (status == STS$K_SEVERE) msg_text[0] = '\0'; else { sys$getmsg (status, &msg_len, &message_desc, 15, 0); msg_text[msg_len] = '\0'; } severity = (status & 7); if (msg_text[0] == '%') msg_text[0] = '-'; add_status_msg (severity, msg_text, 0); status = sys$qio ( 0, /* EFN */ out_mbx_chan, /* I/O channel */ IO$_WRITEVBLK, /* I/O function */ &out_mbx_iosb, /* I/O status block */ 0, /* Completion AST routine */ 0, /* Completion AST parameter */ output_data, /* P1 - buffer address */ sizeof output_data, /* P2 - buffer length */ 0, /* P3 - Not used */ 0, /* P4 - Not used */ 0, /* P5 - Not used */ 0); /* P6 - Not used */ if ( !(status & STS$M_SUCCESS) ) { sys$dassgn (in_mbx_chan); sys$dassgn (out_mbx_chan); return status; } } /* END of main while loop */ } /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function add_status_msg ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** **------------------------------------------------------------------------ */ void add_status_msg (char sev, char msg[128], int hex_status) { char current_sev; char newline_char[] = { "\n\0" }; char newline_space[] = { " \0" }; current_sev = output_data[0]; /* order of severity: 0-WARNING, 1-SUCCESS, 2-ERROR, 3-INFO, 4-SEVERE (FATAL) Remainder of dividing severity by two indicates whether or not the "level" of severity has increased */ /* If current severity is success or info, and new severity is NOT success or info, store new severity */ if (sev % 2 < current_sev % 2) output_data[0] = sev; /* If current severity and new severity are either success or info, OR warning, error, or fatal, store new severity if it is "more severe" (i.e., more important */ if ((sev % 2 == current_sev % 2) && (sev > current_sev)) output_data[0] = sev; if ((strlen (msg) + 6) > (sizeof (output_data) - strlen (output_data))) return; strcat (output_data, newline_space); strcat (output_data, msg); strcat (output_data, newline_char); return; } /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function obtain_label extracts the label data from the data string ** for an individual disk device. If the label is wildcarded (contains ** a "*"), then this function calls the read_homeblock_label function ** to read the actual label from the physical device and uses that ** label if it matches the wildcard construct. ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** **------------------------------------------------------------------------ */ void obtain_label () { do /* do-loop for "label" data */ { if (((lcurr_ptr[0] == '\0') && (lcurr_ptr > ldata_ptr)) || (lcurr_ptr[0] == ',')) { if (lcurr_ptr[0] == ',') { lcurr_ptr[0] = '\0'; ++lcurr_ptr; /* to skip comma position */ } /* If label data contains a wildcard, read the label from the homeblock on the device */ status = 1; if (strpbrk (ldata_ptr, "*%") != NULL) { status = read_homeblock_label (); /* Possible status: 1 : success -1 : unable to packack device -2 : no valid home block to read label from -3 : device label does not match wildcard data */ if (status == -1) add_status_msg (STS$K_SEVERE, "-Can't PACKACK device", 0); if (status == -2) add_status_msg (STS$K_SEVERE, "-NO valid homeblock", 0); if (status == -3) add_status_msg (STS$K_SEVERE, "-NOMATCH wildcard label", 0); } if (status == 1) { ITM_RET0_INIT (mnt_itmlst[itm_nbr], MNT$_VOLNAM, strlen (ldata_ptr), ldata_ptr); } else { mnt_type = 0; } itm_nbr++; ldata_ptr = lcurr_ptr; break; } lcurr_ptr++; } while (ldata_ptr[0] != '\0'); /* End do-loop for "label" */ lcurr_ptr++; } /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function read_homeblock_label reads the homeblock from an ODS-2 ** disk device and extracts the label information from the homeblock. ** ** Homeblock checksum is used to check if homeblock is valid ** and alternate home blocks (up to 10) are read until a valid ** homeblock is found. ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** ** -1: Can't assign channel to device ** -2: Can't find/read home block ** -3: No match for volume label ** **------------------------------------------------------------------------ */ read_homeblock_label () { /* Define alternate structs for ODS-2 disk device homeblock */ union { /* Array of 512 bytes, used for reading the homeblock from disk */ struct { unsigned char hm_byte[512]; } home_block; /* Array of words, used for checksum calculation */ struct { unsigned short hm_word[256]; } chk_block; /* Definition of individual fields */ struct { unsigned int HM2$L_HOMELBN; unsigned int HM2$L_ALHOMELBN; unsigned int HM2$L_ALTIDXLBN; unsigned char HM2$B_STRUCVER; unsigned char HM2$B_STRUCLEV; unsigned short HM2$W_CLUSTER; unsigned short HM2$W_HOMEVBN; unsigned short HM2$W_ALHOMEVBN; unsigned short HM2$W_ALTIDXVBN; unsigned short HM2$W_IBMAPVBN; unsigned int HM2$L_IBMAPLBN; unsigned int HM2$L_MAXFILES; unsigned short HM2$W_IBMAPSIZE; unsigned short HM2$W_RESFILES; unsigned short HM2$W_DEVTYPE; unsigned short HM2$W_RVN; unsigned short HM2$W_SETCOUNT; unsigned short HM2$W_VOLCHAR; unsigned int HM2$L_VOLOWNER; unsigned int HM2$L_SEC_MASK; unsigned short HM2$W_PROTECT; unsigned short HM2$W_FILEPROT; unsigned short HM2$W_RECPROT; unsigned short HM2$W_CHECKSUM1; unsigned char HM2$Q_CREDATE[8]; unsigned char HM2$B_WINDOW; unsigned char HM2$B_LRU_LIM; unsigned short HM2$W_EXTEND; unsigned char HM2$Q_RETAINMIN[8]; unsigned char HM2$Q_RETAINMAX[8]; unsigned char HM2$Q_REVDATE[8]; unsigned char HM2$R_MIN_CLASS[20]; unsigned char HM2$R_MAX_CLASS[20]; unsigned short HM2$W_FILETAB_FID; unsigned char unused_1[4]; unsigned char HM2$B_LOWSTRUCVER; unsigned char HM2$B_LOWSTRUCLEV; unsigned char HM2$B_HIGHSTRUCVER; unsigned char HM2$B_HIGHSTRUCLEV; unsigned char unused_2[310]; unsigned int HM2$L_SERIALNUM; unsigned char HM2$T_STRUCNAME[12]; unsigned char HM2$T_VOLNAME[12]; unsigned char HM2$T_OWNERNAME[12]; unsigned char HM2$T_FORMAT[12]; unsigned char unused_3[2]; unsigned short HM2$W_CHECKSUM2; } hm2_block; } h_blk; char disk_label[16]; char dev_tmp[64]; char temp[255]; int status, iosb, lbn, i; unsigned short chan, chk_sum; struct dsc$descriptor_s disk_label_desc; struct dsc$descriptor_s label_data_desc; struct dsc$descriptor_s hm_devnam_dsc; /* Initialize device name descriptor with the device name */ DSC_INIT (hm_devnam_dsc, ddata_ptr); /* Assign a channel to device */ status = sys$assign ( &hm_devnam_dsc, /* Device name descriptor */ &chan, /* I/O channel */ 0, /* Access mode */ 0); /* Mailbox name */ /* Send a PACKACK QIO to channel to establish connection to device. Add IO$M_INHERLOG to inhibit any error log entries that may result from this action */ status = sys$qiow ( 0, /* EFN */ chan, /* I/O channel */ IO$_PACKACK | IO$M_INHERLOG,/* I/O function */ &iosb, /* I/O status block */ 0, /* Completion AST routine */ 0, /* Completion AST parameter */ 0, /* P1 - buffer address */ 0, /* P2 - buffer length */ 0, /* P3 - Not used */ 0, /* P4 - Not used */ 0, /* P5 - Not used */ 0); /* P6 - Not used */ /* "Success" status is either ILLIOFUNC (returned by some disk devices) or NORMAL - any other status meanse that no device connection was made */ if (( !(status & STS$M_SUCCESS) ) && status != SS$_ILLIOFUNC) return (-1); /* Read up to 10 possible homeblocks (LBN 1-10) until a valid homeblock is found (determined by checksum value) */ for (lbn = 1; lbn < 11; lbn++) { status = sys$qiow ( 0, /* EFN */ chan, /* I/O channel */ IO$_READLBLK, /* I/O function */ &iosb, /* I/O status block */ 0, /* Completion AST routine */ 0, /* Completion AST parameter */ &h_blk.home_block, /* P1 - buffer address */ 512, /* P2 - buffer length */ lbn, /* P3 - Logical block to read */ 0, /* P4 - Not used */ 0, /* P5 - Not used */ 0); /* P6 - Not used */ /* Sum (into a word) of first 255 words in homeblock should be equal to the value of the 256th word for a valid homeblock */ /* *** CHECK STATUS *** */ chk_sum = 0; for (i = 0; i < 255; i++) chk_sum = chk_sum + h_blk.chk_block.hm_word[i]; if (chk_sum == h_blk.hm2_block.HM2$W_CHECKSUM2) break; /* If checksums match, found valid home block */ } sys$dassgn (chan); /* Deassign channel */ /* Exited loop for reading homeblock - check if valid homeblock was obtained, or if loop end was reached without valid homeblock */ if ( ( !(status & STS$M_SUCCESS) ) || (chk_sum != h_blk.hm2_block.HM2$W_CHECKSUM2) ) return (-2); strncpy (disk_label, h_blk.hm2_block.HM2$T_VOLNAME, 12); disk_label[12] = '\0'; /* Returns STR$_NOMATCH or STR$_MATCH */ DSC_INIT (disk_label_desc, disk_label); DSC_INIT (label_data_desc, ldata_ptr); status = STR$MATCH_WILD (&disk_label_desc, &label_data_desc); if (status == STR$_NOMATCH) return (-3); /* Read valid label from device, and successfully matched specified wildcard - replace original wildcarded label in data string with actual label */ strcpy (temp, (lcurr_ptr + 1)); strcpy (ldata_ptr, disk_label); lcurr_ptr = ldata_ptr + strlen (disk_label); strcpy ((lcurr_ptr + 1), temp); return (1); } /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function set_pref_path uses a QIO to set (and optionally force) ** a preferred path for HSC-connected or MSCP-served disks. The ** function checks that the specified path is one of the available ** paths to the device and that the path is actually available and ** does not attempt to set the path otherwise. ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** **------------------------------------------------------------------------ */ int set_pref_path (int path_action) { ITMDSC item_list[5]; char devnam[64]; $DESCRIPTOR (devnam_dsc, devnam); char path_ascic[10]; char ci_path[12], mscp_path[12]; unsigned short chan; int path; int iosb; int status; char dvi_ahnam[64]; char dvi_hnam[64]; unsigned long dvi_ahavl; unsigned long dvi_havl; short dvi_ahnam_len; short dvi_hnam_len; struct dsc$descriptor_s dvi_ahnam_dsc; struct dsc$descriptor_s dvi_hnam_dsc; struct dsc$descriptor_s dvi_ahavl_dsc; struct dsc$descriptor_s dvi_havl_dsc; strcpy (devnam, ddata_ptr); ci_path[0] = '\0'; mscp_path[0] = '\0'; /* DVI$_ALT_HOST_AVAIL (returns longword 1 or 0) DVI$_ALT_HOST_NAME (returns 64-byte char string padded with 0) DVI$_HOST_AVAIL (returns longword 1 or 0) DVI$_HOST_NAME (returns 64-byte char string padded with 0) */ DSC_INIT_BUF (dvi_ahnam_dsc, dvi_ahnam); DSC_INIT_BUF (dvi_hnam_dsc, dvi_hnam); DSC_INIT_BUF (dvi_ahavl_dsc, dvi_ahavl); DSC_INIT_BUF (dvi_havl_dsc, dvi_havl); ITM_INIT (item_list[0], DVI$_HOST_NAME, dvi_hnam, dvi_hnam_dsc.dsc$w_length); ITM_INIT (item_list[1], DVI$_ALT_HOST_NAME, dvi_ahnam, dvi_ahnam_dsc.dsc$w_length); ITM_INIT (item_list[2], DVI$_HOST_AVAIL, dvi_havl, dvi_havl_dsc.dsc$w_length); ITM_INIT (item_list[3], DVI$_ALT_HOST_AVAIL, dvi_ahavl, dvi_ahavl_dsc.dsc$w_length); ITM_TERM (item_list[4]); status = 0; iosb = 0; status = sys$assign ( &devnam_dsc, /* Device name descriptor */ &chan, /* I/O channel */ 0, /* Access mode */ 0); /* Mailbox name */ if ( !(status & STS$M_SUCCESS) ) { return (status); } if ((path_action & 1) == 1) /* 1 means set preferred path */ { ci_path[0] = '\0'; mscp_path[0] = '\0'; do /* do loop for "path" data */ { if ((pcurr_ptr[0] == '\0') && (pcurr_ptr > pdata_ptr)) { strcpy (mscp_path, pdata_ptr); pdata_ptr = pcurr_ptr; } if (pcurr_ptr[0] == '|') { pcurr_ptr[0] = '\0'; strcpy (ci_path, pdata_ptr); pdata_ptr = pcurr_ptr + 1; } if (pcurr_ptr[0] == ',') { pcurr_ptr[0] = '\0'; strcpy (mscp_path, pdata_ptr); pdata_ptr = pcurr_ptr + 1; break; } pcurr_ptr++; } while (pdata_ptr[0] != '\0');/* end of do-loop for "path" */ if ((ci_path[0] == '\0') && (mscp_path[0] == '\0')) { status = sys$dassgn (chan); /* Deassign channel */ return (STS_NOPATHSPEC); } status = sys$getdviw ( 0, /* Event flag */ 0, /* I/O channel */ &devnam_dsc, /* Device name */ &item_list, /* Item list */ &iosb, /* I/O status block */ 0, /* AST address */ 0, /* AST parameter */ 0); /* Reserved */ if ( !(status & STS$M_SUCCESS) ) { status = sys$dassgn (chan); /* Deassign channel */ return (status); } path_ascic[0] = '\0'; path = 3; if ((ci_path[0] != '\0') && (strcmp (dvi_hnam, ci_path) == 0)) { sprintf (path_ascic, "%c%s\0", strlen (ci_path), ci_path); path = 1 * dvi_havl; /* 1 for CI path, 2 for MSCP path */ } else if ((ci_path[0] != '\0') && (strcmp (dvi_ahnam, ci_path) == 0)) { sprintf (path_ascic, "%c%s\0", strlen (ci_path), ci_path); path = 1 * dvi_ahavl; /* 1 for CI path, 2 for MSCP path */ } else if ((mscp_path[0] != '\0') && (strcmp (dvi_hnam, mscp_path) == 0)) { sprintf (path_ascic, "%c%s\0", strlen (mscp_path), mscp_path); path = 2 * dvi_havl; /* 1 for CI path, 2 for MSCP path */ } else if ((mscp_path[0] != '\0') && (strcmp (dvi_ahnam, mscp_path) == 0)) { sprintf (path_ascic, "%c%s\0", strlen (mscp_path), mscp_path); path = 2 * dvi_havl; /* 1 for CI path, 2 for MSCP path */ } if (path == 3) { add_status_msg (STS$K_WARNING, "-specified path NOT matched", 0); return; } if (path == 0) { add_status_msg (STS$K_WARNING, "-specified path NOT available", 0); return; } status = sys$qiow ( 0, chan, IO$_SETPRFPATH, &iosb, 0, 0, &path_ascic, 0, 0, 0, 0, 0); if ( !(status & STS$M_SUCCESS) ) add_status_msg (STS$K_WARNING, "-Path error: ", status); /* ??? getmsg (status) and add_status_msg ??? */ status = sys$dassgn (chan); /* Deassign channel */ return (status); } if ((path_action & 2) == 2) /* 2 means force preferred path */ { status = sys$qiow ( 0, chan, IO$_SETPRFPATH | IO$M_FORCEPATH, &iosb, 0, 0, 0, 0, 0, 0, 0, 0); if ( !(status & STS$M_SUCCESS) ) /* ??? getmsg (status) and add_status_msg ??? */ return (status); } return (1); } /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function build_phys_device_items ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** **------------------------------------------------------------------------ */ build_phys_device_items (unsigned int tmp_code, unsigned int tmp_label) { /* this code is called for each physical device - needs to add items to itemlist for device and label??? */ #ifdef LAD if (strncmp (ddata_ptr, "DAD|", 4) == 0) dad_bind_service (); #endif /* Future DFS support? if (strncmp (ddata_ptr, "DFSC", 4) == 0) { dfs_??? (); ?if (mnt_type == 1) mnt_type = 2; */ ITM_RET0_INIT (mnt_itmlst[itm_nbr], tmp_code, strlen (ddata_ptr), ddata_ptr); itm_nbr++; #ifdef LAD if (strncmp (ddata_ptr, "DAD|", 4) != 0) #endif set_pref_path (action); if (tmp_label == 1) { obtain_label (); /* itm_nbr incremented by obtain_label */ } } /* **++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ** FUNCTIONAL DESCRIPTION: ** ** Function dad_bind_service performs the equivalent of an ** ESS$LADCP> BIND/SYSTEM/NOWRITE service-name ** and determines the DAD unit number created and assigns ** a logical name of the form DAD$service-name. This code ** is based on the actions performed by the BLISS code in ** the VMS LADCP module, but doesn't include any code to ** handle creation of other types of DAD devices (such as ** password-protected, writeable, group logical, etc). ** ** ** FORMAL PARAMETERS: ** ** RETURN VALUE: ** **------------------------------------------------------------------------ */ #ifdef LAD dad_bind_service () { ITMDSC dvi_item_list[2]; ITMDSC lnm_item_list[4]; $DESCRIPTOR (lnmtab_dsc, "LNM$SYSTEM_TABLE"); struct dsc$descriptor_s dvi_devnam_dsc; char dvi_devnam[12]; char logname[255]; struct dsc$descriptor_s logname_dsc; char devnam[255]; /* Fails for some reason if >255 */ struct dsc$descriptor_s devnam_dsc; struct dsc$descriptor_s equiv_dsc; char temp[512]; char service_name[255]; char *ptr; unsigned short chan; int lnm_attr, path, iosb, status; strcpy (service_name, (ddata_ptr + 4)); /* Remove "DAD|" */ sprintf (logname, "DAD$%s\0", service_name); /* Build devnam array to be passed to DADDRIVER */ /* LADCP and DADDRIVER allow for several options for creating DAD devices, but the following construct creates only devices with the following characteristics: virtual volume defined by service name read-only synchronous write access (irrelevant in this case, but required) NO password */ strncpy (devnam, "DAD0:", 5); ptr = &devnam[5]; *(ptr++) = BIND_C_SERVICE_NAME; *(ptr++) = strlen (service_name) + 4; *(ptr++) = DAD$C_ACCESS_VIRTUAL_VOLUME; *(ptr++) = strlen (service_name) + 2; *(ptr++) = DAD$C_VOLUME_NAME; strcpy (ptr, service_name); ptr += strlen (service_name) + 1; *(ptr++) = BIND_C_ACCESS_MODE; *(ptr++) = 1; *(ptr++) = BIND_C_READ_ACCESS; *(ptr++) = BIND_C_ASYNCH_WRITE; *(ptr++) = 1; *(ptr++) = BIND_C_SYNCH; *(ptr++) = BIND_C_END_OF_LIST; DSC_INIT_BUF (devnam_dsc, devnam); /* Assign a channel to devnam array constructed above. This causes the DADDRIVER to clone a UCB from the DAD0: template and assign the next DAD unit number to the "device" */ status = sys$assign ( &devnam_dsc, /* Device name descriptor */ &chan, /* I/O channel */ 0, /* Access mode */ 0); /* Mailbox name */ /* Obtain the DEVNAM for the DAD device just created on the assigned channel */ ITM_INIT (dvi_item_list[0], DVI$_DEVNAM, dvi_devnam, dvi_devnam_dsc.dsc$w_length); ITM_TERM (dvi_item_list[1]); status = sys$getdviw ( 0, /* Event flag */ chan, /* I/O channel */ 0, /* Device name */ &dvi_item_list, /* Item list */ &iosb, /* I/O status block */ 0, /* AST address */ 0, /* AST parameter */ 0); /* Reserved */ /* Create a logical name of the form DAD$service-name for the DAD unit that was created. The logical name is created in the SYSTEM table with EXEC mode access and CONCEALED attribute. */ DSC_INIT (equiv_dsc, dvi_devnam); DSC_INIT (logname_dsc, logname); lnm_attr = LNM$M_CONCEALED; ITM_RET0_INIT (lnm_item_list[0], LNM$_ATTRIBUTES, 4, &lnm_attr); ITM_RET0_INIT (lnm_item_list[1], LNM$_STRING, strlen (dvi_devnam), dvi_devnam); ITM_TERM (lnm_item_list[2]); status = sys$crelnm ( 0, &lnmtab_dsc, &logname_dsc, &PSL$C_EXEC, &lnm_item_list); /* Good returns - SS$_NORMAL or SS$_SUPERSEDE */ status = sys$dassgn (chan); /* Deassign channel */ strcpy (temp, (dcurr_ptr + 1)); strcpy (ddata_ptr, dvi_devnam); dcurr_ptr = ddata_ptr + strlen (dvi_devnam); strcpy ((dcurr_ptr + 1), temp); } #endif